From 6973532ccdc564212a7928d4dd3228bf78f83956 Mon Sep 17 00:00:00 2001 From: Shiva Date: Sun, 3 May 2015 17:56:44 -0700 Subject: [PATCH 01/23] Remove dependency on boost - Replace Boost Regex with Std::Regex - Replace Boost trim with custom trim function - Remove boost from build files --- Makefile.am | 5 +- configure.ac | 2 +- include/plustache/template.hpp | 11 +++-- src/template.cpp | 86 ++++++++++++++++++++++------------ 4 files changed, 65 insertions(+), 39 deletions(-) diff --git a/Makefile.am b/Makefile.am index 27615a1..ba3ced2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,10 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -LDFLAGS=-lboost_regex-mt +#LDFLAGS=-lboost_regex-mt pkginclude_HEADERS = include/plustache/template.hpp include/plustache/context.hpp include/plustache/plustache_types.hpp check_PROGRAMS = test-program test_program_CPPFLAGS=-Ivendor/gtest-1.6.0/include -I$(top_srcdir)/include -test_program_LDFLAGS=-Lvendor/gtest-1.6.0/lib/.libs -lgtest -lboost_regex-mt +test_program_LDFLAGS=-Lvendor/gtest-1.6.0/lib/.libs -lgtest +#-lboost_regex-mt test_program_SOURCES = tests/test_change_delimiter.cpp tests/test_collections_plustache.cpp tests/test_html_escape_plustache.cpp tests/test_inverted_sections.cpp tests/test_multiple_plustache.cpp tests/test_nested_sections_plustache.cpp tests/test_partials_plustache.cpp tests/test_sections_plustache.cpp tests/test_simple_plustache.cpp tests/tests.cpp test_program_LDADD = .libs/libplustache.a diff --git a/configure.ac b/configure.ac index af39180..2bd88a6 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ AC_PROG_CC AC_PROG_INSTALL # Checks for libraries. -AC_CHECK_LIB([boost_regex], [main]) +#AC_CHECK_LIB([boost_regex], [main]) AC_CHECK_LIB([gtest], [main]) # Checks for header files. diff --git a/include/plustache/template.hpp b/include/plustache/template.hpp index 81ba3ed..238f57b 100644 --- a/include/plustache/template.hpp +++ b/include/plustache/template.hpp @@ -8,8 +8,9 @@ #include #include #include -#include -#include +//#include +//#include +#include #include #include @@ -31,9 +32,9 @@ namespace Plustache { std::string otag; std::string ctag; /* regex */ - boost::regex tag; - boost::regex section; - boost::regex escape_chars; + std::regex tag; + std::regex section; + std::regex escape_chars; /* lut for HTML escape chars */ std::map escape_lut; /* render and helper methods */ diff --git a/src/template.cpp b/src/template.cpp index b2f93d0..c1e581a 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -7,14 +7,38 @@ #include #include -#include -#include +#include +#include + +//#include +//#include #include #include using namespace Plustache; + +// trim from start +static inline std::string <rim(std::string &s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) +{ + return ltrim(rtrim(s)); +} + /** * @brief constructor taking no arguments */ @@ -80,23 +104,23 @@ std::string template_t::render_tags(const std::string& tmplate, std::string ret = ""; std::string rest = ""; std::string::const_iterator start, end; - boost::match_results matches; + std::match_results matches; start = tmplate.begin(); end = tmplate.end(); // return whole std::string when no tags are found if (!regex_search(start, end, matches, tag, - boost::match_default | boost::format_all)) + std::regex_constants::match_default | std::regex_constants::format_default)) { ret = tmplate; } // loop through tags and replace while (regex_search(start, end, matches, tag, - boost::match_default | boost::format_all)) + std::regex_constants::match_default | std::regex_constants::format_default)) { std::string modifier(matches[1].first, matches[1].second); std::string key(matches[2].first, matches[2].second); - boost::algorithm::trim(key); - boost::algorithm::trim(modifier); + trim(key); + trim(modifier); std::string text(start, matches[0].second); std::string repl; // don't html escape this @@ -141,17 +165,17 @@ std::string template_t::render_tags(const std::string& tmplate, // replace ret += regex_replace(text, tag, repl, - boost::match_default | boost::format_all); + std::regex_constants::match_default | std::regex_constants::format_default); // change delimiter after was removed if (modifier == "=") { // regex for finding delimiters - boost::regex delim("(.+?) (.+?)="); + std::regex delim("(.+?) (.+?)="); // match object - boost::match_results delim_m; + std::match_results delim_m; // search for the delimiters - boost::regex_search(matches[2].first, matches[2].second, delim_m, delim, - boost::match_default | boost::format_all); + std::regex_search(matches[2].first, matches[2].second, delim_m, delim, + std::regex_constants::match_default | std::regex_constants::format_default); // set new otag and ctag std::string new_otag = delim_m[1]; std::string new_ctag = delim_m[2]; @@ -182,26 +206,26 @@ std::string template_t::render_sections(const std::string& tmplate, std::string ret = ""; std::string rest = ""; std::string::const_iterator start, end; - boost::match_results matches; + std::match_results matches; start = tmplate.begin(); end = tmplate.end(); // return the whole template if no sections are found - if (!boost::regex_search(start, end, matches, section, - boost::match_default | boost::format_all)) + if (!std::regex_search(start, end, matches, section, + std::regex_constants::match_default | std::regex_constants::format_default)) { ret = tmplate; } // loop through sections and render - while (boost::regex_search(start, end, matches, section, - boost::match_default | boost::format_all)) + while (std::regex_search(start, end, matches, section, + std::regex_constants::match_default | std::regex_constants::format_default)) { // std::string assignments std::string text(start, matches[0].second); std::string key(matches[2].first, matches[2].second); std::string modifier(matches[1]); // trimming - boost::algorithm::trim(key); - boost::algorithm::trim(modifier); + trim(key); + trim(modifier); std::string repl = ""; std::string show = "false"; CollectionType values; @@ -231,8 +255,8 @@ std::string template_t::render_sections(const std::string& tmplate, // assign replacement content if (show == "true") { - if (boost::regex_search(matches[3].first, matches[3].second, section, - boost::match_default | boost::format_all)) + if (std::regex_search(matches[3].first, matches[3].second, section, + std::regex_constants::match_default | std::regex_constants::format_default)) { repl.assign(template_t::render_sections(matches[3], ctx)); } @@ -249,8 +273,8 @@ std::string template_t::render_sections(const std::string& tmplate, } } else repl.assign(""); - ret += boost::regex_replace(text, section, repl, - boost::match_default | boost::format_all); + ret += std::regex_replace(text, section, repl, + std::regex_constants::match_default | std::regex_constants::format_default); rest.assign(matches[0].second, end); start = matches[0].second; } @@ -316,26 +340,26 @@ std::string template_t::html_escape(const std::string& s) std::string ret = ""; std::string rest = ""; std::string::const_iterator start, end; - boost::match_results matches; + std::match_results matches; start = s.begin(); end = s.end(); // return original std::string if nothing is found - if (!boost::regex_search(start, end, matches, escape_chars, - boost::match_default | boost::format_all)) + if (!std::regex_search(start, end, matches, escape_chars, + std::regex_constants::match_default | std::regex_constants::format_default)) { ret = s; } // search for html chars - while (boost::regex_search(start, end, matches, escape_chars, - boost::match_default | boost::format_all)) + while (std::regex_search(start, end, matches, escape_chars, + std::regex_constants::match_default | std::regex_constants::format_default)) { std::string key(matches[0].first, matches[0].second); std::string text(start, matches[0].second); - boost::algorithm::trim(key); + trim(key); std::string repl; repl = escape_lut[key]; - ret += boost::regex_replace(text, escape_chars, repl, - boost::match_default | boost::format_all); + ret += std::regex_replace(text, escape_chars, repl, + std::regex_constants::match_default | std::regex_constants::format_default); rest.assign(matches[0].second, end); start = matches[0].second; } From f328ffcdf10c25ba84c1a6269b14acb8307bb562 Mon Sep 17 00:00:00 2001 From: Shiva Date: Sun, 3 May 2015 18:01:40 -0700 Subject: [PATCH 02/23] Fix README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 87aef66..e2df2c0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +Fork of plustache to remove dependency on Boost. +NOTE: Unit-tests are broken now + # plustache - mustache templates for C++ Basic port of [mustache templating](http://mustache.github.com) to C++. From cc53a4fb0846bac68fddd58584c7b2f667704a0a Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 19:11:14 -0700 Subject: [PATCH 03/23] Xcode project with integrated testing --- platforms/xcode/.gitignore | 18 + platforms/xcode/GoogleTests.mm | 239 ++++++ .../xcode/plustache.xcodeproj/project.pbxproj | 754 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/plustache.xcscheme | 96 +++ 6 files changed, 1122 insertions(+) create mode 100644 platforms/xcode/.gitignore create mode 100755 platforms/xcode/GoogleTests.mm create mode 100644 platforms/xcode/plustache.xcodeproj/project.pbxproj create mode 100644 platforms/xcode/plustache.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 platforms/xcode/plustache.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme diff --git a/platforms/xcode/.gitignore b/platforms/xcode/.gitignore new file mode 100644 index 0000000..81bf6c8 --- /dev/null +++ b/platforms/xcode/.gitignore @@ -0,0 +1,18 @@ +# Created by https://www.gitignore.io + +### Xcode ### +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.xcuserstate + diff --git a/platforms/xcode/GoogleTests.mm b/platforms/xcode/GoogleTests.mm new file mode 100755 index 0000000..9b252ed --- /dev/null +++ b/platforms/xcode/GoogleTests.mm @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2013 Matthew Stevens + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// Downloaded from https://github.com/mattstevens/xcode-googletest on 21 Apr 2015 - kah + +#import +#import +#import + +using testing::TestCase; +using testing::TestInfo; +using testing::TestPartResult; +using testing::UnitTest; + +static NSString * const GoogleTestDisabledPrefix = @"DISABLED_"; + +/** + * A Google Test listener that reports failures to XCTest. + */ +class XCTestListener : public testing::EmptyTestEventListener { +public: + XCTestListener(XCTestCase *testCase) : + _testCase(testCase) {} + + void OnTestPartResult(const TestPartResult& test_part_result) { + if (test_part_result.passed()) + return; + + int lineNumber = test_part_result.line_number(); + const char *fileName = test_part_result.file_name(); + NSString *path = fileName ? [@(fileName) stringByStandardizingPath] : nil; + NSString *description = @(test_part_result.message()); + [_testCase recordFailureWithDescription:description + inFile:path + atLine:(lineNumber >= 0 ? (NSUInteger)lineNumber : 0) + expected:YES]; + } + +private: + XCTestCase *_testCase; +}; + +/** + * Test suite used to run Google Test cases. + * + * This test suite skips its own run and instead runs each of its sub-tests. This results + * in the Google Test cases being reported at the same level as other XCTest cases. + * + * Additionally, if a test case has been completely filtered out it is not run at all. + * This eliminates noise from the test report when running only a subset of tests. + */ +@interface GoogleTestSuite : XCTestSuite +@end + +@implementation GoogleTestSuite + +- (void)performTest:(XCTestSuiteRun *)testRun { + for (XCTest *test in self.tests) { + if (test.testCaseCount > 0) { + [testRun addTestRun:[test run]]; + } + } +} + +@end + +/** + * A test case that executes Google Test, reporting test results to XCTest. + * + * XCTest loads tests by looking for all classes derived from XCTestCase and calling + * +defaultTestSuite on each of them. Normally this method returns an XCTestSuite + * containing an XCTestCase for each method of the receiver whose name begins with "test". + * Instead this class returns a custom test suite that runs an XCTestSuite for each Google + * Test case. + */ +@interface GoogleTests : XCTestCase +@end + +@implementation GoogleTests { + NSString *_name; + NSString *_className; + NSString *_methodName; + NSString *_googleTestFilter; +} + +- (id)initWithClassName:(NSString *)className methodName:(NSString *)methodName testFilter:(NSString *)filter { + self = [super initWithSelector:@selector(runTest)]; + if (self) { + _className = [className copy]; + _methodName = [methodName copy]; + _name = [NSString stringWithFormat:@"-[%@ %@]", _className, _methodName]; + _googleTestFilter = [filter copy]; + } + return self; +} + +- (NSString *)name { + return _name; +} + +/** + * Returns the test name logged to the console for this test. + */ +- (NSString *)nameForLegacyLogging { + return _name; +} + +/** + * Returns the class name reported to Xcode for this test. + */ +- (NSString *)testClassName { + return _className; +} + +/** + * Returns the method name reported to Xcode for this test. + */ +- (NSString *)testMethodName { + return _methodName; +} + ++ (id)defaultTestSuite { + // Pass the command-line arguments to Google Test to support the --gtest options + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + + int i = 0; + int argc = (int)[arguments count]; + const char **argv = (const char **)calloc((unsigned int)argc + 1, sizeof(const char *)); + for (NSString *arg in arguments) { + argv[i++] = [arg UTF8String]; + } + + testing::InitGoogleTest(&argc, (char **)argv); + UnitTest *googleTest = UnitTest::GetInstance(); + testing::TestEventListeners& listeners = googleTest->listeners(); + delete listeners.Release(listeners.default_result_printer()); + free(argv); + + BOOL runDisabledTests = testing::GTEST_FLAG(also_run_disabled_tests); + NSCharacterSet *decimalDigitCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; + + XCTestSuite *testSuite = [GoogleTestSuite testSuiteWithName:NSStringFromClass([self class])]; + + for (int testCaseIndex = 0; testCaseIndex < googleTest->total_test_case_count(); testCaseIndex++) { + const TestCase *testCase = googleTest->GetTestCase(testCaseIndex); + NSString *testCaseName = @(testCase->name()); + + // For typed tests '/' is used to separate the parts of the test case name. + NSArray *testCaseNameComponents = [testCaseName componentsSeparatedByString:@"/"]; + + if (runDisabledTests == NO) { + BOOL testCaseDisabled = NO; + + for (NSString *component in testCaseNameComponents) { + if ([component hasPrefix:GoogleTestDisabledPrefix]) { + testCaseDisabled = YES; + break; + } + } + + if (testCaseDisabled) { + continue; + } + } + + // Xcode's parsing expects that the test's class and method names are valid + // Objective-C names. If they are not the tests will not be displayed properly in + // the UI. Join the test case name components with '_' rather than '/' to address + // this. + NSString *className = [testCaseNameComponents componentsJoinedByString:@"_"]; + + XCTestSuite *testCaseSuite = [XCTestSuite testSuiteWithName:className]; + + for (int testIndex = 0; testIndex < testCase->total_test_count(); testIndex++) { + const TestInfo *testInfo = testCase->GetTestInfo(testIndex); + NSString *testName = @(testInfo->name()); + if (runDisabledTests == NO && [testName hasPrefix:GoogleTestDisabledPrefix]) { + continue; + } + + // Google Test allows test names starting with a digit, prefix these with an + // underscore to create a valid method name. + NSString *methodName = testName; + if ([methodName length] > 0 && [decimalDigitCharacterSet characterIsMember:[methodName characterAtIndex:0]]) { + methodName = [@"_" stringByAppendingString:methodName]; + } + + NSString *testFilter = [NSString stringWithFormat:@"%@.%@", testCaseName, testName]; + + [testCaseSuite addTest:[[self alloc] initWithClassName:className + methodName:methodName + testFilter:testFilter]]; + } + + [testSuite addTest:testCaseSuite]; + } + + return testSuite; +} + +/** + * Runs a single test. + */ +- (void)runTest { + XCTestListener *listener = new XCTestListener(self); + UnitTest *googleTest = UnitTest::GetInstance(); + googleTest->listeners().Append(listener); + + testing::GTEST_FLAG(filter) = [_googleTestFilter UTF8String]; + + (void)RUN_ALL_TESTS(); + + delete googleTest->listeners().Release(listener); + + int totalTestsRun = googleTest->successful_test_count() + googleTest->failed_test_count(); + XCTAssertEqual(totalTestsRun, 1, @"Expected to run a single test for filter \"%@\"", _googleTestFilter); +} + +@end diff --git a/platforms/xcode/plustache.xcodeproj/project.pbxproj b/platforms/xcode/plustache.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1d72c21 --- /dev/null +++ b/platforms/xcode/plustache.xcodeproj/project.pbxproj @@ -0,0 +1,754 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 2F9708E31AF998CB00D82006 /* plustache-automake */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 2F9708E41AF998CB00D82006 /* Build configuration list for PBXAggregateTarget "plustache-automake" */; + buildPhases = ( + 2F9708FF1AF99A2300D82006 /* ShellScript */, + ); + dependencies = ( + ); + name = "plustache-automake"; + productName = plustache; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 2F9709151AF9A6D600D82006 /* libplustache.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F9709061AF9A6A900D82006 /* libplustache.a */; }; + 2F97091B1AF9A73900D82006 /* context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708ED1AF9992D00D82006 /* context.cpp */; }; + 2F97091D1AF9A73900D82006 /* template.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708EF1AF9992D00D82006 /* template.cpp */; }; + 2F97091E1AF9A73E00D82006 /* test_change_delimiter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F01AF9993B00D82006 /* test_change_delimiter.cpp */; }; + 2F97091F1AF9A73E00D82006 /* test_collections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F11AF9993B00D82006 /* test_collections_plustache.cpp */; }; + 2F9709201AF9A73E00D82006 /* test_html_escape_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F21AF9993B00D82006 /* test_html_escape_plustache.cpp */; }; + 2F9709211AF9A73E00D82006 /* test_inverted_sections.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F31AF9993B00D82006 /* test_inverted_sections.cpp */; }; + 2F9709221AF9A73E00D82006 /* test_multiple_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F41AF9993B00D82006 /* test_multiple_plustache.cpp */; }; + 2F9709231AF9A73E00D82006 /* test_nested_sections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F51AF9993B00D82006 /* test_nested_sections_plustache.cpp */; }; + 2F9709241AF9A73E00D82006 /* test_partials_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F61AF9993B00D82006 /* test_partials_plustache.cpp */; }; + 2F9709251AF9A73E00D82006 /* test_sections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F71AF9993B00D82006 /* test_sections_plustache.cpp */; }; + 2F9709261AF9A73E00D82006 /* test_simple_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F81AF9993B00D82006 /* test_simple_plustache.cpp */; }; + 2F9709281AF9A75300D82006 /* context.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FB1AF999B700D82006 /* context.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; + 2F9709291AF9A75300D82006 /* plustache_types.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FC1AF999B700D82006 /* plustache_types.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; + 2F97092A1AF9A75300D82006 /* template.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FD1AF999B700D82006 /* template.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; + 2F9709381AF9A8C700D82006 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709331AF9A86D00D82006 /* gtest-all.cc */; }; + 2F97093B1AF9A8D600D82006 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F97092F1AF9A7F200D82006 /* libgtest.a */; }; + 2F97093C1AF9AAC100D82006 /* GoogleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709011AF9A63800D82006 /* GoogleTests.mm */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2F9709161AF9A6D600D82006 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2F9708DD1AF9988D00D82006 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2F9709051AF9A6A900D82006; + remoteInfo = plustache; + }; + 2F9709391AF9A8CE00D82006 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2F9708DD1AF9988D00D82006 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2F97092E1AF9A7F200D82006; + remoteInfo = gtest; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 2F9708ED1AF9992D00D82006 /* context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = context.cpp; sourceTree = ""; }; + 2F9708EF1AF9992D00D82006 /* template.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = template.cpp; sourceTree = ""; }; + 2F9708F01AF9993B00D82006 /* test_change_delimiter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_change_delimiter.cpp; sourceTree = ""; }; + 2F9708F11AF9993B00D82006 /* test_collections_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_collections_plustache.cpp; sourceTree = ""; }; + 2F9708F21AF9993B00D82006 /* test_html_escape_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_html_escape_plustache.cpp; sourceTree = ""; }; + 2F9708F31AF9993B00D82006 /* test_inverted_sections.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_inverted_sections.cpp; sourceTree = ""; }; + 2F9708F41AF9993B00D82006 /* test_multiple_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_multiple_plustache.cpp; sourceTree = ""; }; + 2F9708F51AF9993B00D82006 /* test_nested_sections_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_nested_sections_plustache.cpp; sourceTree = ""; }; + 2F9708F61AF9993B00D82006 /* test_partials_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_partials_plustache.cpp; sourceTree = ""; }; + 2F9708F71AF9993B00D82006 /* test_sections_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_sections_plustache.cpp; sourceTree = ""; }; + 2F9708F81AF9993B00D82006 /* test_simple_plustache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_simple_plustache.cpp; sourceTree = ""; }; + 2F9708FB1AF999B700D82006 /* context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = context.hpp; sourceTree = ""; }; + 2F9708FC1AF999B700D82006 /* plustache_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = plustache_types.hpp; sourceTree = ""; }; + 2F9708FD1AF999B700D82006 /* template.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = template.hpp; sourceTree = ""; }; + 2F9709011AF9A63800D82006 /* GoogleTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GoogleTests.mm; sourceTree = SOURCE_ROOT; }; + 2F9709061AF9A6A900D82006 /* libplustache.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libplustache.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 2F97090F1AF9A6D600D82006 /* tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2F97092F1AF9A7F200D82006 /* libgtest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 2F9709331AF9A86D00D82006 /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "gtest-all.cc"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2F9709031AF9A6A900D82006 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2F97090C1AF9A6D600D82006 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9709151AF9A6D600D82006 /* libplustache.a in Frameworks */, + 2F97093B1AF9A8D600D82006 /* libgtest.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2F97092C1AF9A7F200D82006 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2F9708DC1AF9988D00D82006 = { + isa = PBXGroup; + children = ( + 2F9708FA1AF9996000D82006 /* include */, + 2F9708EB1AF998E400D82006 /* src */, + 2F9708EC1AF9990500D82006 /* tests */, + 2F9709361AF9A87F00D82006 /* vendor */, + 2F9709071AF9A6A900D82006 /* Products */, + ); + sourceTree = ""; + }; + 2F9708EB1AF998E400D82006 /* src */ = { + isa = PBXGroup; + children = ( + 2F9708ED1AF9992D00D82006 /* context.cpp */, + 2F9708EF1AF9992D00D82006 /* template.cpp */, + ); + name = src; + path = ../../src; + sourceTree = ""; + }; + 2F9708EC1AF9990500D82006 /* tests */ = { + isa = PBXGroup; + children = ( + 2F9708F01AF9993B00D82006 /* test_change_delimiter.cpp */, + 2F9708F11AF9993B00D82006 /* test_collections_plustache.cpp */, + 2F9708F21AF9993B00D82006 /* test_html_escape_plustache.cpp */, + 2F9708F31AF9993B00D82006 /* test_inverted_sections.cpp */, + 2F9708F41AF9993B00D82006 /* test_multiple_plustache.cpp */, + 2F9708F51AF9993B00D82006 /* test_nested_sections_plustache.cpp */, + 2F9708F61AF9993B00D82006 /* test_partials_plustache.cpp */, + 2F9708F71AF9993B00D82006 /* test_sections_plustache.cpp */, + 2F9708F81AF9993B00D82006 /* test_simple_plustache.cpp */, + ); + name = tests; + path = ../../tests; + sourceTree = ""; + }; + 2F9708FA1AF9996000D82006 /* include */ = { + isa = PBXGroup; + children = ( + 2F9708FE1AF999CE00D82006 /* plustache */, + ); + name = include; + path = ../../include; + sourceTree = ""; + }; + 2F9708FE1AF999CE00D82006 /* plustache */ = { + isa = PBXGroup; + children = ( + 2F9708FB1AF999B700D82006 /* context.hpp */, + 2F9708FC1AF999B700D82006 /* plustache_types.hpp */, + 2F9708FD1AF999B700D82006 /* template.hpp */, + ); + path = plustache; + sourceTree = ""; + }; + 2F9709071AF9A6A900D82006 /* Products */ = { + isa = PBXGroup; + children = ( + 2F9709061AF9A6A900D82006 /* libplustache.a */, + 2F97090F1AF9A6D600D82006 /* tests.xctest */, + 2F97092F1AF9A7F200D82006 /* libgtest.a */, + ); + name = Products; + sourceTree = ""; + }; + 2F9709361AF9A87F00D82006 /* vendor */ = { + isa = PBXGroup; + children = ( + 2F9709371AF9A89A00D82006 /* gtest */, + ); + name = vendor; + path = ../../vendor; + sourceTree = ""; + }; + 2F9709371AF9A89A00D82006 /* gtest */ = { + isa = PBXGroup; + children = ( + 2F9709011AF9A63800D82006 /* GoogleTests.mm */, + 2F9709331AF9A86D00D82006 /* gtest-all.cc */, + ); + name = gtest; + path = "gtest-1.6.0/src"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 2F9709041AF9A6A900D82006 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F97092A1AF9A75300D82006 /* template.hpp in Headers */, + 2F9709291AF9A75300D82006 /* plustache_types.hpp in Headers */, + 2F9709281AF9A75300D82006 /* context.hpp in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2F97092D1AF9A7F200D82006 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 2F9709051AF9A6A900D82006 /* plustache */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F9709081AF9A6A900D82006 /* Build configuration list for PBXNativeTarget "plustache" */; + buildPhases = ( + 2F9709021AF9A6A900D82006 /* Sources */, + 2F9709031AF9A6A900D82006 /* Frameworks */, + 2F9709041AF9A6A900D82006 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = plustache; + productName = plustache; + productReference = 2F9709061AF9A6A900D82006 /* libplustache.a */; + productType = "com.apple.product-type.library.static"; + }; + 2F97090E1AF9A6D600D82006 /* tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F9709181AF9A6D600D82006 /* Build configuration list for PBXNativeTarget "tests" */; + buildPhases = ( + 2F97090B1AF9A6D600D82006 /* Sources */, + 2F97090C1AF9A6D600D82006 /* Frameworks */, + 2F97090D1AF9A6D600D82006 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 2F9709171AF9A6D600D82006 /* PBXTargetDependency */, + 2F97093A1AF9A8CE00D82006 /* PBXTargetDependency */, + ); + name = tests; + productName = tests; + productReference = 2F97090F1AF9A6D600D82006 /* tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 2F97092E1AF9A7F200D82006 /* gtest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F9709301AF9A7F200D82006 /* Build configuration list for PBXNativeTarget "gtest" */; + buildPhases = ( + 2F97092B1AF9A7F200D82006 /* Sources */, + 2F97092C1AF9A7F200D82006 /* Frameworks */, + 2F97092D1AF9A7F200D82006 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = gtest; + productName = gtest; + productReference = 2F97092F1AF9A7F200D82006 /* libgtest.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2F9708DD1AF9988D00D82006 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + TargetAttributes = { + 2F9708E31AF998CB00D82006 = { + CreatedOnToolsVersion = 6.3.1; + }; + 2F9709051AF9A6A900D82006 = { + CreatedOnToolsVersion = 6.3.1; + }; + 2F97090E1AF9A6D600D82006 = { + CreatedOnToolsVersion = 6.3.1; + }; + 2F97092E1AF9A7F200D82006 = { + CreatedOnToolsVersion = 6.3.1; + }; + }; + }; + buildConfigurationList = 2F9708E01AF9988D00D82006 /* Build configuration list for PBXProject "plustache" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2F9708DC1AF9988D00D82006; + productRefGroup = 2F9709071AF9A6A900D82006 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2F9709051AF9A6A900D82006 /* plustache */, + 2F97090E1AF9A6D600D82006 /* tests */, + 2F9708E31AF998CB00D82006 /* plustache-automake */, + 2F97092E1AF9A7F200D82006 /* gtest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2F97090D1AF9A6D600D82006 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2F9708FF1AF99A2300D82006 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cwd=$(pwd)\nset -e\nexport PATH=\"/usr/local/bin:$PATH\"\n\nsrc_root=\"$cwd/../..\"\ninstall_root=\"$BUILT_PRODUCTS_DIR\"\nbuild_root=\"$PROJECT_TEMP_ROOT/plustache.build/src\"\n\nif [ ! -d \"$build_root\" ]; then\n mkdir -p \"$build_root\"\nfi\n\ncp -af \"$src_root/\" \"$build_root\"\ncd \"$build_root\"\n\nif [ ! -f \"configure\" ]; then\n autoreconf -i\nfi\n\nif [ ! -f Makefile ]; then\n ./configure --prefix=\"$install_root\"\nfi\n\nmake\nmake install\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2F9709021AF9A6A900D82006 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F97091B1AF9A73900D82006 /* context.cpp in Sources */, + 2F97091D1AF9A73900D82006 /* template.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2F97090B1AF9A6D600D82006 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F97091F1AF9A73E00D82006 /* test_collections_plustache.cpp in Sources */, + 2F9709221AF9A73E00D82006 /* test_multiple_plustache.cpp in Sources */, + 2F9709211AF9A73E00D82006 /* test_inverted_sections.cpp in Sources */, + 2F9709251AF9A73E00D82006 /* test_sections_plustache.cpp in Sources */, + 2F9709241AF9A73E00D82006 /* test_partials_plustache.cpp in Sources */, + 2F9709261AF9A73E00D82006 /* test_simple_plustache.cpp in Sources */, + 2F9709231AF9A73E00D82006 /* test_nested_sections_plustache.cpp in Sources */, + 2F97091E1AF9A73E00D82006 /* test_change_delimiter.cpp in Sources */, + 2F97093C1AF9AAC100D82006 /* GoogleTests.mm in Sources */, + 2F9709201AF9A73E00D82006 /* test_html_escape_plustache.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2F97092B1AF9A7F200D82006 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9709381AF9A8C700D82006 /* gtest-all.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2F9709171AF9A6D600D82006 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2F9709051AF9A6A900D82006 /* plustache */; + targetProxy = 2F9709161AF9A6D600D82006 /* PBXContainerItemProxy */; + }; + 2F97093A1AF9A8CE00D82006 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2F97092E1AF9A7F200D82006 /* gtest */; + targetProxy = 2F9709391AF9A8CE00D82006 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 2F9708E11AF9988D00D82006 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DGTEST_USE_OWN_TR1_TUPLE=1", + ); + }; + name = Debug; + }; + 2F9708E21AF9988D00D82006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DGTEST_USE_OWN_TR1_TUPLE=1", + ); + }; + name = Release; + }; + 2F9708E51AF998CB00D82006 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 2F9708E61AF998CB00D82006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 2F9709091AF9A6A900D82006 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2F97090A1AF9A6A900D82006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + 2F9709191AF9A6D600D82006 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + ); + INFOPLIST_FILE = ""; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2F97091A1AF9A6D600D82006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + ); + INFOPLIST_FILE = ""; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + 2F9709311AF9A7F200D82006 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2F9709321AF9A7F200D82006 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2F9708E01AF9988D00D82006 /* Build configuration list for PBXProject "plustache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9708E11AF9988D00D82006 /* Debug */, + 2F9708E21AF9988D00D82006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F9708E41AF998CB00D82006 /* Build configuration list for PBXAggregateTarget "plustache-automake" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9708E51AF998CB00D82006 /* Debug */, + 2F9708E61AF998CB00D82006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F9709081AF9A6A900D82006 /* Build configuration list for PBXNativeTarget "plustache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9709091AF9A6A900D82006 /* Debug */, + 2F97090A1AF9A6A900D82006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F9709181AF9A6D600D82006 /* Build configuration list for PBXNativeTarget "tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9709191AF9A6D600D82006 /* Debug */, + 2F97091A1AF9A6D600D82006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F9709301AF9A7F200D82006 /* Build configuration list for PBXNativeTarget "gtest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9709311AF9A7F200D82006 /* Debug */, + 2F9709321AF9A7F200D82006 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2F9708DD1AF9988D00D82006 /* Project object */; +} diff --git a/platforms/xcode/plustache.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/platforms/xcode/plustache.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/platforms/xcode/plustache.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/platforms/xcode/plustache.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/platforms/xcode/plustache.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..08de0be --- /dev/null +++ b/platforms/xcode/plustache.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme b/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme new file mode 100644 index 0000000..dc486a6 --- /dev/null +++ b/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9b6b6c3dbd6da79742655b4930c8f72e85c30bcc Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 22:43:43 -0700 Subject: [PATCH 04/23] regex fix for multiline section support (incidentally fixes failing nested section test) --- src/template.cpp | 6 ++++-- tests/test_collections_plustache.cpp | 30 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index c1e581a..c57700a 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -77,8 +77,10 @@ void template_t::compile_data() ctag = "\\}\\}"; // tag and section regex tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag); - section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + "\\s*(.+?)\\s*" - + otag + "/\\2"+ctag); + section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + + "(?:[ \\t]*\\n)?" + // ignore leading whitespace + "((?:.|\\s)+?)" + // section content + otag + "\\/\\2" + ctag); } /** diff --git a/tests/test_collections_plustache.cpp b/tests/test_collections_plustache.cpp index aa88b4e..8e2fee1 100644 --- a/tests/test_collections_plustache.cpp +++ b/tests/test_collections_plustache.cpp @@ -100,3 +100,33 @@ TEST_F(CollectionsTest, TestCollectionMultipleWithMultipleFields) expected += "Hi Daniel, I am Jerry, I do Magic."; EXPECT_EQ(expected, result_multiple_fields); } +TEST_F(CollectionsTest, TestCollectionMultiLine) +{ + std::string template_string = + "Hi I am {{me}}.\n" + "{{#people}}\n" + "Hi {{me}}, I am {{name}}, I do {{work}}.\n" + "{{/people}}"; + + Plustache::Context ctx; + ctx.add("me", "Daniel"); + + PlustacheTypes::ObjectType tom; + tom["name"] = "Tom"; + tom["work"] = "Accounting"; + ctx.add("people", tom); + + PlustacheTypes::ObjectType jerry; + jerry["name"] = "Jerry"; + jerry["work"] = "Magic"; + ctx.add("people", jerry); + + std::string expected = "Hi I am Daniel.\n"; + expected += "Hi Daniel, I am Tom, I do Accounting.\n"; + expected += "Hi Daniel, I am Jerry, I do Magic.\n"; + + Plustache::template_t t; + std::string actual = t.render(template_string, ctx); + + EXPECT_EQ(expected, actual); +} From cc4c60351af13191996ff3188a462bca4968a898 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 22:48:11 -0700 Subject: [PATCH 05/23] DRYer tag/section construction --- include/plustache/template.hpp | 1 + src/template.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/plustache/template.hpp b/include/plustache/template.hpp index 238f57b..c9311b9 100644 --- a/include/plustache/template.hpp +++ b/include/plustache/template.hpp @@ -48,6 +48,7 @@ namespace Plustache { const std::string& closetag); void compile_data(); std::string get_template(const std::string& tmpl); + void update_tags(); }; } // namespace Plustache #endif diff --git a/src/template.cpp b/src/template.cpp index c57700a..734f1cc 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -71,10 +71,16 @@ void template_t::compile_data() escape_lut[">"] = ">"; escape_lut["\\"] = "\"; escape_lut["\""] = """; + // regex for what to escape in a html std::string escape_chars.assign("(<|>|\"|\\\\|&)"); + + // tag delimiters otag = "\\{\\{"; ctag = "\\}\\}"; + update_tags(); +} +void template_t::update_tags() { // tag and section regex tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag); section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + @@ -417,10 +423,7 @@ void template_t::change_delimiter(const std::string& opentag, { otag = opentag; ctag = closetag; - // tag and section regex - template_t::tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag); - template_t::section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + - "\\s*(.+?)\\s*" + otag + "/\\2"+ctag); + update_tags(); } /** From 3e598e8560874fce4af08a9834f2775d91151e98 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 23:08:07 -0700 Subject: [PATCH 06/23] fixing failing unescape test --- src/template.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template.cpp b/src/template.cpp index 734f1cc..e13b41f 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -143,7 +143,7 @@ std::string template_t::render_tags(const std::string& tmplate, size_t found = s.find(f); while(found != std::string::npos) { - s.replace(found,f.length(),"\\\\"); + s.replace(found,f.length(),"\\"); found = s.find(f, found+2); } repl.assign(s); From ae7fc1e7da05871d7d82d1c7c0f4b29b44b0214e Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 23:22:31 -0700 Subject: [PATCH 07/23] cleaning up commented-out boost code; updating README --- Makefile.am | 2 -- README.md | 6 ++---- configure.ac | 1 - include/plustache/template.hpp | 2 -- src/template.cpp | 3 --- 5 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Makefile.am b/Makefile.am index ba3ced2..37c2132 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,10 +1,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -#LDFLAGS=-lboost_regex-mt pkginclude_HEADERS = include/plustache/template.hpp include/plustache/context.hpp include/plustache/plustache_types.hpp check_PROGRAMS = test-program test_program_CPPFLAGS=-Ivendor/gtest-1.6.0/include -I$(top_srcdir)/include test_program_LDFLAGS=-Lvendor/gtest-1.6.0/lib/.libs -lgtest -#-lboost_regex-mt test_program_SOURCES = tests/test_change_delimiter.cpp tests/test_collections_plustache.cpp tests/test_html_escape_plustache.cpp tests/test_inverted_sections.cpp tests/test_multiple_plustache.cpp tests/test_nested_sections_plustache.cpp tests/test_partials_plustache.cpp tests/test_sections_plustache.cpp tests/test_simple_plustache.cpp tests/tests.cpp test_program_LDADD = .libs/libplustache.a diff --git a/README.md b/README.md index e2df2c0..a7d4efe 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -Fork of plustache to remove dependency on Boost. -NOTE: Unit-tests are broken now - # plustache - mustache templates for C++ Basic port of [mustache templating](http://mustache.github.com) to C++. +This is a fork of plustache to remove the dependency on Boost. Also adds an Xcode project with library and test targets, and fixes some bugs. + ## Motivation I just wanted to port mustache and build simple templating for C++. And I am still trying hard to keep it simple. @@ -155,5 +154,4 @@ If you get the tr1/tuple error, do: * plustache executable ## Dependencies -* boost for regex and some other things * google test for unit testing (included) diff --git a/configure.ac b/configure.ac index 2bd88a6..38c76b8 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,6 @@ AC_PROG_CC AC_PROG_INSTALL # Checks for libraries. -#AC_CHECK_LIB([boost_regex], [main]) AC_CHECK_LIB([gtest], [main]) # Checks for header files. diff --git a/include/plustache/template.hpp b/include/plustache/template.hpp index c9311b9..f3667c5 100644 --- a/include/plustache/template.hpp +++ b/include/plustache/template.hpp @@ -8,8 +8,6 @@ #include #include #include -//#include -//#include #include #include diff --git a/src/template.cpp b/src/template.cpp index e13b41f..b8aaba1 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -10,9 +10,6 @@ #include #include -//#include -//#include - #include #include From c7c90b8cf01f871707a43627a3316ba8f83cfae2 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Tue, 5 May 2015 23:49:52 -0700 Subject: [PATCH 08/23] further improving multiline section support by collapsing dangling newlines --- src/template.cpp | 9 +++++++++ tests/test_collections_plustache.cpp | 13 +++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index b8aaba1..b7e70d6 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -283,8 +283,17 @@ std::string template_t::render_sections(const std::string& tmplate, rest.assign(matches[0].second, end); start = matches[0].second; } + + // Collapse end-of-section newlines + if (rest.length() && ret.length() && + rest[0] == '\n' && + rest[0] == ret[ret.length() - 1]) { + ret = ret.substr(0, ret.length() - 1); + } + // append and return ret += rest; + return ret; } diff --git a/tests/test_collections_plustache.cpp b/tests/test_collections_plustache.cpp index 8e2fee1..35debd2 100644 --- a/tests/test_collections_plustache.cpp +++ b/tests/test_collections_plustache.cpp @@ -106,7 +106,9 @@ TEST_F(CollectionsTest, TestCollectionMultiLine) "Hi I am {{me}}.\n" "{{#people}}\n" "Hi {{me}}, I am {{name}}, I do {{work}}.\n" - "{{/people}}"; + "{{/people}}\n" + "\n" + "Farewell!\n"; Plustache::Context ctx; ctx.add("me", "Daniel"); @@ -121,9 +123,12 @@ TEST_F(CollectionsTest, TestCollectionMultiLine) jerry["work"] = "Magic"; ctx.add("people", jerry); - std::string expected = "Hi I am Daniel.\n"; - expected += "Hi Daniel, I am Tom, I do Accounting.\n"; - expected += "Hi Daniel, I am Jerry, I do Magic.\n"; + std::string expected = + "Hi I am Daniel.\n" + "Hi Daniel, I am Tom, I do Accounting.\n" + "Hi Daniel, I am Jerry, I do Magic.\n" + "\n" + "Farewell!\n"; Plustache::template_t t; std::string actual = t.render(template_string, ctx); From eaca99733e3822af3206f41ae9562d832faa3e8f Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Wed, 6 May 2015 02:45:56 -0700 Subject: [PATCH 09/23] using raw strings for more readable tests --- tests/test_collections_plustache.cpp | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/tests/test_collections_plustache.cpp b/tests/test_collections_plustache.cpp index 35debd2..2863086 100644 --- a/tests/test_collections_plustache.cpp +++ b/tests/test_collections_plustache.cpp @@ -102,14 +102,6 @@ TEST_F(CollectionsTest, TestCollectionMultipleWithMultipleFields) } TEST_F(CollectionsTest, TestCollectionMultiLine) { - std::string template_string = - "Hi I am {{me}}.\n" - "{{#people}}\n" - "Hi {{me}}, I am {{name}}, I do {{work}}.\n" - "{{/people}}\n" - "\n" - "Farewell!\n"; - Plustache::Context ctx; ctx.add("me", "Daniel"); @@ -123,15 +115,27 @@ TEST_F(CollectionsTest, TestCollectionMultiLine) jerry["work"] = "Magic"; ctx.add("people", jerry); + std::string tmplate = +R"---tmplate---( +Hi! I am {{me}}. +{{#people}} +Hello, {{me}}; I am {{name}}, and I do {{work}}. +{{/people}} + +*crickets* +)---tmplate---"; + std::string expected = - "Hi I am Daniel.\n" - "Hi Daniel, I am Tom, I do Accounting.\n" - "Hi Daniel, I am Jerry, I do Magic.\n" - "\n" - "Farewell!\n"; - +R"---expected---( +Hi! I am Daniel. +Hello, Daniel; I am Tom, and I do Accounting. +Hello, Daniel; I am Jerry, and I do Magic. + +*crickets* +)---expected---"; + Plustache::template_t t; - std::string actual = t.render(template_string, ctx); + std::string actual = t.render(tmplate, ctx); EXPECT_EQ(expected, actual); } From b643ea5f93abe9c5060d7bf2e5212ad9baa1b59f Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Wed, 6 May 2015 02:52:00 -0700 Subject: [PATCH 10/23] list sections with nested sections weren't iterating properly; now they are --- src/template.cpp | 38 ++++++++++++++--------- tests/test_collections_plustache.cpp | 46 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index b7e70d6..ac10b59 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -228,6 +228,7 @@ std::string template_t::render_sections(const std::string& tmplate, std::string text(start, matches[0].second); std::string key(matches[2].first, matches[2].second); std::string modifier(matches[1]); + // trimming trim(key); trim(modifier); @@ -235,6 +236,7 @@ std::string template_t::render_sections(const std::string& tmplate, std::string show = "false"; CollectionType values; values = ctx.get(key); + if (values.size() == 1) { // if we don't have a collection, we find the key and an @@ -254,33 +256,39 @@ std::string template_t::render_sections(const std::string& tmplate, { show = "true"; } + // inverted section? if (modifier == "^" && show == "false") show = "true"; else if (modifier == "^" && show == "true") show = "false"; - // assign replacement content + + // Generate content if (show == "true") { - if (std::regex_search(matches[3].first, matches[3].second, section, - std::regex_constants::match_default | std::regex_constants::format_default)) + for(CollectionType::iterator it = values.begin(); + it != values.end(); ++it) { - repl.assign(template_t::render_sections(matches[3], ctx)); - } - else - { - for(CollectionType::iterator it = values.begin(); - it != values.end(); ++it) + std::string content = matches[3]; + Context small_ctx; + small_ctx = ctx; + small_ctx.add(*it); + + if (std::regex_search(content, section, + std::regex_constants::match_default | std::regex_constants::format_default)) { - Context small_ctx; - small_ctx = ctx; - small_ctx.add(*it); - repl += template_t::render_tags(matches[3], small_ctx); + content.assign(template_t::render_sections(content, small_ctx)); } + + repl += template_t::render_tags(content, small_ctx); } } + // Hide section with empty content else repl.assign(""); - ret += std::regex_replace(text, section, repl, - std::regex_constants::match_default | std::regex_constants::format_default); + + // Replace matched section with generated text + ret += std::regex_replace(text, section, repl, std::regex_constants::match_default | std::regex_constants::format_default); + // Store the rest of the template for the next pass rest.assign(matches[0].second, end); + // Set the next starting point at the end of the current section start = matches[0].second; } diff --git a/tests/test_collections_plustache.cpp b/tests/test_collections_plustache.cpp index 2863086..0b4430f 100644 --- a/tests/test_collections_plustache.cpp +++ b/tests/test_collections_plustache.cpp @@ -139,3 +139,49 @@ Hello, Daniel; I am Jerry, and I do Magic. EXPECT_EQ(expected, actual); } + +TEST_F(CollectionsTest, TestCollectionMultiLineConditionals) +{ + Plustache::Context ctx; + ctx.add("me", "Daniel"); + + PlustacheTypes::ObjectType tom; + tom["name"] = "Tom"; + tom["work"] = "Accounting"; + tom["surprise"] = "false"; + ctx.add("people", tom); + + PlustacheTypes::ObjectType jerry; + jerry["name"] = "Jerry"; + jerry["work"] = "Magic"; + jerry["surprise"] = "true"; + ctx.add("people", jerry); + + std::string tmplate = +R"---tmplate---( +Hi! I am {{me}}. +{{#people}} +Hello, {{me}}; I am {{name}}, and I do {{work}}. +{{#surprise}} +*{{name}} disappears in a flash of light and smoke* +{{/surprise}} +{{/people}} + +*crickets* +)---tmplate---"; + + std::string expected = +R"---expected---( +Hi! I am Daniel. +Hello, Daniel; I am Tom, and I do Accounting. +Hello, Daniel; I am Jerry, and I do Magic. +*Jerry disappears in a flash of light and smoke* + +*crickets* +)---expected---"; + + Plustache::template_t t; + std::string actual = t.render(tmplate, ctx); + + EXPECT_EQ(expected, actual); +} From 1b2d36dec1dbc480a73622a08153967f69d56c43 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Wed, 6 May 2015 04:14:32 -0700 Subject: [PATCH 11/23] even better section newline handling --- src/template.cpp | 21 +++---- tests/test_inverted_sections.cpp | 96 ++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index ac10b59..b21113c 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -286,17 +286,18 @@ std::string template_t::render_sections(const std::string& tmplate, // Replace matched section with generated text ret += std::regex_replace(text, section, repl, std::regex_constants::match_default | std::regex_constants::format_default); + + // Check on end-of-section newlines + bool shouldSwallowNextNewline = + // If the section ended in a newline, or was empty, it's swallowable... + ((repl[repl.length() - 1] == '\n') || show == "false") && + // ...if that's the case, and the section is followed by a newline, swallow it. + (std::string(matches[0].second, matches[0].second + 1) == "\n"); + // Store the rest of the template for the next pass - rest.assign(matches[0].second, end); - // Set the next starting point at the end of the current section - start = matches[0].second; - } - - // Collapse end-of-section newlines - if (rest.length() && ret.length() && - rest[0] == '\n' && - rest[0] == ret[ret.length() - 1]) { - ret = ret.substr(0, ret.length() - 1); + auto next = matches[0].second + (shouldSwallowNextNewline ? 1 : 0); + rest.assign(next, end); + start = next; } // append and return diff --git a/tests/test_inverted_sections.cpp b/tests/test_inverted_sections.cpp index de8efd8..0ac94bb 100644 --- a/tests/test_inverted_sections.cpp +++ b/tests/test_inverted_sections.cpp @@ -10,11 +10,7 @@ class InvertedSectionsTest : public ::testing::Test { protected: - std::string result_string; - std::string result_file; - std::string template_string; PlustacheTypes::ObjectType ctx; - std::string file; InvertedSectionsTest() { @@ -26,58 +22,76 @@ class InvertedSectionsTest : public ::testing::Test virtual void SetUp() { - template_string = "Hi I am {{name}}.\n"; - template_string += "{{# showme}}"; - template_string += "I like {{pet}}."; - template_string += "{{/ showme}}"; - template_string += "{{^ inverted}}"; - template_string += "Hope you can see me."; - template_string += "{{/ inverted}}"; - template_string += "{{^ inverted2}}"; - template_string += "me too."; - template_string += "{{/ inverted2}}"; - template_string += "{{^ stealth}}"; - template_string += "I'm invisible."; - template_string += "{{/ stealth}}"; - file = "sections.mustache"; - - std::ofstream myfile; - myfile.open (file.c_str()); - myfile << template_string; - myfile.close(); - ctx["name"] = "Daniel"; ctx["pet"] = "turtles"; ctx["showme"] = "true"; ctx["stealth"] = "true"; ctx["inverted"] = "false"; - Plustache::template_t t; - result_string = t.render(template_string, ctx); - result_file = t.render(file, ctx); } virtual void TearDown() { - remove(file.c_str()); } - }; // Tests that a simple mustache tag is replaced -TEST_F(InvertedSectionsTest, TestInvertedSectionMustacheFromString) +TEST_F(InvertedSectionsTest, TestInvertedSection) { - std::string expected = "Hi I am Daniel.\n"; - expected += "I like turtles."; - expected += "Hope you can see me."; - expected += "me too."; - EXPECT_EQ(expected, result_string); + std::string tmplate= + "Hi I am {{name}}.\n" + "{{# showme}}" + "I like {{pet}}." + "{{/ showme}}" + "{{^ inverted}}" + "Hope you can see me." + "{{/ inverted}}" + "{{^ inverted2}}" + "me too." + "{{/ inverted2}}" + "{{^ stealth}}" + "I'm invisible." + "{{/ stealth}}"; + std::string expected = + "Hi I am Daniel.\n" + "I like turtles." + "Hope you can see me." + "me too."; + + Plustache::template_t t; + std::string actual = t.render(tmplate, ctx); + + EXPECT_EQ(expected, actual); } -TEST_F(InvertedSectionsTest, TestInvertedSectionMustacheFromFile) +TEST_F(InvertedSectionsTest, TestInvertedSectionWithNewlines) { - std::string expected = "Hi I am Daniel.\n"; - expected += "I like turtles."; - expected += "Hope you can see me."; - expected += "me too."; - EXPECT_EQ(expected, result_file); + std::string tmplate = +R"---tmplate---( +Hi I am {{name}}. +{{# showme}} +I like {{pet}}. +{{/ showme}} +{{^ inverted}} +Hope you can see me. +{{/ inverted}} +{{^ inverted2}} +me too. +{{/ inverted2}} +{{^ stealth}} +I'm invisible. +{{/ stealth}} +)---tmplate---"; + + std::string expected = +R"---expected---( +Hi I am Daniel. +I like turtles. +Hope you can see me. +me too. +)---expected---"; + + Plustache::template_t t; + std::string actual = t.render(tmplate, ctx); + + EXPECT_EQ(expected, actual); } From a88cd2d6bbcfd4dee7aea749088026ccafff3254 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Fri, 5 Jun 2015 07:53:41 -0700 Subject: [PATCH 12/23] Use copy files instead of headers build phase --- .../xcode/plustache.xcodeproj/project.pbxproj | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/platforms/xcode/plustache.xcodeproj/project.pbxproj b/platforms/xcode/plustache.xcodeproj/project.pbxproj index 1d72c21..8030a1c 100644 --- a/platforms/xcode/plustache.xcodeproj/project.pbxproj +++ b/platforms/xcode/plustache.xcodeproj/project.pbxproj @@ -33,12 +33,12 @@ 2F9709241AF9A73E00D82006 /* test_partials_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F61AF9993B00D82006 /* test_partials_plustache.cpp */; }; 2F9709251AF9A73E00D82006 /* test_sections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F71AF9993B00D82006 /* test_sections_plustache.cpp */; }; 2F9709261AF9A73E00D82006 /* test_simple_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F81AF9993B00D82006 /* test_simple_plustache.cpp */; }; - 2F9709281AF9A75300D82006 /* context.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FB1AF999B700D82006 /* context.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F9709291AF9A75300D82006 /* plustache_types.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FC1AF999B700D82006 /* plustache_types.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F97092A1AF9A75300D82006 /* template.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2F9708FD1AF999B700D82006 /* template.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; 2F9709381AF9A8C700D82006 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709331AF9A86D00D82006 /* gtest-all.cc */; }; 2F97093B1AF9A8D600D82006 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F97092F1AF9A7F200D82006 /* libgtest.a */; }; 2F97093C1AF9AAC100D82006 /* GoogleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709011AF9A63800D82006 /* GoogleTests.mm */; }; + 2FEF3FFC1B21EC3F00A1FFD7 /* context.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FB1AF999B700D82006 /* context.hpp */; }; + 2FEF3FFD1B21EC3F00A1FFD7 /* plustache_types.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FC1AF999B700D82006 /* plustache_types.hpp */; }; + 2FEF3FFE1B21EC3F00A1FFD7 /* template.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FD1AF999B700D82006 /* template.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -58,6 +58,21 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 2FEF3FFB1B21EC3800A1FFD7 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 2FEF3FFC1B21EC3F00A1FFD7 /* context.hpp in CopyFiles */, + 2FEF3FFD1B21EC3F00A1FFD7 /* plustache_types.hpp in CopyFiles */, + 2FEF3FFE1B21EC3F00A1FFD7 /* template.hpp in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 2F9708ED1AF9992D00D82006 /* context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = context.cpp; sourceTree = ""; }; 2F9708EF1AF9992D00D82006 /* template.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = template.cpp; sourceTree = ""; }; @@ -196,16 +211,6 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 2F9709041AF9A6A900D82006 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 2F97092A1AF9A75300D82006 /* template.hpp in Headers */, - 2F9709291AF9A75300D82006 /* plustache_types.hpp in Headers */, - 2F9709281AF9A75300D82006 /* context.hpp in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 2F97092D1AF9A7F200D82006 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -220,9 +225,9 @@ isa = PBXNativeTarget; buildConfigurationList = 2F9709081AF9A6A900D82006 /* Build configuration list for PBXNativeTarget "plustache" */; buildPhases = ( + 2FEF3FFB1B21EC3800A1FFD7 /* CopyFiles */, 2F9709021AF9A6A900D82006 /* Sources */, 2F9709031AF9A6A900D82006 /* Frameworks */, - 2F9709041AF9A6A900D82006 /* Headers */, ); buildRules = ( ); From c45900f84aeb14b3f4dbb4687783fa798ace87c5 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Fri, 19 Jun 2015 19:11:14 -0700 Subject: [PATCH 13/23] Switch to c++0x for Xcode project --- .../xcode/plustache.xcodeproj/project.pbxproj | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/platforms/xcode/plustache.xcodeproj/project.pbxproj b/platforms/xcode/plustache.xcodeproj/project.pbxproj index 8030a1c..f03b8ee 100644 --- a/platforms/xcode/plustache.xcodeproj/project.pbxproj +++ b/platforms/xcode/plustache.xcodeproj/project.pbxproj @@ -397,6 +397,8 @@ 2F9708E11AF9988D00D82006 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DGTEST_USE_OWN_TR1_TUPLE=1", @@ -407,6 +409,8 @@ 2F9708E21AF9988D00D82006 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DGTEST_USE_OWN_TR1_TUPLE=1", @@ -432,8 +436,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -476,8 +478,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -513,8 +513,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -568,8 +566,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -616,8 +612,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -666,8 +660,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; From c4def92bfe4c8b89da515b4c8518bdab23eb1230 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Fri, 19 Jun 2015 19:14:26 -0700 Subject: [PATCH 14/23] Update travis with clang and gcc C++11 support --- .travis.yml | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa85df5..fe84fa2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,36 @@ +sudo: false language: cpp -script: autoreconf -i && ./configure && make check && ./test-program +compiler: + - gcc + - clang +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - clang +before_install: + - if [ "$CXX" = "g++" ]; then + export CXX="g++-4.9" CC="gcc-4.9"; + export CXXFLAGS="-std=c++11"; + elif [ "$CXX" = "clang++" ]; then + export CXXFLAGS="-std=c++11 -stdlib=libc++ -DGTEST_USE_OWN_TR1_TUPLE=1"; + fi +install: + - if [ "$CXX" == "clang++" ]; then + svn co --quiet http://llvm.org/svn/llvm-project/libcxx/trunk libcxx; + cd libcxx/lib && bash buildit; + ln -sf libc++.so.1.0 libc++.so.1; + cd "$TRAVIS_BUILD_DIR"; + export CXXFLAGS="$CXXFLAGS -L`pwd`/libcxx/lib -I`pwd`/libcxx/include"; + export LD_LIBRARY_PATH="`pwd`/libcxx/lib:$LD_LIBRARY_PATH"; + fi before_script: - - sudo apt-get install libgtest-dev libboost-regex-dev build-essential - ./utils/build_gtest.sh + - autoreconf -i && ./configure && make check +script: ./test-program +notifications: + email: false From d7418dbcb322b9c8ad2e5609086f3e61851fd683 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 25 Jun 2015 08:32:34 -0700 Subject: [PATCH 15/23] Add manual test runner to Xcode --- .../xcode/plustache.xcodeproj/project.pbxproj | 208 +++++++++++++++++- 1 file changed, 206 insertions(+), 2 deletions(-) diff --git a/platforms/xcode/plustache.xcodeproj/project.pbxproj b/platforms/xcode/plustache.xcodeproj/project.pbxproj index f03b8ee..9f9e05a 100644 --- a/platforms/xcode/plustache.xcodeproj/project.pbxproj +++ b/platforms/xcode/plustache.xcodeproj/project.pbxproj @@ -36,6 +36,19 @@ 2F9709381AF9A8C700D82006 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709331AF9A86D00D82006 /* gtest-all.cc */; }; 2F97093B1AF9A8D600D82006 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F97092F1AF9A7F200D82006 /* libgtest.a */; }; 2F97093C1AF9AAC100D82006 /* GoogleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2F9709011AF9A63800D82006 /* GoogleTests.mm */; }; + 2F9BE7CA1B3B5A510098800C /* tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9BE7C81B3B5A3D0098800C /* tests.cpp */; }; + 2F9BE7D61B3B5BCF0098800C /* tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9BE7C81B3B5A3D0098800C /* tests.cpp */; }; + 2F9BE7D71B3B5BE30098800C /* test_change_delimiter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F01AF9993B00D82006 /* test_change_delimiter.cpp */; }; + 2F9BE7D81B3B5BE30098800C /* test_collections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F11AF9993B00D82006 /* test_collections_plustache.cpp */; }; + 2F9BE7D91B3B5BE30098800C /* test_html_escape_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F21AF9993B00D82006 /* test_html_escape_plustache.cpp */; }; + 2F9BE7DA1B3B5BE30098800C /* test_inverted_sections.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F31AF9993B00D82006 /* test_inverted_sections.cpp */; }; + 2F9BE7DB1B3B5BE30098800C /* test_multiple_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F41AF9993B00D82006 /* test_multiple_plustache.cpp */; }; + 2F9BE7DC1B3B5BE30098800C /* test_nested_sections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F51AF9993B00D82006 /* test_nested_sections_plustache.cpp */; }; + 2F9BE7DD1B3B5BE30098800C /* test_partials_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F61AF9993B00D82006 /* test_partials_plustache.cpp */; }; + 2F9BE7DE1B3B5BE30098800C /* test_sections_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F71AF9993B00D82006 /* test_sections_plustache.cpp */; }; + 2F9BE7DF1B3B5BE30098800C /* test_simple_plustache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F9708F81AF9993B00D82006 /* test_simple_plustache.cpp */; }; + 2F9BE7E41B3B5C4C0098800C /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F97092F1AF9A7F200D82006 /* libgtest.a */; }; + 2F9BE7E51B3B5C4F0098800C /* libplustache.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F9709061AF9A6A900D82006 /* libplustache.a */; }; 2FEF3FFC1B21EC3F00A1FFD7 /* context.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FB1AF999B700D82006 /* context.hpp */; }; 2FEF3FFD1B21EC3F00A1FFD7 /* plustache_types.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FC1AF999B700D82006 /* plustache_types.hpp */; }; 2FEF3FFE1B21EC3F00A1FFD7 /* template.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2F9708FD1AF999B700D82006 /* template.hpp */; }; @@ -56,9 +69,32 @@ remoteGlobalIDString = 2F97092E1AF9A7F200D82006; remoteInfo = gtest; }; + 2F9BE7E01B3B5C450098800C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2F9708DD1AF9988D00D82006 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2F97092E1AF9A7F200D82006; + remoteInfo = gtest; + }; + 2F9BE7E21B3B5C480098800C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2F9708DD1AF9988D00D82006 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2F9709051AF9A6A900D82006; + remoteInfo = plustache; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 2F9BE7CD1B3B5B9C0098800C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 2FEF3FFB1B21EC3800A1FFD7 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -93,6 +129,8 @@ 2F97090F1AF9A6D600D82006 /* tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 2F97092F1AF9A7F200D82006 /* libgtest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; }; 2F9709331AF9A86D00D82006 /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "gtest-all.cc"; sourceTree = ""; }; + 2F9BE7C81B3B5A3D0098800C /* tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tests.cpp; path = ../../tests/tests.cpp; sourceTree = SOURCE_ROOT; }; + 2F9BE7CF1B3B5B9C0098800C /* tests-manual */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "tests-manual"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -119,6 +157,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2F9BE7CC1B3B5B9C0098800C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9BE7E51B3B5C4F0098800C /* libplustache.a in Frameworks */, + 2F9BE7E41B3B5C4C0098800C /* libgtest.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -128,6 +175,7 @@ 2F9708FA1AF9996000D82006 /* include */, 2F9708EB1AF998E400D82006 /* src */, 2F9708EC1AF9990500D82006 /* tests */, + 2F9BE7D01B3B5B9C0098800C /* tests-manual */, 2F9709361AF9A87F00D82006 /* vendor */, 2F9709071AF9A6A900D82006 /* Products */, ); @@ -185,6 +233,7 @@ 2F9709061AF9A6A900D82006 /* libplustache.a */, 2F97090F1AF9A6D600D82006 /* tests.xctest */, 2F97092F1AF9A7F200D82006 /* libgtest.a */, + 2F9BE7CF1B3B5B9C0098800C /* tests-manual */, ); name = Products; sourceTree = ""; @@ -208,6 +257,14 @@ path = "gtest-1.6.0/src"; sourceTree = ""; }; + 2F9BE7D01B3B5B9C0098800C /* tests-manual */ = { + isa = PBXGroup; + children = ( + 2F9BE7C81B3B5A3D0098800C /* tests.cpp */, + ); + path = "tests-manual"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -274,6 +331,25 @@ productReference = 2F97092F1AF9A7F200D82006 /* libgtest.a */; productType = "com.apple.product-type.library.static"; }; + 2F9BE7CE1B3B5B9C0098800C /* tests-manual */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F9BE7D31B3B5B9C0098800C /* Build configuration list for PBXNativeTarget "tests-manual" */; + buildPhases = ( + 2F9BE7CB1B3B5B9C0098800C /* Sources */, + 2F9BE7CC1B3B5B9C0098800C /* Frameworks */, + 2F9BE7CD1B3B5B9C0098800C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 2F9BE7E31B3B5C480098800C /* PBXTargetDependency */, + 2F9BE7E11B3B5C450098800C /* PBXTargetDependency */, + ); + name = "tests-manual"; + productName = "tests-manual"; + productReference = 2F9BE7CF1B3B5B9C0098800C /* tests-manual */; + productType = "com.apple.product-type.tool"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -294,6 +370,9 @@ 2F97092E1AF9A7F200D82006 = { CreatedOnToolsVersion = 6.3.1; }; + 2F9BE7CE1B3B5B9C0098800C = { + CreatedOnToolsVersion = 6.3.2; + }; }; }; buildConfigurationList = 2F9708E01AF9988D00D82006 /* Build configuration list for PBXProject "plustache" */; @@ -310,6 +389,7 @@ targets = ( 2F9709051AF9A6A900D82006 /* plustache */, 2F97090E1AF9A6D600D82006 /* tests */, + 2F9BE7CE1B3B5B9C0098800C /* tests-manual */, 2F9708E31AF998CB00D82006 /* plustache-automake */, 2F97092E1AF9A7F200D82006 /* gtest */, ); @@ -366,6 +446,7 @@ 2F9709231AF9A73E00D82006 /* test_nested_sections_plustache.cpp in Sources */, 2F97091E1AF9A73E00D82006 /* test_change_delimiter.cpp in Sources */, 2F97093C1AF9AAC100D82006 /* GoogleTests.mm in Sources */, + 2F9BE7CA1B3B5A510098800C /* tests.cpp in Sources */, 2F9709201AF9A73E00D82006 /* test_html_escape_plustache.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -378,6 +459,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 2F9BE7CB1B3B5B9C0098800C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9BE7D61B3B5BCF0098800C /* tests.cpp in Sources */, + 2F9BE7D71B3B5BE30098800C /* test_change_delimiter.cpp in Sources */, + 2F9BE7D81B3B5BE30098800C /* test_collections_plustache.cpp in Sources */, + 2F9BE7D91B3B5BE30098800C /* test_html_escape_plustache.cpp in Sources */, + 2F9BE7DA1B3B5BE30098800C /* test_inverted_sections.cpp in Sources */, + 2F9BE7DB1B3B5BE30098800C /* test_multiple_plustache.cpp in Sources */, + 2F9BE7DC1B3B5BE30098800C /* test_nested_sections_plustache.cpp in Sources */, + 2F9BE7DD1B3B5BE30098800C /* test_partials_plustache.cpp in Sources */, + 2F9BE7DE1B3B5BE30098800C /* test_sections_plustache.cpp in Sources */, + 2F9BE7DF1B3B5BE30098800C /* test_simple_plustache.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -391,6 +489,16 @@ target = 2F97092E1AF9A7F200D82006 /* gtest */; targetProxy = 2F9709391AF9A8CE00D82006 /* PBXContainerItemProxy */; }; + 2F9BE7E11B3B5C450098800C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2F97092E1AF9A7F200D82006 /* gtest */; + targetProxy = 2F9BE7E01B3B5C450098800C /* PBXContainerItemProxy */; + }; + 2F9BE7E31B3B5C480098800C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2F9709051AF9A6A900D82006 /* plustache */; + targetProxy = 2F9BE7E21B3B5C480098800C /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -398,10 +506,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LIBRARY = "compiler-default"; + GCC_VERSION = ""; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DGTEST_USE_OWN_TR1_TUPLE=1", + "-std=c++11", ); }; name = Debug; @@ -410,10 +520,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LIBRARY = "compiler-default"; + GCC_VERSION = ""; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DGTEST_USE_OWN_TR1_TUPLE=1", + "-std=c++11", ); }; name = Release; @@ -697,6 +809,89 @@ }; name = Release; }; + 2F9BE7D41B3B5B9C0098800C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 2F9BE7D51B3B5B9C0098800C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SOURCE_ROOT)/../../vendor/gtest-1.6.0/include", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -745,6 +940,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 2F9BE7D31B3B5B9C0098800C /* Build configuration list for PBXNativeTarget "tests-manual" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9BE7D41B3B5B9C0098800C /* Debug */, + 2F9BE7D51B3B5B9C0098800C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 2F9708DD1AF9988D00D82006 /* Project object */; From 05f821037640a5bbb96951d99f4f7e16467618e7 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 25 Jun 2015 08:34:34 -0700 Subject: [PATCH 16/23] Simplify test_change_delimiter --- tests/test_change_delimiter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_change_delimiter.cpp b/tests/test_change_delimiter.cpp index 127e296..6a94cb8 100644 --- a/tests/test_change_delimiter.cpp +++ b/tests/test_change_delimiter.cpp @@ -41,10 +41,6 @@ class ChangeDelimiterTest : public ::testing::Test ctx["name"] = "Daniel"; ctx["pet"] = "turtles"; - Plustache::template_t t; - result_string = t.render(template_string, ctx); - Plustache::template_t t2; - result_file = t2.render(file, ctx); } virtual void TearDown() @@ -57,6 +53,8 @@ class ChangeDelimiterTest : public ::testing::Test // Tests that a simple mustache tag is replaced TEST_F(ChangeDelimiterTest, TestChangeDelimiterFromString) { + Plustache::template_t t; + result_string = t.render(template_string, ctx); std::string expected = "Hi I am Daniel.\n"; expected += "I like turtles."; EXPECT_EQ(expected, result_string); @@ -64,6 +62,8 @@ TEST_F(ChangeDelimiterTest, TestChangeDelimiterFromString) TEST_F(ChangeDelimiterTest, TestChangeDelimiterFromFile) { + Plustache::template_t t2; + result_file = t2.render(file, ctx); std::string expected = "Hi I am Daniel.\n"; expected += "I like turtles."; EXPECT_EQ(expected, result_file); From 1304486e8a32177148edad9262d919f51d02b28e Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 25 Jun 2015 08:40:00 -0700 Subject: [PATCH 17/23] Account for difference in GCC's regex implementation The while loop was written with the assumption that the match object would be completely repopulated on the next call to regex_search. That makes sense, and GCC's failure to reset the object is probably a bug, but this accounts for it. --- src/template.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/template.cpp b/src/template.cpp index b21113c..ef1d83e 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -190,6 +190,9 @@ std::string template_t::render_tags(const std::string& tmplate, // set start for next tag and rest of std::string rest.assign(matches[0].second, end); start = matches[0].second; + + // Reset for next round (required for libstdc++ implementation) + matches = std::match_results(); } // append and return ret += rest; From e0f6fcc030febbfc43207a8d0481ea1a6f84bfd3 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 25 Jun 2015 08:59:17 -0700 Subject: [PATCH 18/23] Update dependencies in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a7d4efe..3f9573f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # plustache - mustache templates for C++ Basic port of [mustache templating](http://mustache.github.com) to C++. -This is a fork of plustache to remove the dependency on Boost. Also adds an Xcode project with library and test targets, and fixes some bugs. - ## Motivation I just wanted to port mustache and build simple templating for C++. And I am still trying hard to keep it simple. @@ -154,4 +152,5 @@ If you get the tr1/tuple error, do: * plustache executable ## Dependencies +* compiler support for C++11's regex implementation (Clang or GCC 4.9+) * google test for unit testing (included) From ce1a4e6a7d4dd58497056c94a50ba9735b860010 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 30 Jul 2015 08:20:47 -0700 Subject: [PATCH 19/23] Update build settings --- .travis.yml | 3 --- platforms/xcode/plustache.xcodeproj/project.pbxproj | 7 ++++++- .../xcshareddata/xcschemes/plustache.xcscheme | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe84fa2..cbfe279 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,3 @@ before_script: - ./utils/build_gtest.sh - autoreconf -i && ./configure && make check script: ./test-program -notifications: - email: false - diff --git a/platforms/xcode/plustache.xcodeproj/project.pbxproj b/platforms/xcode/plustache.xcodeproj/project.pbxproj index 9f9e05a..906ef26 100644 --- a/platforms/xcode/plustache.xcodeproj/project.pbxproj +++ b/platforms/xcode/plustache.xcodeproj/project.pbxproj @@ -356,7 +356,7 @@ 2F9708DD1AF9988D00D82006 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0640; TargetAttributes = { 2F9708E31AF998CB00D82006 = { CreatedOnToolsVersion = 6.3.1; @@ -508,6 +508,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "compiler-default"; GCC_VERSION = ""; + ONLY_ACTIVE_ARCH = YES; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DGTEST_USE_OWN_TR1_TUPLE=1", @@ -559,6 +560,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -601,6 +603,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -735,6 +738,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -783,6 +787,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; diff --git a/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme b/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme index dc486a6..c7e4ff8 100644 --- a/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme +++ b/platforms/xcode/plustache.xcodeproj/xcshareddata/xcschemes/plustache.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 30 Jul 2015 08:27:40 -0700 Subject: [PATCH 20/23] Apply project whitespace styles --- src/template.cpp | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index ef1d83e..3a55463 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -19,14 +19,16 @@ using namespace Plustache; // trim from start static inline std::string <rim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), + std::not1(std::ptr_fun(std::isspace)))); return s; } // trim from end static inline std::string &rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), + std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; } @@ -114,13 +116,15 @@ std::string template_t::render_tags(const std::string& tmplate, end = tmplate.end(); // return whole std::string when no tags are found if (!regex_search(start, end, matches, tag, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { ret = tmplate; } // loop through tags and replace while (regex_search(start, end, matches, tag, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { std::string modifier(matches[1].first, matches[1].second); std::string key(matches[2].first, matches[2].second); @@ -170,7 +174,8 @@ std::string template_t::render_tags(const std::string& tmplate, // replace ret += regex_replace(text, tag, repl, - std::regex_constants::match_default | std::regex_constants::format_default); + std::regex_constants::match_default | + std::regex_constants::format_default); // change delimiter after was removed if (modifier == "=") { @@ -180,7 +185,8 @@ std::string template_t::render_tags(const std::string& tmplate, std::match_results delim_m; // search for the delimiters std::regex_search(matches[2].first, matches[2].second, delim_m, delim, - std::regex_constants::match_default | std::regex_constants::format_default); + std::regex_constants::match_default | + std::regex_constants::format_default); // set new otag and ctag std::string new_otag = delim_m[1]; std::string new_ctag = delim_m[2]; @@ -219,13 +225,15 @@ std::string template_t::render_sections(const std::string& tmplate, end = tmplate.end(); // return the whole template if no sections are found if (!std::regex_search(start, end, matches, section, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { ret = tmplate; } // loop through sections and render while (std::regex_search(start, end, matches, section, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { // std::string assignments std::string text(start, matches[0].second); @@ -276,9 +284,11 @@ std::string template_t::render_sections(const std::string& tmplate, small_ctx.add(*it); if (std::regex_search(content, section, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { - content.assign(template_t::render_sections(content, small_ctx)); + content.assign(template_t::render_sections( + content, small_ctx)); } repl += template_t::render_tags(content, small_ctx); @@ -288,7 +298,9 @@ std::string template_t::render_sections(const std::string& tmplate, else repl.assign(""); // Replace matched section with generated text - ret += std::regex_replace(text, section, repl, std::regex_constants::match_default | std::regex_constants::format_default); + ret += std::regex_replace(text, section, repl, + std::regex_constants::match_default | + std::regex_constants::format_default); // Check on end-of-section newlines bool shouldSwallowNextNewline = @@ -371,13 +383,15 @@ std::string template_t::html_escape(const std::string& s) end = s.end(); // return original std::string if nothing is found if (!std::regex_search(start, end, matches, escape_chars, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { ret = s; } // search for html chars while (std::regex_search(start, end, matches, escape_chars, - std::regex_constants::match_default | std::regex_constants::format_default)) + std::regex_constants::match_default | + std::regex_constants::format_default)) { std::string key(matches[0].first, matches[0].second); std::string text(start, matches[0].second); @@ -385,7 +399,8 @@ std::string template_t::html_escape(const std::string& s) std::string repl; repl = escape_lut[key]; ret += std::regex_replace(text, escape_chars, repl, - std::regex_constants::match_default | std::regex_constants::format_default); + std::regex_constants::match_default | + std::regex_constants::format_default); rest.assign(matches[0].second, end); start = matches[0].second; } From 3ba012927071ac98b0c92a97777c279ed852791c Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 30 Jul 2015 08:29:06 -0700 Subject: [PATCH 21/23] Clarify newline skipping --- src/template.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index 3a55463..451aa5a 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -303,14 +303,14 @@ std::string template_t::render_sections(const std::string& tmplate, std::regex_constants::format_default); // Check on end-of-section newlines - bool shouldSwallowNextNewline = - // If the section ended in a newline, or was empty, it's swallowable... + bool shouldSkipNextNewline = + // If the section ended in a newline, or was empty... ((repl[repl.length() - 1] == '\n') || show == "false") && - // ...if that's the case, and the section is followed by a newline, swallow it. + // ...and the section is also followed by a newline, skip it. (std::string(matches[0].second, matches[0].second + 1) == "\n"); // Store the rest of the template for the next pass - auto next = matches[0].second + (shouldSwallowNextNewline ? 1 : 0); + auto next = matches[0].second + (shouldSkipNextNewline ? 1 : 0); rest.assign(next, end); start = next; } From 8a042926197b1a1425d5bdde6e3a6cd41f38523e Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 30 Jul 2015 08:31:09 -0700 Subject: [PATCH 22/23] Wrap else clause in braces --- src/template.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/template.cpp b/src/template.cpp index 451aa5a..13432d9 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -295,7 +295,9 @@ std::string template_t::render_sections(const std::string& tmplate, } } // Hide section with empty content - else repl.assign(""); + else { + repl.assign(""); + } // Replace matched section with generated text ret += std::regex_replace(text, section, repl, From 5f13c29f140462f8dd829498627005df9d447620 Mon Sep 17 00:00:00 2001 From: Kyle Alan Hale Date: Thu, 30 Jul 2015 08:36:35 -0700 Subject: [PATCH 23/23] Add comments to new methods --- src/template.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index 13432d9..7c43d03 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -16,24 +16,42 @@ using namespace Plustache; -// trim from start -static inline std::string <rim(std::string &s) +/** + * @brief trim whitespace from the start of a string + * + * @param s the string to trim + * + * @return s, trimmed + */ +static inline std::string <rim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); return s; } -// trim from end -static inline std::string &rtrim(std::string &s) +/** + * @brief trim whitespace from the end of a string + * + * @param s the string to trim + * + * @return s, trimmed + */ +static inline std::string &rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; } -// trim from both ends -static inline std::string &trim(std::string &s) +/** + * @brief trim whitespace from both ends of a string + * + * @param s the string to trim + * + * @return s, trimmed + */ +static inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } @@ -79,6 +97,10 @@ void template_t::compile_data() ctag = "\\}\\}"; update_tags(); } +/** + * @brief applies the current ctag/otag settings to the tag & section + * regex patterns + */ void template_t::update_tags() { // tag and section regex tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag);