#ifndef JINJA2CPP_SRC_HELPERS_H #define JINJA2CPP_SRC_HELPERS_H #include #include #include #include #include namespace jinja2 { struct MultiStringLiteral { const char* charValue; const wchar_t* wcharValue; constexpr MultiStringLiteral(const char* val, const wchar_t* wval) : charValue(val) , wcharValue(wval) { } template constexpr auto GetValue() const { #if __cplusplus < 202002L return GetValueStr(); #else constexpr auto memPtr = SelectMemberPtr::GetPtr(); return nonstd::basic_string_view(this->*memPtr); #endif } template constexpr auto GetValueStr() const { constexpr auto memPtr = SelectMemberPtr::GetPtr(); return std::basic_string(this->*memPtr); } template struct SelectMemberPtr; template struct SelectMemberPtr { static constexpr auto GetPtr() {return charMemPtr;} }; template struct SelectMemberPtr { static constexpr auto GetPtr() {return wcharMemPtr;} }; template friend std::basic_ostream& operator << (std::basic_ostream& os, const MultiStringLiteral& lit) { os << lit.GetValue(); return os; } }; #define UNIVERSAL_STR(Str) \ ::jinja2::MultiStringLiteral { Str, L##Str } //! CompileEscapes replaces escape characters by their meanings. /** * @param[in] s Characters sequence with zero or more escape characters. * @return Characters sequence copy where replaced all escape characters by * their meanings. */ template Sequence CompileEscapes(Sequence s) { auto itr1 = s.begin(); auto itr2 = s.begin(); const auto end = s.cend(); auto removalCount = 0; while (end != itr1) { if ('\\' == *itr1) { ++removalCount; if (end == ++itr1) break; if ('\\' != *itr1) { switch (*itr1) { case 'n': *itr1 = '\n'; break; case 'r': *itr1 = '\r'; break; case 't': *itr1 = '\t'; break; default: break; } continue; } } if (itr1 != itr2) *itr2 = *itr1; ++itr1; ++itr2; } s.resize(s.size() - removalCount); return s; } } // namespace jinja2 #endif // JINJA2CPP_SRC_HELPERS_H