Compare commits

..

2 Commits

Author SHA1 Message Date
Sipka Dániel
9b27c7db88 no wrapper 2020-02-12 20:58:52 +01:00
Sipka Dániel
c2ec0d9ce8 boost -> std 2020-02-12 20:53:14 +01:00
84 changed files with 1489 additions and 1033 deletions

93
.clang-format Normal file
View File

@ -0,0 +1,93 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
#BreakConstructorInitializers: BeforeComma
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 96
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: false
SpaceAfterTemplateKeyword: false
FixNamespaceComments: true
PointerAlignment: Left
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 200
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 5000
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 400
BreakBeforeInheritanceComma: true
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 4
UseTab: Never
...

View File

@ -6,12 +6,12 @@ option(WITH_BENCHMARK "enable building benchmark executable" OFF)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_BUILD_TYPE Debug)
set(mstch_VERSION 1.0.1)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -Wextra -O3")
endif()
add_subdirectory(src)

437
CMakeLists.txt.user Normal file
View File

@ -0,0 +1,437 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.6.0, 2020-02-12T19:36:25. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{6c3a783b-4a95-47a1-a553-14efac437a7d}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">2</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Unnamed</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Unnamed</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{85ec3516-307e-4a38-9ec9-10c74ad47576}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}</value>
<value type="QString">CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}</value>
<value type="QString">CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}</value>
<value type="QString">QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}</value>
<value type="QString">WITH_UNIT_TESTS:BOOL=ON</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/msd/work/build-mstch-Unnamed-Default</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=Debug</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/msd/work/build-mstch-Unnamed-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=Release</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/msd/work/build-mstch-Unnamed-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=RelWithDebInfo</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/msd/work/build-mstch-Unnamed-Release with Debug Information</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release with Debug Information</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=MinSizeRel</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/msd/work/build-mstch-Unnamed-Minimum Size Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Minimum Size Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Minimum Size Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">5</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguation.Title">headerize</value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory.default">/tmp/QtCreator-poSNJS/qtc-cmake-DajvkCJW/vendor/headerize/src</value>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">headerize</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.headerize</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguation.Title">mstch_test</value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory.default">/tmp/QtCreator-poSNJS/qtc-cmake-DajvkCJW/test</value>
<value type="int" key="PE.EnvironmentAspect.Base">-1</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">mstch_test</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.mstch_test</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

View File

@ -1,62 +1,60 @@
#pragma once
#include <vector>
#include <map>
#include <string>
#include <memory>
#include <functional>
#include <boost/variant.hpp>
#include <map>
#include <memory>
#include <string>
#include <variant>
#include <vector>
namespace mstch {
struct config {
static std::function<std::string(const std::string&)> escape;
static std::function<std::string(const std::string&)> escape;
};
namespace internal {
template<class N>
class object_t {
public:
const N& at(const std::string& name) const {
cache[name] = (methods.at(name))();
return cache[name];
}
public:
const N& at(const std::string& name) const {
cache[name] = (methods.at(name))();
return cache[name];
}
bool has(const std::string name) const {
return methods.count(name) != 0;
}
bool has(const std::string name) const { return methods.count(name) != 0; }
protected:
template<class S>
void register_methods(S* s, std::map<std::string,N(S::*)()> methods) {
for(auto& item: methods)
this->methods.insert({item.first, std::bind(item.second, s)});
}
protected:
template<class S>
void register_methods(S* s, std::map<std::string, N (S::*)()> methods) {
for (auto& item : methods)
this->methods.insert({item.first, std::bind(item.second, s)});
}
private:
std::map<std::string, std::function<N()>> methods;
mutable std::map<std::string, N> cache;
private:
std::map<std::string, std::function<N()>> methods;
mutable std::map<std::string, N> cache;
};
template<class T, class N>
class is_fun {
private:
using not_fun = char;
using fun_without_args = char[2];
using fun_with_args = char[3];
template <typename U, U> struct really_has;
template <typename C> static fun_without_args& test(
really_has<N(C::*)() const, &C::operator()>*);
template <typename C> static fun_with_args& test(
really_has<N(C::*)(const std::string&) const,
&C::operator()>*);
template <typename> static not_fun& test(...);
private:
using not_fun = char;
using fun_without_args = char[2];
using fun_with_args = char[3];
template<typename U, U>
struct really_has;
template<typename C>
static fun_without_args& test(really_has<N (C::*)() const, &C::operator()>*);
template<typename C>
static fun_with_args& test(really_has<N (C::*)(const std::string&) const, &C::operator()>*);
template<typename>
static not_fun& test(...);
public:
static bool const no_args = sizeof(test<T>(0)) == sizeof(fun_without_args);
static bool const has_args = sizeof(test<T>(0)) == sizeof(fun_with_args);
public:
static bool const no_args = sizeof(test<T>(0)) == sizeof(fun_without_args);
static bool const has_args = sizeof(test<T>(0)) == sizeof(fun_with_args);
};
template<class N>
@ -64,50 +62,68 @@ using node_renderer = std::function<std::string(const N& n)>;
template<class N>
class lambda_t {
public:
template<class F>
lambda_t(F f, typename std::enable_if<is_fun<F, N>::no_args>::type* = 0):
fun([f](node_renderer<N> renderer, const std::string&) {
return renderer(f());
})
{
}
public:
template<class F>
lambda_t(F f, typename std::enable_if<is_fun<F, N>::no_args>::type* = 0)
: fun([f](node_renderer<N> renderer, const std::string&) { return renderer(f()); })
{}
template<class F>
lambda_t(F f, typename std::enable_if<is_fun<F, N>::has_args>::type* = 0):
fun([f](node_renderer<N> renderer, const std::string& text) {
return renderer(f(text));
})
{
}
template<class F>
lambda_t(F f, typename std::enable_if<is_fun<F, N>::has_args>::type* = 0)
: fun([f](node_renderer<N> renderer, const std::string& text) {
return renderer(f(text));
})
{}
std::string operator()(node_renderer<N> renderer,
const std::string& text = "") const
{
return fun(renderer, text);
}
std::string operator()(node_renderer<N> renderer, const std::string& text = "") const {
return fun(renderer, text);
}
private:
std::function<std::string(node_renderer<N> renderer, const std::string&)> fun;
private:
std::function<std::string(node_renderer<N> renderer, const std::string&)> fun;
};
}
} // namespace internal
struct object_wrapper;
struct map_wrapper;
struct array_wrapper;
struct lambda_wrapper;
using node = std::variant<std::nullptr_t,
std::string,
int,
double,
bool,
lambda_wrapper,
object_wrapper,
map_wrapper,
array_wrapper>;
using node = boost::make_recursive_variant<
std::nullptr_t, std::string, int, double, bool,
internal::lambda_t<boost::recursive_variant_>,
std::shared_ptr<internal::object_t<boost::recursive_variant_>>,
std::map<const std::string, boost::recursive_variant_>,
std::vector<boost::recursive_variant_>>::type;
using object = internal::object_t<node>;
using lambda = internal::lambda_t<node>;
using map = std::map<const std::string, node>;
using array = std::vector<node>;
using map = std::map<const std::string, node>;
using array = std::vector<node>;
std::string render(
const std::string& tmplt,
const node& root,
const std::map<std::string,std::string>& partials =
std::map<std::string,std::string>());
struct array_wrapper {
array values;
};
}
struct map_wrapper {
map values;
};
struct object_wrapper {
std::shared_ptr<object> values;
};
struct lambda_wrapper {
lambda values;
};
std::string render(const std::string& tmplt,
const node& root,
const std::map<std::string, std::string>& partials =
std::map<std::string, std::string>());
} // namespace mstch

View File

