forked from flit/cpptemplate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpptempl.h
307 lines (276 loc) · 10.1 KB
/
cpptempl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
// Copyright (c) 2010-2014 Ryan Ginstrom
// Copyright (c) 2014 Martinho Fernandes
// Copyright (c) 2014-2016 Freescale Semiconductor, Inc.
//
// 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.
#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'
#define NOEXCEPT // hide unsupported noexcept keyword under VC++
#else
#define NOEXCEPT noexcept
#endif // NOEXCEPT
#if __MINGW32__
#define NOTHROW throw() // add throw() keyword under MinGW
#else
#define NOTHROW
#endif // NOTHROW
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <unordered_map>
#include <boost/lexical_cast.hpp>
#include <iostream>
namespace cpptempl
{
// various typedefs
class data_ptr;
class data_map;
class DataMap;
class DataTemplate;
typedef std::vector<data_ptr> data_list ;
// data classes
class Data
{
public:
virtual ~Data()=default;
virtual bool empty() = 0 ;
virtual std::string getvalue();
virtual data_list& getlist();
virtual data_map& getmap() ;
virtual int getint() const;
virtual void dump(int indent=0) = 0 ;
};
class DataBool : public Data
{
bool m_value;
public:
DataBool(bool value) : m_value(value) {}
std::string getvalue();
virtual int getint() const;
bool empty();
virtual void dump(int indent=0) ;
};
class DataInt : public Data
{
int m_value;
public:
DataInt(int value) : m_value(value) {}
DataInt(unsigned int value) : m_value(value) {}
std::string getvalue();
virtual int getint() const;
bool empty();
virtual void dump(int indent=0) ;
};
class DataValue : public Data
{
std::string m_value ;
public:
DataValue(const std::string& value) : m_value(value){}
DataValue(std::string&& value) : m_value(std::move(value)){}
std::string getvalue();
virtual int getint() const;
bool empty();
virtual void dump(int indent=0) ;
};
class DataList : public Data
{
data_list m_items ;
public:
DataList(const data_list &items) : m_items(items){}
DataList(data_list &&items) : m_items(std::move(items)){}
data_list& getlist() ;
bool empty();
void dump(int indent=0);
};
class data_ptr {
public:
data_ptr() {}
template<typename T> data_ptr(const T& data) {
this->operator =(data);
}
data_ptr(DataBool* data);
data_ptr(DataInt* data);
data_ptr(DataValue* data);
data_ptr(DataList* data);
data_ptr(DataMap* data);
data_ptr(DataTemplate* data);
data_ptr(const data_ptr& data) {
ptr = data.ptr;
}
data_ptr(data_ptr&& data) {
ptr = std::move(data.ptr);
}
data_ptr& operator = (const data_ptr& data) {
ptr = data.ptr;
return *this;
}
data_ptr& operator = (data_ptr&& data) {
ptr = std::move(data.ptr);
return *this;
}
data_ptr& operator =(std::string&& data);
data_ptr& operator =(data_map&& data);
data_ptr& operator =(data_list&& data);
template<typename T> void operator = (const T& data);
void push_back(const data_ptr& data);
virtual ~data_ptr() {}
Data* operator ->() {
return ptr.get();
}
std::shared_ptr<Data> get() { return ptr; }
bool is_template() const;
private:
std::shared_ptr<Data> ptr;
};
class data_map {
public:
class key_error : public std::runtime_error
{
public:
key_error(const std::string & msg) : std::runtime_error(msg) {}
};
data_map() : data(), parent(nullptr) {}
data_ptr& operator [](const std::string& key);
bool empty();
bool has(const std::string& key);
data_ptr& parse_path(const std::string& key, bool create=false);
void set_parent(data_map * p) { parent = p; }
private:
std::unordered_map<std::string, data_ptr> data;
data_map * parent;
friend class DataMap;
};
class DataMap : public Data
{
data_map m_items ;
public:
DataMap(const data_map &items) : m_items(items){}
DataMap(data_map &&items) : m_items(std::move(items)){}
data_map& getmap();
bool empty();
void dump(int indent=0);
};
template<> void data_ptr::operator = (const bool& data);
template<> void data_ptr::operator = (const int& data);
template<> void data_ptr::operator = (const unsigned int& data);
template<> void data_ptr::operator = (const std::string& data);
template<> void data_ptr::operator = (const data_map& data);
template<> void data_ptr::operator = (const data_list& data);
template<typename T>
void data_ptr::operator = (const T& data) {
this->operator =(boost::lexical_cast<std::string>(data));
}
// Custom exception class for library errors
class TemplateException : public std::exception
{
uint32_t m_line;
std::string m_reason;
public:
TemplateException(std::string reason) : std::exception(), m_line(0), m_reason(reason) {}
TemplateException(size_t line, std::string reason);
TemplateException(const TemplateException & other)=default;
TemplateException& operator=(const TemplateException & other)=default;
virtual ~TemplateException()=default;
void set_reason(std::string reason) { m_reason = reason; }
void set_line_if_missing(size_t line);
virtual const char* what() const NOEXCEPT NOTHROW { return m_reason.c_str(); }
};
// convenience functions for making data objects
inline data_ptr make_data(bool val)
{
return data_ptr(new DataBool(val)) ;
}
inline data_ptr make_data(int val)
{
return data_ptr(new DataInt(val)) ;
}
inline data_ptr make_data(unsigned int val)
{
return data_ptr(new DataInt(val)) ;
}
inline data_ptr make_data(std::string &val)
{
return data_ptr(new DataValue(val)) ;
}
inline data_ptr make_data(std::string &&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_list &&val)
{
return data_ptr(new DataList(val)) ;
}
inline data_ptr make_data(data_map &val)
{
return data_ptr(new DataMap(val)) ;
}
inline data_ptr make_data(data_map &&val)
{
return data_ptr(new DataMap(val)) ;
}
template <typename T>
data_ptr make_data(const T &val)
{
return data_ptr(boost::lexical_cast<std::string>(val));
}
void dump_data(data_ptr data);
namespace impl {
// node classes
class Node ;
typedef std::shared_ptr<Node> node_ptr ;
typedef std::vector<node_ptr> node_vector ;
} // namespace impl
// List of param names.
typedef std::vector<std::string> string_vector;
class DataTemplate : public Data
{
impl::node_vector m_tree;
string_vector m_params;
public:
DataTemplate(const std::string & templateText);
DataTemplate(const impl::node_vector &tree) : m_tree(tree) {}
DataTemplate(impl::node_vector &&tree) : m_tree(std::move(tree)) {}
virtual std::string getvalue();
virtual bool empty();
std::string eval(data_map & data, data_list * param_values=nullptr);
void eval(std::ostream &stream, data_map & data, data_list * param_values=nullptr);
string_vector & params() { return m_params; }
void dump(int indent=0);
};
inline data_ptr make_template(const std::string & templateText, const string_vector * param_names=nullptr)
{
DataTemplate * t = new DataTemplate(templateText);
if (param_names)
{
t->params() = *param_names;
}
return data_ptr(t);
}
// The big daddy. Pass in the template and data,
// and get out a completed doc.
void parse(std::ostream &stream, const std::string &templ_text, data_map &data) ;
std::string parse(const std::string &templ_text, data_map &data);
}