From 9f97c9add15b4ec99fe6fa99640ca4fe9ab5963b Mon Sep 17 00:00:00 2001 From: pantor Date: Sun, 18 Feb 2018 19:41:56 +0100 Subject: [PATCH] add sort function --- README.md | 15 ++++++++++----- src/inja.hpp | 9 +++++++++ test/src/unit-renderer.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 63a313d..74b463d 100644 --- a/README.md +++ b/README.md @@ -99,12 +99,12 @@ Variables are rendered within the `{{ ... }}` expressions. ```c++ json data; data["neighbour"] = "Peter"; -data["guests"] = {"Jeff", "Patrick", "Tom"}; +data["guests"] = {"Jeff", "Tom", "Patrick"}; data["time"]["start"] = 16; data["time"]["end"] = 22; // Indexing in array -render("{{ guests/1 }}", data); // "Patrick" +render("{{ guests/1 }}", data); // "Tom" // Objects render("{{ time/start }} to {{ time/end }}pm"); // "16 to 22pm" @@ -127,8 +127,8 @@ render(R"(Guest List: /* Guest List: 1: Jeff - 2: Pierre - 3: Tom */ + 2: Tom + 3: Patrick */ ``` In a loop, the special variables `index (number)`, `index1 (number)`, `is_first (boolean)` and `is_last (boolean)` are available. You can also iterate over objects like `{% for key, value in time %}`. @@ -172,7 +172,12 @@ render("I count {{ length(guests) }} guests.", data); // "I count 3 guests." // Get first and last element in a list render("{{ first(guests) }} was first.", data); // "Jeff was first." -render("{{ last(guests) }} was last.", data); // "Tom was last." +render("{{ last(guests) }} was last.", data); // "Patir was last." + +// Sort a list +render("{{ sort([3,2,1]) }}", data); // "[1,2,3]" +render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]" + // Round numbers to a given precision render("{{ round(3.1415, 0) }}", data); // 3 diff --git a/src/inja.hpp b/src/inja.hpp index cb2db34..4f629c0 100644 --- a/src/inja.hpp +++ b/src/inja.hpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include @@ -242,6 +244,7 @@ struct Parsed { Lower, Range, Length, + Sort, First, Last, Round, @@ -372,6 +375,11 @@ public: const std::vector list = eval_expression>(element.args[0], data); return list.size(); } + case Parsed::Function::Sort: { + std::vector list = eval_expression>(element.args[0], data); + std::sort(list.begin(), list.end()); + return list; + } case Parsed::Function::First: { const std::vector list = eval_expression>(element.args[0], data); return list.front(); @@ -605,6 +613,7 @@ public: {Parsed::Function::Lower, function_regex("lower", 1)}, {Parsed::Function::Range, function_regex("range", 1)}, {Parsed::Function::Length, function_regex("length", 1)}, + {Parsed::Function::Sort, function_regex("sort", 1)}, {Parsed::Function::First, function_regex("first", 1)}, {Parsed::Function::Last, function_regex("last", 1)}, {Parsed::Function::Round, function_regex("round", 2)}, diff --git a/test/src/unit-renderer.cpp b/test/src/unit-renderer.cpp index ef786b5..44d91b5 100644 --- a/test/src/unit-renderer.cpp +++ b/test/src/unit-renderer.cpp @@ -107,6 +107,12 @@ TEST_CASE("functions") { // CHECK_THROWS_WITH( env.render("{{ length(5) }}", data), "[json.exception.type_error.302] type must be array, but is number" ); } + SECTION("sort") { + CHECK( env.render("{{ sort([3, 2, 1]) }}", data) == "[1,2,3]" ); + CHECK( env.render("{{ sort([\"bob\", \"charlie\", \"alice\"]) }}", data) == "[\"alice\",\"bob\",\"charlie\"]" ); + // CHECK_THROWS_WITH( env.render("{{ sort(5) }}", data), "[json.exception.type_error.302] type must be array, but is number" ); + } + SECTION("first") { CHECK( env.render("{{ first(names) }}", data) == "Jeff" ); // CHECK_THROWS_WITH( env.render("{{ length(5) }}", data), "[json.exception.type_error.302] type must be array, but is number" );