@ -1,11 +1,8 @@
find_package(Boost 1.54 REQUIRED)
set(mstch_INCLUDE_DIR
${PROJECT_SOURCE_DIR}/include CACHE STRING "mstch include directory")
include_directories(
${mstch_INCLUDE_DIR}
${Boost_INCLUDE_DIR})
${mstch_INCLUDE_DIR})
set(SRC
state/in_section.cpp

View File

@ -7,14 +7,13 @@ using namespace mstch;
std::function<std::string(const std::string&)> mstch::config::escape;
std::string mstch::render(
const std::string& tmplt,
const node& root,
const std::map<std::string,std::string>& partials)
std::string mstch::render(const std::string& tmplt,
const node& root,
const std::map<std::string, std::string>& partials)
{
std::map<std::string, template_type> partial_templates;
for (auto& partial: partials)
partial_templates.insert({partial.first, {partial.second}});
std::map<std::string, template_type> partial_templates;
for (auto& partial : partials)
partial_templates.insert({partial.first, {partial.second}});
return render_context(root, partial_templates).render(tmplt);
return render_context(root, partial_templates).render(tmplt);
}

View File

@ -6,67 +6,62 @@ using namespace mstch;
const mstch::node render_context::null_node;
render_context::push::push(render_context& context, const mstch::node& node):
m_context(context)
render_context::push::push(render_context& context, const mstch::node& node)
: m_context(context)
{
context.m_nodes.emplace_front(node);
context.m_node_ptrs.emplace_front(&node);
context.m_state.push(std::unique_ptr<render_state>(new outside_section));
context.m_nodes.emplace_front(node);
context.m_node_ptrs.emplace_front(&node);
context.m_state.push(std::unique_ptr<render_state>(new outside_section));
}
render_context::push::~push() {
m_context.m_nodes.pop_front();
m_context.m_node_ptrs.pop_front();
m_context.m_state.pop();
m_context.m_nodes.pop_front();
m_context.m_node_ptrs.pop_front();
m_context.m_state.pop();
}
std::string render_context::push::render(const template_type& templt) {
return m_context.render(templt);
return m_context.render(templt);
}
render_context::render_context(
const mstch::node& node,
const std::map<std::string, template_type>& partials):
m_partials(partials), m_nodes(1, node), m_node_ptrs(1, &node)
render_context::render_context(const mstch::node& node,
const std::map<std::string, template_type>& partials)
: m_partials(partials), m_nodes(1, node), m_node_ptrs(1, &node)
{
m_state.push(std::unique_ptr<render_state>(new outside_section));
m_state.push(std::unique_ptr<render_state>(new outside_section));
}
const mstch::node& render_context::find_node(
const std::string& token,
std::list<node const*> current_nodes)
const mstch::node& render_context::find_node(const std::string& token,
std::list<node const*> current_nodes)
{
if (token != "." && token.find('.') != std::string::npos)
return find_node(token.substr(token.rfind('.') + 1),
{&find_node(token.substr(0, token.rfind('.')), current_nodes)});
else
for (auto& node: current_nodes)
if (visit(has_token(token), *node))
return visit(get_token(token, *node), *node);
return null_node;
if (token != "." && token.find('.') != std::string::npos)
return find_node(token.substr(token.rfind('.') + 1),
{&find_node(token.substr(0, token.rfind('.')), current_nodes)});
else
for (auto& node : current_nodes)
if (visit(has_token(token), *node))
return visit(get_token(token, *node), *node);
return null_node;
}
const mstch::node& render_context::get_node(const std::string& token) {
return find_node(token, m_node_ptrs);
}
std::string render_context::render(
const template_type& templt, const std::string& prefix)
{
std::string output;
bool prev_eol = true;
for (auto& token: templt) {
if (prev_eol && prefix.length() != 0)
output += m_state.top()->render(*this, {prefix});
output += m_state.top()->render(*this, token);
prev_eol = token.eol();
}
return output;
std::string render_context::render(const template_type& templt, const std::string& prefix) {
std::string output;
bool prev_eol = true;
for (auto& token : templt) {
if (prev_eol && prefix.length() != 0)
output += m_state.top()->render(*this, {prefix});
output += m_state.top()->render(*this, token);
prev_eol = token.eol();
}
return output;
}
std::string render_context::render_partial(
const std::string& partial_name, const std::string& prefix)
std::string render_context::render_partial(const std::string& partial_name,
const std::string& prefix)
{
return m_partials.count(partial_name) ?
render(m_partials.at(partial_name), prefix) : "";
return m_partials.count(partial_name) ? render(m_partials.at(partial_name), prefix) : "";
}

View File

@ -3,8 +3,8 @@
#include <deque>
#include <list>
#include <sstream>
#include <string>
#include <stack>
#include <string>
#include "mstch/mstch.hpp"
#include "state/render_state.hpp"
@ -13,39 +13,35 @@
namespace mstch {
class render_context {
public:
class push {
public:
push(render_context& context, const mstch::node& node = {});
~push();
std::string render(const template_type& templt);
private:
render_context& m_context;
};
public:
class push {
public:
push(render_context& context, const mstch::node& node = {});
~push();
std::string render(const template_type& templt);
render_context(
const mstch::node& node,
const std::map<std::string, template_type>& partials);
const mstch::node& get_node(const std::string& token);
std::string render(
const template_type& templt, const std::string& prefix = "");
std::string render_partial(
const std::string& partial_name, const std::string& prefix);
template<class T, class... Args>
void set_state(Args&& ... args) {
m_state.top() = std::unique_ptr<render_state>(
new T(std::forward<Args>(args)...));
}
private:
render_context& m_context;
};
private:
static const mstch::node null_node;
const mstch::node& find_node(
const std::string& token,
std::list<node const*> current_nodes);
std::map<std::string, template_type> m_partials;
std::deque<mstch::node> m_nodes;
std::list<const mstch::node*> m_node_ptrs;
std::stack<std::unique_ptr<render_state>> m_state;
render_context(const mstch::node& node,
const std::map<std::string, template_type>& partials);
const mstch::node& get_node(const std::string& token);
std::string render(const template_type& templt, const std::string& prefix = "");
std::string render_partial(const std::string& partial_name, const std::string& prefix);
template<class T, class... Args>
void set_state(Args&&... args) {
m_state.top() = std::unique_ptr<render_state>(new T(std::forward<Args>(args)...));
}
private:
static const mstch::node null_node;
const mstch::node& find_node(const std::string& token,
std::list<node const*> current_nodes);
std::map<std::string, template_type> m_partials;
std::deque<mstch::node> m_nodes;
std::list<const mstch::node*> m_node_ptrs;
std::stack<std::unique_ptr<render_state>> m_state;
};
}
} // namespace mstch

View File

@ -5,30 +5,30 @@
using namespace mstch;
in_section::in_section(type type, const token& start_token):
m_type(type), m_start_token(start_token), m_skipped_openings(0)
in_section::in_section(type type, const token& start_token)
: m_type(type), m_start_token(start_token), m_skipped_openings(0)
{
}
std::string in_section::render(render_context& ctx, const token& token) {
if (token.token_type() == token::type::section_close)
if (token.name() == m_start_token.name() && m_skipped_openings == 0) {
auto& node = ctx.get_node(m_start_token.name());
std::string out;
if (token.token_type() == token::type::section_close)
if (token.name() == m_start_token.name() && m_skipped_openings == 0) {
auto& node = ctx.get_node(m_start_token.name());
std::string out;
if (m_type == type::normal && !visit(is_node_empty(), node))
out = visit(render_section(ctx, m_section, m_start_token.delims()), node);
else if (m_type == type::inverted && visit(is_node_empty(), node))
out = render_context::push(ctx).render(m_section);
if (m_type == type::normal && !visit(is_node_empty(), node))
out = visit(render_section(ctx, m_section, m_start_token.delims()), node);
else if (m_type == type::inverted && visit(is_node_empty(), node))
out = render_context::push(ctx).render(m_section);
ctx.set_state<outside_section>();
return out;
} else
m_skipped_openings--;
else if (token.token_type() == token::type::inverted_section_open ||
token.token_type() == token::type::section_open)
m_skipped_openings++;
ctx.set_state<outside_section>();
return out;
} else
m_skipped_openings--;
else if (token.token_type() == token::type::inverted_section_open ||
token.token_type() == token::type::section_open)
m_skipped_openings++;
m_section << token;
return "";
m_section << token;
return "";
}

View File

@ -8,17 +8,17 @@
namespace mstch {
class in_section: public render_state {
public:
enum class type { inverted, normal };
in_section(type type, const token& start_token);
std::string render(render_context& context, const token& token) override;
class in_section : public render_state {
public:
enum class type { inverted, normal };
in_section(type type, const token& start_token);
std::string render(render_context& context, const token& token) override;
private:
const type m_type;
const token& m_start_token;
template_type m_section;
int m_skipped_openings;
private:
const type m_type;
const token& m_start_token;
template_type m_section;
int m_skipped_openings;
};
}
} // namespace mstch

View File

@ -1,32 +1,30 @@
#include "outside_section.hpp"
#include "visitor/render_node.hpp"
#include "in_section.hpp"
#include "render_context.hpp"
#include "visitor/render_node.hpp"
using namespace mstch;
std::string outside_section::render(
render_context& ctx, const token& token)
{
using flag = render_node::flag;
switch (token.token_type()) {
std::string outside_section::render(render_context& ctx, const token& token) {
using flag = render_node::flag;
switch (token.token_type()) {
case token::type::section_open:
ctx.set_state<in_section>(in_section::type::normal, token);
break;
ctx.set_state<in_section>(in_section::type::normal, token);
break;
case token::type::inverted_section_open:
ctx.set_state<in_section>(in_section::type::inverted, token);
break;
ctx.set_state<in_section>(in_section::type::inverted, token);
break;
case token::type::variable:
return visit(render_node(ctx, flag::escape_html), ctx.get_node(token.name()));
return visit(render_node(ctx, flag::escape_html), ctx.get_node(token.name()));
case token::type::unescaped_variable:
return visit(render_node(ctx, flag::none), ctx.get_node(token.name()));
return visit(render_node(ctx, flag::none), ctx.get_node(token.name()));
case token::type::text:
return token.raw();
return token.raw();
case token::type::partial:
return ctx.render_partial(token.name(), token.partial_prefix());
return ctx.render_partial(token.name(), token.partial_prefix());
default:
break;
}
return "";
break;
}
return "";
}

View File

@ -4,9 +4,9 @@
namespace mstch {
class outside_section: public render_state {
public:
std::string render(render_context& context, const token& token) override;
class outside_section : public render_state {
public:
std::string render(render_context& context, const token& token) override;
};
}
} // namespace mstch

View File

@ -9,9 +9,9 @@ namespace mstch {
class render_context;
class render_state {
public:
virtual ~render_state() {}
virtual std::string render(render_context& context, const token& token) = 0;
public:
virtual ~render_state() {}
virtual std::string render(render_context& context, const token& token) = 0;
};
}
} // namespace mstch

View File

@ -2,103 +2,98 @@
using namespace mstch;
template_type::template_type(const std::string& str, const delim_type& delims):
m_open(delims.first), m_close(delims.second)
template_type::template_type(const std::string& str, const delim_type& delims)
: m_open(delims.first), m_close(delims.second)
{
tokenize(str);
strip_whitespace();
tokenize(str);
strip_whitespace();
}
template_type::template_type(const std::string& str):
m_open("{{"), m_close("}}")
{
tokenize(str);
strip_whitespace();
template_type::template_type(const std::string& str) : m_open("{{"), m_close("}}") {
tokenize(str);
strip_whitespace();
}
void template_type::process_text(citer begin, citer end) {
if (begin == end)
return;
auto start = begin;
for (auto it = begin; it != end; ++it)
if (*it == '\n' || it == end - 1) {
m_tokens.push_back({{start, it + 1}});
start = it + 1;
}
if (begin == end)
return;
auto start = begin;
for (auto it = begin; it != end; ++it)
if (*it == '\n' || it == end - 1) {
m_tokens.push_back({{start, it + 1}});
start = it + 1;
}
}
void template_type::tokenize(const std::string& tmp) {
citer beg = tmp.begin();
auto npos = std::string::npos;
citer beg = tmp.begin();
auto npos = std::string::npos;
for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
auto open_pos = tmp.find(m_open, cur_pos);
auto close_pos = tmp.find(
m_close, open_pos == npos ? open_pos : open_pos + 1);
for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
auto open_pos = tmp.find(m_open, cur_pos);
auto close_pos = tmp.find(m_close, open_pos == npos ? open_pos : open_pos + 1);
if (close_pos != npos && open_pos != npos) {
if (*(beg + open_pos + m_open.size()) == '{' &&
*(beg + close_pos + m_close.size()) == '}')
++close_pos;
if (close_pos != npos && open_pos != npos) {
if (*(beg + open_pos + m_open.size()) == '{' &&
*(beg + close_pos + m_close.size()) == '}')
++close_pos;
process_text(beg + cur_pos, beg + open_pos);
cur_pos = close_pos + m_close.size();
m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()},
m_open.size(), m_close.size()});
process_text(beg + cur_pos, beg + open_pos);
cur_pos = close_pos + m_close.size();
m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()},
m_open.size(),
m_close.size()});
if (cur_pos == tmp.size()) {
m_tokens.push_back({{""}});
m_tokens.back().eol(true);
}
if (cur_pos == tmp.size()) {
m_tokens.push_back({{""}});
m_tokens.back().eol(true);
}
if (*(beg + open_pos + m_open.size()) == '=' &&
*(beg + close_pos - 1) == '=')
{
auto tok_beg = beg + open_pos + m_open.size() + 1;
auto tok_end = beg + close_pos - 1;
auto front_skip = first_not_ws(tok_beg, tok_end);
auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
}
} else {
process_text(beg + cur_pos, tmp.end());
cur_pos = close_pos;
if (*(beg + open_pos + m_open.size()) == '=' && *(beg + close_pos - 1) == '=') {
auto tok_beg = beg + open_pos + m_open.size() + 1;
auto tok_end = beg + close_pos - 1;
auto front_skip = first_not_ws(tok_beg, tok_end);
auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
}
} else {
process_text(beg + cur_pos, tmp.end());
cur_pos = close_pos;
}
}
}
}
void template_type::strip_whitespace() {
auto line_begin = m_tokens.begin();
bool has_tag = false, non_space = false;
auto line_begin = m_tokens.begin();
bool has_tag = false, non_space = false;
for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) {
auto type = (*it).token_type();
if (type != token::type::text && type != token::type::variable &&
type != token::type::unescaped_variable)
has_tag = true;
else if (!(*it).ws_only())
non_space = true;
for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) {
auto type = (*it).token_type();
if (type != token::type::text && type != token::type::variable &&
type != token::type::unescaped_variable)
has_tag = true;
else if (!(*it).ws_only())
non_space = true;
if ((*it).eol()) {
if (has_tag && !non_space) {
store_prefixes(line_begin);
if ((*it).eol()) {
if (has_tag && !non_space) {
store_prefixes(line_begin);
auto c = line_begin;
for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c)
if ((end = (*c).eol()))
it = c - 1;
}
auto c = line_begin;
for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c)
if ((end = (*c).eol()))
it = c - 1;
}
non_space = has_tag = false;
line_begin = it + 1;
non_space = has_tag = false;
line_begin = it + 1;
}
}
}
}
void template_type::store_prefixes(std::vector<token>::iterator beg) {
for (auto cur = beg; !(*cur).eol(); ++cur)
if ((*cur).token_type() == token::type::partial &&
cur != beg && (*(cur - 1)).ws_only())
(*cur).partial_prefix((*(cur - 1)).raw());
for (auto cur = beg; !(*cur).eol(); ++cur)
if ((*cur).token_type() == token::type::partial && cur != beg && (*(cur - 1)).ws_only())
(*cur).partial_prefix((*(cur - 1)).raw());
}

