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
|
/*
* Simple config/test file reader
* (C) 2013,2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/parsing.h>
#include <ctype.h>
namespace Botan {
void lex_cfg(std::istream& is,
std::function<void (std::string)> cb)
{
while(is.good())
{
std::string s;
std::getline(is, s);
while(is.good() && s.back() == '\\')
{
while(s.size() && (s.back() == '\\' || s.back() == '\n'))
s.resize(s.size()-1);
std::string x;
std::getline(is, x);
size_t i = 0;
while(i < x.size() && (::isspace(x[i])))
++i;
s += x.substr(i);
}
auto comment = s.find('#');
if(comment)
s = s.substr(0, comment);
if(s.empty())
continue;
auto parts = split_on_pred(s, [](char c) { return ::isspace(c); });
for(auto& p : parts)
{
if(p.empty())
continue;
auto eq = p.find("=");
if(eq == std::string::npos || p.size() < 2)
{
cb(p);
}
else if(eq == 0)
{
cb("=");
cb(p.substr(1, std::string::npos));
}
else if(eq == p.size() - 1)
{
cb(p.substr(0, p.size() - 1));
cb("=");
}
else if(eq != std::string::npos)
{
cb(p.substr(0, eq));
cb("=");
cb(p.substr(eq + 1, std::string::npos));
}
}
}
}
void lex_cfg_w_headers(std::istream& is,
std::function<void (std::string)> cb,
std::function<void (std::string)> hdr_cb)
{
auto intercept = [cb,hdr_cb](const std::string& s)
{
if(s[0] == '[' && s[s.length()-1] == ']')
hdr_cb(s.substr(1, s.length()-2));
else
cb(s);
};
lex_cfg(is, intercept);
}
std::map<std::string, std::map<std::string, std::string>>
parse_cfg(std::istream& is)
{
std::string header = "default";
std::map<std::string, std::map<std::string, std::string>> vals;
std::string key;
auto header_cb = [&header](const std::string i) { header = i; };
auto cb = [&header,&key,&vals](const std::string s)
{
if(s == "=")
{
BOTAN_ASSERT(!key.empty(), "Valid assignment in config");
}
else if(key.empty())
key = s;
else
{
vals[header][key] = s;
key = "";
}
};
lex_cfg_w_headers(is, cb, header_cb);
return vals;
}
}
|