diff options
author | snaury <snaury@yandex-team.com> | 2024-10-16 12:16:48 +0300 |
---|---|---|
committer | snaury <snaury@yandex-team.com> | 2024-10-16 12:32:13 +0300 |
commit | e0fb25470a47f0c243091ed28bf54a186f732f6a (patch) | |
tree | e85dfe628401f4f21749ab95b9d711242e3b49cd /contrib/libs/jinja2cpp/src/render_context.h | |
parent | b3b4a0b9681eb0981f9958a426c95a53f79169a7 (diff) | |
download | ydb-e0fb25470a47f0c243091ed28bf54a186f732f6a.tar.gz |
ydblib: add jinja2cpp
commit_hash:f3563041f6f6f7443e75fc99acd2c967d0debb04
Diffstat (limited to 'contrib/libs/jinja2cpp/src/render_context.h')
-rw-r--r-- | contrib/libs/jinja2cpp/src/render_context.h | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/contrib/libs/jinja2cpp/src/render_context.h b/contrib/libs/jinja2cpp/src/render_context.h new file mode 100644 index 0000000000..f6edcf444e --- /dev/null +++ b/contrib/libs/jinja2cpp/src/render_context.h @@ -0,0 +1,182 @@ +#ifndef JINJA2CPP_SRC_RENDER_CONTEXT_H +#define JINJA2CPP_SRC_RENDER_CONTEXT_H + +#include "internal_value.h" +#include <jinja2cpp/error_info.h> +#include <jinja2cpp/utils/i_comparable.h> + +#include <contrib/restricted/expected-lite/include/nonstd/expected.hpp> + +#include <list> +#include <deque> + +namespace jinja2 +{ +template<typename CharT> +class TemplateImpl; + +struct IRendererCallback : IComparable +{ + virtual ~IRendererCallback() {} + virtual TargetString GetAsTargetString(const InternalValue& val) = 0; + virtual OutStream GetStreamOnString(TargetString& str) = 0; + virtual std::variant<EmptyValue, + nonstd::expected<std::shared_ptr<TemplateImpl<char>>, ErrorInfo>, + nonstd::expected<std::shared_ptr<TemplateImpl<wchar_t>>, ErrorInfoW>> LoadTemplate(const std::string& fileName) const = 0; + virtual std::variant<EmptyValue, + nonstd::expected<std::shared_ptr<TemplateImpl<char>>, ErrorInfo>, + nonstd::expected<std::shared_ptr<TemplateImpl<wchar_t>>, ErrorInfoW>> LoadTemplate(const InternalValue& fileName) const = 0; + virtual void ThrowRuntimeError(ErrorCode code, ValuesList extraParams) = 0; +}; + +class RenderContext +{ +public: + RenderContext(const InternalValueMap& extValues, const InternalValueMap& globalValues, IRendererCallback* rendererCallback) + : m_rendererCallback(rendererCallback) + { + m_externalScope = &extValues; + m_globalScope = &globalValues; + EnterScope(); + (*m_currentScope)["self"] = CreateMapAdapter(InternalValueMap()); + } + + RenderContext(const RenderContext& other) + : m_rendererCallback(other.m_rendererCallback) + , m_externalScope(other.m_externalScope) + , m_globalScope(other.m_globalScope) + , m_boundScope(other.m_boundScope) + , m_scopes(other.m_scopes) + { + m_currentScope = &m_scopes.back(); + } + + InternalValueMap& EnterScope() + { + m_scopes.push_back(InternalValueMap()); + m_currentScope = &m_scopes.back(); + return *m_currentScope; + } + + void ExitScope() + { + m_scopes.pop_back(); + if (!m_scopes.empty()) + m_currentScope = &m_scopes.back(); + else + m_currentScope = nullptr; + } + + auto FindValue(const std::string& val, bool& found) const + { + auto finder = [&val, &found](auto& map) mutable + { + auto p = map.find(val); + if (p != map.end()) + found = true; + + return p; + }; + + if (m_boundScope) + { + auto valP = finder(*m_boundScope); + if (found) + return valP; + } + + for (auto p = m_scopes.rbegin(); p != m_scopes.rend(); ++ p) + { + auto valP = finder(*p); + if (found) + return valP; + } + + auto valP = finder(*m_externalScope); + if (found) + return valP; + + return finder(*m_globalScope); + } + + auto& GetCurrentScope() const + { + return *m_currentScope; + } + + auto& GetCurrentScope() + { + return *m_currentScope; + } + auto& GetGlobalScope() + { + return m_scopes.front(); + } + auto GetRendererCallback() + { + return m_rendererCallback; + } + RenderContext Clone(bool includeCurrentContext) const + { + if (!includeCurrentContext) + return RenderContext(m_emptyScope, *m_globalScope, m_rendererCallback); + + return RenderContext(*this); + } + + void BindScope(InternalValueMap* scope) + { + m_boundScope = scope; + } + + bool IsEqual(const RenderContext& other) const + { + if (!IsEqual(m_rendererCallback, other.m_rendererCallback)) + return false; + if (!IsEqual(this->m_currentScope, other.m_currentScope)) + return false; + if (!IsEqual(m_externalScope, other.m_externalScope)) + return false; + if (!IsEqual(m_globalScope, other.m_globalScope)) + return false; + if (!IsEqual(m_boundScope, other.m_boundScope)) + return false; + if (m_emptyScope != other.m_emptyScope) + return false; + if (m_scopes != other.m_scopes) + return false; + return true; + } + +private: + + bool IsEqual(const IRendererCallback* lhs, const IRendererCallback* rhs) const + { + if (lhs && rhs) + return lhs->IsEqual(*rhs); + if ((!lhs && rhs) || (lhs && !rhs)) + return false; + return true; + } + + bool IsEqual(const InternalValueMap* lhs, const InternalValueMap* rhs) const + { + if (lhs && rhs) + return *lhs == *rhs; + if ((!lhs && rhs) || (lhs && !rhs)) + return false; + return true; + } + +private: + IRendererCallback* m_rendererCallback{}; + InternalValueMap* m_currentScope{}; + const InternalValueMap* m_externalScope{}; + const InternalValueMap* m_globalScope{}; + const InternalValueMap* m_boundScope{}; + InternalValueMap m_emptyScope; + std::deque<InternalValueMap> m_scopes; +}; +} // namespace jinja2 + +#endif // JINJA2CPP_SRC_RENDER_CONTEXT_H |