View File

@ -9,22 +9,22 @@
namespace mstch {
class template_type {
public:
template_type() = default;
template_type(const std::string& str);
template_type(const std::string& str, const delim_type& delims);
std::vector<token>::const_iterator begin() const { return m_tokens.begin(); }
std::vector<token>::const_iterator end() const { return m_tokens.end(); }
void operator<<(const token& token) { m_tokens.push_back(token); }
public:
template_type() = default;
template_type(const std::string& str);
template_type(const std::string& str, const delim_type& delims);
std::vector<token>::const_iterator begin() const { return m_tokens.begin(); }
std::vector<token>::const_iterator end() const { return m_tokens.end(); }
void operator<<(const token& token) { m_tokens.push_back(token); }
private:
std::vector<token> m_tokens;
std::string m_open;
std::string m_close;
void strip_whitespace();
void process_text(citer beg, citer end);
void tokenize(const std::string& tmp);
void store_prefixes(std::vector<token>::iterator beg);
private:
std::vector<token> m_tokens;
std::string m_open;
std::string m_close;
void strip_whitespace();
void process_text(citer beg, citer end);
void tokenize(const std::string& tmp);
void store_prefixes(std::vector<token>::iterator beg);
};
}
} // namespace mstch

View File

@ -4,39 +4,45 @@
using namespace mstch;
token::type token::token_info(char c) {
switch (c) {
case '>': return type::partial;
case '^': return type::inverted_section_open;
case '/': return type::section_close;
case '&': return type::unescaped_variable;
case '#': return type::section_open;
case '!': return type::comment;
default: return type::variable;
}
switch (c) {
case '>':
return type::partial;
case '^':
return type::inverted_section_open;
case '/':
return type::section_close;
case '&':
return type::unescaped_variable;
case '#':
return type::section_open;
case '!':
return type::comment;
default:
return type::variable;
}
}
token::token(const std::string& str, std::size_t left, std::size_t right):
m_raw(str), m_eol(false), m_ws_only(false)
token::token(const std::string& str, std::size_t left, std::size_t right)
: m_raw(str), m_eol(false), m_ws_only(false)
{
if (left != 0 && right != 0) {
if (str[left] == '=' && str[str.size() - right - 1] == '=') {
m_type = type::delimiter_change;
} else if (str[left] == '{' && str[str.size() - right - 1] == '}') {
m_type = type::unescaped_variable;
m_name = {first_not_ws(str.begin() + left + 1, str.end() - right),
first_not_ws(str.rbegin() + 1 + right, str.rend() - left) + 1};
if (left != 0 && right != 0) {
if (str[left] == '=' && str[str.size() - right - 1] == '=') {
m_type = type::delimiter_change;
} else if (str[left] == '{' && str[str.size() - right - 1] == '}') {
m_type = type::unescaped_variable;
m_name = {first_not_ws(str.begin() + left + 1, str.end() - right),
first_not_ws(str.rbegin() + 1 + right, str.rend() - left) + 1};
} else {
auto c = first_not_ws(str.begin() + left, str.end() - right);
m_type = token_info(*c);
if (m_type != type::variable)
c = first_not_ws(c + 1, str.end() - right);
m_name = {c, first_not_ws(str.rbegin() + right, str.rend() - left) + 1};
m_delims = {{str.begin(), str.begin() + left}, {str.end() - right, str.end()}};
}
} else {
auto c = first_not_ws(str.begin() + left, str.end() - right);
m_type = token_info(*c);
if (m_type != type::variable)
c = first_not_ws(c + 1, str.end() - right);
m_name = {c, first_not_ws(str.rbegin() + right, str.rend() - left) + 1};
m_delims = {{str.begin(), str.begin() + left},
{str.end() - right, str.end()}};
m_type = type::text;
m_eol = (str.size() > 0 && str[str.size() - 1] == '\n');
m_ws_only = (str.find_first_not_of(" \r\n\t") == std::string::npos);
}
} else {
m_type = type::text;
m_eol = (str.size() > 0 && str[str.size() - 1] == '\n');
m_ws_only = (str.find_first_not_of(" \r\n\t") == std::string::npos);
}
}

View File

@ -7,33 +7,40 @@ namespace mstch {
using delim_type = std::pair<std::string, std::string>;
class token {
public:
enum class type {
text, variable, section_open, section_close, inverted_section_open,
unescaped_variable, comment, partial, delimiter_change
};
token(const std::string& str, std::size_t left = 0, std::size_t right = 0);
type token_type() const { return m_type; };
const std::string& raw() const { return m_raw; };
const std::string& name() const { return m_name; };
const std::string& partial_prefix() const { return m_partial_prefix; };
const delim_type& delims() const { return m_delims; };
void partial_prefix(const std::string& p_partial_prefix) {
m_partial_prefix = p_partial_prefix;
};
bool eol() const { return m_eol; }
void eol(bool eol) { m_eol = eol; }
bool ws_only() const { return m_ws_only; }
public:
enum class type {
text,
variable,
section_open,
section_close,
inverted_section_open,
unescaped_variable,
comment,
partial,
delimiter_change
};
token(const std::string& str, std::size_t left = 0, std::size_t right = 0);
type token_type() const { return m_type; };
const std::string& raw() const { return m_raw; };
const std::string& name() const { return m_name; };
const std::string& partial_prefix() const { return m_partial_prefix; };
const delim_type& delims() const { return m_delims; };
void partial_prefix(const std::string& p_partial_prefix) {
m_partial_prefix = p_partial_prefix;
};
bool eol() const { return m_eol; }
void eol(bool eol) { m_eol = eol; }
bool ws_only() const { return m_ws_only; }
private:
type m_type;
std::string m_name;
std::string m_raw;
std::string m_partial_prefix;
delim_type m_delims;
bool m_eol;
bool m_ws_only;
type token_info(char c);
private:
type m_type;
std::string m_name;
std::string m_raw;
std::string m_partial_prefix;
delim_type m_delims;
bool m_eol;
bool m_ws_only;
type token_info(char c);
};
}
} // namespace mstch

View File

