allow callbacks with the same name but different number of arguments

This commit is contained in:
pantor
2018-02-23 20:07:04 +01:00
parent 49b396c20b
commit c29fd9189d
3 changed files with 29 additions and 12 deletions
+1 -1
View File
@@ -206,7 +206,7 @@ Environment env = Environment();
/*
* Callbacks are defined by its:
* - name, which is equal to the function name
* - name
* - number of arguments
* - callback function. Implemented with std::function, you can for example use lambdas.
*/
+15 -11
View File
@@ -217,8 +217,8 @@ inline MatchClosed search_closed(const std::string& input, const Regex& regex_st
return search_closed_on_level(input, regex_statement, regex_open, regex_close, regex_close, open_match);
}
template<typename T>
inline MatchType<T> match(const std::string& input, std::map<T, Regex> regexes) {
template<typename T, typename S>
inline MatchType<T> match(const std::string& input, std::map<T, Regex, S> regexes) {
MatchType<T> match;
for (const auto e : regexes) {
if (std::regex_match(input.cbegin(), input.cend(), match, e.second)) {
@@ -330,7 +330,6 @@ struct Parsed {
explicit ElementExpression(): ElementExpression(Function::ReadJson) { }
explicit ElementExpression(const Function function_): Element(Type::Expression), function(function_), args({}), command("") { }
};
typedef std::vector<ElementExpression> Arguments;
struct ElementLoop: public Element {
Loop loop;
@@ -353,6 +352,9 @@ struct Parsed {
explicit ElementConditionBranch(const std::string& inner, const Condition condition_type): Element(Type::ConditionBranch, inner), condition_type(condition_type) { }
explicit ElementConditionBranch(const std::string& inner, const Condition condition_type, const ElementExpression& condition): Element(Type::ConditionBranch, inner), condition_type(condition_type), condition(condition) { }
};
using Arguments = std::vector<ElementExpression>;
using CallbackSignature = std::pair<std::string, int>;
};
@@ -369,7 +371,7 @@ class Renderer {
public:
ElementNotation element_notation;
std::map<std::string, std::function<json(Parsed::Arguments, const json&)>> map_callbacks;
std::map<Parsed::CallbackSignature, std::function<json(Parsed::Arguments, const json&)>> map_callbacks;
template<bool>
bool eval_expression(const Parsed::ElementExpression& element, const json &data) {
@@ -503,7 +505,8 @@ public:
}
}
case Parsed::Function::Callback: {
return map_callbacks[element.command](element.args, data);
Parsed::CallbackSignature signature = std::make_pair(element.command, element.args.size());
return map_callbacks.at(signature)(element.args, data);
}
}
@@ -656,13 +659,13 @@ public:
{Parsed::Function::ReadJson, Regex{"\\s*([^\\(\\)]*\\S)\\s*"}}
};
std::map<std::string, Regex> regex_map_callbacks;
std::map<Parsed::CallbackSignature, Regex, std::greater<Parsed::CallbackSignature>> regex_map_callbacks;
Parser() { }
Parsed::ElementExpression parse_expression(const std::string& input) {
MatchType<std::string> match_callback = match(input, regex_map_callbacks);
if (!match_callback.type().empty()) {
MatchType<Parsed::CallbackSignature> match_callback = match(input, regex_map_callbacks);
if (!match_callback.type().first.empty()) {
std::vector<Parsed::ElementExpression> args = {};
for (unsigned int i = 1; i < match_callback.size(); i++) { // str(0) is whole group
args.push_back( parse_expression(match_callback.str(i)) );
@@ -670,7 +673,7 @@ public:
Parsed::ElementExpression result = Parsed::ElementExpression(Parsed::Function::Callback);
result.args = args;
result.command = match_callback.type();
result.command = match_callback.type().first;
return result;
}
@@ -951,8 +954,9 @@ public:
}
void add_callback(std::string name, int number_arguments, std::function<json(Parsed::Arguments, const json&)> callback) {
parser.regex_map_callbacks[name] = Parser::function_regex(name, number_arguments);
renderer.map_callbacks[name] = callback;
Parsed::CallbackSignature signature = std::make_pair(name, number_arguments);
parser.regex_map_callbacks[signature] = Parser::function_regex(name, number_arguments);
renderer.map_callbacks[signature] = callback;
}
template<typename T = json>
+13
View File
@@ -196,10 +196,23 @@ TEST_CASE("callbacks") {
return number1 * number2;
});
env.add_callback("multiply", 3, [&env](inja::Parsed::Arguments args, json data) {
double number1 = env.get_argument(args, 0, data);
double number2 = env.get_argument(args, 1, data);
double number3 = env.get_argument(args, 2, data);
return number1 * number2 * number3;
});
env.add_callback("multiply", 0, [&env](inja::Parsed::Arguments args, json data) {
return 1.0;
});
CHECK( env.render("{{ double(age) }}", data) == "56" );
CHECK( env.render("{{ half(age) }}", data) == "14" );
CHECK( env.render("{{ double-greetings }}", data) == "Hello Hello!" );
CHECK( env.render("{{ multiply(4, 5) }}", data) == "20.0" );
CHECK( env.render("{{ multiply(3, 4, 5) }}", data) == "60.0" );
CHECK( env.render("{{ multiply }}", data) == "1.0" );
}
TEST_CASE("combinations") {