Browse Source

adding cpptemplate library

Former-commit-id: 8f4d61de7a [formerly 9f307fe358]
Former-commit-id: 3f30d88de8
tempestpy_adaptions
dehnert 8 years ago
parent
commit
69a351999c
  1. 8
      resources/3rdparty/cpptemplate/LICENSE.txt
  2. 57
      resources/3rdparty/cpptemplate/README.rst
  3. 419
      resources/3rdparty/cpptemplate/cpptempl.cpp
  4. 308
      resources/3rdparty/cpptemplate/cpptempl.h
  5. 883
      resources/3rdparty/cpptemplate/cpptempl_test.cpp
  6. 41
      resources/3rdparty/cpptemplate/unit_testing.h

8
resources/3rdparty/cpptemplate/LICENSE.txt

@ -0,0 +1,8 @@
cpptempl
Copyright (c) Ryan Ginstrom
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.

57
resources/3rdparty/cpptemplate/README.rst

@ -0,0 +1,57 @@
cpptempl
=================
This is a template engine for C++.
Copyright
==================
Author: Ryan Ginstrom
MIT License
Syntax
=================
Variables::
{$variable_name}
Loops::
{% for person in people %}Name: {$person.name}{% endfor %}
If::
{% if person.name == "Bob" %}Full name: Robert{% endif %}
Usage
=======================
Define a template::
string text = "{% if item %}{$item}{% endif %}\n"
"{% if thing %}{$thing}{% endif %}" ;
Set up data::
cpptempl::data_map data ;
data["item"] = "aaa" ;
data["thing"] = "bbb" ;
Parse the template and data::
string result = cpptempl::parse(text, data) ;
Lists, nested maps
========================
Example::
cpptempl::data_map person ;
person["name"] = "Bob" ;
person["occupation"] = "Plumber" ;
cpptempl::data_map content ;
content["person"] = person ;
content["friends"].push_back("Alice") ;
content["friends"].push_back("Bob") ;
string result = parse(text, data) ;

419
resources/3rdparty/cpptemplate/cpptempl.cpp

