-
Notifications
You must be signed in to change notification settings - Fork 26
/
variable_string.cpp
100 lines (87 loc) · 2.36 KB
/
variable_string.cpp
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
#include "variable_string.h"
#include "json/json.h"
#include <sstream>
bool apply_variable_string(variable_string & var, Json::Value & data, const std::string & name, std::string & error, bool append)
{
Json::Value value = data[name];
data.removeMember(name);
try
{
variable_string str(value);
if (append)
{
var.contents.insert(var.contents.end(), str.contents.begin(), str.contents.end());
}
else
{
var.contents = str.contents;
}
return true;
}
catch (std::invalid_argument & ex)
{
error = name + " is invalid (" + ex.what() + ")";
return false;
}
}
variable_string::element_t::element_t(const std::string & text) :
element_t(text.empty() || text.at(0) != '$' ? text : text.substr(1), !text.empty() && text.at(0) == '$')
{
}
variable_string::element_t::element_t(const std::string & text, bool variable) :
text(text),
variable(variable)
{
}
variable_string::context_t::context_t(const context_t & parent, const std::map<std::string, variable_string> & values) :
variables(parent.variables)
{
for (auto & v : values)
{
variables[v.first] = v.second(parent);
}
}
std::string variable_string::context_t::operator[](const std::string & name) const
{
auto it = variables.find(name);
return it == variables.end() ? "$" + name : it->second;
}
variable_string::variable_string(const std::string & text)
{
contents.push_back(element_t(text, false));
}
variable_string::variable_string(const Json::Value & value)
{
if (value.isString())
{
contents.push_back(element_t(value.asString(), false));
}
else if (value.isArray())
{
contents.reserve(value.size());
for (auto & el : value)
{
if (el.isString())
{
contents.push_back(element_t(el.asString()));
}
else
{
throw std::invalid_argument("elements of array should be strings");
}
}
}
else
{
throw std::invalid_argument("should be string or array of strings");
}
}
std::string variable_string::operator()(const variable_string::context_t & ctx) const
{
std::ostringstream str;
for (auto v : contents)
{
str << (v.variable ? ctx[v.text] : v.text);
}
return str.str();
}