mirror of
https://github.com/pantor/inja.git
synced 2026-07-02 23:34:23 +00:00
allow callbacks with the same name but different number of arguments
This commit is contained in:
@@ -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
@@ -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>
|
||||
|
||||
@@ -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") {
|
||||
|
||||
Reference in New Issue
Block a user