@ -0,0 +1,419 @@
#ifdef _MSC_VER
#include "stdafx.h"
#endif
#include "cpptempl.h"
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
namespace cpptempl
{
//////////////////////////////////////////////////////////////////////////
// Data classes
//////////////////////////////////////////////////////////////////////////
// data_map
data_ptr& data_map::operator [](const std::wstring& key) {
return data[key];
}
data_ptr& data_map::operator [](const std::string& key) {
return data[utf8_to_wide(key)];
}
bool data_map::empty() {
return data.empty();
}
bool data_map::has(const wstring& key) {
return data.find(key) != data.end();
}
// data_ptr
template<>
inline void data_ptr::operator = (const data_ptr& data) {
ptr = data.ptr;
}
template<>
void data_ptr::operator = (const std::string& data) {
ptr.reset(new DataValue(utf8_to_wide(data)));
}
template<>
void data_ptr::operator = (const std::wstring& data) {
ptr.reset(new DataValue(data));
}
template<>
void data_ptr::operator = (const data_map& data) {
ptr.reset(new DataMap(data));
}
void data_ptr::push_back(const data_ptr& data) {
if (!ptr) {
ptr.reset(new DataList(data_list()));
}
data_list& list = ptr->getlist();
list.push_back(data);
}
// base data
wstring Data::getvalue()
{
throw TemplateException("Data item is not a value") ;
}
data_list& Data::getlist()
{
throw TemplateException("Data item is not a list") ;
}
data_map& Data::getmap()
{
throw TemplateException("Data item is not a dictionary") ;
}
// data value
wstring DataValue::getvalue()
{
return m_value ;
}
bool DataValue::empty()
{
return m_value.empty();
}
// data list
data_list& DataList::getlist()
{
return m_items ;
}
bool DataList::empty()
{
return m_items.empty();
}
// data map
data_map& DataMap:: getmap()
{
return m_items ;
}
bool DataMap::empty()
{
return m_items.empty();
}
//////////////////////////////////////////////////////////////////////////
// parse_val
//////////////////////////////////////////////////////////////////////////
data_ptr parse_val(wstring key, data_map &data)
{
// quoted string
if (key[0] == L'\"')
{
return make_data(boost::trim_copy_if(key, boost::is_any_of(L"\""))) ;
}
// check for dotted notation, i.e [foo.bar]
size_t index = key.find(L".") ;
if (index == wstring::npos)
{
if (!data.has(key))
{
return make_data(L"{$" + key + L"}") ;
}
return data[key] ;
}
wstring sub_key = key.substr(0, index) ;
if (!data.has(sub_key))
{
return make_data(L"{$" + key + L"}") ;
}
data_ptr item = data[sub_key] ;
return parse_val(key.substr(index+1), item->getmap()) ;
}
//////////////////////////////////////////////////////////////////////////
// Token classes
//////////////////////////////////////////////////////////////////////////
// defaults, overridden by subclasses with children
void Token::set_children( token_vector & )
{
throw TemplateException("This token type cannot have children") ;
}
token_vector & Token::get_children()
{
throw TemplateException("This token type cannot have children") ;
}
// TokenText
TokenType TokenText::gettype()
{
return TOKEN_TYPE_TEXT ;
}
void TokenText::gettext( std::wostream &stream, data_map & )
{
stream << m_text ;
}
// TokenVar
TokenType TokenVar::gettype()
{
return TOKEN_TYPE_VAR ;
}
void TokenVar::gettext( std::wostream &stream, data_map &data )
{
stream << parse_val(m_key, data)->getvalue() ;
}
// TokenFor
TokenFor::TokenFor(wstring expr)
{
std::vector<wstring> elements ;
boost::split(elements, expr, boost::is_space()) ;
if (elements.size() != 4u)
{
throw TemplateException("Invalid syntax in for statement") ;
}
m_val = elements[1] ;
m_key = elements[3] ;
}
TokenType TokenFor::gettype()
{
return TOKEN_TYPE_FOR ;
}
void TokenFor::gettext( std::wostream &stream, data_map &data )
{
data_ptr value = parse_val(m_key, data) ;
data_list &items = value->getlist() ;
for (size_t i = 0 ; i < items.size() ; ++i)
{
data_map loop ;
loop[L"index"] = make_data(boost::lexical_cast<wstring>(i+1)) ;
loop[L"index0"] = make_data(boost::lexical_cast<wstring>(i)) ;
data[L"loop"] = make_data(loop);
data[m_val] = items[i] ;
for(size_t j = 0 ; j < m_children.size() ; ++j)
{
m_children[j]->gettext(stream, data) ;
}
}
}
void TokenFor::set_children( token_vector &children )
{
m_children.assign(children.begin(), children.end()) ;
}
token_vector & TokenFor::get_children()
{
return m_children;
}
// TokenIf
TokenType TokenIf::gettype()
{
return TOKEN_TYPE_IF ;
}
void TokenIf::gettext( std::wostream &stream, data_map &data )
{
if (is_true(m_expr, data))
{
for(size_t j = 0 ; j < m_children.size() ; ++j)
{
m_children[j]->gettext(stream, data) ;
}
}
}
bool TokenIf::is_true( wstring expr, data_map &data )
{
std::vector<wstring> elements ;
boost::split(elements, expr, boost::is_space()) ;
if (elements[1] == L"not")
{
return parse_val(elements[2], data)->empty() ;
}
if (elements.size() == 2)
{
return ! parse_val(elements[1], data)->empty() ;
}
data_ptr lhs = parse_val(elements[1], data) ;
data_ptr rhs = parse_val(elements[3], data) ;
if (elements[2] == L"==")
{
return lhs->getvalue() == rhs->getvalue() ;
}
return lhs->getvalue() != rhs->getvalue() ;
}
void TokenIf::set_children( token_vector &children )
{
m_children.assign(children.begin(), children.end()) ;
}
token_vector & TokenIf::get_children()
{
return m_children;
}
// TokenEnd
TokenType TokenEnd::gettype()
{
return m_type == L"endfor" ? TOKEN_TYPE_ENDFOR : TOKEN_TYPE_ENDIF ;
}
void TokenEnd::gettext( std::wostream &, data_map &)
{
throw TemplateException("End-of-control statements have no associated text") ;
}
// gettext
// generic helper for getting text from tokens.
wstring gettext(token_ptr token, data_map &data)
{
std::wostringstream stream ;
token->gettext(stream, data) ;
return stream.str() ;
}
//////////////////////////////////////////////////////////////////////////
// parse_tree
// recursively parses list of tokens into a tree
//////////////////////////////////////////////////////////////////////////
void parse_tree(token_vector &tokens, token_vector &tree, TokenType until)
{
while(! tokens.empty())
{
// 'pops' first item off list
token_ptr token = tokens[0] ;
tokens.erase(tokens.begin()) ;
if (token->gettype() == TOKEN_TYPE_FOR)
{
token_vector children ;
parse_tree(tokens, children, TOKEN_TYPE_ENDFOR) ;
token->set_children(children) ;
}
else if (token->gettype() == TOKEN_TYPE_IF)
{
token_vector children ;
parse_tree(tokens, children, TOKEN_TYPE_ENDIF) ;
token->set_children(children) ;
}
else if (token->gettype() == until)
{
return ;
}
tree.push_back(token) ;
}
}
//////////////////////////////////////////////////////////////////////////
// tokenize
// parses a template into tokens (text, for, if, variable)
//////////////////////////////////////////////////////////////////////////
token_vector & tokenize(wstring text, token_vector &tokens)
{
while(! text.empty())
{
size_t pos = text.find(L"{") ;
if (pos == wstring::npos)
{
if (! text.empty())
{
tokens.push_back(token_ptr(new TokenText(text))) ;
}
return tokens ;
}
wstring pre_text = text.substr(0, pos) ;
if (! pre_text.empty())
{
tokens.push_back(token_ptr(new TokenText(pre_text))) ;
}
text = text.substr(pos+1) ;
if (text.empty())
{
tokens.push_back(token_ptr(new TokenText(L"{"))) ;
return tokens ;
}
// variable
if (text[0] == L'$')
{
pos = text.find(L"}") ;
if (pos != wstring::npos)
{
tokens.push_back(token_ptr (new TokenVar(text.substr(1, pos-1)))) ;
text = text.substr(pos+1) ;
}
}
// control statement
else if (text[0] == L'%')
{
pos = text.find(L"}") ;
if (pos != wstring::npos)
{
wstring expression = boost::trim_copy(text.substr(1, pos-2)) ;
text = text.substr(pos+1) ;
if (boost::starts_with(expression, L"for"))
{
tokens.push_back(token_ptr (new TokenFor(expression))) ;
}
else if (boost::starts_with(expression, L"if"))
{
tokens.push_back(token_ptr (new TokenIf(expression))) ;
}
else
{
tokens.push_back(token_ptr (new TokenEnd(boost::trim_copy(expression)))) ;
}
}
}
else
{
tokens.push_back(token_ptr(new TokenText(L"{"))) ;
}
}
return tokens ;
}
/************************************************************************
* parse
*
* 1. tokenizes template
* 2. parses tokens into tree
* 3. resolves template
* 4. returns converted text
************************************************************************/
wstring parse(wstring templ_text, data_map &data)
{
std::wostringstream stream ;
parse(stream, templ_text, data) ;
return stream.str() ;
}
std::string parse(std::string templ_text, data_map &data)
{
return wide_to_utf8(parse(utf8_to_wide(templ_text), data));
}
void parse(std::wostream &stream, wstring templ_text, data_map &data)
{
token_vector tokens ;
tokenize(templ_text, tokens) ;
token_vector tree ;
parse_tree(tokens, tree) ;
for (size_t i = 0 ; i < tree.size() ; ++i)
{
// Recursively calls gettext on each node in the tree.
// gettext returns the appropriate text for that node.
// for text, itself;
// for variable, substitution;
// for control statement, recursively gets kids
tree[i]->gettext(stream, data) ;
}
}
}

