11 bool ini_unescape(string::const_iterator, string::const_iterator,
string *);
14 from_string(
const string &s,
string *sp)
20 from_string(
const string &s,
bool *bp)
24 else if (s ==
"false")
27 throw std::invalid_argument (
"boolean must be \"true\" or \"false\"");
30 template<
class T>
inline T
31 add_base(T (&conv)(
const string &,
size_t *,
int),
const string &s,
size_t *pos)
33 return conv(s, pos, 0);
35 template<
class T>
inline T
36 add_base(T (&conv)(
const string &,
size_t *),
const string &s,
size_t *pos)
41 template<
typename T,
typename U,
typename ...Base>
inline void 42 from_string_with(U (&conv)(
const string &,
size_t *, Base...),
43 const string &s, T *rp)
46 U r (add_base(conv, s, &pos));
48 if (static_cast<U>(t) != r)
49 throw std::out_of_range (
"value out of range");
50 else if (s.find_first_not_of(
"\t\n\r ", pos) != string::npos)
51 throw std::invalid_argument (
"trailing garbage: " + s.substr(pos));
55 #define FROM_STRING(T, conv) \ 56 void from_string(const string &s, T *rp) { from_string_with(conv, s, rp); } 57 FROM_STRING(
int, std::stoi)
58 FROM_STRING(
long, std::stol)
59 FROM_STRING(
long long, std::stoll)
60 FROM_STRING(
unsigned char, std::stoul)
61 FROM_STRING(
unsigned short, std::stoul)
62 FROM_STRING(
unsigned int, std::stoul)
63 FROM_STRING(
unsigned long, std::stoul)
64 FROM_STRING(
unsigned long long, std::stoll)
65 FROM_STRING(
float, std::stof)
66 FROM_STRING(
double, std::stod)
67 FROM_STRING(
long double, std::stold)
72 std::vector<string> av;
78 e =
rawvalue_.find_first_of(
"\t\r ", e+1);
79 }
while (e != string::npos && e > 0 &&
rawvalue_[e-1] ==
'\\');
80 if (e == string::npos)
84 throw std::invalid_argument(
"stray backslash at end of line");
86 i =
rawvalue_.find_first_not_of(
"\t\r ", e);
97 IniGroup::parse(
const IniLine &li)
99 auto i (cbs_.find(li.
key_));
100 if (i == cbs_.end()) {
101 li.
warn() <<
"unknown property " 103 cbs_.emplace(li.
key_, ignoreline);
110 ini_unescape(string::const_iterator i, string::const_iterator e,
string *out)
114 for (; i != e; i++) {
142 out->assign(std::move(v));
147 parsekv(
const string &line,
string *kout,
string *vout,
string *rvout)
150 auto li = (line.cbegin());
152 while (li < line.cend() && isspace(*li))
154 while (li < line.cend() && !isspace(*li) && *li !=
'=')
156 while (li < line.cend() && isspace(*li))
158 if (k.empty() || li >= line.cend() || *li++ !=
'=')
160 while (li < line.cend() && isspace(*li))
163 if (!ini_unescape(li, line.cend(), vout))
165 rvout->assign(
string(li, line.cend()));
166 kout->assign(std::move(k));
173 auto group = a.end();
175 while (getline(s, line).good()) {
177 line.erase(0, line.find_first_not_of(
"\t\r "));
178 if (line.empty() || line[0] ==
'#')
181 if (line[0] ==
'[') {
182 size_t e = line.rfind(
']');
183 if (e == 1 || e == string::npos
184 || line.find_first_not_of(
"\t\r ", e+1) != string::npos)
185 st.
fail() <<
"syntax error" << std::endl;
187 st.
group_ = line.substr(1, e-1);
188 group = a.find(st.
group_);
189 if (group == a.end())
190 st.
warn() <<
"unknown group " << st.
group_ <<
"\n";
193 else if (st.
group_.empty())
194 st.
fail() <<
"key precedes group" << std::endl;
195 else if (group == a.end())
198 try { group->second.parse(st); }
199 catch (std::logic_error &e) { st.
fail() << e.what() << std::endl; }
202 st.
fail() <<
"syntax error" << std::endl;
211 std::ifstream s {st.file_};
213 std::cerr << file <<
": " << std::strerror (errno) << std::endl;
std::unordered_map< string, IniGroup > IniActions
Holds the actions to execute on various properties in the ini file.
Most of the xdrpp library is encapsulated in the xdr namespace.
string value_
Value of the property.
void ini_runparse(IniActions &a, IniLine &st, std::istream &s)
Run the ini parser.
Parser for .ini style files.
bool ini_parse(IniActions &a, string file)
Run the parser on a file.
string rawvalue_
Raw value of the property (with escape sequences unexpanded).
string group_
Name of the group containing property.
bool error() const
Returns true if there has been a parsing error in the ini file.
string key_
Key of the property.
Contents of a specific property.
std::ostream & warn() const
Print a message to cerr with the file ane line number prefixed.
std::ostream & fail() const
Like IniLine::warn, but also sets the error flag to indicate failure.
std::vector< string > argv() const
Transform the line into a vector of words.