use submodules
This commit is contained in:
parent
873de4933f
commit
d07260fbf8
11 changed files with 6 additions and 9548 deletions
|
@ -5,5 +5,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -O3")
|
|||
add_subdirectory(src)
|
||||
if(WITH_UNIT_TESTS)
|
||||
enable_testing()
|
||||
include_directories(
|
||||
vendor/Catch/single_include
|
||||
vendor/json.hpp/include)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
|
|
@ -42,8 +42,8 @@ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp PROPERTIES
|
|||
add_custom_target(test_data_hpp DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp)
|
||||
|
||||
file(GLOB specs_files RELATIVE
|
||||
"${CMAKE_SOURCE_DIR}/test/specs"
|
||||
"${CMAKE_SOURCE_DIR}/test/specs/*.json")
|
||||
"${CMAKE_SOURCE_DIR}/vendor/spec/specs"
|
||||
"${CMAKE_SOURCE_DIR}/vendor/spec/specs/*.json")
|
||||
|
||||
foreach(specs_file ${specs_files})
|
||||
list(APPEND specsargs "-S${specs_file}")
|
||||
|
@ -55,7 +55,7 @@ add_custom_command(
|
|||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp
|
||||
COMMAND ${headerize_exe} --output ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp --namespace mstchtest ${specsargs}
|
||||
DEPENDS ${headerize_exe}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test/specs/)
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/vendor/spec/specs/)
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp PROPERTIES GENERATED TRUE)
|
||||
add_custom_target(specs_data_hpp DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp)
|
||||
|
||||
|
|
9427
test/catch.hpp
9427
test/catch.hpp
File diff suppressed because it is too large
Load diff
111
test/json.hpp
111
test/json.hpp
|
@ -1,111 +0,0 @@
|
|||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/fusion/adapted/std_pair.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace json {
|
||||
|
||||
namespace spirit = boost::spirit;
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
using node = boost::make_recursive_variant<
|
||||
std::nullptr_t, std::string, int, double, bool,
|
||||
std::map<const std::string, boost::recursive_variant_>,
|
||||
std::vector<boost::recursive_variant_>>::type;
|
||||
using map = std::map<const std::string, node>;
|
||||
using array = std::vector<node>;
|
||||
|
||||
template<class Iterator, class Node, class Map, class Array>
|
||||
struct json_grammar: qi::grammar<Iterator, Node(), ascii::space_type> {
|
||||
struct esc_parser: qi::symbols<char,char> {
|
||||
esc_parser() {
|
||||
add("\\\\" , '\\') ("\\\"" , '"' ) ("\\n" , '\n') ("\\r" , '\r')
|
||||
("\\b" , '\b') ("\\f" , '\f') ("\\t" , '\t');
|
||||
}
|
||||
} escaped;
|
||||
|
||||
json_grammar(): json_grammar::base_type(value_rule) {
|
||||
value_rule %= string_rule |
|
||||
qi::double_ |
|
||||
object_rule |
|
||||
array_rule |
|
||||
qi::lit("true" )[spirit::_val = true ] |
|
||||
qi::lit("false")[spirit::_val = false] |
|
||||
"null";
|
||||
string_rule = spirit::lexeme['"' >> *(escaped | (qi::char_ - '"')) >> '"'];
|
||||
object_rule = '{' >> -((string_rule >> ':' >> value_rule) % ',') >> '}';
|
||||
array_rule = '[' >> -(value_rule % ',') >> ']';
|
||||
}
|
||||
|
||||
qi::rule<Iterator, Node(), ascii::space_type> value_rule;
|
||||
qi::rule<Iterator, Map(), ascii::space_type> object_rule;
|
||||
qi::rule<Iterator, Array(), ascii::space_type> array_rule;
|
||||
qi::rule<Iterator, std::string(), ascii::space_type> string_rule;
|
||||
};
|
||||
|
||||
struct json_visitor: boost::static_visitor<std::string> {
|
||||
std::string escape(const std::string& str) const {
|
||||
std::string ret{str};
|
||||
boost::replace_all(ret, "\\", "\\\\");
|
||||
boost::replace_all(ret, "\"", "\\\"");
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string operator()(const std::nullptr_t& value) const {
|
||||
return "null";
|
||||
}
|
||||
|
||||
std::string operator()(const std::string& value) const {
|
||||
return "\"" + escape(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 bool& value) const {
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
std::string operator()(const json::map& value) const {
|
||||
std::string out;
|
||||
bool comma = false;
|
||||
for(auto& item: value)
|
||||
out += (comma++ ? ", \"" : "\"") + escape(item.first) + "\": " +
|
||||
boost::apply_visitor(json_visitor(), item.second);
|
||||
return "{" + out + "}";
|
||||
}
|
||||
|
||||
std::string operator()(const json::array& value) const {
|
||||
std::string out;
|
||||
bool comma = false;
|
||||
for(auto& item: value)
|
||||
out += (comma++ ? ", " : "") + boost::apply_visitor(json_visitor(), item);
|
||||
return "[" + out + "]";
|
||||
}
|
||||
};
|
||||
|
||||
template<class Node = node, class Map = map, class Array = array>
|
||||
Node parse(const std::string& str) {
|
||||
Node out;
|
||||
json_grammar<std::string::const_iterator, Node, Map, Array> json;
|
||||
auto first = str.begin(), last = str.end();
|
||||
bool ret = qi::phrase_parse(first, last, json, ascii::space, out);
|
||||
return (!ret || first != last) ? Node() : out;
|
||||
}
|
||||
|
||||
template<class Node = node>
|
||||
std::string stringify(const Node& node) {
|
||||
return boost::apply_visitor(json_visitor(), node);
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Comment tags represent content that should never appear in the resulting\noutput.\n\nThe tag's content may contain any substring (including newlines) EXCEPT the\nclosing delimiter.\n\nComment tags SHOULD be treated as standalone when appropriate.\n","tests":[{"name":"Inline","data":{},"expected":"1234567890","template":"12345{{! Comment Block! }}67890","desc":"Comment blocks should be removed from the template."},{"name":"Multiline","data":{},"expected":"1234567890\n","template":"12345{{!\n This is a\n multi-line comment...\n}}67890\n","desc":"Multiline comments should be permitted."},{"name":"Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{! Comment Block! }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{! Indented Comment Block! }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n|","template":"|\r\n{{! Standalone Comment }}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{},"expected":"!","template":" {{! I'm Still Standalone }}\n!","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{},"expected":"!\n","template":"!\n {{! I'm Still Standalone }}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Multiline Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{!\nSomething's going on here...\n}}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Multiline Standalone","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{!\n Something's going on here...\n }}\nEnd.\n","desc":"All standalone comment lines should be removed."},{"name":"Indented Inline","data":{},"expected":" 12 \n","template":" 12 {{! 34 }}\n","desc":"Inline comments should not strip whitespace"},{"name":"Surrounding Whitespace","data":{},"expected":"12345 67890","template":"12345 {{! Comment Block! }} 67890","desc":"Comment removal should preserve surrounding whitespace."}]}
|
|
@ -1 +0,0 @@
|
|||
{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Set Delimiter tags are used to change the tag delimiters for all content\nfollowing the tag in the current compilation unit.\n\nThe tag's content MUST be any two non-whitespace sequences (separated by\nwhitespace) EXCEPT an equals sign ('=') followed by the current closing\ndelimiter.\n\nSet Delimiter tags SHOULD be treated as standalone when appropriate.\n","tests":[{"name":"Pair Behavior","data":{"text":"Hey!"},"expected":"(Hey!)","template":"{{=<% %>=}}(<%text%>)","desc":"The equals sign (used on both sides) should permit delimiter changes."},{"name":"Special Characters","data":{"text":"It worked!"},"expected":"(It worked!)","template":"({{=[ ]=}}[text])","desc":"Characters with special meaning regexen should be valid delimiters."},{"name":"Sections","data":{"section":true,"data":"I got interpolated."},"expected":"[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n","template":"[\n{{#section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|#section|\n {{data}}\n |data|\n|/section|\n]\n","desc":"Delimiters set outside sections should persist."},{"name":"Inverted Sections","data":{"section":false,"data":"I got interpolated."},"expected":"[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n","template":"[\n{{^section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|^section|\n {{data}}\n |data|\n|/section|\n]\n","desc":"Delimiters set outside inverted sections should persist."},{"name":"Partial Inheritence","data":{"value":"yes"},"expected":"[ .yes. ]\n[ .yes. ]\n","template":"[ {{>include}} ]\n{{= | | =}}\n[ |>include| ]\n","desc":"Delimiters set in a parent template should not affect a partial.","partials":{"include":".{{value}}."}},{"name":"Post-Partial Behavior","data":{"value":"yes"},"expected":"[ .yes. .yes. ]\n[ .yes. .|value|. ]\n","template":"[ {{>include}} ]\n[ .{{value}}. .|value|. ]\n","desc":"Delimiters set in a partial should not affect the parent template.","partials":{"include":".{{value}}. {{= | | =}} .|value|."}},{"name":"Surrounding Whitespace","data":{},"expected":"| |","template":"| {{=@ @=}} |","desc":"Surrounding whitespace should be left untouched."},{"name":"Outlying Whitespace (Inline)","data":{},"expected":" | \n","template":" | {{=@ @=}}\n","desc":"Whitespace should be left untouched."},{"name":"Standalone Tag","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n{{=@ @=}}\nEnd.\n","desc":"Standalone lines should be removed from the template."},{"name":"Indented Standalone Tag","data":{},"expected":"Begin.\nEnd.\n","template":"Begin.\n {{=@ @=}}\nEnd.\n","desc":"Indented standalone lines should be removed from the template."},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n|","template":"|\r\n{{= @ @ =}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags."},{"name":"Standalone Without Previous Line","data":{},"expected":"=","template":" {{=@ @=}}\n=","desc":"Standalone tags should not require a newline to precede them."},{"name":"Standalone Without Newline","data":{},"expected":"=\n","template":"=\n {{=@ @=}}","desc":"Standalone tags should not require a newline to follow them."},{"name":"Pair with Padding","data":{},"expected":"||","template":"|{{= @ @ =}}|","desc":"Superfluous in-tag whitespace should be ignored."}]}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Partial tags are used to expand an external template into the current\ntemplate.\n\nThe tag's content MUST be a non-whitespace character sequence NOT containing\nthe current closing delimiter.\n\nThis tag's content names the partial to inject. Set Delimiter tags MUST NOT\naffect the parsing of a partial. The partial MUST be rendered against the\ncontext stack local to the tag.\n\nPartial tags SHOULD be treated as standalone when appropriate. If this tag\nis used standalone, any whitespace preceding the tag should treated as\nindentation, and prepended to each line of the partial before rendering.\n","tests":[{"name":"Basic Behavior","data":{},"expected":"\"from partial\"","template":"\"{{>text}}\"","desc":"The greater-than operator should expand to the named partial.","partials":{"text":"from partial"}},{"name":"Context","data":{"text":"content"},"expected":"\"*content*\"","template":"\"{{>partial}}\"","desc":"The greater-than operator should operate within the current context.","partials":{"partial":"*{{text}}*"}},{"name":"Recursion","data":{"content":"X","nodes":[{"content":"Y","nodes":[]}]},"expected":"X<Y<>>","template":"{{>node}}","desc":"The greater-than operator should properly recurse.","partials":{"node":"{{content}}<{{#nodes}}{{>node}}{{/nodes}}>"}},{"name":"Surrounding Whitespace","data":{},"expected":"| \t|\t |","template":"| {{>partial}} |","desc":"The greater-than operator should not alter surrounding whitespace.","partials":{"partial":"\t|\t"}},{"name":"Inline Indentation","data":{"data":"|"},"expected":" | >\n>\n","template":" {{data}} {{> partial}}\n","desc":"Whitespace should be left untouched.","partials":{"partial":">\n>"}},{"name":"Standalone Line Endings","data":{},"expected":"|\r\n>|","template":"|\r\n{{>partial}}\r\n|","desc":"\"\\r\\n\" should be considered a newline for standalone tags.","partials":{"partial":">"}},{"name":"Standalone Without Previous Line","data":{},"expected":" >\n >>","template":" {{>partial}}\n>","desc":"Standalone tags should not require a newline to precede them.","partials":{"partial":">\n>"}},{"name":"Standalone Without Newline","data":{},"expected":">\n >\n >","template":">\n {{>partial}}","desc":"Standalone tags should not require a newline to follow them.","partials":{"partial":">\n>"}},{"name":"Standalone Indentation","data":{"content":"<\n->"},"expected":"\\\n |\n <\n->\n |\n/\n","template":"\\\n {{>partial}}\n/\n","desc":"Each line of the partial should be indented before rendering.","partials":{"partial":"|\n{{{content}}}\n|\n"}},{"name":"Padding Whitespace","data":{"boolean":true},"expected":"|[]|","template":"|{{> partial }}|","desc":"Superfluous in-tag whitespace should be ignored.","partials":{"partial":"[]"}}]}
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
{"__ATTN__":"Do not edit this file; changes belong in the appropriate YAML file.","overview":"Lambdas are a special-cased data type for use in interpolations and\nsections.\n\nWhen used as the data value for an Interpolation tag, the lambda MUST be\ntreatable as an arity 0 function, and invoked as such. The returned value\nMUST be rendered, then interpolated in place of the lambda.\n\nWhen used as the data value for a Section tag, the lambda MUST be treatable\nas an arity 1 function, and invoked as such (passing a String containing the\nunprocessed section contents). The returned value MUST be rendered, then\ninterpolated in place of the section.\n","tests":[{"name":"Interpolation","data":{"lambda":{"php":"return \"world\";","__tag__":"code","perl":"sub { \"world\" }","python":"lambda: \"world\"","ruby":"proc { \"world\" }","js":"function() { return \"world\" }"}},"expected":"Hello, world!","template":"Hello, {{lambda}}!","desc":"A lambda's return value should be interpolated."},{"name":"Interpolation - Expansion","data":{"planet":"world","lambda":{"php":"return \"{{planet}}\";","__tag__":"code","perl":"sub { \"{{planet}}\" }","python":"lambda: \"{{planet}}\"","ruby":"proc { \"{{planet}}\" }","js":"function() { return \"{{planet}}\" }"}},"expected":"Hello, world!","template":"Hello, {{lambda}}!","desc":"A lambda's return value should be parsed."},{"name":"Interpolation - Multiple Calls","data":{"lambda":{"php":"global $calls; return ++$calls;","__tag__":"code","perl":"sub { no strict; $calls += 1 }","python":"lambda: globals().update(calls=globals().get(\"calls\",0)+1) or calls","ruby":"proc { $calls ||= 0; $calls += 1 }","js":"function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }"}},"expected":"1 == 2 == 3","template":"{{lambda}} == {{{lambda}}} == {{lambda}}","desc":"Interpolated lambdas should not be cached."},{"name":"Escaping","data":{"lambda":{"php":"return \">\";","__tag__":"code","perl":"sub { \">\" }","python":"lambda: \">\"","ruby":"proc { \">\" }","js":"function() { return \">\" }"}},"expected":"<>>","template":"<{{lambda}}{{{lambda}}}","desc":"Lambda results should be appropriately escaped."},{"name":"Section","data":{"x":"Error!","lambda":{"php":"return ($text == \"{{x}}\") ? \"yes\" : \"no\";","__tag__":"code","perl":"sub { $_[0] eq \"{{x}}\" ? \"yes\" : \"no\" }","python":"lambda text: text == \"{{x}}\" and \"yes\" or \"no\"","ruby":"proc { |text| text == \"{{x}}\" ? \"yes\" : \"no\" }","js":"function(txt) { return (txt == \"{{x}}\" ? \"yes\" : \"no\") }"}},"expected":"<yes>","template":"<{{#lambda}}{{x}}{{/lambda}}>","desc":"Lambdas used for sections should receive the raw section string."},{"name":"Section - Expansion","data":{"planet":"Earth","lambda":{"php":"return $text . \"{{planet}}\" . $text;","__tag__":"code","perl":"sub { $_[0] . \"{{planet}}\" . $_[0] }","python":"lambda text: \"%s{{planet}}%s\" % (text, text)","ruby":"proc { |text| \"#{text}{{planet}}#{text}\" }","js":"function(txt) { return txt + \"{{planet}}\" + txt }"}},"expected":"<-Earth->","template":"<{{#lambda}}-{{/lambda}}>","desc":"Lambdas used for sections should have their results parsed."},{"name":"Section - Multiple Calls","data":{"lambda":{"php":"return \"__\" . $text . \"__\";","__tag__":"code","perl":"sub { \"__\" . $_[0] . \"__\" }","python":"lambda text: \"__%s__\" % (text)","ruby":"proc { |text| \"__#{text}__\" }","js":"function(txt) { return \"__\" + txt + \"__\" }"}},"expected":"__FILE__ != __LINE__","template":"{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}","desc":"Lambdas used for sections should not be cached."},{"name":"Inverted Section","data":{"static":"static","lambda":{"php":"return false;","__tag__":"code","perl":"sub { 0 }","python":"lambda text: 0","ruby":"proc { |text| false }","js":"function(txt) { return false }"}},"expected":"<>","template":"<{{^lambda}}{{static}}{{/lambda}}>","desc":"Lambdas used for inverted sections should be considered truthy."}]}
|
Loading…
Reference in a new issue