diff --git a/include/inja/node.hpp b/include/inja/node.hpp index 6247d12..20435ac 100644 --- a/include/inja/node.hpp +++ b/include/inja/node.hpp @@ -74,9 +74,9 @@ public: class TextNode : public AstNode { public: - std::string content; + size_t length; - explicit TextNode(nonstd::string_view content, size_t pos): AstNode(pos), content(content) { } + explicit TextNode(size_t pos, size_t length): AstNode(pos), length(length) { } void accept(NodeVisitor& v) const { v.visit(*this); @@ -108,14 +108,19 @@ public: std::string name; std::string ptr {""}; - explicit JsonNode(nonstd::string_view ptr_name, size_t pos) : ExpressionNode(pos), name(ptr_name) { - // Convert dot notation to json pointer notation + static std::string convert_dot_to_json_ptr(nonstd::string_view ptr_name) { + std::string result; do { nonstd::string_view part; std::tie(part, ptr_name) = string_view::split(ptr_name, '.'); - ptr.push_back('/'); - ptr.append(part.begin(), part.end()); + result.push_back('/'); + result.append(part.begin(), part.end()); } while (!ptr_name.empty()); + return result; + } + + explicit JsonNode(nonstd::string_view ptr_name, size_t pos) : ExpressionNode(pos), name(ptr_name) { + ptr = convert_dot_to_json_ptr(ptr_name); } void accept(NodeVisitor& v) const { diff --git a/include/inja/parser.hpp b/include/inja/parser.hpp index c6d46a3..909fd6e 100644 --- a/include/inja/parser.hpp +++ b/include/inja/parser.hpp @@ -471,7 +471,7 @@ class Parser { } } return; case Token::Kind::Text: { - current_block->nodes.emplace_back(std::make_shared(tok.text, tok.text.data() - tmpl.content.c_str())); + current_block->nodes.emplace_back(std::make_shared(tok.text.data() - tmpl.content.c_str(), tok.text.size())); } break; case Token::Kind::StatementOpen: { get_next_token(); diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp index 1c0d97e..08f822f 100644 --- a/include/inja/renderer.hpp +++ b/include/inja/renderer.hpp @@ -147,7 +147,7 @@ class Renderer : public NodeVisitor { } void visit(const TextNode& node) { - *output_stream << node.content; + output_stream->write(current_template->content.c_str() + node.pos, node.length); } void visit(const ExpressionNode&) { } @@ -344,7 +344,7 @@ class Renderer : public NodeVisitor { } break; case Op::Exists: { auto &&name = get_arguments<1>(node)[0]->get_ref(); - result_ptr = std::make_shared(json_input->contains(json::json_pointer(JsonNode(name, 0).ptr))); + result_ptr = std::make_shared(json_input->contains(json::json_pointer(JsonNode::convert_dot_to_json_ptr(name)))); json_tmp_stack.push_back(result_ptr); json_eval_stack.push(result_ptr.get()); } break; diff --git a/test/test-functions.cpp b/test/test-functions.cpp index def0c6d..e42ede3 100644 --- a/test/test-functions.cpp +++ b/test/test-functions.cpp @@ -74,6 +74,7 @@ TEST_CASE("functions") { SUBCASE("at") { CHECK(env.render("{{ at(names, 0) }}", data) == "Jeff"); CHECK(env.render("{{ at(names, i) }}", data) == "Seb"); + // CHECK(env.render("{{ at(names, 45) }}", data) == "Jeff"); } SUBCASE("first") {