mirror of
https://github.com/pantor/inja.git
synced 2026-02-17 09:03:58 +00:00
Merge branch 'master' of https://github.com/pantor/inja
This commit is contained in:
@@ -16,11 +16,11 @@ set(INJA_INSTALL_INCLUDE_DIR "include")
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
add_compile_options(-Wall)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
add_compile_options(/W4 /permissive- /utf-8 /Zc:__cplusplus)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ platform:
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
# - Debug
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# Visual Studio 2015
|
||||
# - TOOLCHAIN: v140
|
||||
# STD: 14
|
||||
- TOOLCHAIN: v140
|
||||
STD: 14
|
||||
# Visual Studio 2017
|
||||
- TOOLCHAIN: v141
|
||||
STD: 14
|
||||
@@ -34,7 +34,7 @@ init:
|
||||
before_build:
|
||||
- mkdir -p build
|
||||
- cd build
|
||||
- cmake .. -A %PLATFORM% -T %TOOLCHAIN% -DCMAKE_CXX_STANDARD=%STD% -DCMAKE_CXX_FLAGS="/permissive- /utf-8 /Zc:__cplusplus"
|
||||
- cmake .. -A %PLATFORM% -T %TOOLCHAIN% -DCMAKE_CXX_STANDARD=%STD%
|
||||
|
||||
build_script:
|
||||
- cmake --build . --config %CONFIGURATION% -- -verbosity:n
|
||||
|
||||
@@ -28,84 +28,64 @@ using json = nlohmann::json;
|
||||
* \brief Class for changing the configuration.
|
||||
*/
|
||||
class Environment {
|
||||
class Impl {
|
||||
public:
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
|
||||
FunctionStorage callbacks;
|
||||
TemplateStorage included_templates;
|
||||
};
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
public:
|
||||
Environment(): Environment("") { }
|
||||
|
||||
explicit Environment(const std::string& global_path): m_impl(stdinja::make_unique<Impl>()) {
|
||||
m_impl->input_path = global_path;
|
||||
m_impl->output_path = global_path;
|
||||
}
|
||||
explicit Environment(const std::string& global_path): m_input_path(global_path), m_output_path(global_path) {}
|
||||
|
||||
explicit Environment(const std::string& input_path, const std::string& output_path): m_impl(stdinja::make_unique<Impl>()) {
|
||||
m_impl->input_path = input_path;
|
||||
m_impl->output_path = output_path;
|
||||
}
|
||||
Environment(const std::string& input_path, const std::string& output_path): m_input_path(input_path), m_output_path(output_path) {}
|
||||
|
||||
/// Sets the opener and closer for template statements
|
||||
void set_statement(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.statement_open = open;
|
||||
m_impl->lexer_config.statement_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.statement_open = open;
|
||||
m_lexer_config.statement_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener for template line statements
|
||||
void set_line_statement(const std::string& open) {
|
||||
m_impl->lexer_config.line_statement = open;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.line_statement = open;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener and closer for template expressions
|
||||
void set_expression(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.expression_open = open;
|
||||
m_impl->lexer_config.expression_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.expression_open = open;
|
||||
m_lexer_config.expression_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener and closer for template comments
|
||||
void set_comment(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.comment_open = open;
|
||||
m_impl->lexer_config.comment_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.comment_open = open;
|
||||
m_lexer_config.comment_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets whether to remove the first newline after a block
|
||||
void set_trim_blocks(bool trim_blocks) {
|
||||
m_impl->lexer_config.trim_blocks = trim_blocks;
|
||||
m_lexer_config.trim_blocks = trim_blocks;
|
||||
}
|
||||
|
||||
/// Sets whether to strip the spaces and tabs from the start of a line to a block
|
||||
void set_lstrip_blocks(bool lstrip_blocks) {
|
||||
m_impl->lexer_config.lstrip_blocks = lstrip_blocks;
|
||||
m_lexer_config.lstrip_blocks = lstrip_blocks;
|
||||
}
|
||||
|
||||
/// Sets the element notation syntax
|
||||
void set_element_notation(ElementNotation notation) {
|
||||
m_impl->parser_config.notation = notation;
|
||||
m_parser_config.notation = notation;
|
||||
}
|
||||
|
||||
|
||||
Template parse(nonstd::string_view input) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.parse(input);
|
||||
}
|
||||
|
||||
Template parse_template(const std::string& filename) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
return parser.parse_template(m_impl->input_path + static_cast<std::string>(filename));
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.parse_template(m_input_path + static_cast<std::string>(filename));
|
||||
}
|
||||
|
||||
std::string render(nonstd::string_view input, const json& data) {
|
||||
@@ -128,13 +108,13 @@ class Environment {
|
||||
}
|
||||
|
||||
void write(const std::string& filename, const json& data, const std::string& filename_out) {
|
||||
std::ofstream file(m_impl->output_path + filename_out);
|
||||
std::ofstream file(m_output_path + filename_out);
|
||||
file << render_file(filename, data);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void write(const Template& temp, const json& data, const std::string& filename_out) {
|
||||
std::ofstream file(m_impl->output_path + filename_out);
|
||||
std::ofstream file(m_output_path + filename_out);
|
||||
file << render(temp, data);
|
||||
file.close();
|
||||
}
|
||||
@@ -150,24 +130,24 @@ class Environment {
|
||||
}
|
||||
|
||||
std::ostream& render_to(std::ostream& os, const Template& tmpl, const json& data) {
|
||||
Renderer(m_impl->included_templates, m_impl->callbacks).render_to(os, tmpl, data);
|
||||
Renderer(m_included_templates, m_callbacks).render_to(os, tmpl, data);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::string load_file(const std::string& filename) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
return parser.load_file(m_impl->input_path + filename);
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.load_file(m_input_path + filename);
|
||||
}
|
||||
|
||||
json load_json(const std::string& filename) {
|
||||
std::ifstream file = open_file_or_throw(m_impl->input_path + filename);
|
||||
std::ifstream file = open_file_or_throw(m_input_path + filename);
|
||||
json j;
|
||||
file >> j;
|
||||
return j;
|
||||
}
|
||||
|
||||
void add_callback(const std::string& name, unsigned int numArgs, const CallbackFunction& callback) {
|
||||
m_impl->callbacks.add_callback(name, numArgs, callback);
|
||||
m_callbacks.add_callback(name, numArgs, callback);
|
||||
}
|
||||
|
||||
/** Includes a template with a given name into the environment.
|
||||
@@ -175,8 +155,18 @@ class Environment {
|
||||
* include "<name>" syntax.
|
||||
*/
|
||||
void include_template(const std::string& name, const Template& tmpl) {
|
||||
m_impl->included_templates[name] = tmpl;
|
||||
m_included_templates[name] = tmpl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_input_path;
|
||||
std::string m_output_path;
|
||||
|
||||
LexerConfig m_lexer_config;
|
||||
ParserConfig m_parser_config;
|
||||
|
||||
FunctionStorage m_callbacks;
|
||||
TemplateStorage m_included_templates;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define NONSTD_SV_LITE_H_INCLUDED
|
||||
|
||||
#define string_view_lite_MAJOR 1
|
||||
#define string_view_lite_MINOR 1
|
||||
#define string_view_lite_MINOR 4
|
||||
#define string_view_lite_PATCH 0
|
||||
|
||||
#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
|
||||
@@ -218,7 +218,7 @@ using std::operator<<;
|
||||
# define nssv_COMPILER_MSVC_VERSION 0
|
||||
#endif
|
||||
|
||||
#define nssv_COMPILER_VERSION( major, minor, patch ) (10 * ( 10 * major + minor) + patch)
|
||||
#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
|
||||
|
||||
#if defined(__clang__)
|
||||
# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
|
||||
@@ -273,8 +273,10 @@ using std::operator<<;
|
||||
#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
|
||||
#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
|
||||
|
||||
#if ! ( ( nssv_CPP11 && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
|
||||
#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
|
||||
# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
|
||||
#else
|
||||
# define nssv_HAVE_STD_DEFINED_LITERALS 0
|
||||
#endif
|
||||
|
||||
// Presence of C++14 language features:
|
||||
@@ -402,6 +404,22 @@ nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
|
||||
|
||||
namespace nonstd { namespace sv_lite {
|
||||
|
||||
#if nssv_CPP11_OR_GREATER
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Expect tail call optimization to make length() non-recursive:
|
||||
|
||||
template< typename CharT >
|
||||
inline constexpr std::size_t length( CharT * s, std::size_t result = 0 )
|
||||
{
|
||||
return *s == '\0' ? result : length( s + 1, result + 1 );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#endif // nssv_CPP11_OR_GREATER
|
||||
|
||||
template
|
||||
<
|
||||
class CharT,
|
||||
@@ -455,14 +473,20 @@ public:
|
||||
{}
|
||||
#endif
|
||||
|
||||
nssv_constexpr basic_string_view( CharT const * s, size_type count )
|
||||
nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
|
||||
: data_( s )
|
||||
, size_( count )
|
||||
{}
|
||||
|
||||
nssv_constexpr basic_string_view( CharT const * s)
|
||||
nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
|
||||
: data_( s )
|
||||
#if nssv_CPP17_OR_GREATER
|
||||
, size_( Traits::length(s) )
|
||||
#elif nssv_CPP11_OR_GREATER
|
||||
, size_( detail::length(s) )
|
||||
#else
|
||||
, size_( Traits::length(s) )
|
||||
#endif
|
||||
{}
|
||||
|
||||
// Assignment:
|
||||
@@ -518,7 +542,7 @@ public:
|
||||
#else
|
||||
if ( pos >= size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::at()");
|
||||
throw std::out_of_range("nonstd::string_view::at()");
|
||||
}
|
||||
#endif
|
||||
return data_at( pos );
|
||||
@@ -560,7 +584,7 @@ public:
|
||||
#else
|
||||
if ( pos > size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::copy()");
|
||||
throw std::out_of_range("nonstd::string_view::copy()");
|
||||
}
|
||||
#endif
|
||||
const size_type rlen = (std::min)( n, size() - pos );
|
||||
@@ -577,7 +601,7 @@ public:
|
||||
#else
|
||||
if ( pos > size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::substr()");
|
||||
throw std::out_of_range("nonstd::string_view::substr()");
|
||||
}
|
||||
#endif
|
||||
return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
|
||||
@@ -588,7 +612,9 @@ public:
|
||||
nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
|
||||
{
|
||||
if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
|
||||
}
|
||||
@@ -684,10 +710,14 @@ public:
|
||||
nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
|
||||
{
|
||||
if ( size() < v.size() )
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
|
||||
if ( v.empty() )
|
||||
{
|
||||
return (std::min)( size(), pos );
|
||||
}
|
||||
|
||||
const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
|
||||
const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
|
||||
@@ -825,7 +855,7 @@ private:
|
||||
{
|
||||
const basic_string_view v;
|
||||
|
||||
nssv_constexpr not_in_view( basic_string_view v ) : v( v ) {}
|
||||
nssv_constexpr explicit not_in_view( basic_string_view v ) : v( v ) {}
|
||||
|
||||
nssv_constexpr bool operator()( CharT c ) const
|
||||
{
|
||||
@@ -952,7 +982,167 @@ nssv_constexpr bool operator>= (
|
||||
// constexpr and noexcept so that an object t with an implicit conversion
|
||||
// to S can be compared according to Table 67.
|
||||
|
||||
#if nssv_CPP11_OR_GREATER && ! nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
|
||||
#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
|
||||
|
||||
// accomodate for older compilers:
|
||||
|
||||
// ==
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
|
||||
|
||||
// !=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.size() != rhs.size() && lhs.compare( rhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return lhs.size() != rhs.size() || rhs.compare( lhs ) != 0; }
|
||||
|
||||
// <
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) > 0; }
|
||||
|
||||
// <=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) >= 0; }
|
||||
|
||||
// >
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) < 0; }
|
||||
|
||||
// >=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) <= 0; }
|
||||
|
||||
#else // newer compilers:
|
||||
|
||||
#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
|
||||
|
||||
@@ -1049,7 +1239,7 @@ nssv_constexpr bool operator>= (
|
||||
#undef nssv_MSVC_ORDER
|
||||
#undef nssv_BASIC_STRING_VIEW_I
|
||||
|
||||
#endif // nssv_CPP11_OR_GREATER
|
||||
#endif // compiler-dependent approach to comparisons
|
||||
|
||||
// 24.4.4 Inserters and extractors:
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef PANTOR_INJA_HPP
|
||||
#define PANTOR_INJA_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_INJA_HPP_
|
||||
#define INCLUDE_INJA_INJA_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@@ -12,8 +14,10 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// #include "environment.hpp"
|
||||
#ifndef PANTOR_INJA_ENVIRONMENT_HPP
|
||||
#define PANTOR_INJA_ENVIRONMENT_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
|
||||
#define INCLUDE_INJA_ENVIRONMENT_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
@@ -23,8 +27,10 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// #include "config.hpp"
|
||||
#ifndef PANTOR_INJA_CONFIG_HPP
|
||||
#define PANTOR_INJA_CONFIG_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_CONFIG_HPP_
|
||||
#define INCLUDE_INJA_CONFIG_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
@@ -44,7 +50,7 @@
|
||||
#define NONSTD_SV_LITE_H_INCLUDED
|
||||
|
||||
#define string_view_lite_MAJOR 1
|
||||
#define string_view_lite_MINOR 1
|
||||
#define string_view_lite_MINOR 4
|
||||
#define string_view_lite_PATCH 0
|
||||
|
||||
#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
|
||||
@@ -250,7 +256,7 @@ using std::operator<<;
|
||||
# define nssv_COMPILER_MSVC_VERSION 0
|
||||
#endif
|
||||
|
||||
#define nssv_COMPILER_VERSION( major, minor, patch ) (10 * ( 10 * major + minor) + patch)
|
||||
#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
|
||||
|
||||
#if defined(__clang__)
|
||||
# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
|
||||
@@ -305,8 +311,10 @@ using std::operator<<;
|
||||
#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
|
||||
#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
|
||||
|
||||
#if ! ( ( nssv_CPP11 && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
|
||||
#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
|
||||
# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
|
||||
#else
|
||||
# define nssv_HAVE_STD_DEFINED_LITERALS 0
|
||||
#endif
|
||||
|
||||
// Presence of C++14 language features:
|
||||
@@ -434,6 +442,22 @@ nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
|
||||
|
||||
namespace nonstd { namespace sv_lite {
|
||||
|
||||
#if nssv_CPP11_OR_GREATER
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Expect tail call optimization to make length() non-recursive:
|
||||
|
||||
template< typename CharT >
|
||||
inline constexpr std::size_t length( CharT * s, std::size_t result = 0 )
|
||||
{
|
||||
return *s == '\0' ? result : length( s + 1, result + 1 );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#endif // nssv_CPP11_OR_GREATER
|
||||
|
||||
template
|
||||
<
|
||||
class CharT,
|
||||
@@ -487,14 +511,20 @@ public:
|
||||
{}
|
||||
#endif
|
||||
|
||||
nssv_constexpr basic_string_view( CharT const * s, size_type count )
|
||||
nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
|
||||
: data_( s )
|
||||
, size_( count )
|
||||
{}
|
||||
|
||||
nssv_constexpr basic_string_view( CharT const * s)
|
||||
nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
|
||||
: data_( s )
|
||||
#if nssv_CPP17_OR_GREATER
|
||||
, size_( Traits::length(s) )
|
||||
#elif nssv_CPP11_OR_GREATER
|
||||
, size_( detail::length(s) )
|
||||
#else
|
||||
, size_( Traits::length(s) )
|
||||
#endif
|
||||
{}
|
||||
|
||||
// Assignment:
|
||||
@@ -550,7 +580,7 @@ public:
|
||||
#else
|
||||
if ( pos >= size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::at()");
|
||||
throw std::out_of_range("nonstd::string_view::at()");
|
||||
}
|
||||
#endif
|
||||
return data_at( pos );
|
||||
@@ -592,7 +622,7 @@ public:
|
||||
#else
|
||||
if ( pos > size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::copy()");
|
||||
throw std::out_of_range("nonstd::string_view::copy()");
|
||||
}
|
||||
#endif
|
||||
const size_type rlen = (std::min)( n, size() - pos );
|
||||
@@ -609,7 +639,7 @@ public:
|
||||
#else
|
||||
if ( pos > size() )
|
||||
{
|
||||
throw std::out_of_range("nonst::string_view::substr()");
|
||||
throw std::out_of_range("nonstd::string_view::substr()");
|
||||
}
|
||||
#endif
|
||||
return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
|
||||
@@ -620,7 +650,9 @@ public:
|
||||
nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
|
||||
{
|
||||
if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
|
||||
}
|
||||
@@ -716,10 +748,14 @@ public:
|
||||
nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
|
||||
{
|
||||
if ( size() < v.size() )
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
|
||||
if ( v.empty() )
|
||||
{
|
||||
return (std::min)( size(), pos );
|
||||
}
|
||||
|
||||
const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
|
||||
const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
|
||||
@@ -857,7 +893,7 @@ private:
|
||||
{
|
||||
const basic_string_view v;
|
||||
|
||||
nssv_constexpr not_in_view( basic_string_view v ) : v( v ) {}
|
||||
nssv_constexpr explicit not_in_view( basic_string_view v ) : v( v ) {}
|
||||
|
||||
nssv_constexpr bool operator()( CharT c ) const
|
||||
{
|
||||
@@ -984,7 +1020,167 @@ nssv_constexpr bool operator>= (
|
||||
// constexpr and noexcept so that an object t with an implicit conversion
|
||||
// to S can be compared according to Table 67.
|
||||
|
||||
#if nssv_CPP11_OR_GREATER && ! nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
|
||||
#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
|
||||
|
||||
// accomodate for older compilers:
|
||||
|
||||
// ==
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator==(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
|
||||
|
||||
// !=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.size() != rhs.size() && lhs.compare( rhs ) != 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator!=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return lhs.size() != rhs.size() || rhs.compare( lhs ) != 0; }
|
||||
|
||||
// <
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) > 0; }
|
||||
|
||||
// <=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator<=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) >= 0; }
|
||||
|
||||
// >
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) < 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) > 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) < 0; }
|
||||
|
||||
// >=
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
char const * rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
char const * lhs,
|
||||
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) <= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
basic_string_view<CharT, Traits> lhs,
|
||||
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
|
||||
{ return lhs.compare( rhs ) >= 0; }
|
||||
|
||||
template< class CharT, class Traits>
|
||||
nssv_constexpr bool operator>=(
|
||||
std::basic_string<CharT, Traits> rhs,
|
||||
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
|
||||
{ return rhs.compare( lhs ) <= 0; }
|
||||
|
||||
#else // newer compilers:
|
||||
|
||||
#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
|
||||
|
||||
@@ -1081,7 +1277,7 @@ nssv_constexpr bool operator>= (
|
||||
#undef nssv_MSVC_ORDER
|
||||
#undef nssv_BASIC_STRING_VIEW_I
|
||||
|
||||
#endif // nssv_CPP11_OR_GREATER
|
||||
#endif // compiler-dependent approach to comparisons
|
||||
|
||||
// 24.4.4 Inserters and extractors:
|
||||
|
||||
@@ -1400,19 +1596,23 @@ struct ParserConfig {
|
||||
ElementNotation notation {ElementNotation::Dot};
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_CONFIG_HPP
|
||||
#endif // INCLUDE_INJA_CONFIG_HPP_
|
||||
|
||||
// #include "function_storage.hpp"
|
||||
#ifndef PANTOR_INJA_FUNCTION_STORAGE_HPP
|
||||
#define PANTOR_INJA_FUNCTION_STORAGE_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
|
||||
#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
|
||||
|
||||
#include <vector>
|
||||
|
||||
// #include "bytecode.hpp"
|
||||
#ifndef PANTOR_INJA_BYTECODE_HPP
|
||||
#define PANTOR_INJA_BYTECODE_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_BYTECODE_HPP_
|
||||
#define INCLUDE_INJA_BYTECODE_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -1543,7 +1743,7 @@ struct Bytecode {
|
||||
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_BYTECODE_HPP
|
||||
#endif // INCLUDE_INJA_BYTECODE_HPP_
|
||||
|
||||
// #include "string_view.hpp"
|
||||
|
||||
@@ -1551,7 +1751,7 @@ struct Bytecode {
|
||||
|
||||
namespace inja {
|
||||
|
||||
using namespace nlohmann;
|
||||
using json = nlohmann::json;
|
||||
|
||||
using Arguments = std::vector<const json*>;
|
||||
using CallbackFunction = std::function<json(Arguments& args)>;
|
||||
@@ -1616,11 +1816,13 @@ class FunctionStorage {
|
||||
|
||||
}
|
||||
|
||||
#endif // PANTOR_INJA_FUNCTION_STORAGE_HPP
|
||||
#endif // INCLUDE_INJA_FUNCTION_STORAGE_HPP_
|
||||
|
||||
// #include "parser.hpp"
|
||||
#ifndef PANTOR_INJA_PARSER_HPP
|
||||
#define PANTOR_INJA_PARSER_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_PARSER_HPP_
|
||||
#define INCLUDE_INJA_PARSER_HPP_
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@@ -1634,8 +1836,10 @@ class FunctionStorage {
|
||||
// #include "function_storage.hpp"
|
||||
|
||||
// #include "lexer.hpp"
|
||||
#ifndef PANTOR_INJA_LEXER_HPP
|
||||
#define PANTOR_INJA_LEXER_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_LEXER_HPP_
|
||||
#define INCLUDE_INJA_LEXER_HPP_
|
||||
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
@@ -1643,8 +1847,10 @@ class FunctionStorage {
|
||||
// #include "config.hpp"
|
||||
|
||||
// #include "token.hpp"
|
||||
#ifndef PANTOR_INJA_TOKEN_HPP
|
||||
#define PANTOR_INJA_TOKEN_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_TOKEN_HPP_
|
||||
#define INCLUDE_INJA_TOKEN_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -1710,11 +1916,13 @@ struct Token {
|
||||
|
||||
}
|
||||
|
||||
#endif // PANTOR_INJA_TOKEN_HPP
|
||||
#endif // INCLUDE_INJA_TOKEN_HPP_
|
||||
|
||||
// #include "utils.hpp"
|
||||
#ifndef PANTOR_INJA_UTILS_HPP
|
||||
#define PANTOR_INJA_UTILS_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_UTILS_HPP_
|
||||
#define INCLUDE_INJA_UTILS_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
@@ -1761,11 +1969,11 @@ namespace string_view {
|
||||
inline bool starts_with(nonstd::string_view view, nonstd::string_view prefix) {
|
||||
return (view.size() >= prefix.size() && view.compare(0, prefix.size(), prefix) == 0);
|
||||
}
|
||||
} // namespace string
|
||||
} // namespace string_view
|
||||
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_UTILS_HPP
|
||||
#endif // INCLUDE_INJA_UTILS_HPP_
|
||||
|
||||
|
||||
|
||||
@@ -1835,7 +2043,7 @@ class Lexer {
|
||||
inja::string_view::starts_with(open_str, m_config.line_statement)) {
|
||||
m_state = State::LineStart;
|
||||
} else {
|
||||
m_pos += 1; // wasn't actually an opening sequence
|
||||
m_pos += 1; // wasn't actually an opening sequence
|
||||
goto again;
|
||||
}
|
||||
|
||||
@@ -2063,11 +2271,13 @@ class Lexer {
|
||||
|
||||
}
|
||||
|
||||
#endif // PANTOR_INJA_LEXER_HPP
|
||||
#endif // INCLUDE_INJA_LEXER_HPP_
|
||||
|
||||
// #include "template.hpp"
|
||||
#ifndef PANTOR_INJA_TEMPLATE_HPP
|
||||
#define PANTOR_INJA_TEMPLATE_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_TEMPLATE_HPP_
|
||||
#define INCLUDE_INJA_TEMPLATE_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -2089,9 +2299,9 @@ struct Template {
|
||||
|
||||
using TemplateStorage = std::map<std::string, Template>;
|
||||
|
||||
}
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_TEMPLATE_HPP
|
||||
#endif // INCLUDE_INJA_TEMPLATE_HPP_
|
||||
|
||||
// #include "token.hpp"
|
||||
|
||||
@@ -2644,11 +2854,13 @@ class Parser {
|
||||
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_PARSER_HPP
|
||||
#endif // INCLUDE_INJA_PARSER_HPP_
|
||||
|
||||
// #include "polyfill.hpp"
|
||||
#ifndef PANTOR_INJA_POLYFILL_HPP
|
||||
#define PANTOR_INJA_POLYFILL_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_POLYFILL_HPP_
|
||||
#define INCLUDE_INJA_POLYFILL_HPP_
|
||||
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
@@ -2660,48 +2872,51 @@ class Parser {
|
||||
|
||||
|
||||
namespace stdinja {
|
||||
template<class T> struct _Unique_if {
|
||||
typedef std::unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef std::unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
template<class T> struct _Unique_if {
|
||||
typedef std::unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef std::unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_unique(size_t n) {
|
||||
typedef typename std::remove_extent<T>::type U;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_unique(Args&&...) = delete;
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_unique(size_t n) {
|
||||
typedef typename std::remove_extent<T>::type U;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_unique(Args&&...) = delete;
|
||||
|
||||
} // namespace stdinja
|
||||
|
||||
#else
|
||||
|
||||
namespace stdinja = std;
|
||||
|
||||
#endif // memory */
|
||||
#endif // memory */
|
||||
|
||||
|
||||
#endif // PANTOR_INJA_POLYFILL_HPP
|
||||
#endif // INCLUDE_INJA_POLYFILL_HPP_
|
||||
|
||||
// #include "renderer.hpp"
|
||||
#ifndef PANTOR_INJA_RENDERER_HPP
|
||||
#define PANTOR_INJA_RENDERER_HPP
|
||||
// Copyright (c) 2019 Pantor. All rights reserved.
|
||||
|
||||
#ifndef INCLUDE_INJA_RENDERER_HPP_
|
||||
#define INCLUDE_INJA_RENDERER_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
@@ -2843,22 +3058,21 @@ class Renderer {
|
||||
enum class Type { Map, Array };
|
||||
|
||||
Type loop_type;
|
||||
nonstd::string_view key_name; // variable name for keys
|
||||
nonstd::string_view value_name; // variable name for values
|
||||
json data; // data with loop info added
|
||||
nonstd::string_view key_name; // variable name for keys
|
||||
nonstd::string_view value_name; // variable name for values
|
||||
json data; // data with loop info added
|
||||
|
||||
json values; // values to iterate over
|
||||
json values; // values to iterate over
|
||||
|
||||
// loop over list
|
||||
size_t index; // current list index
|
||||
size_t size; // length of list
|
||||
size_t index; // current list index
|
||||
size_t size; // length of list
|
||||
|
||||
// loop over map
|
||||
using KeyValue = std::pair<nonstd::string_view, json*>;
|
||||
using MapValues = std::vector<KeyValue>;
|
||||
MapValues map_values; // values to iterate over
|
||||
MapValues::iterator map_it; // iterator over values
|
||||
|
||||
MapValues map_values; // values to iterate over
|
||||
MapValues::iterator map_it; // iterator over values
|
||||
};
|
||||
|
||||
std::vector<LoopLevel> m_loop_stack;
|
||||
@@ -3213,7 +3427,8 @@ class Renderer {
|
||||
for (auto it = level.values.begin(), end = level.values.end(); it != end; ++it) {
|
||||
level.map_values.emplace_back(it.key(), &it.value());
|
||||
}
|
||||
std::sort(level.map_values.begin(), level.map_values.end(), [](const LoopLevel::KeyValue& a, const LoopLevel::KeyValue& b) { return a.first < b.first; });
|
||||
auto sort_lambda = [](const LoopLevel::KeyValue& a, const LoopLevel::KeyValue& b) { return a.first < b.first; };
|
||||
std::sort(level.map_values.begin(), level.map_values.end(), sort_lambda);
|
||||
level.map_it = level.map_values.begin();
|
||||
} else {
|
||||
if (!level.values.is_array()) {
|
||||
@@ -3281,7 +3496,7 @@ class Renderer {
|
||||
|
||||
} // namespace inja
|
||||
|
||||
#endif // PANTOR_INJA_RENDERER_HPP
|
||||
#endif // INCLUDE_INJA_RENDERER_HPP_
|
||||
|
||||
// #include "string_view.hpp"
|
||||
|
||||
@@ -3293,91 +3508,71 @@ class Renderer {
|
||||
|
||||
namespace inja {
|
||||
|
||||
using namespace nlohmann;
|
||||
using json = nlohmann::json;
|
||||
|
||||
/*!
|
||||
* \brief Class for changing the configuration.
|
||||
*/
|
||||
class Environment {
|
||||
class Impl {
|
||||
public:
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
|
||||
FunctionStorage callbacks;
|
||||
TemplateStorage included_templates;
|
||||
};
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
public:
|
||||
Environment(): Environment("") { }
|
||||
|
||||
explicit Environment(const std::string& global_path): m_impl(stdinja::make_unique<Impl>()) {
|
||||
m_impl->input_path = global_path;
|
||||
m_impl->output_path = global_path;
|
||||
}
|
||||
explicit Environment(const std::string& global_path): m_input_path(global_path), m_output_path(global_path) {}
|
||||
|
||||
explicit Environment(const std::string& input_path, const std::string& output_path): m_impl(stdinja::make_unique<Impl>()) {
|
||||
m_impl->input_path = input_path;
|
||||
m_impl->output_path = output_path;
|
||||
}
|
||||
Environment(const std::string& input_path, const std::string& output_path): m_input_path(input_path), m_output_path(output_path) {}
|
||||
|
||||
/// Sets the opener and closer for template statements
|
||||
void set_statement(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.statement_open = open;
|
||||
m_impl->lexer_config.statement_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.statement_open = open;
|
||||
m_lexer_config.statement_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener for template line statements
|
||||
void set_line_statement(const std::string& open) {
|
||||
m_impl->lexer_config.line_statement = open;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.line_statement = open;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener and closer for template expressions
|
||||
void set_expression(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.expression_open = open;
|
||||
m_impl->lexer_config.expression_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.expression_open = open;
|
||||
m_lexer_config.expression_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets the opener and closer for template comments
|
||||
void set_comment(const std::string& open, const std::string& close) {
|
||||
m_impl->lexer_config.comment_open = open;
|
||||
m_impl->lexer_config.comment_close = close;
|
||||
m_impl->lexer_config.update_open_chars();
|
||||
m_lexer_config.comment_open = open;
|
||||
m_lexer_config.comment_close = close;
|
||||
m_lexer_config.update_open_chars();
|
||||
}
|
||||
|
||||
/// Sets whether to remove the first newline after a block
|
||||
void set_trim_blocks(bool trim_blocks) {
|
||||
m_impl->lexer_config.trim_blocks = trim_blocks;
|
||||
m_lexer_config.trim_blocks = trim_blocks;
|
||||
}
|
||||
|
||||
/// Sets whether to strip the spaces and tabs from the start of a line to a block
|
||||
void set_lstrip_blocks(bool lstrip_blocks) {
|
||||
m_impl->lexer_config.lstrip_blocks = lstrip_blocks;
|
||||
m_lexer_config.lstrip_blocks = lstrip_blocks;
|
||||
}
|
||||
|
||||
/// Sets the element notation syntax
|
||||
void set_element_notation(ElementNotation notation) {
|
||||
m_impl->parser_config.notation = notation;
|
||||
m_parser_config.notation = notation;
|
||||
}
|
||||
|
||||
|
||||
Template parse(nonstd::string_view input) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.parse(input);
|
||||
}
|
||||
|
||||
Template parse_template(const std::string& filename) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
return parser.parse_template(m_impl->input_path + static_cast<std::string>(filename));
|
||||
}
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.parse_template(m_input_path + static_cast<std::string>(filename));
|
||||
}
|
||||
|
||||
std::string render(nonstd::string_view input, const json& data) {
|
||||
return render(parse(input), data);
|
||||
@@ -3390,55 +3585,55 @@ class Environment {
|
||||
}
|
||||
|
||||
std::string render_file(const std::string& filename, const json& data) {
|
||||
return render(parse_template(filename), data);
|
||||
}
|
||||
return render(parse_template(filename), data);
|
||||
}
|
||||
|
||||
std::string render_file_with_json_file(const std::string& filename, const std::string& filename_data) {
|
||||
const json data = load_json(filename_data);
|
||||
return render_file(filename, data);
|
||||
}
|
||||
const json data = load_json(filename_data);
|
||||
return render_file(filename, data);
|
||||
}
|
||||
|
||||
void write(const std::string& filename, const json& data, const std::string& filename_out) {
|
||||
std::ofstream file(m_impl->output_path + filename_out);
|
||||
file << render_file(filename, data);
|
||||
file.close();
|
||||
}
|
||||
std::ofstream file(m_output_path + filename_out);
|
||||
file << render_file(filename, data);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void write(const Template& temp, const json& data, const std::string& filename_out) {
|
||||
std::ofstream file(m_impl->output_path + filename_out);
|
||||
file << render(temp, data);
|
||||
file.close();
|
||||
}
|
||||
std::ofstream file(m_output_path + filename_out);
|
||||
file << render(temp, data);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void write_with_json_file(const std::string& filename, const std::string& filename_data, const std::string& filename_out) {
|
||||
const json data = load_json(filename_data);
|
||||
write(filename, data, filename_out);
|
||||
}
|
||||
void write_with_json_file(const std::string& filename, const std::string& filename_data, const std::string& filename_out) {
|
||||
const json data = load_json(filename_data);
|
||||
write(filename, data, filename_out);
|
||||
}
|
||||
|
||||
void write_with_json_file(const Template& temp, const std::string& filename_data, const std::string& filename_out) {
|
||||
const json data = load_json(filename_data);
|
||||
write(temp, data, filename_out);
|
||||
}
|
||||
void write_with_json_file(const Template& temp, const std::string& filename_data, const std::string& filename_out) {
|
||||
const json data = load_json(filename_data);
|
||||
write(temp, data, filename_out);
|
||||
}
|
||||
|
||||
std::ostream& render_to(std::ostream& os, const Template& tmpl, const json& data) {
|
||||
Renderer(m_impl->included_templates, m_impl->callbacks).render_to(os, tmpl, data);
|
||||
Renderer(m_included_templates, m_callbacks).render_to(os, tmpl, data);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::string load_file(const std::string& filename) {
|
||||
Parser parser(m_impl->parser_config, m_impl->lexer_config, m_impl->included_templates);
|
||||
return parser.load_file(m_impl->input_path + filename);
|
||||
}
|
||||
Parser parser(m_parser_config, m_lexer_config, m_included_templates);
|
||||
return parser.load_file(m_input_path + filename);
|
||||
}
|
||||
|
||||
json load_json(const std::string& filename) {
|
||||
std::ifstream file = open_file_or_throw(m_impl->input_path + filename);
|
||||
json j;
|
||||
file >> j;
|
||||
return j;
|
||||
}
|
||||
std::ifstream file = open_file_or_throw(m_input_path + filename);
|
||||
json j;
|
||||
file >> j;
|
||||
return j;
|
||||
}
|
||||
|
||||
void add_callback(const std::string& name, unsigned int numArgs, const CallbackFunction& callback) {
|
||||
m_impl->callbacks.add_callback(name, numArgs, callback);
|
||||
m_callbacks.add_callback(name, numArgs, callback);
|
||||
}
|
||||
|
||||
/** Includes a template with a given name into the environment.
|
||||
@@ -3446,8 +3641,18 @@ class Environment {
|
||||
* include "<name>" syntax.
|
||||
*/
|
||||
void include_template(const std::string& name, const Template& tmpl) {
|
||||
m_impl->included_templates[name] = tmpl;
|
||||
m_included_templates[name] = tmpl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_input_path;
|
||||
std::string m_output_path;
|
||||
|
||||
LexerConfig m_lexer_config;
|
||||
ParserConfig m_parser_config;
|
||||
|
||||
FunctionStorage m_callbacks;
|
||||
TemplateStorage m_included_templates;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -3467,7 +3672,7 @@ inline void render_to(std::ostream& os, nonstd::string_view input, const json& d
|
||||
|
||||
}
|
||||
|
||||
#endif // PANTOR_INJA_ENVIRONMENT_HPP
|
||||
#endif // INCLUDE_INJA_ENVIRONMENT_HPP_
|
||||
|
||||
// #include "string_view.hpp"
|
||||
|
||||
@@ -3479,4 +3684,4 @@ inline void render_to(std::ostream& os, nonstd::string_view input, const json& d
|
||||
|
||||
|
||||
|
||||
#endif // PANTOR_INJA_HPP
|
||||
#endif // INCLUDE_INJA_INJA_HPP_
|
||||
|
||||
@@ -2,3 +2,33 @@
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch/catch.hpp"
|
||||
#include "inja/inja.hpp"
|
||||
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
||||
TEST_CASE("copy-environment") {
|
||||
inja::Environment env;
|
||||
env.add_callback("double", 1, [](inja::Arguments& args) {
|
||||
int number = args.at(0)->get<int>();
|
||||
return 2 * number;
|
||||
});
|
||||
|
||||
inja::Template t1 = env.parse("{{ double(2) }}");
|
||||
env.include_template("tpl", t1);
|
||||
std::string test_tpl = "{% include \"tpl\" %}";
|
||||
|
||||
REQUIRE(env.render(test_tpl, json()) == "4");
|
||||
|
||||
inja::Environment copy(env);
|
||||
CHECK(copy.render(test_tpl, json()) == "4");
|
||||
|
||||
// overwrite template in source env
|
||||
inja::Template t2 = env.parse("{{ double(4) }}");
|
||||
env.include_template("tpl", t2);
|
||||
REQUIRE(env.render(test_tpl, json()) == "8");
|
||||
|
||||
// template is unchanged in copy
|
||||
CHECK(copy.render(test_tpl, json()) == "4");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user