308
resources/3rdparty/cpptemplate/cpptempl.h

@ -0,0 +1,308 @@
/*
cpptempl
=================
This is a template engine for C++.
Syntax
=================
Variables: {$variable_name}
Loops: {% for person in people %}Name: {$person.name}{% endfor %}
If: {% for person.name == "Bob" %}Full name: Robert{% endif %}
Copyright
==================
Author: Ryan Ginstrom
MIT License
Usage
=======================
wstring text = L"{% if item %}{$item}{% endif %}\n"
L"{% if thing %}{$thing}{% endif %}" ;
cpptempl::data_map data ;
data[L"item"] = cpptempl::make_data(L"aaa") ;
data[L"thing"] = cpptempl::make_data(L"bbb") ;
wstring result = cpptempl::parse(text, data) ;
Handy Functions
========================
make_data() : Feed it a string, data_map, or data_list to create a data entry.
Example:
data_map person ;
person[L"name"] = make_data(L"Bob") ;
person[L"occupation"] = make_data(L"Plumber") ;
data_map data ;
data[L"person"] = make_data(person) ;
wstring result = parse(templ_text, data) ;
*/
#pragma once
#ifdef _WIN32
#pragma warning( disable : 4996 ) // 'std::copy': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
#pragma warning( disable : 4512 ) // 'std::copy': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
#endif
#include <string>
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#ifndef _MSC_VER
#include <boost/locale.hpp>
#else
#include <boost/scoped_array.hpp>
#include "windows.h"
#include "winnls.h" // unicode-multibyte conversion
#endif
#include <boost/unordered_map.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
namespace cpptempl
{
using std::wstring ;
// various typedefs
class data_ptr;
typedef std::vector<data_ptr> data_list ;
class data_map {
public:
data_ptr& operator [](const std::wstring& key);
data_ptr& operator [](const std::string& key);
bool empty();
bool has(const wstring& key);
private:
boost::unordered_map<wstring, data_ptr> data;
};
// data classes
class Data ;
class DataValue ;
class DataList ;
class DataMap ;
class data_ptr {
public:
data_ptr() {}
template<typename T> data_ptr(const T& data) {
this->operator =(data);
}
data_ptr(DataValue* data) : ptr(data) {}
data_ptr(DataList* data) : ptr(data) {}
data_ptr(DataMap* data) : ptr(data) {}
data_ptr(const data_ptr& data) {
ptr = data.ptr;
}
template<typename T> void operator = (const T& data);
void push_back(const data_ptr& data);
virtual ~data_ptr() {}
Data* operator ->() {
return ptr.get();
}
private:
boost::shared_ptr<Data> ptr;
};
template<> inline void data_ptr::operator = (const data_ptr& data);
template<> void data_ptr::operator = (const std::string& data);
template<> void data_ptr::operator = (const std::wstring& data);
template<> void data_ptr::operator = (const data_map& data);
template<typename T>
void data_ptr::operator = (const T& data) {
#ifndef _MSC_VER
std::wstring data_str = boost::lexical_cast<std::wstring>(data);
#else
#endif
this->operator =(data_str);
}
// convenience functions for recoding utf8 string to wstring and back
inline std::wstring utf8_to_wide(const std::string& text) {
#ifndef _MSC_VER
return boost::locale::conv::to_utf<wchar_t>(text, "UTF-8");
#else
// Calculate the required length of the buffer
const size_t len_needed = ::MultiByteToWideChar(CP_UTF8, 0, text.c_str(), (UINT)(text.length()) , NULL, 0 );
boost::scoped_array<wchar_t> buff(new wchar_t[len_needed+1]) ;
const size_t num_copied = ::MultiByteToWideChar(CP_UTF8, 0, text.c_str(), text.size(), buff.get(), len_needed+1) ;
return std::wstring(buff.get(), num_copied) ;
#endif
}
inline std::string wide_to_utf8(const std::wstring& text) {
#ifndef _MSC_VER
return boost::locale::conv::from_utf<>(text, "UTF-8");
#else
const size_t len_needed = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (UINT)(text.length()) , NULL, 0, NULL, NULL) ;
boost::scoped_array<char> buff(new char[len_needed+1]) ;
const size_t num_copied = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (UINT)(text.length()) , buff.get(), len_needed+1, NULL, NULL) ;
return std::string(buff.get(), num_copied) ;
#endif
}
// token classes
class Token ;
typedef boost::shared_ptr<Token> token_ptr ;
typedef std::vector<token_ptr> token_vector ;
// Custom exception class for library errors
class TemplateException : public std::exception
{
public:
TemplateException(std::string reason) : m_reason(reason){}
~TemplateException() throw() {}
const char* what() throw() {
return m_reason.c_str();
}
private:
std::string m_reason;
};
// Data types used in templates
class Data
{
public:
virtual bool empty() = 0 ;
virtual wstring getvalue();
virtual data_list& getlist();
virtual data_map& getmap() ;
};
class DataValue : public Data
{
wstring m_value ;
public:
DataValue(wstring value) : m_value(value){}
wstring getvalue();
bool empty();
};
class DataList : public Data
{
data_list m_items ;
public:
DataList(const data_list &items) : m_items(items){}
data_list& getlist() ;
bool empty();
};
class DataMap : public Data
{
data_map m_items ;
public:
DataMap(const data_map &items) : m_items(items){}
data_map& getmap();
bool empty();
};
// convenience functions for making data objects
inline data_ptr make_data(wstring val)
{
return data_ptr(new DataValue(val)) ;
}
inline data_ptr make_data(data_list &val)
{
return data_ptr(new DataList(val)) ;
}
inline data_ptr make_data(data_map &val)
{
return data_ptr(new DataMap(val)) ;
}
// get a data value from a data map
// e.g. foo.bar => data["foo"]["bar"]
data_ptr parse_val(wstring key, data_map &data) ;
typedef enum
{
TOKEN_TYPE_NONE,
TOKEN_TYPE_TEXT,
TOKEN_TYPE_VAR,
TOKEN_TYPE_IF,
TOKEN_TYPE_FOR,
TOKEN_TYPE_ENDIF,
TOKEN_TYPE_ENDFOR,
} TokenType;
// Template tokens
// base class for all token types
class Token
{
public:
virtual TokenType gettype() = 0 ;
virtual void gettext(std::wostream &stream, data_map &data) = 0 ;
virtual void set_children(token_vector &children);
virtual token_vector & get_children();
};
// normal text
class TokenText : public Token
{
wstring m_text ;
public:
TokenText(wstring text) : m_text(text){}
TokenType gettype();
void gettext(std::wostream &stream, data_map &data);
};
// variable
class TokenVar : public Token
{
wstring m_key ;
public:
TokenVar(wstring key) : m_key(key){}
TokenType gettype();
void gettext(std::wostream &stream, data_map &data);
};
// for block
class TokenFor : public Token
{
public:
wstring m_key ;
wstring m_val ;
token_vector m_children ;
TokenFor(wstring expr);
TokenType gettype();
void gettext(std::wostream &stream, data_map &data);
void set_children(token_vector &children);
token_vector &get_children();
};
// if block
class TokenIf : public Token
{
public:
wstring m_expr ;
token_vector m_children ;
TokenIf(wstring expr) : m_expr(expr){}
TokenType gettype();
void gettext(std::wostream &stream, data_map &data);
bool is_true(wstring expr, data_map &data);
void set_children(token_vector &children);
token_vector &get_children();
};
// end of block
class TokenEnd : public Token // end of control block
{
wstring m_type ;
public:
TokenEnd(wstring text) : m_type(text){}
TokenType gettype();
void gettext(std::wostream &stream, data_map &data);
};
wstring gettext(token_ptr token, data_map &data) ;
void parse_tree(token_vector &tokens, token_vector &tree, TokenType until=TOKEN_TYPE_NONE) ;
token_vector & tokenize(wstring text, token_vector &tokens) ;
// The big daddy. Pass in the template and data,
// and get out a completed doc.
void parse(std::wostream &stream, wstring templ_text, data_map &data) ;
wstring parse(wstring templ_text, data_map &data);
std::string parse(std::string templ_text, data_map &data);
}

