diff --git a/README.md b/README.md index 48e86c6..543f355 100644 --- a/README.md +++ b/README.md @@ -321,6 +321,11 @@ Comments can be written with the `{# ... #}` syntax. render("Hello{# Todo #}!", data); // "Hello!" ``` +### Exceptions + +Inja uses exceptions to handle ill-formed template input. However, exceptions can be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `INJA_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. + + ## Supported compilers Inja uses `string_view` from C++17, but includes the [polyfill](https://github.com/martinmoene/string-view-lite) from martinmoene. This way, the minimum version is C++11. Currently, the following compilers are tested: diff --git a/include/inja/inja.hpp b/include/inja/inja.hpp index fff245b..86b8a0a 100644 --- a/include/inja/inja.hpp +++ b/include/inja/inja.hpp @@ -5,6 +5,13 @@ #include +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(INJA_NOEXCEPTION) + #define INJA_THROW(exception) throw exception +#else + #include + #define INJA_THROW(exception) std::abort() +#endif + #include "environment.hpp" #include "exceptions.hpp" #include "parser.hpp" diff --git a/include/inja/parser.hpp b/include/inja/parser.hpp index d676d75..6266c4a 100644 --- a/include/inja/parser.hpp +++ b/include/inja/parser.hpp @@ -51,7 +51,7 @@ class Parser { std::stack for_statement_stack; void throw_parser_error(const std::string &message) { - throw ParserError(message, lexer.current_position()); + INJA_THROW(ParserError(message, lexer.current_position())); } void get_next_token() { diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp index 8b3a270..7bc518f 100644 --- a/include/inja/renderer.hpp +++ b/include/inja/renderer.hpp @@ -91,7 +91,7 @@ class Renderer : public NodeVisitor { void throw_renderer_error(const std::string &message, const AstNode& node) { SourceLocation loc = get_source_location(current_template->content, node.pos); - throw RenderError(message, loc); + INJA_THROW(RenderError(message, loc)); } template diff --git a/include/inja/utils.hpp b/include/inja/utils.hpp index ee58ccc..fb1736c 100644 --- a/include/inja/utils.hpp +++ b/include/inja/utils.hpp @@ -18,7 +18,7 @@ inline void open_file_or_throw(const std::string &path, std::ifstream &file) { try { file.open(path); } catch (const std::ios_base::failure & /*e*/) { - throw FileError("failed accessing file at '" + path + "'"); + INJA_THROW(FileError("failed accessing file at '" + path + "'")); } } diff --git a/single_include/inja/inja.hpp b/single_include/inja/inja.hpp index 516aa95..42dea1c 100644 --- a/single_include/inja/inja.hpp +++ b/single_include/inja/inja.hpp @@ -5,6 +5,13 @@ #include +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(INJA_NOEXCEPTION) + #define INJA_THROW(exception) throw exception +#else + #include + #define INJA_THROW(exception) std::abort() +#endif + // #include "environment.hpp" // Copyright (c) 2019 Pantor. All rights reserved. @@ -1838,7 +1845,7 @@ inline void open_file_or_throw(const std::string &path, std::ifstream &file) { try { file.open(path); } catch (const std::ios_base::failure & /*e*/) { - throw FileError("failed accessing file at '" + path + "'"); + INJA_THROW(FileError("failed accessing file at '" + path + "'")); } } @@ -2780,7 +2787,7 @@ class Parser { std::stack for_statement_stack; void throw_parser_error(const std::string &message) { - throw ParserError(message, lexer.current_position()); + INJA_THROW(ParserError(message, lexer.current_position())); } void get_next_token() { @@ -3409,7 +3416,7 @@ class Renderer : public NodeVisitor { void throw_renderer_error(const std::string &message, const AstNode& node) { SourceLocation loc = get_source_location(current_template->content, node.pos); - throw RenderError(message, loc); + INJA_THROW(RenderError(message, loc)); } template diff --git a/test/test-files.cpp b/test/test-files.cpp index a999d90..74d099a 100644 --- a/test/test-files.cpp +++ b/test/test-files.cpp @@ -1,9 +1,5 @@ // Copyright (c) 2020 Pantor. All rights reserved. -#include "doctest/doctest.h" -#include "inja/inja.hpp" - - TEST_CASE("loading") { inja::Environment env; json data; diff --git a/test/test-functions.cpp b/test/test-functions.cpp index 60c8b79..4870205 100644 --- a/test/test-functions.cpp +++ b/test/test-functions.cpp @@ -1,9 +1,5 @@ // Copyright (c) 2020 Pantor. All rights reserved. -#include "doctest/doctest.h" -#include "inja/inja.hpp" - - TEST_CASE("functions") { inja::Environment env; diff --git a/test/test-renderer.cpp b/test/test-renderer.cpp index 8d5b447..fe38738 100644 --- a/test/test-renderer.cpp +++ b/test/test-renderer.cpp @@ -1,9 +1,5 @@ // Copyright (c) 2020 Pantor. All rights reserved. -#include "doctest/doctest.h" -#include "inja/inja.hpp" - - TEST_CASE("types") { inja::Environment env; json data; diff --git a/test/test-units.cpp b/test/test-units.cpp index f84197a..95862f2 100644 --- a/test/test-units.cpp +++ b/test/test-units.cpp @@ -1,9 +1,5 @@ // Copyright (c) 2020 Pantor. All rights reserved. -#include "doctest/doctest.h" -#include "inja/inja.hpp" - - TEST_CASE("source location") { std::string content = R""""(Lorem Ipsum Dolor