@ -2,43 +2,58 @@
#include "mstch/mstch.hpp"
mstch::citer mstch::first_not_ws(mstch::citer begin, mstch::citer end) {
for (auto it = begin; it != end; ++it)
if (*it != ' ') return it;
return end;
for (auto it = begin; it != end; ++it)
if (*it != ' ')
return it;
return end;
}
mstch::citer mstch::first_not_ws(mstch::criter begin, mstch::criter end) {
for (auto rit = begin; rit != end; ++rit)
if (*rit != ' ') return --(rit.base());
return --(end.base());
for (auto rit = begin; rit != end; ++rit)
if (*rit != ' ')
return --(rit.base());
return --(end.base());
}
mstch::criter mstch::reverse(mstch::citer it) {
return std::reverse_iterator<mstch::citer>(it);
return std::reverse_iterator<mstch::citer>(it);
}
std::string mstch::html_escape(const std::string& str) {
if (mstch::config::escape)
return mstch::config::escape(str);
std::string out;
citer start = str.begin();
if (mstch::config::escape)
return mstch::config::escape(str);
auto add_escape = [&out, &start](const std::string& escaped, citer& it) {
out += std::string{start, it} + escaped;
start = it + 1;
};
std::string out;
citer start = str.begin();
for (auto it = str.begin(); it != str.end(); ++it)
switch (*it) {
case '&': add_escape("&amp;", it); break;
case '\'': add_escape("&#39;", it); break;
case '"': add_escape("&quot;", it); break;
case '<': add_escape("&lt;", it); break;
case '>': add_escape("&gt;", it); break;
case '/': add_escape("&#x2F;", it); break;
default: break;
}
auto add_escape = [&out, &start](const std::string& escaped, citer& it) {
out += std::string{start, it} + escaped;
start = it + 1;
};
return out + std::string{start, str.end()};
for (auto it = str.begin(); it != str.end(); ++it)
switch (*it) {
case '&':
add_escape("&amp;", it);
break;
case '\'':
add_escape("&#39;", it);
break;
case '"':
add_escape("&quot;", it);
break;
case '<':
add_escape("&lt;", it);
break;
case '>':
add_escape("&gt;", it);
break;
case '/':
add_escape("&#x2F;", it);
break;
default:
break;
}
return out + std::string{start, str.end()};
}

View File

@ -1,11 +1,11 @@
#pragma once
#include <string>
#include <boost/variant/apply_visitor.hpp>
#include <variant>
namespace mstch {
using citer = std::string::const_iterator;
using citer = std::string::const_iterator;
using criter = std::string::const_reverse_iterator;
citer first_not_ws(citer begin, citer end);
@ -14,10 +14,8 @@ std::string html_escape(const std::string& str);
criter reverse(citer it);
template<class... Args>
auto visit(Args&&... args) -> decltype(boost::apply_visitor(
std::forward<Args>(args)...))
{
return boost::apply_visitor(std::forward<Args>(args)...);
auto visit(Args&&... args) -> decltype(std::visit(std::forward<Args>(args)...)) {
return std::visit(std::forward<Args>(args)...);
}
}
} // namespace mstch

View File

@ -1,35 +1,32 @@
#pragma once
#include <boost/variant/static_visitor.hpp>
#include "mstch/mstch.hpp"
#include "has_token.hpp"
#include "mstch/mstch.hpp"
namespace mstch {
class get_token: public boost::static_visitor<const mstch::node&> {
public:
get_token(const std::string& token, const mstch::node& node):
m_token(token), m_node(node)
{
}
class get_token {
public:
get_token(const std::string& token, const mstch::node& node)
: m_token(token), m_node(node)
{}
template<class T>
const mstch::node& operator()(const T&) const {
return m_node;
}
template<class T>
const mstch::node& operator()(const T&) const {
return m_node;
}
const mstch::node& operator()(const map& map) const {
return map.at(m_token);
}
const mstch::node& operator()(const map_wrapper& map) const {
return map.values.at(m_token);
}
const mstch::node& operator()(const std::shared_ptr<object>& object) const {
return object->at(m_token);
}
const mstch::node& operator()(const object_wrapper& object) const {
return object.values->at(m_token);
}
private:
const std::string& m_token;
const mstch::node& m_node;
private:
const std::string& m_token;
const mstch::node& m_node;
};
}
} // namespace mstch

View File

@ -1,31 +1,24 @@
#pragma once
#include <boost/variant/static_visitor.hpp>
#include "mstch/mstch.hpp"
namespace mstch {
class has_token: public boost::static_visitor<bool> {
public:
has_token(const std::string& token): m_token(token) {
}
class has_token {
public:
has_token(const std::string& token) : m_token(token) {}
template<class T>
bool operator()(const T&) const {
return m_token == ".";
}
template<class T>
bool operator()(const T&) const {
return m_token == ".";
}
bool operator()(const map& map) const {
return map.count(m_token) == 1;
}
bool operator()(const map_wrapper& map) const { return map.values.count(m_token) == 1; }
bool operator()(const std::shared_ptr<object>& object) const {
return object->has(m_token);
}
bool operator()(const object_wrapper& object) const { return object.values->has(m_token); }
private:
const std::string& m_token;
private:
const std::string& m_token;
};
}
} // namespace mstch

View File

@ -1,41 +1,27 @@
#pragma once
#include <boost/variant/static_visitor.hpp>
#include "mstch/mstch.hpp"
namespace mstch {
class is_node_empty: public boost::static_visitor<bool> {
public:
template<class T>
bool operator()(const T&) const {
return false;
}
class is_node_empty {
public:
template<class T>
bool operator()(const T&) const {
return false;
}
bool operator()(const std::nullptr_t&) const {
return true;
}
bool operator()(const std::nullptr_t&) const { return true; }
bool operator()(const int& value) const {
return value == 0;
}
bool operator()(const int& value) const { return value == 0; }
bool operator()(const double& value) const {
return value == 0;
}
bool operator()(const double& value) const { return value == 0; }
bool operator()(const bool& value) const {
return !value;
}
bool operator()(const bool& value) const { return !value; }
bool operator()(const std::string& value) const {
return value == "";
}
bool operator()(const std::string& value) const { return value == ""; }
bool operator()(const array& array) const {
return array.size() == 0;
}
bool operator()(const array_wrapper& array) const { return array.values.size() == 0; }
};
}
} // namespace mstch

View File

@ -1,56 +1,48 @@
#pragma once
#include <sstream>
#include <boost/variant/static_visitor.hpp>
#include "render_context.hpp"
#include "mstch/mstch.hpp"
#include "render_context.hpp"
#include "utils.hpp"
namespace mstch {
class render_node: public boost::static_visitor<std::string> {
public:
enum class flag { none, escape_html };
render_node(render_context& ctx, flag p_flag = flag::none):
m_ctx(ctx), m_flag(p_flag)
{
}
class render_node {
public:
enum class flag { none, escape_html };
render_node(render_context& ctx, flag p_flag = flag::none) : m_ctx(ctx), m_flag(p_flag) {}
template<class T>
std::string operator()(const T&) const {
return "";
}
template<class T>
std::string operator()(const T&) const {
return "";
}
std::string operator()(const int& value) const {
return std::to_string(value);
}
std::string operator()(const int& value) const { return std::to_string(value); }
std::string operator()(const double& value) const {
std::stringstream ss;
ss << value;
return ss.str();
}
std::string operator()(const double& value) const {
std::stringstream ss;
ss << value;
return ss.str();
}
std::string operator()(const bool& value) const {
return value ? "true" : "false";
}
std::string operator()(const bool& value) const { return value ? "true" : "false"; }
std::string operator()(const lambda& value) const {
template_type interpreted{value([this](const mstch::node& n) {
return visit(render_node(m_ctx), n);
})};
auto rendered = render_context::push(m_ctx).render(interpreted);
return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered;
}
std::string operator()(const lambda_wrapper& value) const {
template_type interpreted{value.values(
[this](const mstch::node& n) { return visit(render_node(m_ctx), n); })};
std::string operator()(const std::string& value) const {
return (m_flag == flag::escape_html) ? html_escape(value) : value;
}
auto rendered = render_context::push(m_ctx).render(interpreted);
return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered;
}
private:
render_context& m_ctx;
flag m_flag;
std::string operator()(const std::string& value) const {
return (m_flag == flag::escape_html) ? html_escape(value) : value;
}
private:
render_context& m_ctx;
flag m_flag;
};
}
} // namespace mstch

View File

@ -1,57 +1,57 @@
#pragma once
#include <boost/variant/static_visitor.hpp>
#include "render_context.hpp"
#include "mstch/mstch.hpp"
#include "utils.hpp"
#include "render_context.hpp"
#include "render_node.hpp"
#include "utils.hpp"
namespace mstch {
class render_section: public boost::static_visitor<std::string> {
public:
enum class flag { none, keep_array };
render_section(
render_context& ctx,
const template_type& section,
const delim_type& delims,
flag p_flag = flag::none):
m_ctx(ctx), m_section(section), m_delims(delims), m_flag(p_flag)
{
}
class render_section {
public:
enum class flag { none, keep_array };
render_section(render_context& ctx,
const template_type& section,
const delim_type& delims,
flag p_flag = flag::none)
: m_ctx(ctx), m_section(section), m_delims(delims), m_flag(p_flag)
{}
template<class T>
std::string operator()(const T& t) const {
return render_context::push(m_ctx, t).render(m_section);
}
template<class T>
std::string operator()(const T& t) const {
return render_context::push(m_ctx, t).render(m_section);
}
std::string operator()(const lambda& fun) const {
std::string section_str;
for (auto& token: m_section)
section_str += token.raw();
template_type interpreted{fun([this](const mstch::node& n) {
return visit(render_node(m_ctx), n);
}, section_str), m_delims};
return render_context::push(m_ctx).render(interpreted);
}
std::string operator()(const lambda_wrapper& fun) const {
std::string section_str;
for (auto& token : m_section)
section_str += token.raw();
template_type interpreted{fun.values(
[this](const mstch::node& n) {
return visit(render_node(m_ctx), n);
},
section_str),
m_delims};
return render_context::push(m_ctx).render(interpreted);
}
std::string operator()(const array& array) const {
std::string out;
if (m_flag == flag::keep_array)
return render_context::push(m_ctx, array).render(m_section);
else
for (auto& item: array)
out += visit(render_section(
m_ctx, m_section, m_delims, flag::keep_array), item);
return out;
}
std::string operator()(const array_wrapper& array) const {
std::string out;
private:
render_context& m_ctx;
const template_type& m_section;
const delim_type& m_delims;
flag m_flag;
if (m_flag == flag::keep_array)
return render_context::push(m_ctx, array).render(m_section);
for (auto& item : array.values)
out += visit(render_section(m_ctx, m_section, m_delims, flag::keep_array), item);
return out;
}
private:
render_context& m_ctx;
const template_type& m_section;
const delim_type& m_delims;
flag m_flag;
};
}
} // namespace mstch

View File

