24 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
25 #include <boost/algorithm/string.hpp>
26 #include <boost/io/ios_state.hpp>
27 #include <boost/property_tree/json_parser.hpp>
28 #include <boost/property_tree/ptree.hpp>
29 #include <boost/property_tree/xml_parser.hpp>
30 #undef BOOST_BIND_GLOBAL_PLACEHOLDERS
48 : entries(new
boost::property_tree::ptree())
55 mangle(
const std::string &s)
64 const bool mangle_whole_string = (s ==
"value");
67 for (
const char c : s)
69 static const std::string allowed_characters(
70 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
72 if ((!mangle_whole_string) &&
73 (allowed_characters.find(c) != std::string::npos))
78 static const char hex[16] = {
'0',
94 u.push_back(hex[
static_cast<unsigned char>(c) / 16]);
95 u.push_back(hex[
static_cast<unsigned char>(c) % 16]);
105 demangle(
const std::string &s)
110 for (
unsigned int i = 0; i < s.size(); ++i)
116 ExcMessage(
"Trying to demangle an invalid string."));
226 u.push_back(
static_cast<char>(c));
240 is_parameter_node(
const boost::property_tree::ptree &p)
242 return static_cast<bool>(p.get_optional<std::string>(
"value"));
251 is_alias_node(
const boost::property_tree::ptree &p)
253 return static_cast<bool>(p.get_optional<std::string>(
"alias"));
263 collate_path_string(
const char separator,
264 const std::vector<std::string> &subsection_path)
266 if (subsection_path.size() > 0)
268 std::string p = mangle(subsection_path[0]);
269 for (
unsigned int i = 1; i < subsection_path.size(); ++i)
272 p += mangle(subsection_path[i]);
286 recursively_sort_parameters(
287 const char separator,
288 const std::vector<std::string> &target_subsection_path,
289 boost::property_tree::ptree & tree)
291 boost::property_tree::ptree ¤t_section =
292 tree.get_child(collate_path_string(separator, target_subsection_path));
297 static auto compare =
298 [](
const std::pair<std::string, boost::property_tree::ptree> &a,
299 const std::pair<std::string, boost::property_tree::ptree> &
b) {
301 (is_parameter_node(a.second) || is_alias_node(a.second));
304 (is_parameter_node(
b.second) || is_alias_node(
b.second));
308 if (a_is_param && !b_is_param)
311 if (!a_is_param && b_is_param)
315 return a.first <
b.first;
318 current_section.sort(compare);
321 for (
auto &p : current_section)
323 if ((is_parameter_node(p.second) ==
false) &&
324 (is_alias_node(p.second) ==
false))
326 const std::string subsection = demangle(p.first);
328 std::vector<std::string> subsection_path = target_subsection_path;
329 subsection_path.emplace_back(subsection);
331 recursively_sort_parameters(separator, subsection_path, tree);
349 "You have chosen either no or multiple style formats. You can choose "
350 "between: PRM, Description, LaTeX, XML, JSON."));
369 if (path.empty() ==
false)
372 path += mangle(name);
381 const std::vector<std::string> &sub_path,
382 const std::string & name)
const
385 if (path.empty() ==
false)
388 if (sub_path.empty() ==
false)
391 path += mangle(name);
400 const std::string &filename,
401 const std::string &last_line,
402 const bool skip_undefined)
409 std::string input_line;
410 std::string fully_concatenated_line;
411 bool is_concatenated =
false;
415 unsigned int current_line_n = 0;
416 unsigned int current_logical_line_n = 0;
430 auto scan_line_or_cleanup = [
this,
432 &saved_path](
const std::string &line,
433 const std::string &filename,
434 const unsigned int line_number) {
437 scan_line(line, filename, line_number, skip_undefined);
449 while (std::getline(input, input_line))
452 if (!is_concatenated)
453 current_logical_line_n = current_line_n;
460 if (last_line.length() != 0 && input_line == last_line)
465 if (input_line.length() != 0 &&
466 input_line.find_last_of(
'\\') == input_line.length() - 1)
468 input_line.erase(input_line.length() - 1);
469 is_concatenated =
true;
471 fully_concatenated_line += input_line;
475 else if (is_concatenated)
477 fully_concatenated_line += input_line;
478 is_concatenated =
false;
484 fully_concatenated_line = input_line;
487 if (!is_concatenated)
489 scan_line_or_cleanup(fully_concatenated_line,
491 current_logical_line_n);
493 fully_concatenated_line.clear();
501 scan_line_or_cleanup(fully_concatenated_line, filename, current_line_n);
505 std::stringstream paths_message;
506 if (saved_path.size() > 0)
508 paths_message <<
"Path before loading input:\n";
511 paths_message << std::setw(i * 2 + 4) <<
" "
512 <<
"subsection " << saved_path[i] <<
'\n';
514 paths_message <<
"Current path:\n";
517 paths_message << std::setw(i * 2 + 4) <<
" "
533 const std::string &last_line,
534 const bool skip_undefined,
535 const bool assert_mandatory_entries_are_found)
537 std::ifstream is(filename);
540 std::string file_ending = filename.substr(filename.find_last_of(
'.') + 1);
541 boost::algorithm::to_lower(file_ending);
542 if (file_ending ==
"prm")
543 parse_input(is, filename, last_line, skip_undefined);
544 else if (file_ending ==
"xml")
546 else if (file_ending ==
"json")
550 ExcMessage(
"Unknown input file name extension. Supported types "
551 "are .prm, .xml, and .json."));
553 if (assert_mandatory_entries_are_found)
561 const std::string &last_line,
562 const bool skip_undefined)
564 std::istringstream input_stream(s);
565 parse_input(input_stream,
"input string", last_line, skip_undefined);
578 read_xml_recursively(
579 const boost::property_tree::ptree &source,
580 const std::string & current_path,
581 const char path_separator,
582 const std::vector<std::unique_ptr<const Patterns::PatternBase>> &patterns,
583 const bool skip_undefined,
586 for (
const auto &p : source)
589 if (p.second.empty())
596 prm.
set(demangle(p.first), p.second.data());
604 prm.
set(demangle(p.first), p.second.data());
606 else if (p.second.get_optional<std::string>(
"value"))
613 prm.
set(demangle(p.first),
614 p.second.get<std::string>(
"value"));
622 prm.
set(demangle(p.first), p.second.get<std::string>(
"value"));
629 else if (p.second.get_optional<std::string>(
"alias"))
639 read_xml_recursively(p.second,
640 (current_path.empty() ?
642 current_path + path_separator + p.first),
673 recursively_compress_tree(boost::property_tree::ptree &source)
675 for (
auto &p : source)
677 if (p.second.get_optional<std::string>(
"value"))
680 const auto temp = p.second.get<std::string>(
"value");
684 p.second.put_value<std::string>(temp);
686 else if (p.second.get_optional<std::string>(
"alias"))
691 recursively_compress_tree(p.second);
701 const bool skip_undefined)
708 boost::property_tree::ptree single_node_tree;
711 read_xml(in, single_node_tree);
715 AssertThrow(single_node_tree.get_optional<std::string>(
"ParameterHandler"),
717 "called \"ParameterHandler\"."));
719 const std::size_t n_top_level_elements =
720 std::distance(single_node_tree.begin(), single_node_tree.end());
721 if (n_top_level_elements != 1)
723 std::ostringstream top_level_message;
724 top_level_message <<
"The ParameterHandler input parser found "
725 << n_top_level_elements
726 <<
" top level elements while reading\n "
727 <<
" an XML format input file, but there should be"
728 <<
" exactly one top level element.\n"
729 <<
" The top level elements are:\n";
731 unsigned int entry_n = 0;
732 for (boost::property_tree::ptree::iterator it = single_node_tree.begin();
733 it != single_node_tree.end();
738 << (entry_n != n_top_level_elements - 1 ?
"\n" :
"");
747 const boost::property_tree::ptree &my_entries =
748 single_node_tree.get_child(
"ParameterHandler");
750 read_xml_recursively(
757 const bool skip_undefined)
761 boost::property_tree::ptree node_tree;
764 read_json(in, node_tree);
768 read_xml_recursively(
777 entries = std_cxx14::make_unique<boost::property_tree::ptree>();
785 const std::string & default_value,
787 const std::string & documentation,
788 const bool has_to_be_set)
798 const std::pair<bool, bool> set_status =
799 std::pair<bool, bool>(has_to_be_set,
false);
807 static_cast<unsigned int>(
patterns.size() - 1));
818 "pattern_description",
831 const std::string & entry,
832 const std::function<
void(
const std::string &)> &action)
837 boost::optional<std::string> current_actions =
846 const std::string all_actions =
847 current_actions.get() +
"," +
858 const std::string default_value =
entries->get<std::string>(
860 action(default_value);
867 const std::string &alias_name,
868 const bool alias_is_deprecated)
873 ExcMessage(
"You are trying to declare an alias entry <" + alias_name +
874 "> that references an entry <" + existing_entry_name +
875 ">, but the latter does not exist."));
881 ExcMessage(
"You are trying to declare an alias entry <" + alias_name +
882 "> that references an entry <" + existing_entry_name +
883 ">, but the latter does not seem to be a "
884 "parameter declaration."));
894 ExcMessage(
"You are trying to declare an alias entry <" +
896 "> but a non-alias entry already exists in this "
897 "subsection (i.e., there is either a preexisting "
898 "further subsection, or a parameter entry, with "
899 "the same name as the alias)."));
904 "You are trying to declare an alias entry <" + alias_name +
905 "> but an alias entry already exists in this "
906 "subsection and this existing alias references a "
907 "different parameter entry. Specifically, "
908 "you are trying to reference the entry <" +
909 existing_entry_name +
910 "> whereas the existing alias references "
918 existing_entry_name);
920 "deprecation_status",
921 (alias_is_deprecated ?
"true" :
"false"));
932 boost::property_tree::ptree());
955 const std::vector<std::string> &sub_path)
const
959 full_path.insert(full_path.end(), sub_path.begin(), sub_path.end());
961 boost::optional<const boost::property_tree::ptree &> subsection(
968 return !(!subsection || is_parameter_node(subsection.get()) ||
969 is_alias_node(subsection.get()));
979 if (boost::optional<std::string>
value =
entries->get_optional<std::string>(
993 const std::string & entry_string)
const
997 if (boost::optional<std::string>
value =
entries->get_optional<std::string>(
1022 ExcMessage(
"Can't convert the parameter value <" +
1023 get(entry_string) +
"> for entry <" +
1024 entry_string +
"> to an integer."));
1033 const std::vector<std::string> &entry_subsection_path,
1034 const std::string & entry_string)
const
1044 "Can't convert the parameter value <" +
1045 get(entry_subsection_path, entry_string) +
"> for entry <" +
1048 "> to an integer."));
1065 ExcMessage(
"Can't convert the parameter value <" +
1066 get(entry_string) +
"> for entry <" +
1068 "> to a double precision variable."));
1077 const std::vector<std::string> &entry_subsection_path,
1078 const std::string & entry_string)
const
1083 get(entry_subsection_path, entry_string));
1089 "Can't convert the parameter value <" +
1090 get(entry_subsection_path, entry_string) +
"> for entry <" +
1093 "> to a double precision variable."));
1103 const std::string s =
get(entry_string);
1105 AssertThrow((s ==
"true") || (s ==
"false") || (s ==
"yes") || (s ==
"no"),
1106 ExcMessage(
"Can't convert the parameter value <" +
1107 get(entry_string) +
"> for entry <" + entry_string +
1108 "> to a boolean."));
1109 if (s ==
"true" || s ==
"yes")
1119 const std::vector<std::string> &entry_subsection_path,
1120 const std::string & entry_string)
const
1122 const std::string s =
get(entry_subsection_path, entry_string);
1124 AssertThrow((s ==
"true") || (s ==
"false") || (s ==
"yes") || (s ==
"no"),
1125 ExcMessage(
"Can't convert the parameter value <" +
1126 get(entry_subsection_path, entry_string) +
1130 "> to a boolean."));
1131 if (s ==
"true" || s ==
"yes")
1141 const std::string &new_value)
1155 const unsigned int pattern_index =
1161 "pattern_description")));
1165 const boost::optional<std::string> action_indices_as_string =
1167 if (action_indices_as_string)
1171 for (
const unsigned int index : action_indices)
1172 if (
actions.size() >= index + 1)
1181 map_iter->second = std::pair<bool, bool>(map_iter->second.first,
true);
1184 ExcMessage(
"Could not find parameter " + path +
1185 " in map entries_set_status."));
1196 set(entry_string, std::string(new_value));
1203 std::ostringstream s;
1204 s << std::setprecision(16);
1209 set(entry_string, s.str());
1217 std::ostringstream s;
1222 set(entry_string, s.str());
1232 set(entry_string, (new_value ?
"true" :
"false"));
1243 assert_validity_of_output_style(style);
1248 boost::property_tree::ptree current_entries = *
entries.get();
1256 std::vector<std::string>(),
1264 boost::io::ios_flags_saver restore_flags(out);
1265 boost::io::basic_ios_fill_saver<char> restore_fill_state(out);
1276 recursively_compress_tree(current_entries);
1290 boost::property_tree::ptree single_node_tree;
1291 single_node_tree.add_child(
"ParameterHandler", current_entries);
1293 write_xml(out, single_node_tree);
1299 write_json(out, current_entries);
1308 else if (style &
Text)
1310 out <<
"# Listing of Parameters" << std::endl
1311 <<
"# ---------------------" << std::endl;
1313 else if (style &
LaTeX)
1315 out <<
"\\subsection{Global parameters}" << std::endl;
1316 out <<
"\\label{parameters:global}" << std::endl;
1317 out << std::endl << std::endl;
1321 out <<
"Listing of Parameters:" << std::endl << std::endl;
1331 std::vector<std::string>(),
1343 const std::string & filename,
1346 std::string extension = filename.substr(filename.find_last_of(
'.') + 1);
1347 boost::algorithm::to_lower(extension);
1350 if (extension ==
"prm")
1351 output_style = style |
PRM;
1352 else if (extension ==
"xml")
1353 output_style = style |
XML;
1354 else if (extension ==
"json")
1355 output_style = style |
JSON;
1356 else if (extension ==
"tex")
1357 output_style = style |
LaTeX;
1359 std::ofstream out(filename);
1368 const boost::property_tree::ptree &tree,
1369 const std::vector<std::string> & target_subsection_path,
1371 const unsigned int indent_level,
1372 std::ostream & out)
const
1379 const boost::property_tree::ptree ¤t_section =
1380 tree.get_child(collate_path_string(
path_separator, target_subsection_path));
1382 unsigned int overall_indent_level = indent_level;
1384 const bool is_short = style &
Short;
1395 std::size_t longest_name = 0;
1396 std::size_t longest_value = 0;
1397 for (
const auto &p : current_section)
1398 if (is_parameter_node(p.second) ==
true)
1400 longest_name =
std::max(longest_name, demangle(p.first).length());
1403 p.second.get<std::string>(
"value").length());
1407 bool first_entry =
true;
1408 for (
const auto &p : current_section)
1409 if (is_parameter_node(p.second) ==
true)
1411 const std::string
value = p.second.get<std::string>(
"value");
1419 !p.second.get<std::string>(
"documentation").empty())
1421 if (first_entry ==
false)
1424 first_entry =
false;
1426 const std::vector<std::string> doc_lines =
1428 p.second.get<std::string>(
"documentation"),
1429 78 - overall_indent_level * 2 - 2);
1431 for (
const auto &doc_line : doc_lines)
1432 out << std::setw(overall_indent_level * 2) <<
""
1433 <<
"# " << doc_line <<
'\n';
1437 out << std::setw(overall_indent_level * 2) <<
""
1438 <<
"set " << demangle(p.first)
1439 << std::setw(longest_name - demangle(p.first).length() + 1)
1446 value != p.second.get<std::string>(
"default_value"))
1448 out << std::setw(longest_value -
value.length() + 1) <<
' '
1451 << p.second.get<std::string>(
"default_value");
1457 else if (style &
LaTeX)
1459 auto escape = [](
const std::string &input) {
1465 const bool parameters_exist_here =
1466 std::any_of(current_section.begin(),
1467 current_section.end(),
1468 [](
const boost::property_tree::ptree::value_type &p) {
1469 return is_parameter_node(p.second) ||
1470 is_alias_node(p.second);
1472 if (parameters_exist_here)
1474 out <<
"\\begin{itemize}" <<
'\n';
1477 for (
const auto &p : current_section)
1478 if (is_parameter_node(p.second) ==
true)
1480 const std::string
value = p.second.get<std::string>(
"value");
1483 out <<
"\\item {\\it Parameter name:} {\\tt "
1484 <<
escape(demangle(p.first)) <<
"}\n"
1485 <<
"\\phantomsection";
1489 std::string label =
"parameters:";
1490 for (
const auto &path : target_subsection_path)
1492 label.append(mangle(path));
1495 label.append(p.first);
1498 if (label.find(
"_20") != std::string::npos)
1502 out <<
"\\label{" << label <<
"}\n";
1506 out <<
"\\index[prmindex]{" <<
escape(demangle(p.first))
1508 out <<
"\\index[prmindexfull]{";
1509 for (
const auto &path : target_subsection_path)
1510 out <<
escape(path) <<
"!";
1511 out <<
escape(demangle(p.first)) <<
"}\n";
1514 out <<
"{\\it Value:} " <<
escape(
value) <<
"\n\n"
1516 <<
"{\\it Default:} "
1517 <<
escape(p.second.get<std::string>(
"default_value"))
1524 !p.second.get<std::string>(
"documentation").empty())
1525 out <<
"{\\it Description:} "
1526 << p.second.get<std::string>(
"documentation") <<
"\n\n"
1532 const unsigned int pattern_index =
1533 p.second.get<
unsigned int>(
"pattern");
1534 const std::string desc_str =
1535 patterns[pattern_index]->description(
1537 out <<
"{\\it Possible values:} " << desc_str <<
'\n';
1540 else if (is_alias_node(p.second) ==
true)
1542 const std::string alias = p.second.get<std::string>(
"alias");
1545 out <<
"\\item {\\it Parameter name:} {\\tt "
1546 <<
escape(demangle(p.first)) <<
"}\n"
1547 <<
"\\phantomsection";
1551 std::string label =
"parameters:";
1552 for (
const auto &path : target_subsection_path)
1554 label.append(mangle(path));
1557 label.append(p.first);
1560 if (label.find(
"_20") != std::string::npos)
1564 out <<
"\\label{" << label <<
"}\n";
1568 out <<
"\\index[prmindex]{" <<
escape(demangle(p.first))
1570 out <<
"\\index[prmindexfull]{";
1571 for (
const auto &path : target_subsection_path)
1572 out <<
escape(path) <<
"!";
1573 out <<
escape(demangle(p.first)) <<
"}\n";
1577 <<
"This parameter is an alias for the parameter ``\\texttt{"
1578 <<
escape(alias) <<
"}''."
1579 << (p.second.get<std::string>(
"deprecation_status") ==
1581 " Its use is deprecated." :
1586 out <<
"\\end{itemize}" <<
'\n';
1593 std::size_t longest_name = 0;
1594 for (
const auto &p : current_section)
1595 if (is_parameter_node(p.second) ==
true)
1596 longest_name =
std::max(longest_name, demangle(p.first).length());
1599 for (
const auto &p : current_section)
1600 if (is_parameter_node(p.second) ==
true)
1603 out << std::setw(overall_indent_level * 2) <<
""
1604 <<
"set " << demangle(p.first)
1605 << std::setw(longest_name - demangle(p.first).length() + 1)
1610 const unsigned int pattern_index =
1611 p.second.get<
unsigned int>(
"pattern");
1612 const std::string full_desc_str =
1614 const std::vector<std::string> description_str =
1616 full_desc_str, 78 - overall_indent_level * 2 - 2,
'|');
1617 if (description_str.size() > 1)
1620 for (
const auto &description : description_str)
1621 out << std::setw(overall_indent_level * 2 + 6) <<
""
1622 << description <<
'\n';
1624 else if (description_str.empty() ==
false)
1625 out <<
" " << description_str[0] <<
'\n';
1631 p.second.get<std::string>(
"documentation").length() != 0)
1632 out << std::setw(overall_indent_level * 2 + longest_name + 10)
1634 <<
"(" << p.second.get<std::string>(
"documentation") <<
")"
1647 unsigned int n_parameters = 0;
1648 unsigned int n_sections = 0;
1649 for (
const auto &p : current_section)
1650 if (is_parameter_node(p.second) ==
true)
1652 else if (is_alias_node(p.second) ==
false)
1656 (n_parameters != 0) && (n_sections != 0))
1661 for (
const auto &p : current_section)
1662 if ((is_parameter_node(p.second) ==
false) &&
1663 (is_alias_node(p.second) ==
false))
1668 out << std::setw(overall_indent_level * 2) <<
""
1669 <<
"subsection " << demangle(p.first) <<
'\n';
1671 else if (style &
LaTeX)
1673 auto escape = [](
const std::string &input) {
1678 out <<
'\n' <<
"\\subsection{Parameters in section \\tt ";
1682 for (
const auto &path : target_subsection_path)
1683 out <<
escape(path) <<
"/";
1684 out <<
escape(demangle(p.first));
1687 out <<
"\\label{parameters:";
1688 for (
const auto &path : target_subsection_path)
1689 out << mangle(path) <<
"/";
1690 out << p.first <<
"}";
1701 const std::string subsection = demangle(p.first);
1702 std::vector<std::string> directory_path = target_subsection_path;
1703 directory_path.emplace_back(subsection);
1706 tree, directory_path, style, overall_indent_level + 1, out);
1708 if (is_short && (style &
Text))
1711 out << std::setw(overall_indent_level * 2) <<
""
1714 else if (style &
Text)
1718 out << std::setw(overall_indent_level * 2) <<
""
1724 if (overall_indent_level == 0)
1731 else if (style &
LaTeX)
1747 out.
push(
"parameters");
1762 boost::property_tree::ptree sorted_entries;
1763 boost::property_tree::ptree *current_entries =
entries.get();
1769 current_entries = &sorted_entries;
1778 const boost::property_tree::ptree ¤t_section =
1782 for (
const auto &p : current_section)
1783 if (is_parameter_node(p.second) ==
true)
1784 out << demangle(p.first) <<
": " << p.second.get<std::string>(
"value")
1788 for (
const auto &p : current_section)
1789 if (is_parameter_node(p.second) ==
false)
1791 out.
push(demangle(p.first));
1803 const std::string &input_filename,
1804 const unsigned int current_line_n,
1805 const bool skip_undefined)
1808 const std::string original_line = line;
1811 if (line.find(
'#') != std::string::npos)
1812 line.erase(line.find(
'#'), std::string::npos);
1815 while (line.find(
'\t') != std::string::npos)
1816 line.replace(line.find(
'\t'), 1,
" ");
1822 if (line.length() == 0)
1831 line.erase(0, std::string(
"subsection").length() + 1);
1850 while ((line.size() > 0) && (std::isspace(line[0])))
1857 "Invalid content after 'end' or 'END' statement."));
1861 "There is no subsection to leave here."));
1873 pos != std::string::npos,
1876 "Invalid format of 'set' or 'SET' statement."));
1880 std::string entry_value =
1889 "deprecation_status") ==
"true")
1891 std::cerr <<
"Warning in line <" << current_line_n
1892 <<
"> of file <" << input_filename
1893 <<
">: You are using the deprecated spelling <"
1894 << entry_name <<
"> of the parameter <"
1897 <<
">." << std::endl;
1911 if (entry_value.find(
'{') == std::string::npos)
1914 const unsigned int pattern_index =
1922 patterns[pattern_index]->description()));
1926 const boost::optional<std::string> action_indices_as_string =
1929 if (action_indices_as_string)
1931 std::vector<int> action_indices =
1933 action_indices_as_string.get()));
1934 for (
const unsigned int index : action_indices)
1935 if (
actions.size() >= index + 1)
1949 (
"No entry with name <" + entry_name +
1950 "> was declared in the current subsection.")));
1959 while ((line.size() > 0) && (line[0] ==
' '))
1966 "The current line is an 'include' or "
1967 "'INCLUDE' statement, but it does not "
1968 "name a file for inclusion."));
1970 std::ifstream input(line.c_str());
1987 "could not be parsed: please check to "
1988 "make sure that the file is not missing a "
1989 "'set', 'include', 'subsection', or 'end' "
2011 for (
unsigned int j = 0; j <
patterns.size(); ++j)
2022 std::ostringstream o1, o2;
2024 write_json(o2, *prm2.
entries);
2025 return (o1.str() == o2.str());
2030 std::set<std::string>
2033 std::set<std::string> entries_wrongly_not_set;
2036 if (it.second.first ==
true && it.second.second ==
false)
2037 entries_wrongly_not_set.insert(it.first);
2039 return entries_wrongly_not_set;
2047 const std::set<std::string> entries_wrongly_not_set =
2050 if (entries_wrongly_not_set.size() > 0)
2052 std::string list_of_missing_parameters =
"\n\n";
2053 for (
const auto &it : entries_wrongly_not_set)
2054 list_of_missing_parameters +=
" " + it +
"\n";
2055 list_of_missing_parameters +=
"\n";
2058 entries_wrongly_not_set.size() == 0,
2060 "Not all entries of the parameter handler that were declared with "
2061 "`has_to_be_set = true` have been set. The following parameters " +
2062 list_of_missing_parameters +
2063 " have not been set. "
2064 "A possible reason might be that you did not add these parameter to "
2065 "the input file or that their spelling is not correct."));
2079 const std::string &filename,
2080 const std::string &last_line,
2081 const bool skip_undefined)
2097 for (
unsigned int run_no = 0; run_no <
n_branches; ++run_no)
2116 multiple_choice.split_different_values();
2122 n_branches *= multiple_choice.different_values.size();
2128 if (multiple_choice.different_values.size() !=
n_branches)
2129 std::cerr <<
" The entry value" << std::endl
2130 <<
" " << multiple_choice.entry_value << std::endl
2131 <<
" for the entry named" << std::endl
2132 <<
" " << multiple_choice.entry_name << std::endl
2133 <<
" does not have the right number of entries for the "
2136 <<
" variant runs that will be performed." << std::endl;
2143 for (
unsigned int i = 0; i <
n_branches; ++i)
2152 const boost::property_tree::ptree ¤t_section =
2158 for (
const auto &p : current_section)
2159 if (is_parameter_node(p.second) ==
true)
2161 const std::string
value = p.second.get<std::string>(
"value");
2162 if (
value.find(
'{') != std::string::npos)
2169 for (
const auto &p : current_section)
2170 if (is_parameter_node(p.second) ==
false)
2183 unsigned int possibilities = 1;
2185 std::vector<Entry>::iterator choice;
2189 const unsigned int selection =
2190 (run_no / possibilities) % choice->different_values.size();
2191 std::string entry_value;
2193 entry_value = choice->different_values[selection];
2196 if (run_no >= choice->different_values.size())
2199 <<
"The given array for entry <" << choice->entry_name
2200 <<
"> does not contain enough elements! Taking empty string instead."
2205 entry_value = choice->different_values[run_no];
2217 set(choice->entry_name, entry_value);
2222 possibilities *= choice->different_values.size();
2233 mem += multiple_choice.memory_consumption();
2241 const std::string & Name,
2242 const std::string & Value)
2243 : subsection_path(ssp)
2245 , entry_value(Value)
2246 , type(
Entry::array)
2258 std::string prefix(entry_value, 0, entry_value.find(
'{'));
2259 std::string multiple(entry_value,
2260 entry_value.find(
'{') + 1,
2261 entry_value.rfind(
'}') - entry_value.find(
'{') - 1);
2262 std::string postfix(entry_value,
2263 entry_value.rfind(
'}') + 1,
2267 if (multiple[0] ==
'{')
2268 multiple.erase(0, 1);
2269 if (multiple[multiple.size() - 1] ==
'}')
2270 multiple.erase(multiple.size() - 1, 1);
2273 while (std::isspace(multiple[0]))
2274 multiple.erase(0, 1);
2275 while (std::isspace(multiple[multiple.size() - 1]))
2276 multiple.erase(multiple.size() - 1, 1);
2279 while (multiple.find(
" |") != std::string::npos)
2280 multiple.replace(multiple.find(
" |"), 2,
"|");
2281 while (multiple.find(
"| ") != std::string::npos)
2282 multiple.replace(multiple.find(
"| "), 2,
"|");
2284 while (multiple.find(
'|') != std::string::npos)
2286 different_values.push_back(
2287 prefix + std::string(multiple, 0, multiple.find(
'|')) + postfix);
2288 multiple.erase(0, multiple.find(
'|') + 1);
2292 different_values.push_back(prefix + multiple + postfix);
2295 if ((entry_value.find(
"{{") != std::string::npos) &&
2296 (entry_value.find(
"}}") != std::string::npos))