added write methods, better error messages for functions

This commit is contained in:
pantor
2017-11-16 22:29:17 +01:00
parent 93ec40b3fb
commit edc14bfc05
2 changed files with 44 additions and 42 deletions

View File

@@ -11,6 +11,7 @@
#include <string>
#include <locale>
#include <regex>
#include <type_traits>
namespace inja {
@@ -424,8 +425,14 @@ public:
json eval_variable(const std::string& input, json data) {
return eval_variable(input, data, true);
template<typename T = json>
T eval_variable(const std::string& input, json data) {
const json var = eval_variable(input, data, true);
if (std::is_same<T, json>::value) {
return var;
}
return var.get<T>();
}
json eval_variable(const std::string& input, json data, bool throw_error) {
@@ -435,54 +442,43 @@ public:
Match match_function = match(input, get_values(parser.regex_map_functions));
switch ( static_cast<Parser::Function>(match_function.regex_number()) ) {
case Parser::Function::Upper: {
const json str = eval_variable(match_function.str(1), data);
if (not str.is_string()) { throw std::runtime_error("Argument in upper function is not a string."); }
std::string data = str.get<std::string>();
std::transform(data.begin(), data.end(), data.begin(), toupper);
return data;
std::string str = eval_variable<std::string>(match_function.str(1), data);
std::transform(str.begin(), str.end(), str.begin(), toupper);
return str;
}
case Parser::Function::Lower: {
const json str = eval_variable(match_function.str(1), data);
if (not str.is_string()) { throw std::runtime_error("Argument in lower function is not a string."); }
std::string data = str.get<std::string>();
std::transform(data.begin(), data.end(), data.begin(), tolower);
return data;
std::string str = eval_variable<std::string>(match_function.str(1), data);
std::transform(str.begin(), str.end(), str.begin(), tolower);
return str;
}
case Parser::Function::Range: {
const json number = eval_variable(match_function.str(1), data);
if (not number.is_number()) { throw std::runtime_error("Argument in range function is not a number."); }
std::vector<int> result(number.get<int>());
const int number = eval_variable<int>(match_function.str(1), data);
std::vector<int> result(number);
std::iota(std::begin(result), std::end(result), 0);
return result;
}
case Parser::Function::Length: {
const json list = eval_variable(match_function.str(1), data);
if (not list.is_array()) { throw std::runtime_error("Argument in length function is not a list."); }
if (not list.is_array()) { throw std::runtime_error("[inja.exception.type_error.302] type must be array"); }
return list.size();
}
case Parser::Function::Round: {
const json number = eval_variable(match_function.str(1), data);
const json precision = eval_variable(match_function.str(2), data);
if (not number.is_number()) { throw std::runtime_error("Argument in round function is not a number."); }
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>());
const double number = eval_variable<double>(match_function.str(1), data);
const int precision = eval_variable<int>(match_function.str(2), data);
return std::round(number * std::pow(10.0, precision)) / std::pow(10.0, precision);
}
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);
const int number = eval_variable<int>(match_function.str(1), data);
const int divisor = eval_variable<int>(match_function.str(2), data);
return (number % divisor == 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);
const int number = eval_variable<int>(match_function.str(1), data);
return (number % 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);
const int number = eval_variable<int>(match_function.str(1), data);
return (number % 2 == 0);
}
}
@@ -643,11 +639,14 @@ public:
}
void write(const std::string& filename, json data, const std::string& filename_out) {
std::ofstream file(global_path + filename_out);
file << render_template_with_json_file(filename, data);
file.close();
}
void write(const std::string& filename, const std::string& filename_data, const std::string& filename_out) {
json data = load_json(filename_data);
write(filename, data, filename_out);
}
std::string load_file(const std::string& filename) {
@@ -664,6 +663,9 @@ public:
}
};
/*!
@brief render with default settings
*/
inline std::string render(const std::string& input, json data) {
return Environment().render(input, data);
}

View File

@@ -232,47 +232,47 @@ TEST_CASE("Parse functions") {
SECTION("Upper") {
CHECK( env.eval_variable("upper(name)", data) == "PETER" );
CHECK( env.eval_variable("upper(city)", data) == "NEW YORK" );
CHECK_THROWS_WITH( env.eval_variable("upper(5)", data), "Argument in upper function is not a string." );
CHECK_THROWS_WITH( env.eval_variable("upper(5)", data), "[json.exception.type_error.302] type must be string, but is number" );
}
SECTION("Lower") {
CHECK( env.eval_variable("lower(name)", data) == "peter" );
CHECK( env.eval_variable("lower(city)", data) == "new york" );
CHECK_THROWS_WITH( env.eval_variable("lower(5)", data), "Argument in lower function is not a string." );
CHECK_THROWS_WITH( env.eval_variable("lower(5.45)", data), "[json.exception.type_error.302] type must be string, but is number" );
}
SECTION("Range") {
CHECK( env.eval_variable("range(4)", data) == std::vector<int>({0, 1, 2, 3}) );
CHECK_THROWS_WITH( env.eval_variable("range(true)", data), "Argument in range function is not a number." );
CHECK_THROWS_WITH( env.eval_variable("range(name)", data), "[json.exception.type_error.302] type must be number, but is string" );
}
SECTION("Length") {
CHECK( env.eval_variable("length(names)", data) == 4 );
CHECK_THROWS_WITH( env.eval_variable("length(5)", data), "Argument in length function is not a list." );
CHECK_THROWS_WITH( env.eval_variable("length(5)", data), "[inja.exception.type_error.302] type must be array" );
}
SECTION("Round") {
CHECK( env.eval_variable("round(4, 0)", data) == 4 );
CHECK( env.eval_variable("round(temperature, 2)", data) == 25.68 );
CHECK_THROWS_WITH( env.eval_variable("round(name, 2)", data), "Argument in round function is not a number." );
CHECK_THROWS_WITH( env.eval_variable("round(name, 2)", data), "[json.exception.type_error.302] type must be number, but is string" );
}
SECTION("DivisibleBy") {
CHECK( env.eval_variable("divisibleBy(50, 5)", data) == true );
CHECK( env.eval_variable("divisibleBy(12, 3)", data) == true );
CHECK( env.eval_variable("divisibleBy(11, 3)", data) == false );
CHECK_THROWS_WITH( env.eval_variable("divisibleBy(name, 2)", data), "Argument in divisibleBy function is not a number." );
CHECK_THROWS_WITH( env.eval_variable("divisibleBy(name, 2)", data), "[json.exception.type_error.302] type must be number, but is string" );
}
SECTION("Odd") {
CHECK( env.eval_variable("odd(11)", data) == true );
CHECK( env.eval_variable("odd(12)", data) == false );
CHECK_THROWS_WITH( env.eval_variable("odd(name)", data), "Argument in odd function is not a number." );
CHECK_THROWS_WITH( env.eval_variable("odd(name)", data), "[json.exception.type_error.302] type must be number, but is string" );
}
SECTION("Even") {
CHECK( env.eval_variable("even(11)", data) == false );
CHECK( env.eval_variable("even(12)", data) == true );
CHECK_THROWS_WITH( env.eval_variable("even(name)", data), "Argument in even function is not a number." );
CHECK_THROWS_WITH( env.eval_variable("even(name)", data), "[json.exception.type_error.302] type must be number, but is string" );
}
}