@ -1,3 +1,2 @@
const auto ampersand_escape_data = mstch::map{
{"message", std::string{"Some <code>"}}
};
const mstch::node ampersand_escape_data =
mstch::map_wrapper{{{"message", std::string{"Some <code>"}}}};

View File

@ -1,4 +1,2 @@
const auto apostrophe_data = mstch::map{
{"apos", std::string{"'"}},
{"control", std::string{"X"}}
};
const mstch::node apostrophe_data =
mstch::map_wrapper{{{"apos", std::string{"'"}}, {"control", std::string{"X"}}}};

View File

@ -1,3 +1,3 @@
const auto array_of_strings_data = mstch::map{
{"array_of_strings", mstch::array{std::string{"hello"}, std::string{"world"}}}
};
const mstch::node array_of_strings_data = mstch::map_wrapper{
{{"array_of_strings",
mstch::array_wrapper{{std::string{"hello"}, std::string{"world"}}}}}};

View File

@ -1,3 +1 @@
const auto backslashes_data = mstch::map{
{"value", std::string{"\\abc"}}
};
const mstch::node backslashes_data = mstch::map_wrapper{{{"value", std::string{"\\abc"}}}};

View File

@ -1,3 +1,2 @@
const auto bug_11_eating_whitespace_data = mstch::map{
{"tag", std::string{"yo"}}
};
const mstch::node bug_11_eating_whitespace_data =
mstch::map_wrapper{{{"tag", std::string{"yo"}}}};

View File

@ -1,3 +1,2 @@
const auto bug_length_property_data = mstch::map{
{"length", std::string{"hello"}}
};
const mstch::node bug_length_property_data =
mstch::map_wrapper{{{"length", std::string{"hello"}}}};

View File

@ -1,4 +1,2 @@
const mstch::node changing_delimiters_data = mstch::map{
{"foo", std::string{"foooooooooooooo"}},
{"bar", std::string{"<b>bar!</b>"}}
};
const mstch::node changing_delimiters_data = mstch::map_wrapper{
{{"foo", std::string{"foooooooooooooo"}}, {"bar", std::string{"<b>bar!</b>"}}}};

View File

@ -1,3 +1,4 @@
const mstch::node comments_data = mstch::map{
{"title", mstch::lambda{[]()->mstch::node{return std::string{"A Comedy of Errors"};}}}
};
const mstch::node comments_data =
mstch::map_wrapper{{{"title", mstch::lambda_wrapper{{[]() -> mstch::node {
return std::string{"A Comedy of Errors"};
}}}}}};

View File

