add divisibleBy, odd, even functions, add ElementNotation for dot or pointer notation

This commit is contained in:
pantor
2017-11-16 17:39:18 +01:00
parent 776bd00e4a
commit 93ec40b3fb
4 changed files with 116 additions and 7 deletions
+63 -3
View File
@@ -17,7 +17,9 @@ namespace inja {
using json = nlohmann::json;
/*!
@brief returns the values of a std key-value-map
*/
template<typename S, typename T>
inline std::vector<T> get_values(std::map<S, T> map) {
std::vector<T> result;
@@ -26,6 +28,25 @@ inline std::vector<T> get_values(std::map<S, T> map) {
}
/*!
@brief dot notation to json pointer notiation
*/
inline std::string dot_to_json_pointer_notation(std::string dot) {
std::string result = dot;
while (result.find(".") != std::string::npos) {
result.replace(result.find("."), 1, "/");
}
result.insert(0, "/");
return result;
}
enum class ElementNotation {
Pointer,
Dot
};
class Regex: public std::regex {
std::string pattern_;
@@ -239,7 +260,10 @@ public:
Lower,
Range,
Length,
Round
Round,
DivisibleBy,
Odd,
Even
};
const std::map<Function, Regex> regex_map_functions = {
@@ -248,6 +272,9 @@ public:
{Function::Range, Regex{"range\\(\\s*(.*?)\\s*\\)"}},
{Function::Length, Regex{"length\\(\\s*(.*?)\\s*\\)"}},
{Function::Round, Regex{"round\\(\\s*(.*?)\\s*,\\s*(.*?)\\s*\\)"}},
{Function::DivisibleBy, Regex{"divisibleBy\\(\\s*(.*?)\\s*,\\s*(.*?)\\s*\\)"}},
{Function::Odd, Regex{"odd\\(\\s*(.*?)\\s*\\)"}},
{Function::Even, Regex{"even\\(\\s*(.*?)\\s*\\)"}}
};
Parser() { }
@@ -367,6 +394,8 @@ public:
class Environment {
const std::string global_path;
ElementNotation elementNotation = ElementNotation::Pointer;
Parser parser;
public:
@@ -389,6 +418,10 @@ public:
parser.regex_map_delimiters[Parser::Delimiter::Comment] = Regex{open + "\\s*(.+?)\\s*" + close};
}
void setElementNotation(const ElementNotation elementNotation_) {
elementNotation = elementNotation_;
}
json eval_variable(const std::string& input, json data) {
@@ -434,10 +467,37 @@ public:
if (not precision.is_number()) { throw std::runtime_error("Argument in round function is not a number."); }
return std::round(number.get<double>() * std::pow(10.0, precision.get<int>())) / std::pow(10.0, precision.get<int>());
}
case Parser::Function::DivisibleBy: {
const json number = eval_variable(match_function.str(1), data);
const json divisor = eval_variable(match_function.str(2), data);
if (not number.is_number()) { throw std::runtime_error("Argument in divisibleBy function is not a number."); }
if (not divisor.is_number()) { throw std::runtime_error("Argument in divisibleBy function is not a number."); }
return (number.get<int>() % divisor.get<int>() == 0);
}
case Parser::Function::Odd: {
const json number = eval_variable(match_function.str(1), data);
if (not number.is_number()) { throw std::runtime_error("Argument in odd function is not a number."); }
return (number.get<int>() % 2 != 0);
}
case Parser::Function::Even: {
const json number = eval_variable(match_function.str(1), data);
if (not number.is_number()) { throw std::runtime_error("Argument in even function is not a number."); }
return (number.get<int>() % 2 == 0);
}
}
std::string input_copy = input;
if (input_copy[0] != '/') { input_copy.insert(0, "/"); }
switch (elementNotation) {
case ElementNotation::Pointer: {
if (input_copy[0] != '/') { input_copy.insert(0, "/"); }
break;
}
case ElementNotation::Dot: {
input_copy = dot_to_json_pointer_notation(input_copy);
break;
}
}
json::json_pointer ptr(input_copy);
json result = data[ptr];