883
resources/3rdparty/cpptemplate/cpptempl_test.cpp

@ -0,0 +1,883 @@
#include "cpptempl.h"
#ifdef UNIT_TEST
#include <boost/test/unit_test.hpp>
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE cpptemplTests
#endif
#pragma warning( disable : 4996 ) // doesn't like wcstombs
#include "unit_testing.h"
using namespace std ;
BOOST_AUTO_TEST_SUITE( TestCppData )
using namespace cpptempl ;
// DataMap
BOOST_AUTO_TEST_CASE(test_DataMap_getvalue)
{
data_map items ;
data_ptr data(new DataMap(items)) ;
BOOST_CHECK_THROW( data->getvalue(), TemplateException ) ;
}
BOOST_AUTO_TEST_CASE(test_DataMap_getlist_throws)
{
data_map items ;
data_ptr data(new DataMap(items)) ;
BOOST_CHECK_THROW( data->getlist(), TemplateException ) ;
}
BOOST_AUTO_TEST_CASE(test_DataMap_getitem_throws)
{
data_map items ;
items[L"key"] = data_ptr(new DataValue(L"foo")) ;
data_ptr data(new DataMap(items)) ;
BOOST_CHECK_EQUAL( data->getmap()[L"key"]->getvalue(), L"foo" ) ;
}
// DataList
BOOST_AUTO_TEST_CASE(test_DataList_getvalue)
{
data_list items ;
data_ptr data(new DataList(items)) ;
BOOST_CHECK_THROW( data->getvalue(), TemplateException ) ;
}
BOOST_AUTO_TEST_CASE(test_DataList_getlist_throws)
{
data_list items ;
items.push_back(make_data(L"bar")) ;
data_ptr data(new DataList(items)) ;
BOOST_CHECK_EQUAL( data->getlist().size(), 1u ) ;
}
BOOST_AUTO_TEST_CASE(test_DataList_getitem_throws)
{
data_list items ;
data_ptr data(new DataList(items)) ;
BOOST_CHECK_THROW( data->getmap(), TemplateException ) ;
}
// DataValue
BOOST_AUTO_TEST_CASE(test_DataValue_getvalue)
{
data_ptr data(new DataValue(L"foo")) ;
BOOST_CHECK_EQUAL( data->getvalue(), L"foo" ) ;
}
BOOST_AUTO_TEST_CASE(test_DataValue_getlist_throws)
{
data_ptr data(new DataValue(L"foo")) ;
BOOST_CHECK_THROW( data->getlist(), TemplateException ) ;
}
BOOST_AUTO_TEST_CASE(test_DataValue_getitem_throws)
{
data_ptr data(new DataValue(L"foo")) ;
BOOST_CHECK_THROW( data->getmap(), TemplateException ) ;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE( TestCppParseVal )
using namespace cpptempl ;
BOOST_AUTO_TEST_CASE(test_quoted)
{
data_map data ;
data[L"foo"] = make_data(L"bar") ;
data_ptr value = parse_val(L"\"foo\"", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"foo" ) ;
}
BOOST_AUTO_TEST_CASE(test_value)
{
data_map data ;
data[L"foo"] = make_data(L"bar") ;
data_ptr value = parse_val(L"foo", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"bar" ) ;
}
BOOST_AUTO_TEST_CASE(test_not_found)
{
data_map data ;
data[L"foo"] = make_data(L"bar") ;
data_ptr value = parse_val(L"kettle", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"{$kettle}" ) ;
}
BOOST_AUTO_TEST_CASE(test_not_found_dotted)
{
data_map data ;
data[L"foo"] = make_data(L"bar") ;
data_ptr value = parse_val(L"kettle.black", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"{$kettle.black}" ) ;
}
BOOST_AUTO_TEST_CASE(test_my_ax)
{
data_map data ;
data[L"item"] = make_data(L"my ax") ;
BOOST_CHECK_EQUAL( parse_val(L"item", data)->getvalue(), L"my ax" ) ;
}
BOOST_AUTO_TEST_CASE(test_list)
{
data_map data ;
data_list items ;
items.push_back(make_data(L"bar")) ;
data[L"foo"] = data_ptr(new DataList(items)) ;
data_ptr value = parse_val(L"foo", data) ;
BOOST_CHECK_EQUAL( value->getlist().size(), 1u ) ;
}
BOOST_AUTO_TEST_CASE(test_dotted)
{
data_map data ;
data_map subdata ;
subdata[L"b"] = data_ptr(new DataValue(L"c")) ;
data[L"a"] = data_ptr(new DataMap(subdata)) ;
data_ptr value = parse_val(L"a.b", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"c" ) ;
}
BOOST_AUTO_TEST_CASE(test_double_dotted)
{
data_map data ;
data_map sub_data ;
data_map sub_sub_data ;
sub_sub_data[L"c"] = data_ptr(new DataValue(L"d")) ;
sub_data[L"b"] = data_ptr(new DataMap(sub_sub_data)) ;
data[L"a"] = data_ptr(new DataMap(sub_data)) ;
data_ptr value = parse_val(L"a.b.c", data) ;
BOOST_CHECK_EQUAL( value->getvalue(), L"d" ) ;
}
BOOST_AUTO_TEST_CASE(test_dotted_to_list)
{
data_list friends ;
friends.push_back(make_data(L"Bob")) ;
data_map person ;
person[L"friends"] = make_data(friends) ;
data_map data ;
data[L"person"] = make_data(person) ;
data_ptr value = parse_val(L"person.friends", data) ;
BOOST_CHECK_EQUAL( value->getlist().size(), 1u ) ;
}
BOOST_AUTO_TEST_CASE(test_dotted_to_dict_list)
{
data_map bob ;
bob[L"name"] = make_data(L"Bob") ;
data_map betty ;
betty[L"name"] = make_data(L"Betty") ;
data_list friends ;
friends.push_back(make_data(bob)) ;
friends.push_back(make_data(betty)) ;
data_map person ;
person[L"friends"] = make_data(friends) ;
data_map data ;
data[L"person"] = make_data(person) ;
data_ptr value = parse_val(L"person.friends", data) ;
BOOST_CHECK_EQUAL( value->getlist()[0]->getmap()[L"name"]->getvalue(), L"Bob" ) ;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE( TestCppToken )
using namespace cpptempl ;
// TokenVar
BOOST_AUTO_TEST_CASE(TestTokenVarType)
{
TokenVar token(L"foo") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_VAR ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenVar)
{
token_ptr token(new TokenVar(L"foo")) ;
data_map data ;
data[L"foo"] = make_data(L"bar") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"bar" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenVarCantHaveChildren)
{
TokenVar token(L"foo") ;
token_vector children ;
BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
}
// TokenText
BOOST_AUTO_TEST_CASE(TestTokenTextType)
{
TokenText token(L"foo") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_TEXT ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenText)
{
token_ptr token(new TokenText(L"foo")) ;
data_map data ;
data[L"foo"] = make_data(L"bar") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenTextCantHaveChildrenSet)
{
TokenText token(L"foo") ;
token_vector children ;
BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
}
BOOST_AUTO_TEST_CASE(TestTokenTextCantHaveChildrenGet)
{
TokenText token(L"foo") ;
token_vector children ;
BOOST_CHECK_THROW(token.get_children(), TemplateException) ;
}
// TokenFor
BOOST_AUTO_TEST_CASE(TestTokenForBadSyntax)
{
BOOST_CHECK_THROW(TokenFor token(L"foo"), TemplateException ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForType)
{
TokenFor token(L"for item in items") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_FOR ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForTextEmpty)
{
token_ptr token(new TokenFor(L"for item in items")) ;
data_map data ;
data_list items ;
items.push_back(make_data(L"first"));
data[L"items"] = make_data(items) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForTextOneVar)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenFor(L"for item in items")) ;
token->set_children(children) ;
data_map data ;
data_list items ;
items.push_back(make_data(L"first "));
items.push_back(make_data(L"second "));
data[L"items"] = make_data(items) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"first second " ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForTextOneVarLoop)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
token_ptr token(new TokenFor(L"for item in items")) ;
token->set_children(children) ;
data_map data ;
data_list items ;
items.push_back(make_data(L"first "));
items.push_back(make_data(L"second "));
data[L"items"] = make_data(items) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"12" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVar)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
children.push_back(token_ptr(new TokenText(L". "))) ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
children.push_back(token_ptr(new TokenText(L" "))) ;
token_ptr token(new TokenFor(L"for item in items")) ;
token->set_children(children) ;
data_map data ;
data_list items ;
items.push_back(make_data(L"first"));
items.push_back(make_data(L"second"));
data[L"items"] = make_data(items) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"1. first 2. second " ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVarDottedKeyAndVal)
{
TokenFor token(L"for friend in person.friends") ;
BOOST_CHECK_EQUAL( token.m_key, L"person.friends" ) ;
BOOST_CHECK_EQUAL( token.m_val, L"friend" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForLoopTextVarDotted)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"loop.index"))) ;
children.push_back(token_ptr(new TokenText(L". "))) ;
children.push_back(token_ptr(new TokenVar(L"friend.name"))) ;
children.push_back(token_ptr(new TokenText(L" "))) ;
token_ptr token(new TokenFor(L"for friend in person.friends")) ;
token->set_children(children) ;
data_map bob ;
bob[L"name"] = make_data(L"Bob") ;
data_map betty ;
betty[L"name"] = make_data(L"Betty") ;
data_list friends ;
friends.push_back(make_data(bob)) ;
friends.push_back(make_data(betty)) ;
data_map person ;
person[L"friends"] = make_data(friends) ;
data_map data ;
data[L"person"] = make_data(person) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"1. Bob 2. Betty " ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenForTextOneText)
{
token_vector children ;
children.push_back(token_ptr(new TokenText(L"{--}"))) ;
token_ptr token(new TokenFor(L"for item in items")) ;
token->set_children(children) ;
data_map data ;
data_list items ;
items.push_back(make_data(L"first "));
items.push_back(make_data(L"second "));
data[L"items"] = make_data(items) ;
BOOST_CHECK_EQUAL( gettext(token, data), L"{--}{--}" ) ;
}
//////////////////////////////////////////////////////////////////////////
// TokenIf
//////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(TestTokenIfType)
{
TokenIf token(L"if items") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_IF ) ;
}
// if not empty
BOOST_AUTO_TEST_CASE(TestTokenIfTrueText)
{
token_vector children ;
children.push_back(token_ptr(new TokenText(L"{--}"))) ;
token_ptr token(new TokenIf(L"if item")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"{--}" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfTrueVar)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfFalse)
{
token_vector children ;
children.push_back(token_ptr(new TokenText(L"{--}"))) ;
token_ptr token(new TokenIf(L"if item")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"") ;
}
// ==
BOOST_AUTO_TEST_CASE(TestTokenIfEqualsTrue)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item == \"foo\"")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfEqualsFalse)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item == \"bar\"")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfEqualsTwoVarsTrue)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item == foo")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"x") ;
data[L"foo"] = make_data(L"x") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"x" ) ;
}
// !=
BOOST_AUTO_TEST_CASE(TestTokenIfNotEqualsTrue)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item != \"foo\"")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"" ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfNotEqualsFalse)
{
token_vector children ;
children.push_back(token_ptr(new TokenVar(L"item"))) ;
token_ptr token(new TokenIf(L"if item != \"bar\"")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"foo" ) ;
}
// not
BOOST_AUTO_TEST_CASE(TestTokenIfNotTrueText)
{
token_vector children ;
children.push_back(token_ptr(new TokenText(L"{--}"))) ;
token_ptr token(new TokenIf(L"if not item")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"") ;
}
BOOST_AUTO_TEST_CASE(TestTokenIfNotFalseText)
{
token_vector children ;
children.push_back(token_ptr(new TokenText(L"{--}"))) ;
token_ptr token(new TokenIf(L"if not item")) ;
token->set_children(children) ;
data_map data ;
data[L"item"] = make_data(L"") ;
BOOST_CHECK_EQUAL( gettext(token, data), L"{--}") ;
}
// TokenEnd
BOOST_AUTO_TEST_CASE(TestTokenEndFor)
{
TokenEnd token(L"endfor") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_ENDFOR ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenEndIf)
{
TokenEnd token(L"endif") ;
BOOST_CHECK_EQUAL( token.gettype(), TOKEN_TYPE_ENDIF ) ;
}
BOOST_AUTO_TEST_CASE(TestTokenEndIfCantHaveChildren)
{
TokenEnd token(L"endif") ;
token_vector children ;
BOOST_CHECK_THROW(token.set_children(children), TemplateException) ;
}
BOOST_AUTO_TEST_CASE(test_throws_on_gettext)
{
data_map data ;
token_ptr token(new TokenEnd(L"endif")) ;
BOOST_CHECK_THROW(gettext(token, data), TemplateException) ;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE( TestCppTokenize )
using namespace cpptempl ;
BOOST_AUTO_TEST_CASE(test_empty)
{
wstring text = L"" ;
token_vector tokens ;
tokenize(text, tokens) ;
BOOST_CHECK_EQUAL( 0u, tokens.size() ) ;
}
BOOST_AUTO_TEST_CASE(test_text_only)
{
wstring text = L"blah blah blah" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"blah blah blah" ) ;
}
BOOST_AUTO_TEST_CASE(test_brackets_no_var)
{
wstring text = L"{foo}" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
BOOST_CHECK_EQUAL( 2u, tokens.size() ) ;
BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"{" ) ;
BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"foo}" ) ;
}
BOOST_AUTO_TEST_CASE(test_ends_with_bracket)
{
wstring text = L"blah blah blah{" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
BOOST_CHECK_EQUAL( 2u, tokens.size() ) ;
BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"blah blah blah" ) ;
BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"{" ) ;
}
// var
BOOST_AUTO_TEST_CASE(test_var)
{
wstring text = L"{$foo}" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
data[L"foo"] = make_data(L"bar") ;
BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
BOOST_CHECK_EQUAL( gettext(tokens[0], data), L"bar" ) ;
}
// for
BOOST_AUTO_TEST_CASE(test_for)
{
wstring text = L"{% for item in items %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
}
BOOST_AUTO_TEST_CASE(test_for_full)
{
wstring text = L"{% for item in items %}{$item}{% endfor %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
BOOST_CHECK_EQUAL( 3u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
BOOST_CHECK_EQUAL( tokens[1]->gettype(), TOKEN_TYPE_VAR ) ;
BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_ENDFOR ) ;
}
BOOST_AUTO_TEST_CASE(test_for_full_with_text)
{
wstring text = L"{% for item in items %}*{$item}*{% endfor %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
data[L"item"] = make_data(L"my ax") ;
BOOST_CHECK_EQUAL( 5u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_FOR ) ;
BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"*" ) ;
BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_VAR ) ;
BOOST_CHECK_EQUAL( gettext(tokens[2], data), L"my ax" ) ;
BOOST_CHECK_EQUAL( gettext(tokens[3], data), L"*" ) ;
BOOST_CHECK_EQUAL( tokens[4]->gettype(), TOKEN_TYPE_ENDFOR ) ;
}
// if
BOOST_AUTO_TEST_CASE(test_if)
{
wstring text = L"{% if foo %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
BOOST_CHECK_EQUAL( 1u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
}
BOOST_AUTO_TEST_CASE(test_if_full)
{
wstring text = L"{% if item %}{$item}{% endif %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
BOOST_CHECK_EQUAL( 3u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
BOOST_CHECK_EQUAL( tokens[1]->gettype(), TOKEN_TYPE_VAR ) ;
BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_ENDIF ) ;
}
BOOST_AUTO_TEST_CASE(test_if_full_with_text)
{
wstring text = L"{% if item %}{{$item}}{% endif %}" ;
token_vector tokens ;
tokenize(text, tokens) ;
data_map data ;
data[L"item"] = make_data(L"my ax") ;
BOOST_CHECK_EQUAL( 5u, tokens.size() ) ;
BOOST_CHECK_EQUAL( tokens[0]->gettype(), TOKEN_TYPE_IF ) ;
BOOST_CHECK_EQUAL( gettext(tokens[1], data), L"{" ) ;
BOOST_CHECK_EQUAL( tokens[2]->gettype(), TOKEN_TYPE_VAR ) ;
BOOST_CHECK_EQUAL( gettext(tokens[2], data), L"my ax" ) ;
BOOST_CHECK_EQUAL( gettext(tokens[3], data), L"}" ) ;
BOOST_CHECK_EQUAL( tokens[4]->gettype(), TOKEN_TYPE_ENDIF ) ;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE( test_parse_tree )
using namespace cpptempl ;
token_ptr make_tt(wstring text)
{
return token_ptr(new TokenText(text)) ;
}
token_ptr make_for(wstring text)
{
return token_ptr(new TokenFor(text)) ;
}
token_ptr make_if(wstring text)
{
return token_ptr(new TokenIf(text)) ;
}
token_ptr make_endfor()
{
return token_ptr(new TokenEnd(L"endfor")) ;
}
token_ptr make_endif()
{
return token_ptr(new TokenEnd(L"endif")) ;
}
BOOST_AUTO_TEST_CASE(test_empty)
{
token_vector tokens ;
token_vector tree ;
parse_tree(tokens, tree) ;
BOOST_CHECK_EQUAL( 0u, tree.size() ) ;
}
BOOST_AUTO_TEST_CASE(test_one)
{
token_vector tokens ;
tokens.push_back(make_tt(L"foo")) ;
token_vector tree ;
parse_tree(tokens, tree) ;
BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
}
BOOST_AUTO_TEST_CASE(test_for)
{
token_vector tokens ;
tokens.push_back(make_for(L"for item in items")) ;
tokens.push_back(make_tt(L"foo")) ;
tokens.push_back(make_endfor()) ;
token_vector tree ;
parse_tree(tokens, tree) ;
BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
BOOST_CHECK_EQUAL( 1u, tree[0]->get_children().size()) ;
}
BOOST_AUTO_TEST_CASE(test_if)
{
token_vector tokens ;
tokens.push_back(make_if(L"if insane")) ;
tokens.push_back(make_tt(L"foo")) ;
tokens.push_back(make_endif()) ;
token_vector tree ;
parse_tree(tokens, tree) ;
BOOST_CHECK_EQUAL( 1u, tree.size() ) ;
BOOST_CHECK_EQUAL( 1u, tree[0]->get_children().size()) ;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(TestCppParse)
using namespace cpptempl ;
BOOST_AUTO_TEST_CASE(test_empty)
{
wstring text = L"" ;
data_map data ;
wstring actual = parse(text, data) ;
wstring expected = L"" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_no_vars)
{
wstring text = L"foo" ;
data_map data ;
wstring actual = parse(text, data) ;
wstring expected = L"foo" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_var)
{
wstring text = L"{$foo}" ;
data_map data ;
data[L"foo"] = make_data(L"bar") ;
wstring actual = parse(text, data) ;
wstring expected = L"bar" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_var_surrounded)
{
wstring text = L"aaa{$foo}bbb" ;
data_map data ;
data[L"foo"] = make_data(L"---") ;
wstring actual = parse(text, data) ;
wstring expected = L"aaa---bbb" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_for)
{
wstring text = L"{% for item in items %}{$item}{% endfor %}" ;
data_map data ;
data_list items ;
items.push_back(make_data(L"0")) ;
items.push_back(make_data(L"1")) ;
data[L"items"] = make_data(items) ;
wstring actual = parse(text, data) ;
wstring expected = L"01" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_if_false)
{
wstring text = L"{% if item %}{$item}{% endif %}" ;
data_map data ;
data[L"item"] = make_data(L"") ;
wstring actual = parse(text, data) ;
wstring expected = L"" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_if_true)
{
wstring text = L"{% if item %}{$item}{% endif %}" ;
data_map data ;
data[L"item"] = make_data(L"foo") ;
wstring actual = parse(text, data) ;
wstring expected = L"foo" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_nested_for)
{
wstring text = L"{% for item in items %}{% for thing in things %}{$item}{$thing}{% endfor %}{% endfor %}" ;
data_map data ;
data_list items ;
items.push_back(make_data(L"0")) ;
items.push_back(make_data(L"1")) ;
data[L"items"] = make_data(items) ;
data_list things ;
things.push_back(make_data(L"a")) ;
things.push_back(make_data(L"b")) ;
data[L"things"] = make_data(things) ;
wstring actual = parse(text, data) ;
wstring expected = L"0a0b1a1b" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_nested_if_false)
{
wstring text = L"{% if item %}{% if thing %}{$item}{$thing}{% endif %}{% endif %}" ;
data_map data ;
data[L"item"] = make_data(L"aaa") ;
data[L"thing"] = make_data(L"") ;
wstring actual = parse(text, data) ;
wstring expected = L"" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_nested_if_true)
{
wstring text = L"{% if item %}{% if thing %}{$item}{$thing}{% endif %}{% endif %}" ;
data_map data ;
data[L"item"] = make_data(L"aaa") ;
data[L"thing"] = make_data(L"bbb") ;
wstring actual = parse(text, data) ;
wstring expected = L"aaabbb" ;
BOOST_CHECK_EQUAL( expected, actual ) ;
}
BOOST_AUTO_TEST_CASE(test_usage_example)
{
wstring text = L"{% if item %}{$item}{% endif %}\n"
L"{% if thing %}{$thing}{% endif %}" ;
cpptempl::data_map data ;
data[L"item"] = cpptempl::make_data(L"aaa") ;
data[L"thing"] = cpptempl::make_data(L"bbb") ;
wstring result = cpptempl::parse(text, data) ;
wstring expected = L"aaa\nbbb" ;
BOOST_CHECK_EQUAL( result, expected ) ;
}
BOOST_AUTO_TEST_CASE(test_syntax_if)
{
wstring text = L"{% if person.name == \"Bob\" %}Full name: Robert{% endif %}" ;
data_map person ;
person[L"name"] = make_data(L"Bob") ;
person[L"occupation"] = make_data(L"Plumber") ;
data_map data ;
data[L"person"] = make_data(person) ;
wstring result = cpptempl::parse(text, data) ;
wstring expected = L"Full name: Robert" ;
BOOST_CHECK_EQUAL( result, expected ) ;
}
BOOST_AUTO_TEST_CASE(test_syntax_dotted)
{
wstring text = L"{% for friend in person.friends %}"
L"{$loop.index}. {$friend.name} "
L"{% endfor %}" ;
data_map bob ;
bob[L"name"] = make_data(L"Bob") ;
data_map betty ;
betty[L"name"] = make_data(L"Betty") ;
data_list friends ;
friends.push_back(make_data(bob)) ;
friends.push_back(make_data(betty)) ;
data_map person ;
person[L"friends"] = make_data(friends) ;
data_map data ;
data[L"person"] = make_data(person) ;
wstring result = cpptempl::parse(text, data) ;
wstring expected = L"1. Bob 2. Betty " ;
BOOST_CHECK_EQUAL( result, expected ) ;
}
BOOST_AUTO_TEST_CASE(test_example_okinawa)
{
// The text template
wstring text = L"I heart {$place}!" ;
// Data to feed the template engine
cpptempl::data_map data ;
// {$place} => Okinawa
data[L"place"] = cpptempl::make_data(L"Okinawa");
// parse the template with the supplied data dictionary
wstring result = cpptempl::parse(text, data) ;
wstring expected = L"I heart Okinawa!" ;
BOOST_CHECK_EQUAL( result, expected ) ;
}
BOOST_AUTO_TEST_CASE(test_example_ul)
{
wstring text = L"<h3>Locations</h3><ul>"
L"{% for place in places %}"
L"<li>{$place}</li>"
L"{% endfor %}"
L"</ul>" ;
// Create the list of items
cpptempl::data_list places;
places.push_back(cpptempl::make_data(L"Okinawa"));
places.push_back(cpptempl::make_data(L"San Francisco"));
// Now set this in the data map
cpptempl::data_map data ;
data[L"places"] = cpptempl::make_data(places);
// parse the template with the supplied data dictionary
wstring result = cpptempl::parse(text, data) ;
wstring expected = L"<h3>Locations</h3><ul>"
L"<li>Okinawa</li>"
L"<li>San Francisco</li>"
L"</ul>" ;
BOOST_CHECK_EQUAL(result, expected) ;
}
BOOST_AUTO_TEST_SUITE_END()
#endif

41
resources/3rdparty/cpptemplate/unit_testing.h

@ -0,0 +1,41 @@
#pragma once
#include <iostream>
#include <ostream>
#include <sstream>
#ifndef _MSC_VER
#include <boost/locale.hpp>
#else
#include <boost/scoped_array.hpp>
#include "windows.h"
#include "winnls.h" // unicode-multibyte conversion
#endif
inline std::string wide2utf8(const std::wstring& text) {
#ifndef _MSC_VER
return boost::locale::conv::to_utf<wchar_t>(text, "UTF-8");
#else
const size_t len_needed = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (UINT)(text.length()) , NULL, 0, NULL, NULL) ;
boost::scoped_array<char> buff(new char[len_needed+1]) ;
const size_t num_copied = ::WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (UINT)(text.length()) , buff.get(), len_needed+1, NULL, NULL) ;
return std::string(buff.get(), num_copied) ;
#endif
}
namespace std {
inline ostream& operator<<(ostream& out, const wchar_t* value)
{
wstring text(value) ;
out << wide2utf8(text);
return out;
}
inline ostream& operator<<(ostream& out, const wstring& value)
{
out << wide2utf8(value);
return out;
}
}
Loading…
Cancel
Save