@ -1,69 +1,61 @@
class complex_item: public mstch::object {
class complex_item : public mstch::object {
private:
std::string m_name;
bool m_current;
std::string m_url;
std::string m_name;
bool m_current;
std::string m_url;
public:
complex_item(const std::string& name, bool current, const std::string& url):
m_name(name), m_current(current), m_url(url)
{
register_methods(this, std::map<std::string,mstch::node(complex_item::*)()>{
{"name", &complex_item::name}, {"current", &complex_item::current},
{"url", &complex_item::url}, {"link", &complex_item::link}
});
}
complex_item(const std::string& name, bool current, const std::string& url)
: m_name(name), m_current(current), m_url(url)
{
register_methods(this,
std::map<std::string, mstch::node (complex_item::*)()>{
{"name", &complex_item::name},
{"current", &complex_item::current},
{"url", &complex_item::url},
{"link", &complex_item::link}});
}
mstch::node current() {
return m_current;
}
mstch::node current() { return m_current; }
mstch::node url() {
return m_url;
}
mstch::node url() { return m_url; }
mstch::node name() {
return m_name;
}
mstch::node name() { return m_name; }
mstch::node link() {
return !m_current;
}
mstch::node link() { return !m_current; }
};
class complex: public mstch::object {
class complex : public mstch::object {
private:
std::string m_header;
mstch::array m_item;
std::string m_header;
mstch::array m_item;
public:
complex():
m_header("Colors"),
m_item(mstch::array{
std::make_shared<complex_item>("red", true, "#Red"),
std::make_shared<complex_item>("green", false, "#Green"),
std::make_shared<complex_item>("blue", false, "#Blue")
})
{
register_methods(this, std::map<std::string,mstch::node(complex::*)()>{
{"header", &complex::header}, {"item", &complex::item},
{"list", &complex::list}, {"empty", &complex::empty}
});
}
complex()
: m_header("Colors")
, m_item(mstch::array{mstch::object_wrapper{
std::make_shared<complex_item>("red", true, "#Red")},
mstch::object_wrapper{
std::make_shared<complex_item>("green", false, "#Green")},
mstch::object_wrapper{std::make_shared<complex_item>("blue",
false,
"#Blue")}})
{
register_methods(
this,
std::map<std::string, mstch::node (complex::*)()>{{"header", &complex::header},
{"item", &complex::item},
{"list", &complex::list},
{"empty", &complex::empty}});
}
mstch::node header() {
return m_header;
}
mstch::node header() { return m_header; }
mstch::node item() {
return m_item;
}
mstch::node item() { return mstch::array_wrapper{m_item}; }
mstch::node list() {
return m_item.size() != 0;
}
mstch::node list() { return m_item.size() != 0; }
mstch::node empty() {
return m_item.size() == 0;
}
mstch::node empty() { return m_item.size() == 0; }
};
const auto complex_data = std::make_shared<complex>();
const auto complex_data = mstch::object_wrapper{std::make_shared<complex>()};

View File

@ -1,8 +1,3 @@
const auto context_lookup_data = mstch::map{
{"outer", mstch::map{
{"id", 1},
{"second", mstch::map{
{"nothing", 2}
}}
}}
};
const mstch::node context_lookup_data = mstch::map_wrapper{
{{"outer",
mstch::map_wrapper{{{"id", 1}, {"second", mstch::map_wrapper{{{"nothing", 2}}}}}}}}};

View File

@ -1,6 +1,5 @@
const mstch::node delimiters_data = mstch::map{
{"first", std::string{"It worked the first time."}},
{"second", std::string{"And it worked the second time."}},
{"third", std::string{"Then, surprisingly, it worked the third time."}},
{"fourth", std::string{"Fourth time also fine!."}}
};
const mstch::node delimiters_data = mstch::map_wrapper{
{{"first", std::string{"It worked the first time."}},
{"second", std::string{"And it worked the second time."}},
{"third", std::string{"Then, surprisingly, it worked the third time."}},
{"fourth", std::string{"Fourth time also fine!."}}}};

View File

@ -1,4 +1,2 @@
const auto disappearing_whitespace_data = mstch::map{
{"bedrooms", true},
{"total", 1}
};
const mstch::node disappearing_whitespace_data =
mstch::map_wrapper{{{"bedrooms", true}, {"total", 1}}};

View File

@ -1,34 +1,32 @@
class dot_notation_price: public mstch::object {
class dot_notation_price : public mstch::object {
private:
int m_value;
mstch::map m_currency;
int m_value;
mstch::map m_currency;
public:
dot_notation_price():
m_value(200), m_currency(mstch::map{{"symbol", std::string{"$"}}, {"name", std::string{"USD"}}})
{
register_methods(this, std::map<std::string,mstch::node(dot_notation_price::*)()>{
{"value", &dot_notation_price::value},
{"vat", &dot_notation_price::vat},
{"currency", &dot_notation_price::currency}});
}
dot_notation_price()
: m_value(200)
, m_currency(mstch::map{{"symbol", std::string{"$"}}, {"name", std::string{"USD"}}})
{
register_methods(this,
std::map<std::string, mstch::node (dot_notation_price::*)()>{
{"value", &dot_notation_price::value},
{"vat", &dot_notation_price::vat},
{"currency", &dot_notation_price::currency}});
}
mstch::node value() {
return m_value;
}
mstch::node value() { return m_value; }
mstch::node vat() {
return m_value * 0.2;
}
mstch::node vat() { return m_value * 0.2; }
mstch::node currency() {
return m_currency;
}
mstch::node currency() { return mstch::map_wrapper{m_currency}; }
};
const auto dot_notation_data = mstch::map{
{"name", std::string{"A Book"}},
{"authors", mstch::array{std::string{"John Power"}, std::string{"Jamie Walsh"}}},
{"price", std::make_shared<dot_notation_price>()},
{"availability", mstch::map{{"status", true}, {"text", std::string{"In Stock"}}}},
{"truthy", mstch::map{{"zero", 0}, {"notTrue", false}}}
};
const mstch::node dot_notation_data = mstch::map_wrapper{
{{"name", std::string{"A Book"}},
{"authors",
mstch::array_wrapper{{std::string{"John Power"}, std::string{"Jamie Walsh"}}}},
{"price", mstch::object_wrapper{std::make_shared<dot_notation_price>()}},
{"availability",
mstch::map_wrapper{{{"status", true}, {"text", std::string{"In Stock"}}}}},
{"truthy", mstch::map_wrapper{{{"zero", 0}, {"notTrue", false}}}}}};

View File

@ -1,5 +1,2 @@
const auto double_render_data = mstch::map{
{"foo", true},
{"bar", std::string{"{{win}}"}},
{"win", std::string{"FAIL"}}
};
const mstch::node double_render_data = mstch::map_wrapper{
{{"foo", true}, {"bar", std::string{"{{win}}"}}, {"win", std::string{"FAIL"}}}};

View File

@ -1,3 +1 @@
const auto empty_list_data = mstch::map{
{"jobs", mstch::array{}}
};
const mstch::node empty_list_data = mstch::map_wrapper{{{"jobs", mstch::array_wrapper{}}}};

View File

@ -1 +1 @@
const auto empty_sections_data = mstch::map{};
const mstch::node empty_sections_data = mstch::map_wrapper{{}};

View File

@ -1,6 +1,5 @@
const auto empty_string_data = mstch::map{
{"description", std::string{"That is all!"}},
{"child", mstch::map{
{"description", std::string{""}}
}}
};
#include "mstch/mstch.hpp"
const auto empty_string_data =
mstch::map_wrapper{{{"description", std::string{"That is all!"}},
{"child", mstch::map_wrapper{{{"description", std::string{""}}}}}}};

View File

@ -1 +1 @@
const auto empty_template_data = mstch::map{};
const mstch::node empty_template_data = mstch::map_wrapper{{}};

View File

@ -1,3 +1,2 @@
const auto error_eof_in_section_data = mstch::map{
{"hello", mstch::array{std::string{"a"}, std::string{"b"}}}
};
const mstch::node error_eof_in_section_data = mstch::map_wrapper{
{{"hello", mstch::array_wrapper{{std::string{"a"}, std::string{"b"}}}}}};

View File

@ -1 +1 @@
const auto error_eof_in_tag_data = mstch::map{{"hello", std::string{"world"}}};
const mstch::node error_eof_in_tag_data = mstch::map_wrapper{{{"hello", std::string{"world"}}}};

View File

@ -1,3 +1 @@
const auto error_not_found_data = mstch::map{
{"bar", 2}
};
const mstch::node error_not_found_data = mstch::map_wrapper{{{"bar", 2}}};

View File

@ -1,4 +1,6 @@
const mstch::node escaped_data = mstch::map{
{"title", mstch::lambda{[]()->mstch::node{ return std::string{"Bear > Shark"}; }}},
{"entities", mstch::lambda{[]()->mstch::node{ return std::string{"&quot; \"'<>/"}; }}}
};
const mstch::node escaped_data = mstch::map_wrapper{
{{"title",
mstch::lambda_wrapper{{[]() -> mstch::node { return std::string{"Bear > Shark"}; }}}},
{"entities", mstch::lambda_wrapper{{[]() -> mstch::node {
return std::string{"&quot; \"'<>/"};
}}}}}};

View File

@ -1,6 +1,4 @@
const auto falsy_data = mstch::map{
{"emptyString", std::string{""}},
{"emptyArray", mstch::array{}},
{"zero", 0},
{"null", mstch::node{}}
};
const auto falsy_data = mstch::map_wrapper{{{"emptyString", std::string{""}},
{"emptyArray", mstch::array_wrapper{}},
{"zero", 0},
{"null", mstch::node{}}}};

View File

@ -1,8 +1,7 @@
const auto falsy_array_data = mstch::map{
{"list", mstch::array{
mstch::array{std::string{""}, std::string{"emptyString"}},
mstch::array{mstch::array{}, std::string{"emptyArray"}},
mstch::array{0, std::string{"zero"}},
mstch::array{mstch::node{}, std::string{"null"}}}
}
};
const auto falsy_array_data = mstch::map_wrapper{
{{"list",
mstch::array_wrapper{
{mstch::array_wrapper{{std::string{""}, std::string{"emptyString"}}},
mstch::array_wrapper{{mstch::array_wrapper{}, std::string{"emptyArray"}}},
mstch::array_wrapper{{0, std::string{"zero"}}},
mstch::array_wrapper{{mstch::node{}, std::string{"null"}}}}}}}};

View File

@ -1,19 +1,22 @@
const auto grandparent_context_data = mstch::map{
{"grand_parent_id", std::string{"grand_parent1"}},
{"parent_contexts", mstch::array{
mstch::map{
{"parent_id", std::string{"parent1"}},
{"child_contexts", mstch::array{
mstch::map{{"child_id", std::string{"parent1-child1"}}},
mstch::map{{"child_id", std::string{"parent1-child2"}}}
}}
},
mstch::map{
{"parent_id", std::string{"parent2"}},
{"child_contexts", mstch::array{
mstch::map{{"child_id", std::string{"parent2-child1"}}},
mstch::map{{"child_id", std::string{"parent2-child2"}}}
}}
}
}}
};
const auto grandparent_context_data = mstch::map_wrapper{
{{"grand_parent_id", std::string{"grand_parent1"}},
{"parent_contexts",
mstch::array_wrapper{
{mstch::map_wrapper{
{{"parent_id", std::string{"parent1"}},
{"child_contexts",
mstch::array_wrapper{
{mstch::map_wrapper{
{{"child_id", std::string{"parent1-child1"}}}},
mstch::map_wrapper{
{{"child_id",
std::string{"parent1-child2"}}}}}}}}},
mstch::map_wrapper{
{{"parent_id", std::string{"parent2"}},
{"child_contexts",
mstch::array_wrapper{
{mstch::map_wrapper{
{{"child_id", std::string{"parent2-child1"}}}},
mstch::map_wrapper{
{{"child_id",
std::string{"parent2-child2"}}}}}}}}}}}}}};

View File

@ -1,28 +1,26 @@
class higher_order_sections: public mstch::object {
private:
std::string m_helper;
public:
higher_order_sections(): m_helper("To tinker?") {
register_methods(this, std::map<std::string,mstch::node(higher_order_sections::*)()>{
{"name", &higher_order_sections::name},
{"helper", &higher_order_sections::helper},
{"bolder", &higher_order_sections::bolder}
});
}
class higher_order_sections : public mstch::object {
private:
std::string m_helper;
mstch::node name() {
return std::string{"Tater"};
}
public:
higher_order_sections() : m_helper("To tinker?") {
register_methods(this,
std::map<std::string, mstch::node (higher_order_sections::*)()>{
{"name", &higher_order_sections::name},
{"helper", &higher_order_sections::helper},
{"bolder", &higher_order_sections::bolder}});
}
mstch::node helper() {
return m_helper;
}
mstch::node name() { return std::string{"Tater"}; }
mstch::node bolder() {
return mstch::lambda{[this](const std::string& text) -> mstch::node {
return "<b>" + text + "</b> " + m_helper;
}};
}
mstch::node helper() { return m_helper; }
mstch::node bolder() {
return mstch::lambda_wrapper{{[this](const std::string& text) -> mstch::node {
return "<b>" + text + "</b> " + m_helper;
}}};
}
};
const mstch::node higher_order_sections_data = std::make_shared<higher_order_sections>();
const mstch::node higher_order_sections_data =
mstch::object_wrapper{std::make_shared<higher_order_sections>()};

View File

@ -1,8 +1,5 @@
const auto implicit_iterator_data = mstch::map{
{"data", mstch::map{
{"author", mstch::map{
{"twitter_id", 819606},
{"name", std::string{"janl"}}
}}
}}
};
const auto implicit_iterator_data = mstch::map_wrapper{
{{"data",
mstch::map_wrapper{{{"author",
mstch::map_wrapper{{{"twitter_id", 819606},
{"name", std::string{"janl"}}}}}}}}}};

View File

@ -1,3 +1,2 @@
const auto included_tag_data = mstch::map{
{"html", std::string{"I like {{mustache}}"}}
};
const mstch::node included_tag_data =
mstch::map_wrapper{{{"html", std::string{"I like {{mustache}}"}}}};

View File

@ -1,3 +1 @@
const auto inverted_section_data = mstch::map{
{"repos", mstch::array{}}
};
const auto inverted_section_data = mstch::map_wrapper{{{"repos", mstch::array_wrapper{}}}};

View File

@ -1,5 +1,2 @@
const auto keys_with_questionmarks_data = mstch::map{
{"person?", mstch::map{
{"name", std::string{"Jon"}}
}}
};
const auto keys_with_questionmarks_data =
mstch::map_wrapper{{{"person?", mstch::map_wrapper{{{"name", std::string{"Jon"}}}}}}};

View File

@ -1 +1 @@
const auto multiline_comment_data = mstch::map{};
const mstch::node multiline_comment_data = mstch::map_wrapper{{}};

View File

@ -1 +1 @@
const auto nested_dot_data = mstch::map{{"name", std::string{"Bruno"}}};
const mstch::node nested_dot_data = mstch::map_wrapper{{{"name", std::string{"Bruno"}}}};

View File

@ -1,6 +1,5 @@
const mstch::node nested_higher_order_sections_data = mstch::map{
{"bold", mstch::lambda{[](const std::string& text) -> mstch::node {
return std::string{"<b>"} + text + std::string{"</b>"};
}}},
{"person", mstch::map{{"name", std::string{"Jonas"}}}}
};
const mstch::node nested_higher_order_sections_data = mstch::map_wrapper{
{{"bold", mstch::lambda_wrapper{{[](const std::string& text) -> mstch::node {
return std::string{"<b>"} + text + std::string{"</b>"};
}}}},
{"person", mstch::map_wrapper{{{"name", std::string{"Jonas"}}}}}}};

View File

@ -1,8 +1,7 @@
const auto nested_iterating_data = mstch::map{
{"inner", mstch::array{mstch::map{
{"foo", std::string{"foo"}},
{"inner", mstch::array{mstch::map{
{"bar", std::string{"bar"}}
}}}
}}}
};
const mstch::node nested_iterating_data = mstch::map_wrapper{
{{"inner",
mstch::array_wrapper{
{mstch::map_wrapper{{{"foo", std::string{"foo"}},
{"inner",
mstch::array_wrapper{{mstch::map_wrapper{
{{"bar", std::string{"bar"}}}}}}}}}}}}}};

View File

@ -1,7 +1,6 @@
const auto nesting_data = mstch::map{
{"foo", mstch::array{
mstch::map{{"a", mstch::map{{"b", 1}}}},
mstch::map{{"a", mstch::map{{"b", 2}}}},
mstch::map{{"a", mstch::map{{"b", 3}}}}
}}
};
const mstch::node nesting_data = mstch::map_wrapper{
{{"foo",
mstch::array_wrapper{
{mstch::map_wrapper{{{"a", mstch::map_wrapper{{{"b", 1}}}}}},
mstch::map_wrapper{{{"a", mstch::map_wrapper{{{"b", 2}}}}}},
mstch::map_wrapper{{{"a", mstch::map_wrapper{{{"b", 3}}}}}}}}}}};

View File

@ -1,8 +1,5 @@
const auto nesting_same_name_data = mstch::map{
{"items", mstch::array{
mstch::map{
{"name", std::string{"name"}},
{"items", mstch::array{1, 2, 3, 4}}
}
}}
};
const mstch::node nesting_same_name_data = mstch::map_wrapper{
{{"items",
mstch::array_wrapper{
{mstch::map_wrapper{{{"name", std::string{"name"}},
{"items", mstch::array_wrapper{{1, 2, 3, 4}}}}}}}}}};

View File

@ -1,8 +1,8 @@
const auto null_lookup_array_data = mstch::map{
{"name", std::string{"David"}},
{"twitter", std::string{"@dasilvacontin"}},
{"farray", mstch::array{
mstch::array{std::string{"Flor"}, std::string{"@florrts"}},
mstch::array{std::string{"Miquel"}, mstch::node{}},
}}
};
const mstch::node null_lookup_array_data = mstch::map_wrapper{
{{"name", std::string{"David"}},
{"twitter", std::string{"@dasilvacontin"}},
{"farray",
mstch::array_wrapper{{
mstch::array_wrapper{{std::string{"Flor"}, std::string{"@florrts"}}},
mstch::array_wrapper{{std::string{"Miquel"}, mstch::node{}}},
}}}}};

View File

@ -1,14 +1,8 @@
const auto null_lookup_object_data = mstch::map{
{"name", std::string{"David"}},
{"twitter", std::string{"@dasilvacontin"}},
{"fobject", mstch::array{
mstch::map{
{"name", std::string{"Flor"}},
{"twitter", std::string{"@florrts"}}
},
mstch::map{
{"name", std::string{"Miquel"}},
{"twitter", mstch::node{}}
}
}}
};
const mstch::node null_lookup_object_data = mstch::map_wrapper{
{{"name", std::string{"David"}},
{"twitter", std::string{"@dasilvacontin"}},
{"fobject",
mstch::array_wrapper{{{mstch::map_wrapper{{{"name", std::string{"Flor"}},
{"twitter", std::string{"@florrts"}}}}},
mstch::map_wrapper{{{"name", std::string{"Miquel"}},
{"twitter", mstch::node{}}}}}}}}};

View File

@ -1,6 +1,4 @@
const auto null_string_data = mstch::map{
{"name", std::string{"Elise"}},
{"glytch", true},
{"binary", false},
{"value", mstch::node{}}
};
const mstch::node null_string_data = mstch::map_wrapper{{{"name", std::string{"Elise"}},
{"glytch", true},
{"binary", false},
{"value", mstch::node{}}}};

View File

@ -1,4 +1,2 @@
const auto null_view_data = mstch::map{
{"name", std::string{"Joe"}},
{"friends", mstch::node{}}
};
const mstch::node null_view_data =
mstch::map_wrapper{{{"name", std::string{"Joe"}}, {"friends", mstch::node{}}}};

View File

@ -1,3 +1,4 @@
const auto partial_array_data = mstch::map{
{"array", mstch::array{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}}
};
const mstch::node partial_array_data = mstch::map_wrapper{
{{"array",
mstch::array_wrapper{
{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}}}}};

View File

@ -1,8 +1,6 @@
const auto partial_array_of_partials_data = mstch::map{
{"numbers", mstch::array{
mstch::map{{"i", std::string{"1"}}},
mstch::map{{"i", std::string{"2"}}},
mstch::map{{"i", std::string{"3"}}},
mstch::map{{"i", std::string{"4"}}}
}}
};
const mstch::node partial_array_of_partials_data = mstch::map_wrapper{
{{"numbers",
mstch::array_wrapper{{mstch::map_wrapper{{{"i", std::string{"1"}}}},
mstch::map_wrapper{{{"i", std::string{"2"}}}},
mstch::map_wrapper{{{"i", std::string{"3"}}}},
mstch::map_wrapper{{{"i", std::string{"4"}}}}}}}}};

View File

@ -1,3 +1,4 @@
const auto partial_array_of_partials_implicit_data = mstch::map{
{"numbers", mstch::array{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}}
};
const mstch::node partial_array_of_partials_implicit_data = mstch::map_wrapper{
{{"numbers",
mstch::array_wrapper{
{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}}}}};

View File

@ -1,3 +1 @@
const auto partial_empty_data = mstch::map{
{"foo", 1}
};
const mstch::node partial_empty_data = mstch::map_wrapper{{{"foo", 1}}};

View File

@ -1,4 +1,6 @@
const mstch::node partial_template_data = mstch::map{
{"title", mstch::lambda{[]()->mstch::node{ return std::string{"Welcome"}; }}},
{"again", mstch::lambda{[]()->mstch::node{ return std::string{"Goodbye"}; }}},
};
const mstch::node partial_template_data = mstch::map_wrapper{{
{"title",
mstch::lambda_wrapper{{[]() -> mstch::node { return std::string{"Welcome"}; }}}},
{"again",
mstch::lambda_wrapper{{[]() -> mstch::node { return std::string{"Goodbye"}; }}}},
}};

View File

@ -39,4 +39,4 @@ public:
}
};
const auto partial_view_data = std::make_shared<partial_view>();
const mstch::node partial_view_data = mstch::object_wrapper{std::make_shared<partial_view>()};

View File

@ -1,41 +1,31 @@
class partial_whitespace: public mstch::object {
class partial_whitespace : public mstch::object {
private:
int m_value;
int m_value;
public:
partial_whitespace(): m_value(10000) {
register_methods(this, std::map<std::string,mstch::node(partial_whitespace::*)()>{
{"greeting", &partial_whitespace::greeting},
{"farewell", &partial_whitespace::farewell},
{"name", &partial_whitespace::name},
{"value", &partial_whitespace::value},
{"taxed_value", &partial_whitespace::taxed_value},
{"in_ca", &partial_whitespace::in_ca}
});
}
partial_whitespace() : m_value(10000) {
register_methods(this,
std::map<std::string, mstch::node (partial_whitespace::*)()>{
{"greeting", &partial_whitespace::greeting},
{"farewell", &partial_whitespace::farewell},
{"name", &partial_whitespace::name},
{"value", &partial_whitespace::value},
{"taxed_value", &partial_whitespace::taxed_value},
{"in_ca", &partial_whitespace::in_ca}});
}
mstch::node greeting() {
return std::string{"Welcome"};
}
mstch::node greeting() { return std::string{"Welcome"}; }
mstch::node farewell() {
return std::string{"Fair enough, right?"};
}
mstch::node farewell() { return std::string{"Fair enough, right?"}; }
mstch::node name() {
return std::string{"Chris"};
}
mstch::node name() { return std::string{"Chris"}; }
mstch::node value() {
return m_value;
}
mstch::node value() { return m_value; }
mstch::node taxed_value() {
return static_cast<int>(m_value - (m_value * 0.4));
}
mstch::node taxed_value() { return static_cast<int>(m_value - (m_value * 0.4)); }
mstch::node in_ca() {
return true;
}
mstch::node in_ca() { return true; }
};
const auto partial_whitespace_data = std::make_shared<partial_whitespace>();
const mstch::node partial_whitespace_data =
mstch::object_wrapper{std::make_shared<partial_whitespace>()};

View File

@ -1,8 +1,7 @@
const auto recursion_with_same_names_data = mstch::map{
{"name", std::string{"name"}},
{"description", std::string{"desc"}},
{"terms", mstch::array{
mstch::map{{"name", std::string{"t1"}}, {"index", 0}},
mstch::map{{"name", std::string{"t2"}}, {"index", 1}}
}}
};
const mstch::node recursion_with_same_names_data = mstch::map_wrapper{
{{"name", std::string{"name"}},
{"description", std::string{"desc"}},
{"terms",
mstch::array_wrapper{
{mstch::map_wrapper{{{"name", std::string{"t1"}}, {"index", 0}}},
mstch::map_wrapper{{{"name", std::string{"t2"}}, {"index", 1}}}}}}}};

View File

@ -1,6 +1,5 @@
const auto reuse_of_enumerables_data = mstch::map{
{"terms", mstch::array{
mstch::map{{"name", std::string{"t1"}}, {"index", 0}},
mstch::map{{"name", std::string{"t2"}}, {"index", 1}}
}}
};
const mstch::node reuse_of_enumerables_data = mstch::map_wrapper{
{{"terms",
mstch::array_wrapper{
{mstch::map_wrapper{{{"name", std::string{"t1"}}, {"index", 0}}},
mstch::map_wrapper{{{"name", std::string{"t2"}}, {"index", 1}}}}}}}};

View File

@ -1,10 +1,9 @@
const auto section_as_context_data = mstch::map{
{"a_object", mstch::map{
{"title", std::string{"this is an object"}},
{"description", std::string{"one of its attributes is a list"}},
{"a_list", mstch::array{
mstch::map{{"label", std::string{"listitem1"}}},
mstch::map{{"label", std::string{"listitem2"}}}
}}
}}
};
const mstch::node section_as_context_data = mstch::map_wrapper{
{{"a_object",
mstch::map_wrapper{
{{"title", std::string{"this is an object"}},
{"description", std::string{"one of its attributes is a list"}},
{"a_list",
mstch::array_wrapper{
{mstch::map_wrapper{{{"label", std::string{"listitem1"}}}},
mstch::map_wrapper{{{"label", std::string{"listitem2"}}}}}}}}}}}};

View File

@ -1,5 +1,4 @@
const mstch::node section_functions_in_partials_data = mstch::map{
{"bold", mstch::lambda{[](const std::string& text) -> mstch::node {
return std::string{"<b>"} + text + std::string{"</b>"};
}}}
};
const mstch::node section_functions_in_partials_data = mstch::map_wrapper{
{{"bold", mstch::lambda_wrapper{{[](const std::string& text) -> mstch::node {
return std::string{"<b>"} + text + std::string{"</b>"};
}}}}}};

View File

@ -29,4 +29,4 @@ public:
}
};
const auto simple_data = std::make_shared<simple>();
const mstch::node simple_data = mstch::object_wrapper{std::make_shared<simple>()};

View File

@ -1,4 +1,4 @@
const auto string_as_context_data = mstch::map{
{"a_string", std::string{"aa"}},
{"a_list", mstch::array{std::string{"a"},std::string{"b"},std::string{"c"}}}
};
const mstch::node string_as_context_data = mstch::map_wrapper{
{{"a_string", std::string{"aa"}},
{"a_list",
mstch::array_wrapper{{std::string{"a"}, std::string{"b"}, std::string{"c"}}}}}};

View File

@ -1,4 +1,2 @@
const auto two_in_a_row_data = mstch::map{
{"name", std::string{"Joe"}},
{"greeting", std::string{"Welcome"}}
};
const mstch::node two_in_a_row_data = mstch::map_wrapper{
{{"name", std::string{"Joe"}}, {"greeting", std::string{"Welcome"}}}};

View File

@ -1 +1 @@
const auto two_sections_data = mstch::map{};
const mstch::node two_sections_data = mstch::map_wrapper{{}};

View File

@ -1,3 +1,4 @@
const mstch::node unescaped_data = mstch::map{
{"title", mstch::lambda{[]()->mstch::node{ return std::string{"Bear > Shark"}; }}}
};
const mstch::node unescaped_data =
mstch::map_wrapper{{{"title", mstch::lambda_wrapper{{[]() -> mstch::node {
return std::string{"Bear > Shark"};
}}}}}};

View File

@ -1,4 +1,2 @@
const auto whitespace_data = mstch::map{
{"tag1", std::string{"Hello"}},
{"tag2", std::string{"World"}}
};
const mstch::node whitespace_data =
mstch::map_wrapper{{{"tag1", std::string{"Hello"}}, {"tag2", std::string{"World"}}}};

View File

@ -1 +1,2 @@
const auto zero_view_data = mstch::map{{"nums", mstch::array{0, 1, 2}}};
const mstch::node zero_view_data =
mstch::map_wrapper{{{"nums", mstch::array_wrapper{{0, 1, 2}}}}};

View File

@ -1,32 +1,36 @@
std::map<std::string,mstch::node> specs_lambdas {
{"Interpolation", mstch::lambda{[](const std::string&) -> mstch::node {
return std::string{"world"};
}}},
{"Interpolation - Expansion", mstch::lambda{[](const std::string&) -> mstch::node {
return std::string{"{{planet}}"};
}}},
{"Interpolation - Alternate Delimiters", mstch::lambda{[](const std::string&) -> mstch::node {
return std::string{"|planet| => {{planet}}"};
}}},
{"Interpolation - Multiple Calls", mstch::lambda{[](const std::string&) -> mstch::node {
static int calls = 0; return ++calls;
}}},
{"Escaping", mstch::lambda{[](const std::string&) -> mstch::node {
return std::string{">"};
}}},
{"Section", mstch::lambda{[](const std::string& txt) -> mstch::node {
return std::string{(txt == "{{x}}") ? "yes" : "no"};
}}},
{"Section - Expansion", mstch::lambda{[](const std::string& txt) -> mstch::node {
return txt + std::string{"{{planet}}"} + txt;
}}},
{"Section - Alternate Delimiters", mstch::lambda{[](const std::string& txt) -> mstch::node {
return txt + std::string{"{{planet}} => |planet|"} + txt;
}}},
{"Section - Multiple Calls", mstch::lambda{[](const std::string& txt) -> mstch::node {
return "__" + txt + "__";
}}},
{"Inverted Section", mstch::lambda{[](const std::string&) -> mstch::node {
return false;
}}}
};
std::map<std::string, mstch::node> specs_lambdas{
{"Interpolation", mstch::lambda_wrapper{{[](const std::string&) -> mstch::node {
return std::string{"world"};
}}}},
{"Interpolation - Expansion",
mstch::lambda_wrapper{{[](const std::string&) -> mstch::node {
return std::string{"{{planet}}"};
}}}},
{"Interpolation - Alternate Delimiters",
mstch::lambda_wrapper{{[](const std::string&) -> mstch::node {
return std::string{"|planet| => {{planet}}"};
}}}},
{"Interpolation - Multiple Calls",
mstch::lambda_wrapper{{[](const std::string&) -> mstch::node {
static int calls = 0;
return ++calls;
}}}},
{"Escaping", mstch::lambda_wrapper{{[](const std::string&) -> mstch::node {
return std::string{">"};
}}}},
{"Section", mstch::lambda_wrapper{{[](const std::string& txt) -> mstch::node {
return std::string{(txt == "{{x}}") ? "yes" : "no"};
}}}},
{"Section - Expansion",
mstch::lambda_wrapper{{[](const std::string& txt) -> mstch::node {
return txt + std::string{"{{planet}}"} + txt;
}}}},
{"Section - Alternate Delimiters",
mstch::lambda_wrapper{{[](const std::string& txt) -> mstch::node {
return txt + std::string{"{{planet}} => |planet|"} + txt;
}}}},
{"Section - Multiple Calls",
mstch::lambda_wrapper{
{[](const std::string& txt) -> mstch::node { return "__" + txt + "__"; }}}},
{"Inverted Section",
mstch::lambda_wrapper{{[](const std::string&) -> mstch::node { return false; }}}}};

View File

@ -1,91 +1,99 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "rapidjson/document.h"
#include "mstch/mstch.hpp"
#include "test_context.hpp"
#include "test_data.hpp"
#include "rapidjson/document.h"
#include "specs_data.hpp"
#include "specs_lambdas.hpp"
#include "test_context.hpp"
#include "test_data.hpp"
using namespace mstchtest;
mstch::node to_value(const rapidjson::Value& val) {
if (val.IsString())
return std::string{val.GetString()};
if (val.IsBool())
return val.GetBool();
if (val.IsDouble())
return val.GetDouble();
if (val.IsInt())
return val.GetInt();
return mstch::node{};
if (val.IsString())
return std::string{val.GetString()};
if (val.IsBool())
return val.GetBool();
if (val.IsDouble())
return val.GetDouble();
if (val.IsInt())
return val.GetInt();
return mstch::node{};
}
mstch::array to_array(const rapidjson::Value& val);
mstch::map to_object(const rapidjson::Value& val) {
mstch::map ret;
for (auto i = val.MemberBegin(); i != val.MemberEnd(); ++i) {
if (i->value.IsArray())
ret.insert(std::make_pair(i->name.GetString(), to_array(i->value)));
else if (i->value.IsObject())
ret.insert(std::make_pair(i->name.GetString(), to_object(i->value)));
else
ret.insert(std::make_pair(i->name.GetString(), to_value(i->value)));
}
return ret;
mstch::map ret;
for (auto i = val.MemberBegin(); i != val.MemberEnd(); ++i) {
if (i->value.IsArray())
ret.insert(std::make_pair(i->name.GetString(),
mstch::array_wrapper{to_array(i->value)}));
else if (i->value.IsObject())
ret.insert(std::make_pair(i->name.GetString(),
mstch::map_wrapper{to_object(i->value)}));
else
ret.insert(std::make_pair(i->name.GetString(), to_value(i->value)));
}
return ret;
}
mstch::array to_array(const rapidjson::Value& val) {
mstch::array ret;
for (auto i = val.Begin(); i != val.End(); ++i) {
if (i->IsArray())
ret.push_back(to_array(*i));
else if (i->IsObject())
ret.push_back(to_object(*i));
else
ret.push_back(to_value(*i));
}
return ret;
mstch::array ret;
for (auto i = val.Begin(); i != val.End(); ++i) {
if (i->IsArray())
ret.push_back(mstch::array_wrapper{to_array(*i)});
else if (i->IsObject())
ret.push_back(mstch::map_wrapper{to_object(*i)});
else
ret.push_back(to_value(*i));
}
return ret;
}
mstch::node parse_with_rapidjson(const std::string& str) {
rapidjson::Document doc;
doc.Parse(str.c_str());
return to_object(doc);
rapidjson::Document doc;
doc.Parse(str.c_str());
return mstch::map_wrapper{to_object(doc)};
}
#define MSTCH_PARTIAL_TEST(x) TEST_CASE(#x) { \
REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data, {{"partial", x ## _partial}})); \
}
#define MSTCH_PARTIAL_TEST(x) \
TEST_CASE(#x) { \
REQUIRE(x##_txt == mstch::render(x##_mustache, x##_data, {{"partial", x##_partial}})); \
}
#define MSTCH_TEST(x) TEST_CASE(#x) { \
REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data)); \
}
#define MSTCH_TEST(x) \
TEST_CASE(#x) { REQUIRE(x##_txt == mstch::render(x##_mustache, x##_data)); }
#define SPECS_TEST(x) TEST_CASE("specs_" #x) { \
using boost::get; \
auto data = parse_with_rapidjson(x ## _json); \
for (auto& test_item: get<mstch::array>(get<mstch::map>(data)["tests"])) {\
auto test = get<mstch::map>(test_item); \
std::map<std::string,std::string> partials; \
if (test.count("partials")) \
for (auto& partial_item: get<mstch::map>(test["partials"])) \
partials.insert(std::make_pair(partial_item.first, get<std::string>(partial_item.second))); \
mstch::map context; \
for (auto& data_item: get<mstch::map>(test["data"])) \
if (data_item.first == "lambda") \
context.insert(std::make_pair(data_item.first, specs_lambdas[get<std::string>(test["name"])])); \
else \
context.insert(data_item); \
SECTION(get<std::string>(test["name"])) \
REQUIRE(mstch::render( \
get<std::string>(test["template"]), \
context, partials) == \
get<std::string>(test["expected"])); \
} \
}
#define SPECS_TEST(x) \
TEST_CASE("specs_" #x) { \
auto data = parse_with_rapidjson(x##_json); \
for (auto& test_item : std::get<mstch::array_wrapper>( \
std::get<mstch::map_wrapper>(data).values["tests"]) \
.values) { \
auto test = std::get<mstch::map_wrapper>(test_item).values; \
std::map<std::string, std::string> partials; \
if (test.count("partials")) \
for (auto& partial_item : \
std::get<mstch::map_wrapper>(test["partials"]).values) \
partials.insert( \
std::make_pair(partial_item.first, \
std::get<std::string>(partial_item.second))); \
mstch::map context; \
for (auto& data_item : std::get<mstch::map_wrapper>(test["data"]).values) \
if (data_item.first == "lambda") \
context.insert(std::make_pair( \
data_item.first, \
specs_lambdas[std::get<std::string>(test["name"])])); \
else \
context.insert(data_item); \
SECTION(std::get<std::string>(test["name"])) \
REQUIRE(mstch::render(std::get<std::string>(test["template"]), \
mstch::map_wrapper{context}, \
partials) == std::get<std::string>(test["expected"])); \
} \
}
MSTCH_TEST(ampersand_escape)
MSTCH_TEST(apostrophe)