From d2821e14fa9735ece3be6eec9d6bdf4cf96c1280 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 14:53:41 -0700 Subject: [PATCH 01/12] ParseExpression: return a std::pair --- .../ControlReference/ControlReference.cpp | 4 +- .../ControlReference/ExpressionParser.cpp | 41 ++++++++----------- .../ControlReference/ExpressionParser.h | 3 +- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index e4162e22a7..e5e4c1a578 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -30,9 +30,9 @@ bool ControlReference::InputGateOn() void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devices, const ciface::Core::DeviceQualifier& default_device) { - Expression* expr; ControlFinder finder(devices, default_device, IsInput()); - m_parse_status = ParseExpression(expression, finder, &expr); + Expression* expr; + std::tie(m_parse_status, expr) = ParseExpression(expression, finder); m_parsed_expression.reset(expr); } diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index d520015cf3..92e6bde502 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -369,15 +369,14 @@ public: m_it = tokens.begin(); } - ParseStatus Parse(Expression** expr_out) + std::pair Parse() { ExpressionNode* node; ParseStatus status = Toplevel(&node); if (status != ParseStatus::Successful) - return status; + return std::make_pair(status, nullptr); - *expr_out = new Expression(node); - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, new Expression(node)); } private: @@ -522,32 +521,28 @@ Expression::~Expression() delete node; } -static ParseStatus ParseExpressionInner(const std::string& str, ControlFinder& finder, - Expression** expr_out) +static std::pair ParseExpressionInner(const std::string& str, + ControlFinder& finder) { - ParseStatus status; - Expression* expr; - *expr_out = nullptr; - if (str == "") - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, nullptr); Lexer l(str); std::vector tokens; - status = l.Tokenize(tokens); - if (status != ParseStatus::Successful) - return status; + ParseStatus tokenize_status = l.Tokenize(tokens); + if (tokenize_status != ParseStatus::Successful) + return std::make_pair(tokenize_status, nullptr); - Parser p(tokens, finder); - status = p.Parse(&expr); + ParseStatus status; + Expression* expr; + std::tie(status, expr) = Parser(tokens, finder).Parse(); if (status != ParseStatus::Successful) - return status; + return std::make_pair(status, nullptr); - *expr_out = expr; - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, expr); } -ParseStatus ParseExpression(const std::string& str, ControlFinder& finder, Expression** expr_out) +std::pair ParseExpression(const std::string& str, ControlFinder& finder) { // Add compatibility with old simple expressions, which are simple // barewords control names. @@ -560,11 +555,11 @@ ParseStatus ParseExpression(const std::string& str, ControlFinder& finder, Expre Device::Control* control = finder.FindControl(qualifier); if (control) { - *expr_out = new Expression(new ControlExpression(qualifier, device, control)); - return ParseStatus::Successful; + Expression* expr = new Expression(new ControlExpression(qualifier, device, control)); + return std::make_pair(ParseStatus::Successful, expr); } - return ParseExpressionInner(str, finder, expr_out); + return ParseExpressionInner(str, finder); } } } diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h index f07c9a1326..2d41933e50 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h @@ -6,6 +6,7 @@ #include #include +#include #include "InputCommon/ControllerInterface/Device.h" namespace ciface @@ -66,6 +67,6 @@ enum class ParseStatus NoDevice, }; -ParseStatus ParseExpression(const std::string& expr, ControlFinder& finder, Expression** expr_out); +std::pair ParseExpression(const std::string& expr, ControlFinder& finder); } } From bbb7c1723569b1f897041851f97a46327a302e48 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:08:55 -0700 Subject: [PATCH 02/12] ExpressionParser: use internal ParseResult struct instead of out-params --- .../ControlReference/ExpressionParser.cpp | 97 +++++++++---------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 92e6bde502..a414c669a0 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -361,6 +361,15 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const return device->FindOutput(qualifier.control_name); } +struct ParseResult +{ + ParseResult(ParseStatus status_, ExpressionNode* expr_ = nullptr) : status(status_), expr(expr_) + { + } + ParseStatus status; + ExpressionNode* expr; +}; + class Parser { public: @@ -369,16 +378,7 @@ public: m_it = tokens.begin(); } - std::pair Parse() - { - ExpressionNode* node; - ParseStatus status = Toplevel(&node); - if (status != ParseStatus::Successful) - return std::make_pair(status, nullptr); - - return std::make_pair(ParseStatus::Successful, new Expression(node)); - } - + ParseResult Parse() { return Toplevel(); } private: std::vector tokens; std::vector::iterator m_it; @@ -392,7 +392,7 @@ private: return tok.type == type; } - ParseStatus Atom(ExpressionNode** expr_out) + ParseResult Atom() { Token tok = Chew(); switch (tok.type) @@ -402,18 +402,14 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - { - *expr_out = new DummyExpression(tok.qualifier); - return ParseStatus::NoDevice; - } + return {ParseStatus::NoDevice, new DummyExpression(tok.qualifier)}; - *expr_out = new ControlExpression(tok.qualifier, device, control); - return ParseStatus::Successful; + return {ParseStatus::Successful, new ControlExpression(tok.qualifier, device, control)}; } case TOK_LPAREN: - return Paren(expr_out); + return Paren(); default: - return ParseStatus::SyntaxError; + return {ParseStatus::SyntaxError}; } } @@ -428,20 +424,18 @@ private: } } - ParseStatus Unary(ExpressionNode** expr_out) + ParseResult Unary() { if (IsUnaryExpression(Peek().type)) { Token tok = Chew(); - ExpressionNode* atom_expr; - ParseStatus status = Atom(&atom_expr); - if (status == ParseStatus::SyntaxError) - return status; - *expr_out = new UnaryExpression(tok.type, atom_expr); - return ParseStatus::Successful; + ParseResult result = Atom(); + if (result.status == ParseStatus::SyntaxError) + return result; + return {ParseStatus::Successful, new UnaryExpression(tok.type, result.expr)}; } - return Atom(expr_out); + return Atom(); } bool IsBinaryToken(TokenType type) @@ -457,47 +451,46 @@ private: } } - ParseStatus Binary(ExpressionNode** expr_out) + ParseResult Binary() { - ParseStatus status = Unary(expr_out); - if (status == ParseStatus::SyntaxError) - return status; + ParseResult result = Unary(); + if (result.status == ParseStatus::SyntaxError) + return result; + ExpressionNode* expr = result.expr; while (IsBinaryToken(Peek().type)) { Token tok = Chew(); - ExpressionNode* unary_expr; - status = Unary(&unary_expr); - if (status == ParseStatus::SyntaxError) + ParseResult unary_result = Unary(); + if (unary_result.status == ParseStatus::SyntaxError) { - delete *expr_out; - return status; + delete expr; + return unary_result; } - *expr_out = new BinaryExpression(tok.type, *expr_out, unary_expr); + expr = new BinaryExpression(tok.type, expr, unary_result.expr); } - return ParseStatus::Successful; + return {ParseStatus::Successful, expr}; } - ParseStatus Paren(ExpressionNode** expr_out) + ParseResult Paren() { - ParseStatus status; - // lparen already chewed - if ((status = Toplevel(expr_out)) != ParseStatus::Successful) - return status; + ParseResult result = Toplevel(); + if (result.status != ParseStatus::Successful) + return result; if (!Expects(TOK_RPAREN)) { - delete *expr_out; - return ParseStatus::SyntaxError; + delete result.expr; + return {ParseStatus::SyntaxError}; } - return ParseStatus::Successful; + return result; } - ParseStatus Toplevel(ExpressionNode** expr_out) { return Binary(expr_out); } + ParseResult Toplevel() { return Binary(); } }; ControlState Expression::GetValue() const @@ -533,13 +526,11 @@ static std::pair ParseExpressionInner(const std::strin if (tokenize_status != ParseStatus::Successful) return std::make_pair(tokenize_status, nullptr); - ParseStatus status; - Expression* expr; - std::tie(status, expr) = Parser(tokens, finder).Parse(); - if (status != ParseStatus::Successful) - return std::make_pair(status, nullptr); + ParseResult result = Parser(tokens, finder).Parse(); + if (result.status != ParseStatus::Successful) + return std::make_pair(result.status, nullptr); - return std::make_pair(ParseStatus::Successful, expr); + return std::make_pair(ParseStatus::Successful, new Expression(result.expr)); } std::pair ParseExpression(const std::string& str, ControlFinder& finder) From c33e391d267223fad8f9f6841c2729668b11da3c Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:24:29 -0700 Subject: [PATCH 03/12] InputConfigDiag: don't use entire ExpressionParse namespace --- Source/Core/DolphinWX/Input/InputConfigDiag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp index 5d8bf9615e..ccf2d42f4f 100644 --- a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp @@ -70,7 +70,7 @@ #include "InputCommon/ControllerInterface/Device.h" #include "InputCommon/InputConfig.h" -using namespace ciface::ExpressionParser; +using ciface::ExpressionParser::ParseStatus; void InputConfigDialog::ConfigExtension(wxCommandEvent& event) { From 3df945f8d0c34677b009c210dd0400b2e9655024 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:29:00 -0700 Subject: [PATCH 04/12] ExpressionParser: replace bare pointers with unique_ptrs --- .../ControlReference/ControlReference.cpp | 4 +- .../ControlReference/ExpressionParser.cpp | 68 ++++++++++--------- .../ControlReference/ExpressionParser.h | 8 +-- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index e5e4c1a578..92577496c5 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -31,9 +31,7 @@ void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devi const ciface::Core::DeviceQualifier& default_device) { ControlFinder finder(devices, default_device, IsInput()); - Expression* expr; - std::tie(m_parse_status, expr) = ParseExpression(expression, finder); - m_parsed_expression.reset(expr); + std::tie(m_parse_status, m_parsed_expression) = ParseExpression(expression, finder); } int ControlReference::BoundCount() const diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index a414c669a0..4f498d6f37 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -253,18 +253,14 @@ class BinaryExpression : public ExpressionNode { public: TokenType op; - ExpressionNode* lhs; - ExpressionNode* rhs; + std::unique_ptr lhs; + std::unique_ptr rhs; - BinaryExpression(TokenType op_, ExpressionNode* lhs_, ExpressionNode* rhs_) - : op(op_), lhs(lhs_), rhs(rhs_) + BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, + std::unique_ptr&& rhs_) + : op(op_), lhs(std::move(lhs_)), rhs(std::move(rhs_)) { } - virtual ~BinaryExpression() - { - delete lhs; - delete rhs; - } ControlState GetValue() const override { @@ -307,10 +303,12 @@ class UnaryExpression : public ExpressionNode { public: TokenType op; - ExpressionNode* inner; + std::unique_ptr inner; - UnaryExpression(TokenType op_, ExpressionNode* inner_) : op(op_), inner(inner_) {} - virtual ~UnaryExpression() { delete inner; } + UnaryExpression(TokenType op_, std::unique_ptr&& inner_) + : op(op_), inner(std::move(inner_)) + { + } ControlState GetValue() const override { ControlState value = inner->GetValue(); @@ -363,11 +361,13 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const struct ParseResult { - ParseResult(ParseStatus status_, ExpressionNode* expr_ = nullptr) : status(status_), expr(expr_) + ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) + : status(status_), expr(std::move(expr_)) { } + ParseStatus status; - ExpressionNode* expr; + std::unique_ptr expr; }; class Parser @@ -402,9 +402,10 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - return {ParseStatus::NoDevice, new DummyExpression(tok.qualifier)}; + return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; - return {ParseStatus::Successful, new ControlExpression(tok.qualifier, device, control)}; + return {ParseStatus::Successful, + std::make_unique(tok.qualifier, device, control)}; } case TOK_LPAREN: return Paren(); @@ -432,7 +433,8 @@ private: ParseResult result = Atom(); if (result.status == ParseStatus::SyntaxError) return result; - return {ParseStatus::Successful, new UnaryExpression(tok.type, result.expr)}; + return {ParseStatus::Successful, + std::make_unique(tok.type, std::move(result.expr))}; } return Atom(); @@ -457,21 +459,21 @@ private: if (result.status == ParseStatus::SyntaxError) return result; - ExpressionNode* expr = result.expr; + std::unique_ptr expr = std::move(result.expr); while (IsBinaryToken(Peek().type)) { Token tok = Chew(); ParseResult unary_result = Unary(); if (unary_result.status == ParseStatus::SyntaxError) { - delete expr; return unary_result; } - expr = new BinaryExpression(tok.type, expr, unary_result.expr); + expr = std::make_unique(tok.type, std::move(expr), + std::move(unary_result.expr)); } - return {ParseStatus::Successful, expr}; + return {ParseStatus::Successful, std::move(expr)}; } ParseResult Paren() @@ -483,7 +485,6 @@ private: if (!Expects(TOK_RPAREN)) { - delete result.expr; return {ParseStatus::SyntaxError}; } @@ -503,19 +504,19 @@ void Expression::SetValue(ControlState value) node->SetValue(value); } -Expression::Expression(ExpressionNode* node_) +Expression::Expression(std::unique_ptr&& node_) { - node = node_; - num_controls = node->CountNumControls(); + node = std::move(node_); + if (node) + num_controls = node->CountNumControls(); } Expression::~Expression() { - delete node; } -static std::pair ParseExpressionInner(const std::string& str, - ControlFinder& finder) +static std::pair> +ParseExpressionInner(const std::string& str, ControlFinder& finder) { if (str == "") return std::make_pair(ParseStatus::Successful, nullptr); @@ -530,10 +531,12 @@ static std::pair ParseExpressionInner(const std::strin if (result.status != ParseStatus::Successful) return std::make_pair(result.status, nullptr); - return std::make_pair(ParseStatus::Successful, new Expression(result.expr)); + return std::make_pair(ParseStatus::Successful, + std::make_unique(std::move(result.expr))); } -std::pair ParseExpression(const std::string& str, ControlFinder& finder) +std::pair> ParseExpression(const std::string& str, + ControlFinder& finder) { // Add compatibility with old simple expressions, which are simple // barewords control names. @@ -546,8 +549,9 @@ std::pair ParseExpression(const std::string& str, Cont Device::Control* control = finder.FindControl(qualifier); if (control) { - Expression* expr = new Expression(new ControlExpression(qualifier, device, control)); - return std::make_pair(ParseStatus::Successful, expr); + return std::make_pair(ParseStatus::Successful, + std::make_unique( + std::make_unique(qualifier, device, control))); } return ParseExpressionInner(str, finder); diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h index 2d41933e50..d05ac6f546 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h @@ -51,13 +51,12 @@ class ExpressionNode; class Expression { public: - Expression() : node(nullptr) {} - Expression(ExpressionNode* node); + explicit Expression(std::unique_ptr&& node = {}); ~Expression(); ControlState GetValue() const; void SetValue(ControlState state); int num_controls; - ExpressionNode* node; + std::unique_ptr node; }; enum class ParseStatus @@ -67,6 +66,7 @@ enum class ParseStatus NoDevice, }; -std::pair ParseExpression(const std::string& expr, ControlFinder& finder); +std::pair> ParseExpression(const std::string& expr, + ControlFinder& finder); } } From f1ff1e3d084c1dd8ae28f2dd8cc409949e378334 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:54:59 -0700 Subject: [PATCH 05/12] ExpressionParser: clean up ControlExpression --- .../ControlReference/ExpressionParser.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 4f498d6f37..277cfb3c70 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -234,19 +234,19 @@ class ControlExpression : public ExpressionNode public: ControlQualifier qualifier; Device::Control* control; + // Keep a shared_ptr to the device so the control pointer doesn't become invalid + std::shared_ptr m_device; ControlExpression(ControlQualifier qualifier_, std::shared_ptr device, Device::Control* control_) - : qualifier(qualifier_), control(control_), m_device(device) + : qualifier(qualifier_), control(control_), m_device(std::move(device)) { } ControlState GetValue() const override { return control->ToInput()->GetState(); } void SetValue(ControlState value) override { control->ToOutput()->SetState(value); } int CountNumControls() const override { return 1; } - operator std::string() const override { return "`" + (std::string)qualifier + "`"; } -private: - std::shared_ptr m_device; + operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; class BinaryExpression : public ExpressionNode @@ -405,7 +405,7 @@ private: return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; return {ParseStatus::Successful, - std::make_unique(tok.qualifier, device, control)}; + std::make_unique(tok.qualifier, std::move(device), control)}; } case TOK_LPAREN: return Paren(); @@ -550,8 +550,8 @@ std::pair> ParseExpression(const std::s if (control) { return std::make_pair(ParseStatus::Successful, - std::make_unique( - std::make_unique(qualifier, device, control))); + std::make_unique(std::make_unique( + qualifier, std::move(device), control))); } return ParseExpressionInner(str, finder); From 754efd75c5f8b843e25f2ff8510bfc2a25fd1de1 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:56:49 -0700 Subject: [PATCH 06/12] ExpressionParser: remove DummyExpression --- .../ControlReference/ExpressionParser.cpp | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 277cfb3c70..4bd4901cdd 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -217,18 +217,6 @@ public: virtual operator std::string() const { return ""; } }; -class DummyExpression : public ExpressionNode -{ -public: - std::string name; - - DummyExpression(const std::string& name_) : name(name_) {} - ControlState GetValue() const override { return 0.0; } - void SetValue(ControlState value) override {} - int CountNumControls() const override { return 0; } - operator std::string() const override { return "`" + name + "`"; } -}; - class ControlExpression : public ExpressionNode { public: @@ -243,9 +231,13 @@ public: { } - ControlState GetValue() const override { return control->ToInput()->GetState(); } - void SetValue(ControlState value) override { control->ToOutput()->SetState(value); } - int CountNumControls() const override { return 1; } + ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } + void SetValue(ControlState value) override + { + if (control) + control->ToOutput()->SetState(value); + } + int CountNumControls() const override { return control ? 1 : 0; } operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; @@ -402,7 +394,7 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; + return {ParseStatus::NoDevice, std::make_unique(tok.qualifier, control)}; return {ParseStatus::Successful, std::make_unique(tok.qualifier, std::move(device), control)}; From 85301e2baeda9a97c4c5ebbf07807566831e22d1 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 16:03:36 -0700 Subject: [PATCH 07/12] ParseStatus: replace NoDevice with EmptyExpression --- Source/Core/DolphinWX/Input/InputConfigDiag.cpp | 9 +++++---- .../InputCommon/ControlReference/ExpressionParser.cpp | 8 +++----- .../Core/InputCommon/ControlReference/ExpressionParser.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp index ccf2d42f4f..a8c70c3ee6 100644 --- a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp @@ -347,11 +347,12 @@ void ControlDialog::UpdateGUI() case ParseStatus::SyntaxError: m_error_label->SetLabel(_("Syntax error")); break; - case ParseStatus::NoDevice: - m_error_label->SetLabel(_("Device not found")); + case ParseStatus::Successful: + m_error_label->SetLabel(control_reference->BoundCount() > 0 ? "" : _("Device not found")); break; - default: + case ParseStatus::EmptyExpression: m_error_label->SetLabel(""); + break; } }; @@ -408,7 +409,7 @@ bool ControlDialog::Validate() UpdateGUI(); const auto parse_status = control_reference->GetParseStatus(); - return parse_status == ParseStatus::Successful || parse_status == ParseStatus::NoDevice; + return parse_status == ParseStatus::Successful || parse_status == ParseStatus::EmptyExpression; } void InputConfigDialog::SetDevice(wxCommandEvent&) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 4bd4901cdd..d2cef8c917 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -10,6 +10,7 @@ #include #include +#include "Common/StringUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" using namespace ciface::Core; @@ -393,9 +394,6 @@ private: { std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); - if (control == nullptr) - return {ParseStatus::NoDevice, std::make_unique(tok.qualifier, control)}; - return {ParseStatus::Successful, std::make_unique(tok.qualifier, std::move(device), control)}; } @@ -510,8 +508,8 @@ Expression::~Expression() static std::pair> ParseExpressionInner(const std::string& str, ControlFinder& finder) { - if (str == "") - return std::make_pair(ParseStatus::Successful, nullptr); + if (StripSpaces(str).empty()) + return std::make_pair(ParseStatus::EmptyExpression, nullptr); Lexer l(str); std::vector tokens; diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h index d05ac6f546..55bf86b951 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h @@ -63,7 +63,7 @@ enum class ParseStatus { Successful, SyntaxError, - NoDevice, + EmptyExpression, }; std::pair> ParseExpression(const std::string& expr, From 7e74961eb150f28a56405403335f4904f888e058 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 17:30:07 -0700 Subject: [PATCH 08/12] ExpressionParser: expose ExpressionNode directly --- .../ControlReference/ControlReference.cpp | 2 +- .../ControlReference/ExpressionParser.cpp | 76 +++++-------------- .../ControlReference/ExpressionParser.h | 12 ++- 3 files changed, 26 insertions(+), 64 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 92577496c5..09bcdaa59f 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -37,7 +37,7 @@ void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devi int ControlReference::BoundCount() const { if (m_parsed_expression) - return m_parsed_expression->num_controls; + return m_parsed_expression->CountNumControls(); else return 0; } diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index d2cef8c917..82829ed818 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -208,17 +208,7 @@ public: } }; -class ExpressionNode -{ -public: - virtual ~ExpressionNode() {} - virtual ControlState GetValue() const { return 0; } - virtual void SetValue(ControlState state) {} - virtual int CountNumControls() const { return 0; } - virtual operator std::string() const { return ""; } -}; - -class ControlExpression : public ExpressionNode +class ControlExpression : public Expression { public: ControlQualifier qualifier; @@ -242,15 +232,15 @@ public: operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; -class BinaryExpression : public ExpressionNode +class BinaryExpression : public Expression { public: TokenType op; - std::unique_ptr lhs; - std::unique_ptr rhs; + std::unique_ptr lhs; + std::unique_ptr rhs; - BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, - std::unique_ptr&& rhs_) + BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, + std::unique_ptr&& rhs_) : op(op_), lhs(std::move(lhs_)), rhs(std::move(rhs_)) { } @@ -292,13 +282,13 @@ public: } }; -class UnaryExpression : public ExpressionNode +class UnaryExpression : public Expression { public: TokenType op; - std::unique_ptr inner; + std::unique_ptr inner; - UnaryExpression(TokenType op_, std::unique_ptr&& inner_) + UnaryExpression(TokenType op_, std::unique_ptr&& inner_) : op(op_), inner(std::move(inner_)) { } @@ -354,13 +344,13 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const struct ParseResult { - ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) + ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) : status(status_), expr(std::move(expr_)) { } ParseStatus status; - std::unique_ptr expr; + std::unique_ptr expr; }; class Parser @@ -449,7 +439,7 @@ private: if (result.status == ParseStatus::SyntaxError) return result; - std::unique_ptr expr = std::move(result.expr); + std::unique_ptr expr = std::move(result.expr); while (IsBinaryToken(Peek().type)) { Token tok = Chew(); @@ -484,45 +474,19 @@ private: ParseResult Toplevel() { return Binary(); } }; -ControlState Expression::GetValue() const -{ - return node->GetValue(); -} - -void Expression::SetValue(ControlState value) -{ - node->SetValue(value); -} - -Expression::Expression(std::unique_ptr&& node_) -{ - node = std::move(node_); - if (node) - num_controls = node->CountNumControls(); -} - -Expression::~Expression() -{ -} - -static std::pair> -ParseExpressionInner(const std::string& str, ControlFinder& finder) +static ParseResult ParseExpressionInner(const std::string& str, ControlFinder& finder) { if (StripSpaces(str).empty()) - return std::make_pair(ParseStatus::EmptyExpression, nullptr); + return {ParseStatus::EmptyExpression}; Lexer l(str); std::vector tokens; ParseStatus tokenize_status = l.Tokenize(tokens); if (tokenize_status != ParseStatus::Successful) - return std::make_pair(tokenize_status, nullptr); + return {tokenize_status}; ParseResult result = Parser(tokens, finder).Parse(); - if (result.status != ParseStatus::Successful) - return std::make_pair(result.status, nullptr); - - return std::make_pair(ParseStatus::Successful, - std::make_unique(std::move(result.expr))); + return result; } std::pair> ParseExpression(const std::string& str, @@ -539,12 +503,12 @@ std::pair> ParseExpression(const std::s Device::Control* control = finder.FindControl(qualifier); if (control) { - return std::make_pair(ParseStatus::Successful, - std::make_unique(std::make_unique( - qualifier, std::move(device), control))); + return std::make_pair(ParseStatus::Successful, std::make_unique( + qualifier, std::move(device), control)); } - return ParseExpressionInner(str, finder); + ParseResult result = ParseExpressionInner(str, finder); + return std::make_pair(result.status, std::move(result.expr)); } } } diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h index 55bf86b951..8fde647390 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h @@ -47,16 +47,14 @@ private: bool is_input; }; -class ExpressionNode; class Expression { public: - explicit Expression(std::unique_ptr&& node = {}); - ~Expression(); - ControlState GetValue() const; - void SetValue(ControlState state); - int num_controls; - std::unique_ptr node; + virtual ~Expression() = default; + virtual ControlState GetValue() const = 0; + virtual void SetValue(ControlState state) = 0; + virtual int CountNumControls() const = 0; + virtual operator std::string() const = 0; }; enum class ParseStatus From ba87a503389a6db8e4ddae5a87f9d1ebc52db46a Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 18:29:02 -0700 Subject: [PATCH 09/12] ExpressionParser: add FallbackExpression node type --- .../ControlReference/ExpressionParser.cpp | 71 ++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 82829ed818..3bac0243dc 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -322,6 +322,40 @@ public: operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; } }; +// This class proxies all methods to its either left-hand child if it has bound controls, or its +// right-hand child. Its intended use is for supporting old-style barewords expressions. +class CoalesceExpression : public Expression +{ +public: + CoalesceExpression(std::unique_ptr&& lhs, std::unique_ptr&& rhs) + : m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) + { + } + + ControlState GetValue() const override { return GetActiveChild()->GetValue(); } + void SetValue(ControlState value) override + { + m_lhs->SetValue(GetActiveChild() == m_lhs ? value : 0.0); + m_rhs->SetValue(GetActiveChild() == m_rhs ? value : 0.0); + } + + int CountNumControls() const override { return GetActiveChild()->CountNumControls(); } + operator std::string() const override + { + return "Coalesce(" + static_cast(*m_lhs) + ", " + + static_cast(*m_rhs) + ')'; + } + +private: + const std::unique_ptr& GetActiveChild() const + { + return m_lhs->CountNumControls() > 0 ? m_lhs : m_rhs; + } + + std::unique_ptr m_lhs; + std::unique_ptr m_rhs; +}; + std::shared_ptr ControlFinder::FindDevice(ControlQualifier qualifier) const { if (qualifier.has_device) @@ -474,41 +508,46 @@ private: ParseResult Toplevel() { return Binary(); } }; -static ParseResult ParseExpressionInner(const std::string& str, ControlFinder& finder) +static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& finder) { - if (StripSpaces(str).empty()) - return {ParseStatus::EmptyExpression}; - Lexer l(str); std::vector tokens; ParseStatus tokenize_status = l.Tokenize(tokens); if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - ParseResult result = Parser(tokens, finder).Parse(); - return result; + return Parser(tokens, finder).Parse(); } -std::pair> ParseExpression(const std::string& str, - ControlFinder& finder) +static std::unique_ptr ParseBarewordExpression(const std::string& str, + ControlFinder& finder) { - // Add compatibility with old simple expressions, which are simple - // barewords control names. - ControlQualifier qualifier; qualifier.control_name = str; qualifier.has_device = false; std::shared_ptr device = finder.FindDevice(qualifier); Device::Control* control = finder.FindControl(qualifier); - if (control) + return std::make_unique(qualifier, std::move(device), control); +} + +std::pair> ParseExpression(const std::string& str, + ControlFinder& finder) +{ + if (StripSpaces(str).empty()) + return std::make_pair(ParseStatus::EmptyExpression, nullptr); + + auto bareword_expr = ParseBarewordExpression(str, finder); + ParseResult complex_result = ParseComplexExpression(str, finder); + + if (complex_result.status != ParseStatus::Successful) { - return std::make_pair(ParseStatus::Successful, std::make_unique( - qualifier, std::move(device), control)); + return std::make_pair(complex_result.status, std::move(bareword_expr)); } - ParseResult result = ParseExpressionInner(str, finder); - return std::make_pair(result.status, std::move(result.expr)); + auto combined_expr = std::make_unique(std::move(bareword_expr), + std::move(complex_result.expr)); + return std::make_pair(complex_result.status, std::move(combined_expr)); } } } From c332580b83ea8cd5650d53378843ceadcbfeb9cb Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 18:48:17 -0700 Subject: [PATCH 10/12] ControlReference/ExpressionParser: separate parsing from binding --- .../ControlReference/ControlReference.cpp | 4 +- .../ControlReference/ExpressionParser.cpp | 59 +++++++++---------- .../ControlReference/ExpressionParser.h | 4 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 09bcdaa59f..e53c5c3877 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -31,7 +31,9 @@ void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devi const ciface::Core::DeviceQualifier& default_device) { ControlFinder finder(devices, default_device, IsInput()); - std::tie(m_parse_status, m_parsed_expression) = ParseExpression(expression, finder); + std::tie(m_parse_status, m_parsed_expression) = ParseExpression(expression); + if (m_parsed_expression) + m_parsed_expression->UpdateReferences(finder); } int ControlReference::BoundCount() const diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 3bac0243dc..ce58b0f968 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -212,16 +212,11 @@ class ControlExpression : public Expression { public: ControlQualifier qualifier; - Device::Control* control; + Device::Control* control = nullptr; // Keep a shared_ptr to the device so the control pointer doesn't become invalid std::shared_ptr m_device; - ControlExpression(ControlQualifier qualifier_, std::shared_ptr device, - Device::Control* control_) - : qualifier(qualifier_), control(control_), m_device(std::move(device)) - { - } - + ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } void SetValue(ControlState value) override { @@ -229,6 +224,11 @@ public: control->ToOutput()->SetState(value); } int CountNumControls() const override { return control ? 1 : 0; } + void UpdateReferences(ControlFinder& finder) override + { + m_device = finder.FindDevice(qualifier); + control = finder.FindControl(qualifier); + } operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; @@ -276,6 +276,12 @@ public: return lhs->CountNumControls() + rhs->CountNumControls(); } + void UpdateReferences(ControlFinder& finder) override + { + lhs->UpdateReferences(finder); + rhs->UpdateReferences(finder); + } + operator std::string() const override { return OpName(op) + "(" + (std::string)(*lhs) + ", " + (std::string)(*rhs) + ")"; @@ -319,6 +325,7 @@ public: } int CountNumControls() const override { return inner->CountNumControls(); } + void UpdateReferences(ControlFinder& finder) override { inner->UpdateReferences(finder); } operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; } }; @@ -346,6 +353,12 @@ public: static_cast(*m_rhs) + ')'; } + void UpdateReferences(ControlFinder& finder) override + { + m_lhs->UpdateReferences(finder); + m_rhs->UpdateReferences(finder); + } + private: const std::unique_ptr& GetActiveChild() const { @@ -390,16 +403,11 @@ struct ParseResult class Parser { public: - Parser(std::vector tokens_, ControlFinder& finder_) : tokens(tokens_), finder(finder_) - { - m_it = tokens.begin(); - } - + explicit Parser(std::vector tokens_) : tokens(tokens_) { m_it = tokens.begin(); } ParseResult Parse() { return Toplevel(); } private: std::vector tokens; std::vector::iterator m_it; - ControlFinder& finder; Token Chew() { return *m_it++; } Token Peek() { return *m_it; } @@ -415,12 +423,7 @@ private: switch (tok.type) { case TOK_CONTROL: - { - std::shared_ptr device = finder.FindDevice(tok.qualifier); - Device::Control* control = finder.FindControl(tok.qualifier); - return {ParseStatus::Successful, - std::make_unique(tok.qualifier, std::move(device), control)}; - } + return {ParseStatus::Successful, std::make_unique(tok.qualifier)}; case TOK_LPAREN: return Paren(); default: @@ -508,7 +511,7 @@ private: ParseResult Toplevel() { return Binary(); } }; -static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& finder) +static ParseResult ParseComplexExpression(const std::string& str) { Lexer l(str); std::vector tokens; @@ -516,29 +519,25 @@ static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - return Parser(tokens, finder).Parse(); + return Parser(tokens).Parse(); } -static std::unique_ptr ParseBarewordExpression(const std::string& str, - ControlFinder& finder) +static std::unique_ptr ParseBarewordExpression(const std::string& str) { ControlQualifier qualifier; qualifier.control_name = str; qualifier.has_device = false; - std::shared_ptr device = finder.FindDevice(qualifier); - Device::Control* control = finder.FindControl(qualifier); - return std::make_unique(qualifier, std::move(device), control); + return std::make_unique(qualifier); } -std::pair> ParseExpression(const std::string& str, - ControlFinder& finder) +std::pair> ParseExpression(const std::string& str) { if (StripSpaces(str).empty()) return std::make_pair(ParseStatus::EmptyExpression, nullptr); - auto bareword_expr = ParseBarewordExpression(str, finder); - ParseResult complex_result = ParseComplexExpression(str, finder); + auto bareword_expr = ParseBarewordExpression(str); + ParseResult complex_result = ParseComplexExpression(str); if (complex_result.status != ParseStatus::Successful) { diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h index 8fde647390..398b273e0f 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h @@ -54,6 +54,7 @@ public: virtual ControlState GetValue() const = 0; virtual void SetValue(ControlState state) = 0; virtual int CountNumControls() const = 0; + virtual void UpdateReferences(ControlFinder& finder) = 0; virtual operator std::string() const = 0; }; @@ -64,7 +65,6 @@ enum class ParseStatus EmptyExpression, }; -std::pair> ParseExpression(const std::string& expr, - ControlFinder& finder); +std::pair> ParseExpression(const std::string& expr); } } From 31f1c062264fcf8628e3a13c44de893d4bac0aa0 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 19:02:16 -0700 Subject: [PATCH 11/12] ControlReference: don't reparse expression when references are updated --- Source/Core/Core/HotkeyManager.cpp | 2 +- .../DolphinQt2/Config/Mapping/IOWindow.cpp | 4 ++-- .../Config/Mapping/MappingButton.cpp | 10 +++++----- .../Core/DolphinWX/Input/InputConfigDiag.cpp | 18 +++++++++--------- .../ControlReference/ControlReference.cpp | 14 ++++++++++++-- .../ControlReference/ControlReference.h | 4 +++- .../ControlReference/ExpressionParser.cpp | 2 +- .../ControlGroup/ControlGroup.cpp | 12 ++++++++---- 8 files changed, 41 insertions(+), 25 deletions(-) diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index b9dab79224..89c394deb7 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -344,7 +344,7 @@ void HotkeyManager::LoadDefaults(const ControllerInterface& ciface) auto set_key_expression = [this](int index, const std::string& expression) { m_keys[FindGroupByID(index)] ->controls[GetIndexForGroup(FindGroupByID(index), index)] - ->control_ref->expression = expression; + ->control_ref->SetExpression(expression); }; // General hotkeys diff --git a/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp index ae40b29c17..294cf5878f 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp @@ -110,7 +110,7 @@ void IOWindow::CreateMainLayout() void IOWindow::Update() { - m_expression_text->setPlainText(QString::fromStdString(m_reference->expression)); + m_expression_text->setPlainText(QString::fromStdString(m_reference->GetExpression())); m_range_spinbox->setValue(m_reference->range * SLIDER_TICK_COUNT); m_range_slider->setValue(m_reference->range * SLIDER_TICK_COUNT); @@ -164,7 +164,7 @@ void IOWindow::OnDialogButtonPressed(QAbstractButton* button) return; } - m_reference->expression = m_expression_text->toPlainText().toStdString(); + m_reference->SetExpression(m_expression_text->toPlainText().toStdString()); if (button != m_apply_button) accept(); diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp index 7c01a527a2..d30be53ec5 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingButton.cpp @@ -27,7 +27,7 @@ static QString EscapeAmpersand(QString&& string) } MappingButton::MappingButton(MappingWidget* widget, ControlReference* ref) - : ElidedButton(EscapeAmpersand(QString::fromStdString(ref->expression))), m_parent(widget), + : ElidedButton(EscapeAmpersand(QString::fromStdString(ref->GetExpression()))), m_parent(widget), m_reference(ref) { Connect(); @@ -66,7 +66,7 @@ void MappingButton::OnButtonPressed() if (!expr.isEmpty()) { - m_reference->expression = expr.toStdString(); + m_reference->SetExpression(expr.toStdString()); Update(); } else @@ -78,13 +78,13 @@ void MappingButton::OnButtonPressed() void MappingButton::OnButtonTimeout() { - setText(EscapeAmpersand(QString::fromStdString(m_reference->expression))); + setText(EscapeAmpersand(QString::fromStdString(m_reference->GetExpression()))); } void MappingButton::Clear() { m_parent->Update(); - m_reference->expression.clear(); + m_reference->SetExpression(""); Update(); } @@ -92,7 +92,7 @@ void MappingButton::Update() { const auto lock = ControllerEmu::EmulatedController::GetStateLock(); m_reference->UpdateReference(g_controller_interface, m_parent->GetParent()->GetDeviceQualifier()); - setText(EscapeAmpersand(QString::fromStdString(m_reference->expression))); + setText(EscapeAmpersand(QString::fromStdString(m_reference->GetExpression()))); m_parent->SaveSettings(); } diff --git a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp index a8c70c3ee6..1e6cba569d 100644 --- a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp @@ -243,7 +243,7 @@ ControlButton::ControlButton(wxWindow* const parent, ControlReference* const _re m_configured_width(FromDIP(width)) { if (label.empty()) - SetLabelText(StrToWxStr(_ref->expression)); + SetLabelText(StrToWxStr(_ref->GetExpression())); else SetLabel(StrToWxStr(label)); } @@ -336,7 +336,7 @@ void ControlDialog::SelectControl(const std::string& name) void ControlDialog::UpdateGUI() { // update textbox - textctrl->SetValue(StrToWxStr(control_reference->expression)); + textctrl->SetValue(StrToWxStr(control_reference->GetExpression())); // updates the "bound controls:" label m_bound_label->SetLabel( @@ -365,7 +365,7 @@ void InputConfigDialog::UpdateGUI() { for (ControlButton* button : cgBox->control_buttons) { - button->SetLabelText(StrToWxStr(button->control_reference->expression)); + button->SetLabelText(StrToWxStr(button->control_reference->GetExpression())); } for (PadSetting* padSetting : cgBox->options) @@ -400,7 +400,7 @@ void InputConfigDialog::LoadDefaults(wxCommandEvent&) bool ControlDialog::Validate() { - control_reference->expression = WxStrToStr(textctrl->GetValue()); + control_reference->SetExpression(WxStrToStr(textctrl->GetValue())); const auto lock = ControllerEmu::EmulatedController::GetStateLock(); control_reference->UpdateReference(g_controller_interface, @@ -439,7 +439,7 @@ void ControlDialog::SetDevice(wxCommandEvent&) void ControlDialog::ClearControl(wxCommandEvent&) { - control_reference->expression.clear(); + control_reference->SetExpression(""); const auto lock = ControllerEmu::EmulatedController::GetStateLock(); control_reference->UpdateReference(g_controller_interface, @@ -498,7 +498,7 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&) return; textctrl->WriteText(expr); - control_reference->expression = textctrl->GetValue(); + control_reference->SetExpression(WxStrToStr(textctrl->GetValue())); const auto lock = ControllerEmu::EmulatedController::GetStateLock(); control_reference->UpdateReference(g_controller_interface, @@ -534,7 +534,7 @@ void ControlDialog::AppendControl(wxCommandEvent& event) } textctrl->WriteText(expr); - control_reference->expression = textctrl->GetValue(); + control_reference->SetExpression(WxStrToStr(textctrl->GetValue())); const auto lock = ControllerEmu::EmulatedController::GetStateLock(); control_reference->UpdateReference(g_controller_interface, @@ -638,7 +638,7 @@ void InputConfigDialog::ConfigControl(wxEvent& event) void InputConfigDialog::ClearControl(wxEvent& event) { ControlButton* const btn = (ControlButton*)event.GetEventObject(); - btn->control_reference->expression.clear(); + btn->control_reference->SetExpression(""); btn->control_reference->range = 1.0; controller->UpdateReferences(g_controller_interface); @@ -717,7 +717,7 @@ bool InputConfigDialog::DetectButton(ControlButton* button) wxString control_name = ctrl->GetName(); wxString expr; GetExpressionForControl(expr, control_name); - button->control_reference->expression = expr; + button->control_reference->SetExpression(WxStrToStr(expr)); const auto lock = ControllerEmu::EmulatedController::GetStateLock(); button->control_reference->UpdateReference(g_controller_interface, controller->default_device); diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index e53c5c3877..c7d652f15b 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -25,13 +25,12 @@ bool ControlReference::InputGateOn() // UpdateReference // // Updates a controlreference's binded devices/controls -// need to call this to re-parse a control reference's expression after changing it +// need to call this to re-bind a control reference after changing its expression // void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devices, const ciface::Core::DeviceQualifier& default_device) { ControlFinder finder(devices, default_device, IsInput()); - std::tie(m_parse_status, m_parsed_expression) = ParseExpression(expression); if (m_parsed_expression) m_parsed_expression->UpdateReferences(finder); } @@ -49,6 +48,17 @@ ParseStatus ControlReference::GetParseStatus() const return m_parse_status; } +std::string ControlReference::GetExpression() const +{ + return m_expression; +} + +void ControlReference::SetExpression(std::string expr) +{ + m_expression = std::move(expr); + std::tie(m_parse_status, m_parsed_expression) = ParseExpression(m_expression); +} + ControlReference::ControlReference() : range(1), m_parsed_expression(nullptr) { } diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.h b/Source/Core/InputCommon/ControlReference/ControlReference.h index 48ce6434e1..6740ed8be0 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.h +++ b/Source/Core/InputCommon/ControlReference/ControlReference.h @@ -34,12 +34,14 @@ public: ciface::ExpressionParser::ParseStatus GetParseStatus() const; void UpdateReference(const ciface::Core::DeviceContainer& devices, const ciface::Core::DeviceQualifier& default_device); + std::string GetExpression() const; + void SetExpression(std::string expr); ControlState range; - std::string expression; protected: ControlReference(); + std::string m_expression; std::unique_ptr m_parsed_expression; ciface::ExpressionParser::ParseStatus m_parse_status; }; diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index ce58b0f968..c9cf998ea9 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -216,7 +216,7 @@ public: // Keep a shared_ptr to the device so the control pointer doesn't become invalid std::shared_ptr m_device; - ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} + explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } void SetValue(ControlState value) override { diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp index fd905ccf1e..24d4a4c36e 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp @@ -54,8 +54,12 @@ void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev, for (auto& c : controls) { - // control expression - sec->Get(group + c->name, &c->control_ref->expression, ""); + { + // control expression + std::string expression; + sec->Get(group + c->name, &expression, ""); + c->control_ref->SetExpression(std::move(expression)); + } // range sec->Get(group + c->name + "/Range", &c->control_ref->range, 100.0); @@ -109,7 +113,7 @@ void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, for (auto& c : controls) { // control expression - sec->Set(group + c->name, c->control_ref->expression, ""); + sec->Set(group + c->name, c->control_ref->GetExpression(), ""); // range sec->Set(group + c->name + "/Range", c->control_ref->range * 100.0, 100.0); @@ -128,6 +132,6 @@ void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, void ControlGroup::SetControlExpression(int index, const std::string& expression) { - controls.at(index)->control_ref->expression = expression; + controls.at(index)->control_ref->SetExpression(expression); } } // namespace ControllerEmu From 294b1895ef2963cfc6fda1818d9a9f3b8b0af48f Mon Sep 17 00:00:00 2001 From: Michael M Date: Thu, 8 Jun 2017 00:23:38 -0700 Subject: [PATCH 12/12] ExpressionParser: std::move() tokens vector to parser --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index c9cf998ea9..85eb86d598 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -519,7 +519,7 @@ static ParseResult ParseComplexExpression(const std::string& str) if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - return Parser(tokens).Parse(); + return Parser(std::move(tokens)).Parse(); } static std::unique_ptr ParseBarewordExpression(const std::string& str)