30#include <boost/algorithm/string.hpp>
31#include <boost/format.hpp>
61 if (iter ==
map_.end()) {
62 throw std::runtime_error(
"property not found: " + key);
68 for (; n != tok.
end(); ++n) {
71 }
catch (std::runtime_error &) {
73 throw std::runtime_error(
"property not found: " + key);
80 return const_cast<Property &
>(
static_cast<const Property &
>(*this).get(key));
94 const std::string &
value) {
96 if (key.size() == 1) {
99 std::vector<std::string> subkey(key.begin() + 1, key.end());
100 if (this->
exists(key[0])) {
125 }
catch (std::exception &) {
166 std::vector<const Property *> selection;
170 selection.push_back(
this);
171 for (
const auto &n : tok) {
172 std::vector<const Property *> selected;
173 for (
const Property *p : selection) {
175 if (
wildcmp(n, child.name())) {
176 selected.push_back(&child);
180 selection = selected;
187 std::vector<Property *> selection;
191 selection.push_back(
this);
192 for (
const auto &n : tok) {
193 std::vector<Property *> selected;
196 if (
wildcmp(n, child.name())) {
197 selected.push_back(&child);
201 selection = selected;
210static void start_hndl(
void *data,
const char *el,
const char **attr) {
211 stack<Property *> *property_stack =
212 (stack<Property *> *)XML_GetUserData((XML_Parser *)data);
214 Property *cur = property_stack->top();
217 for (
Index i = 0; attr[i]; i += 2) {
221 property_stack->push(&np);
225 stack<Property *> *property_stack =
226 (stack<Property *> *)XML_GetUserData((XML_Parser *)data);
227 property_stack->pop();
230void char_hndl(
void *data,
const char *txt,
int txtlen) {
231 stack<Property *> *property_stack =
232 (stack<Property *> *)XML_GetUserData((XML_Parser *)data);
234 Property *cur = property_stack->top();
235 cur->
value().append(txt, txtlen);
242 throw std::ios_base::failure(
"Error on open xml file: " + filename);
245 XML_Parser parser = XML_ParserCreate(
nullptr);
247 throw std::runtime_error(
"Couldn't allocate memory for xml parser");
250 XML_UseParserAsHandlerArg(parser);
252 XML_SetCharacterDataHandler(parser,
char_hndl);
254 stack<Property *> pstack;
257 XML_SetUserData(parser, (
void *)&pstack);
262 if (line.length() > (
size_t)std::numeric_limits<int>::max()) {
263 throw std::runtime_error(
"Property::LoadFromXML: line is too long");
265 if (!XML_Parse(parser, line.c_str(), (
int)line.length(), fl.eof())) {
267#if XML_MAJOR_VERSION > 2 || (XML_MAJOR_VERSION == 2 && XML_MINOR_VERSION >= 9)
268 const auto line_number = XML_GetCurrentLineNumber64(parser);
270 const auto line_number = XML_GetCurrentLineNumber(parser);
272 throw std::ios_base::failure(filename +
": Parse error at line " +
273 boost::lexical_cast<string>(line_number) +
275 XML_ErrorString(XML_GetErrorCode(parser)));
279 XML_ParserFree(parser);
283 Index level = 0,
string prefix =
"",
string offset =
"") {
285 if (level >= start_level) {
286 if ((p.
value()).find_first_not_of(
"\t\n ") != std::string::npos) {
287 out << offset << prefix <<
" = " << p.
value() << endl;
297 PrintNodeTXT(out, prop, start_level, level, prefix + prop.name(), offset);
299 PrintNodeTXT(out, prop, start_level, level, prefix +
"." + prop.name(),
308 string offset =
"") {
310 bool linebreak =
true;
311 bool has_value =
false;
316 Index start_level(0);
324 string cKey = color->
Magenta();
325 string cAttribute = color->
Blue();
326 string cAttributeValue = color->
Green();
327 string cReset = color->
Reset();
331 if (level >= start_level) {
333 out << indent << offset <<
"<" << cKey << p.
name() << cReset;
336 out <<
" " << cAttribute << ia->first << cReset <<
"=\""
337 << cAttributeValue << ia->second << cReset <<
"\"";
340 has_value = ((p.
value()).find_first_not_of(
"\t\n ") != std::string::npos);
344 out <<
"/>" << std::endl;
347 out << cAttributeValue << p.
value() << cReset;
363 if (level > start_level) {
367 if (level > start_level) {
368 offset.resize(offset.size() - 1);
373 if (level >= start_level) {
375 out << indent << offset <<
"</" << cKey << p.
name() << cReset <<
">"
377 }
else if (has_value) {
378 out <<
"</" << cKey << p.
name() << cReset <<
">" << std::endl;
385 const string &prefix =
"",
const string &offset =
"") {
388 string fmt =
"t|%1%%|15t|" + string(RGB.
Blue()) +
"%2%" +
389 string(RGB.
Green()) +
"%|40t|%3%%|55t|" + string(RGB.
Reset()) +
392 Index leveloffset = level;
395 if (level == start_level) {
396 string head_name = string(RGB.
Magenta()) + p.
name();
401 out << boost::format(
" %1%: %|18t| %2%" +
string(RGB.
Reset()) +
"\n") %
405 out << boost::format(
"%|3" + fmt) %
"OPTION" %
"DEFAULT" %
"UNIT" %
409 if (level > start_level) {
410 string ofmt =
"%|" + boost::lexical_cast<string>(leveloffset) + fmt;
423 unit =
"[" + unit +
"]";
425 if (!defaults.empty()) {
426 defaults =
"(" + defaults +
")";
429 string name = p.
name();
431 out << boost::format(ofmt) % name % defaults % unit % help;
437 PrintNodeHLP(out, pp, start_level, level, pp.name(), offset);
439 PrintNodeHLP(out, pp, start_level, level, prefix +
"." + pp.name(),
451 std::ostream::sentry sentry(out);
458 string indentation(
"");
468 if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) {
Provides a means for comparing floating point numbers.