22#define BOOST_BIND_GLOBAL_PLACEHOLDERS
23#include <boost/algorithm/string.hpp>
24#include <boost/io/ios_state.hpp>
25#include <boost/property_tree/json_parser.hpp>
26#include <boost/property_tree/ptree.hpp>
27#include <boost/property_tree/xml_parser.hpp>
28#undef BOOST_BIND_GLOBAL_PLACEHOLDERS
46 : entries(new
boost::property_tree::ptree())
53 mangle(
const std::string &s)
62 const bool mangle_whole_string = (s ==
"value");
65 for (
const char c : s)
67 static const std::string allowed_characters(
68 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
70 if ((!mangle_whole_string) &&
71 (allowed_characters.find(c) != std::string::npos))
76 static const char hex[16] = {
'0',
92 u.push_back(hex[
static_cast<unsigned char>(c) / 16]);
93 u.push_back(hex[
static_cast<unsigned char>(c) % 16]);
103 demangle(
const std::string &s)
108 for (
unsigned int i = 0; i < s.size(); ++i)
114 ExcMessage(
"Trying to demangle an invalid string."));
224 u.push_back(
static_cast<char>(c));
238 is_parameter_node(
const boost::property_tree::ptree &p)
240 return static_cast<bool>(p.get_optional<std::string>(
"value"));
249 is_alias_node(
const boost::property_tree::ptree &p)
251 return static_cast<bool>(p.get_optional<std::string>(
"alias"));
261 collate_path_string(
const char separator,
262 const std::vector<std::string> &subsection_path)
264 if (subsection_path.size() > 0)
266 std::string p = mangle(subsection_path[0]);
267 for (
unsigned int i = 1; i < subsection_path.size(); ++i)
270 p += mangle(subsection_path[i]);
284 recursively_sort_parameters(
285 const char separator,
286 const std::vector<std::string> &target_subsection_path,
287 boost::property_tree::ptree &tree)
289 boost::property_tree::ptree ¤t_section =
290 tree.get_child(collate_path_string(separator, target_subsection_path));
295 static auto compare =
296 [](
const std::pair<std::string, boost::property_tree::ptree> &a,
297 const std::pair<std::string, boost::property_tree::ptree> &
b) {
299 (is_parameter_node(a.second) || is_alias_node(a.second));
302 (is_parameter_node(
b.second) || is_alias_node(
b.second));
306 if (a_is_param && !b_is_param)
309 if (!a_is_param && b_is_param)
313 return a.first <
b.first;
316 current_section.sort(compare);
319 for (
const auto &p : current_section)
321 if ((is_parameter_node(p.second) ==
false) &&
322 (is_alias_node(p.second) ==
false))
324 const std::string subsection = demangle(p.first);
326 std::vector<std::string> subsection_path = target_subsection_path;
327 subsection_path.emplace_back(subsection);
329 recursively_sort_parameters(separator, subsection_path, tree);
342 recursively_mangle_or_demangle(
const boost::property_tree::ptree &tree_in,
343 boost::property_tree::ptree &tree_out,
344 const bool do_mangle,
345 const bool is_parameter_or_alias_node =
false)
347 for (
const auto &p : tree_in)
349 if (is_parameter_or_alias_node)
351 tree_out.put_child(p.first, p.second);
355 boost::property_tree::ptree temp;
357 if (
const auto val = p.second.get_value_optional<std::string>())
358 temp.put_value<std::string>(*val);
360 recursively_mangle_or_demangle(p.second,
363 is_parameter_node(p.second) ||
364 is_alias_node(p.second));
365 tree_out.put_child(do_mangle ? mangle(p.first) : demangle(p.
first),
384 "You have chosen either no or multiple style formats. You can choose "
385 "between: PRM, Description, LaTeX, XML, JSON."));
404 if (path.empty() ==
false)
407 path += mangle(name);
416 const std::vector<std::string> &sub_path,
417 const std::string &name)
const
420 if (path.empty() ==
false)
423 if (sub_path.empty() ==
false)
426 path += mangle(name);
435 const std::string &filename,
436 const std::string &last_line,
437 const bool skip_undefined)
444 std::string input_line;
445 std::string fully_concatenated_line;
446 bool is_concatenated =
false;
450 unsigned int current_line_n = 0;
451 unsigned int current_logical_line_n = 0;
454 std::string deprecation_messages;
468 auto scan_line_or_cleanup =
472 &deprecation_messages](
const std::string &line,
473 const std::string &filename,
474 const unsigned int line_number) {
477 scan_line(line, filename, line_number, skip_undefined);
481 deprecation_messages += e.what();
494 while (std::getline(input, input_line))
497 if (!is_concatenated)
498 current_logical_line_n = current_line_n;
505 if (last_line.size() != 0 && input_line == last_line)
510 if (input_line.size() != 0 &&
511 input_line.find_last_of(
'\\') == input_line.size() - 1)
513 input_line.erase(input_line.size() - 1);
514 is_concatenated =
true;
516 fully_concatenated_line += input_line;
520 else if (is_concatenated)
522 fully_concatenated_line += input_line;
523 is_concatenated =
false;
529 fully_concatenated_line = input_line;
532 if (!is_concatenated)
534 scan_line_or_cleanup(fully_concatenated_line,
536 current_logical_line_n);
538 fully_concatenated_line.clear();
546 scan_line_or_cleanup(fully_concatenated_line, filename, current_line_n);
550 std::stringstream paths_message;
551 if (saved_path.size() > 0)
553 paths_message <<
"Path before loading input:\n";
556 paths_message << std::setw(i * 2 + 4) <<
" "
557 <<
"subsection " << saved_path[i] <<
'\n';
559 paths_message <<
"Current path:\n";
562 paths_message << std::setw(i * 2 + 4) <<
" "
583 const std::string &last_line,
584 const bool skip_undefined,
585 const bool assert_mandatory_entries_are_found)
587 std::ifstream is(filename);
590 std::string file_ending = filename.substr(filename.find_last_of(
'.') + 1);
591 boost::algorithm::to_lower(file_ending);
592 if (file_ending ==
"prm")
593 parse_input(is, filename, last_line, skip_undefined);
594 else if (file_ending ==
"xml")
596 else if (file_ending ==
"json")
600 ExcMessage(
"The given input file <" + filename +
601 "> has a file name extension <" + file_ending +
602 "> that is not recognized. Supported types "
603 "are .prm, .xml, and .json."));
605 if (assert_mandatory_entries_are_found)
613 const std::string &last_line,
614 const bool skip_undefined)
616 std::istringstream input_stream(s);
617 parse_input(input_stream,
"input string", last_line, skip_undefined);
630 read_xml_recursively(
631 const boost::property_tree::ptree &source,
632 const std::string ¤t_path,
633 const char path_separator,
634 const std::vector<std::unique_ptr<const Patterns::PatternBase>> &patterns,
635 const bool skip_undefined,
638 for (
const auto &p : source)
641 if (p.second.empty())
648 prm.
set(demangle(p.first), p.second.data());
656 prm.
set(demangle(p.first), p.second.data());
658 else if (p.second.get_optional<std::string>(
"value"))
665 prm.
set(demangle(p.first),
666 p.second.get<std::string>(
"value"));
674 prm.
set(demangle(p.first), p.second.get<std::string>(
"value"));
681 else if (p.second.get_optional<std::string>(
"alias"))
693 read_xml_recursively(p.second,
694 (current_path.empty() ?
696 current_path + path_separator +
733 recursively_compress_tree(boost::property_tree::ptree &source)
735 for (
auto &p : source)
737 if (p.second.get_optional<std::string>(
"value"))
740 const auto temp = p.second.get<std::string>(
"value");
744 p.second.put_value<std::string>(temp);
746 else if (p.second.get_optional<std::string>(
"alias"))
752 recursively_compress_tree(p.second);
758 recursively_keep_non_default(
const boost::property_tree::ptree &tree_in,
759 boost::property_tree::ptree &tree_out)
761 for (
const auto &p : tree_in)
763 if (is_parameter_node(p.second))
765 const std::string
value = p.second.get<std::string>(
"value");
767 if (value != p.second.get<std::string>(
"default_value"))
768 tree_out.put_child(p.first, p.second);
770 else if (is_alias_node(p.second))
776 boost::property_tree::ptree temp;
778 if (
const auto val = p.second.get_value_optional<std::string>())
779 temp.put_value<std::string>(*val);
781 recursively_keep_non_default(p.second, temp);
784 tree_out.put_child(p.first, temp);
794 const bool skip_undefined)
801 boost::property_tree::ptree single_node_tree;
804 read_xml(in, single_node_tree);
808 AssertThrow(single_node_tree.get_optional<std::string>(
"ParameterHandler"),
810 "called \"ParameterHandler\"."));
812 const std::size_t n_top_level_elements =
813 std::distance(single_node_tree.begin(), single_node_tree.end());
814 if (n_top_level_elements != 1)
816 std::ostringstream top_level_message;
817 top_level_message <<
"The ParameterHandler input parser found "
818 << n_top_level_elements
819 <<
" top level elements while reading\n "
820 <<
" an XML format input file, but there should be"
821 <<
" exactly one top level element.\n"
822 <<
" The top level elements are:\n";
824 unsigned int entry_n = 0;
825 for (boost::property_tree::ptree::iterator it = single_node_tree.begin();
826 it != single_node_tree.end();
831 << (entry_n != n_top_level_elements - 1 ?
"\n" :
"");
840 const boost::property_tree::ptree &my_entries =
841 single_node_tree.get_child(
"ParameterHandler");
843 read_xml_recursively(
850 const bool skip_undefined)
854 boost::property_tree::ptree node_tree;
859 read_json(in, node_tree);
861 catch (
const std::exception &e)
866 "The provided JSON file is not valid. Boost aborted with the "
867 "following assert message: \n\n" +
868 std::string(e.what())));
874 boost::property_tree::ptree node_tree_mangled;
875 recursively_mangle_or_demangle(node_tree,
878 read_xml_recursively(
887 entries = std::make_unique<boost::property_tree::ptree>();
895 const std::string &default_value,
897 const std::string &documentation,
898 const bool has_to_be_set)
908 const std::pair<bool, bool> set_status =
909 std::pair<bool, bool>(has_to_be_set,
false);
917 static_cast<unsigned int>(
patterns.size() - 1));
928 "pattern_description",
941 const std::string &entry,
942 const std::function<
void(
const std::string &)> &action,
943 const bool execute_action)
948 boost::optional<std::string> current_actions =
957 const std::string all_actions =
958 current_actions.get() +
"," +
969 const std::string default_value =
entries->get<std::string>(
971 action(default_value);
979 const std::string &alias_name,
980 const bool alias_is_deprecated)
985 ExcMessage(
"You are trying to declare an alias entry <" + alias_name +
986 "> that references an entry <" + existing_entry_name +
987 ">, but the latter does not exist."));
993 ExcMessage(
"You are trying to declare an alias entry <" + alias_name +
994 "> that references an entry <" + existing_entry_name +
995 ">, but the latter does not seem to be a "
996 "parameter declaration."));
1006 ExcMessage(
"You are trying to declare an alias entry <" +
1008 "> but a non-alias entry already exists in this "
1009 "subsection (i.e., there is either a preexisting "
1010 "further subsection, or a parameter entry, with "
1011 "the same name as the alias)."));
1014 existing_entry_name,
1016 "You are trying to declare an alias entry <" + alias_name +
1017 "> but an alias entry already exists in this "
1018 "subsection and this existing alias references a "
1019 "different parameter entry. Specifically, "
1020 "you are trying to reference the entry <" +
1021 existing_entry_name +
1022 "> whereas the existing alias references "
1030 existing_entry_name);
1032 if (alias_is_deprecated)
1042 const bool is_deprecated)
1047 ExcMessage(
"You are trying to mark the entry <" + existing_entry_name +
1048 "> as deprecated, but the entry does not exist."));
1053 entries->get_optional<std::string>(
1055 entries->get_optional<std::string>(
1057 ExcMessage(
"You are trying to mark the entry <" + existing_entry_name +
1058 "> as deprecated, but the entry does not seem to be a "
1059 "parameter declaration or a parameter alias."));
1062 "deprecation_status",
1063 is_deprecated ?
"true" :
"false");
1070 const bool create_path_if_needed)
1073 const auto path_exists =
1076 if (!create_path_if_needed)
1084 boost::property_tree::ptree());
1107 const std::vector<std::string> &sub_path)
const
1111 full_path.insert(full_path.end(), sub_path.begin(), sub_path.end());
1113 boost::optional<const boost::property_tree::ptree &> subsection(
1120 return !(!subsection || is_parameter_node(subsection.get()) ||
1121 is_alias_node(subsection.get()));
1131 if (boost::optional<std::string> value =
entries->get_optional<std::string>(
1145 const std::string &entry_string)
const
1149 if (boost::optional<std::string> value =
entries->get_optional<std::string>(
1174 ExcMessage(
"Can't convert the parameter value <" +
1175 get(entry_string) +
"> for entry <" +
1176 entry_string +
"> to an integer."));
1185 const std::vector<std::string> &entry_subsection_path,
1186 const std::string &entry_string)
const
1196 "Can't convert the parameter value <" +
1197 get(entry_subsection_path, entry_string) +
"> for entry <" +
1200 "> to an integer."));
1217 ExcMessage(
"Can't convert the parameter value <" +
1218 get(entry_string) +
"> for entry <" +
1220 "> to a double precision variable."));
1229 const std::vector<std::string> &entry_subsection_path,
1230 const std::string &entry_string)
const
1235 get(entry_subsection_path, entry_string));
1241 "Can't convert the parameter value <" +
1242 get(entry_subsection_path, entry_string) +
"> for entry <" +
1245 "> to a double precision variable."));
1255 const std::string s =
get(entry_string);
1257 AssertThrow((s ==
"true") || (s ==
"false") || (s ==
"yes") || (s ==
"no"),
1258 ExcMessage(
"Can't convert the parameter value <" +
1259 get(entry_string) +
"> for entry <" + entry_string +
1260 "> to a boolean."));
1261 if (s ==
"true" || s ==
"yes")
1271 const std::vector<std::string> &entry_subsection_path,
1272 const std::string &entry_string)
const
1274 const std::string s =
get(entry_subsection_path, entry_string);
1276 AssertThrow((s ==
"true") || (s ==
"false") || (s ==
"yes") || (s ==
"no"),
1277 ExcMessage(
"Can't convert the parameter value <" +
1278 get(entry_subsection_path, entry_string) +
1282 "> to a boolean."));
1283 if (s ==
"true" || s ==
"yes")
1293 const std::string &new_value)
1307 const unsigned int pattern_index =
1313 "pattern_description")));
1317 const boost::optional<std::string> action_indices_as_string =
1319 if (action_indices_as_string)
1323 for (
const unsigned int index : action_indices)
1324 if (
actions.size() >= index + 1)
1333 map_iter->second = std::pair<bool, bool>(map_iter->second.first,
true);
1336 ExcMessage(
"Could not find parameter " + path +
1337 " in map entries_set_status."));
1348 set(entry_string, std::string(new_value));
1355 std::ostringstream s;
1356 s << std::setprecision(16);
1361 set(entry_string, s.str());
1369 std::ostringstream s;
1374 set(entry_string, s.str());
1384 set(entry_string, (new_value ?
"true" :
"false"));
1395 assert_validity_of_output_style(style);
1400 boost::property_tree::ptree current_entries = *
entries.get();
1408 std::vector<std::string>(),
1414 boost::property_tree::ptree current_entries_without_default;
1415 recursively_keep_non_default(current_entries,
1416 current_entries_without_default);
1417 current_entries = current_entries_without_default;
1424 boost::io::ios_flags_saver restore_flags(out);
1425 boost::io::basic_ios_fill_saver<char> restore_fill_state(out);
1433 if (((style &
Short) != 0) && ((style & (
XML |
JSON)) != 0))
1436 recursively_compress_tree(current_entries);
1439 if ((style &
XML) != 0)
1450 boost::property_tree::ptree single_node_tree;
1451 single_node_tree.add_child(
"ParameterHandler", current_entries);
1453 write_xml(out, single_node_tree);
1457 if ((style &
JSON) != 0)
1459 boost::property_tree::ptree current_entries_demangled;
1460 recursively_mangle_or_demangle(current_entries,
1461 current_entries_demangled,
1463 write_json(out, current_entries_demangled);
1468 if (((style &
Short) != 0) && ((style &
PRM) != 0))
1472 else if ((style &
PRM) != 0)
1474 out <<
"# Listing of Parameters" << std::endl
1475 <<
"# ---------------------" << std::endl;
1477 else if ((style &
LaTeX) != 0)
1479 out <<
"\\subsection{Global parameters}" << std::endl;
1480 out <<
"\\label{parameters:global}" << std::endl;
1481 out << std::endl << std::endl;
1485 out <<
"Listing of Parameters:" << std::endl << std::endl;
1495 std::vector<std::string>(),
1507 const std::string &filename,
1510 std::string extension = filename.substr(filename.find_last_of(
'.') + 1);
1511 boost::algorithm::to_lower(extension);
1514 if (extension ==
"prm")
1515 output_style = style |
PRM;
1516 else if (extension ==
"xml")
1517 output_style = style |
XML;
1518 else if (extension ==
"json")
1519 output_style = style |
JSON;
1520 else if (extension ==
"tex")
1521 output_style = style |
LaTeX;
1523 std::ofstream out(filename);
1532 const boost::property_tree::ptree &tree,
1533 const std::vector<std::string> &target_subsection_path,
1535 const unsigned int indent_level,
1536 std::ostream &out)
const
1543 const boost::property_tree::ptree ¤t_section =
1544 tree.get_child(collate_path_string(
path_separator, target_subsection_path));
1546 unsigned int overall_indent_level = indent_level;
1548 const bool is_short = (style &
Short) != 0;
1550 if ((style &
PRM) != 0)
1559 std::size_t longest_name = 0;
1560 std::size_t longest_value = 0;
1561 for (
const auto &p : current_section)
1562 if (is_parameter_node(p.second) ==
true)
1564 longest_name =
std::max(longest_name, demangle(p.first).size());
1565 longest_value =
std::max(longest_value,
1566 p.second.get<std::string>(
"value").size());
1570 bool first_entry =
true;
1571 for (
const auto &p : current_section)
1572 if (is_parameter_node(p.second) ==
true)
1574 const std::string value = p.second.get<std::string>(
"value");
1582 !p.second.get<std::string>(
"documentation").empty())
1584 if (first_entry ==
false)
1587 first_entry =
false;
1589 const std::vector<std::string> doc_lines =
1591 p.second.get<std::string>(
"documentation"),
1592 78 - overall_indent_level * 2 - 2);
1594 for (
const auto &doc_line : doc_lines)
1598 out << std::setw(overall_indent_level * 2) <<
"" <<
'#';
1600 if (!doc_line.empty())
1601 out <<
' ' << doc_line;
1609 out << std::setw(overall_indent_level * 2) <<
""
1610 <<
"set " << demangle(p.first)
1611 << std::setw(longest_name - demangle(p.first).size() + 1) <<
' '
1614 out <<
' ' << value;
1619 value != p.second.get<std::string>(
"default_value"))
1621 out << std::setw(longest_value - value.size() + 1) <<
' '
1624 << p.second.get<std::string>(
"default_value");
1630 else if ((style &
LaTeX) != 0)
1632 auto escape = [](
const std::string &input) {
1638 const bool parameters_exist_here =
1639 std::any_of(current_section.begin(),
1640 current_section.end(),
1641 [](
const boost::property_tree::ptree::value_type &p) {
1642 return is_parameter_node(p.second) ||
1643 is_alias_node(p.second);
1645 if (parameters_exist_here)
1647 out <<
"\\begin{itemize}" <<
'\n';
1650 for (
const auto &p : current_section)
1651 if (is_parameter_node(p.second) ==
true)
1653 const std::string value = p.second.get<std::string>(
"value");
1656 out <<
"\\item {\\it Parameter name:} {\\tt "
1657 << escape(demangle(p.first)) <<
"}\n"
1658 <<
"\\phantomsection";
1662 std::string label =
"parameters:";
1663 for (
const auto &path : target_subsection_path)
1665 label.append(mangle(path));
1668 label.append(p.first);
1671 if (label.find(
"_20") != std::string::npos)
1675 out <<
"\\label{" << label <<
"}\n";
1679 out <<
"\\index[prmindex]{" << escape(demangle(p.first))
1681 out <<
"\\index[prmindexfull]{";
1682 for (
const auto &path : target_subsection_path)
1683 out << escape(path) <<
"!";
1684 out << escape(demangle(p.first)) <<
"}\n";
1687 out <<
"{\\it Value:} " << escape(value) <<
"\n\n"
1689 <<
"{\\it Default:} "
1690 << escape(p.second.get<std::string>(
"default_value"))
1697 !p.second.get<std::string>(
"documentation").empty())
1698 out <<
"{\\it Description:} "
1699 << p.second.get<std::string>(
"documentation")
1700 << ((p.second.get_optional<std::string>(
1701 "deprecation_status") &&
1702 p.second.get<std::string>(
"deprecation_status") ==
1704 " This parameter is deprecated.\n\n" :
1711 const unsigned int pattern_index =
1712 p.second.get<
unsigned int>(
"pattern");
1713 const std::string desc_str =
1714 patterns[pattern_index]->description(
1716 out <<
"{\\it Possible values:} " << desc_str <<
'\n';
1719 else if (is_alias_node(p.second) ==
true)
1721 const std::string alias = p.second.get<std::string>(
"alias");
1724 out <<
"\\item {\\it Parameter name:} {\\tt "
1725 << escape(demangle(p.first)) <<
"}\n"
1726 <<
"\\phantomsection";
1730 std::string label =
"parameters:";
1731 for (
const auto &path : target_subsection_path)
1733 label.append(mangle(path));
1736 label.append(p.first);
1739 if (label.find(
"_20") != std::string::npos)
1743 out <<
"\\label{" << label <<
"}\n";
1747 out <<
"\\index[prmindex]{" << escape(demangle(p.first))
1749 out <<
"\\index[prmindexfull]{";
1750 for (
const auto &path : target_subsection_path)
1751 out << escape(path) <<
"!";
1752 out << escape(demangle(p.first)) <<
"}\n";
1756 <<
"This parameter is an alias for the parameter ``\\texttt{"
1757 << escape(alias) <<
"}''."
1758 << (p.second.get<std::string>(
"deprecation_status") ==
1760 " Its use is deprecated." :
1765 out <<
"\\end{itemize}" <<
'\n';
1772 std::size_t longest_name = 0;
1773 for (
const auto &p : current_section)
1774 if (is_parameter_node(p.second) ==
true)
1775 longest_name =
std::max(longest_name, demangle(p.first).size());
1778 for (
const auto &p : current_section)
1779 if (is_parameter_node(p.second) ==
true)
1782 out << std::setw(overall_indent_level * 2) <<
""
1783 <<
"set " << demangle(p.first)
1784 << std::setw(longest_name - demangle(p.first).size() + 1) <<
" "
1788 const unsigned int pattern_index =
1789 p.second.get<
unsigned int>(
"pattern");
1790 const std::string full_desc_str =
1792 const std::vector<std::string> description_str =
1794 full_desc_str, 78 - overall_indent_level * 2 - 2,
'|');
1795 if (description_str.size() > 1)
1798 for (
const auto &description : description_str)
1799 out << std::setw(overall_indent_level * 2 + 6) <<
""
1800 << description <<
'\n';
1802 else if (description_str.empty() ==
false)
1803 out <<
" " << description_str[0] <<
'\n';
1809 p.second.get<std::string>(
"documentation").size() != 0)
1810 out << std::setw(overall_indent_level * 2 + longest_name + 10)
1812 <<
"(" << p.second.get<std::string>(
"documentation") <<
")"
1825 unsigned int n_parameters = 0;
1826 unsigned int n_sections = 0;
1827 for (
const auto &p : current_section)
1828 if (is_parameter_node(p.second) ==
true)
1830 else if (is_alias_node(p.second) ==
false)
1833 if (((style &
Description) == 0) && (!(((style &
PRM) != 0) && is_short)) &&
1834 (n_parameters != 0) && (n_sections != 0))
1839 for (
const auto &p : current_section)
1840 if ((is_parameter_node(p.second) ==
false) &&
1841 (is_alias_node(p.second) ==
false))
1846 out << std::setw(overall_indent_level * 2) <<
""
1847 <<
"subsection " << demangle(p.first) <<
'\n';
1849 else if ((style &
LaTeX) != 0)
1851 auto escape = [](
const std::string &input) {
1856 out <<
'\n' <<
"\\subsection{Parameters in section \\tt ";
1860 for (
const auto &path : target_subsection_path)
1861 out << escape(path) <<
"/";
1862 out << escape(demangle(p.first));
1865 out <<
"\\label{parameters:";
1866 for (
const auto &path : target_subsection_path)
1867 out << mangle(path) <<
"/";
1868 out << p.first <<
"}";
1879 const std::string subsection = demangle(p.first);
1880 std::vector<std::string> directory_path = target_subsection_path;
1881 directory_path.emplace_back(subsection);
1884 tree, directory_path, style, overall_indent_level + 1, out);
1886 if (is_short && ((style &
PRM) != 0))
1889 out << std::setw(overall_indent_level * 2) <<
""
1892 else if ((style &
PRM) != 0)
1896 out << std::setw(overall_indent_level * 2) <<
""
1902 if (overall_indent_level == 0)
1909 else if ((style &
LaTeX) != 0)
1925 out.
push(
"parameters");
1940 boost::property_tree::ptree sorted_entries;
1941 boost::property_tree::ptree *current_entries =
entries.get();
1947 current_entries = &sorted_entries;
1956 const boost::property_tree::ptree ¤t_section =
1960 for (
const auto &p : current_section)
1961 if (is_parameter_node(p.second) ==
true)
1962 out << demangle(p.first) <<
": " << p.second.get<std::string>(
"value")
1966 for (
const auto &p : current_section)
1967 if (is_parameter_node(p.second) ==
false)
1969 out.
push(demangle(p.first));
1981 const std::string &input_filename,
1982 const unsigned int current_line_n,
1983 const bool skip_undefined)
1986 const std::string original_line = line;
1989 if (line.find(
'#') != std::string::npos)
1990 line.erase(line.find(
'#'), std::string::npos);
1993 while (line.find(
'\t') != std::string::npos)
1994 line.replace(line.find(
'\t'), 1,
" ");
2009 line.erase(0, std::string(
"subsection").
size() + 1);
2028 while ((line.size() > 0) && ((std::isspace(line[0])) != 0))
2035 "Invalid content after 'end' or 'END' statement."));
2039 "There is no subsection to leave here."));
2049 std::string::size_type pos = line.find(
'=');
2051 pos != std::string::npos,
2054 "Invalid format of 'set' or 'SET' statement."));
2058 std::string entry_value =
2067 "deprecation_status") ==
"true")
2069 std::cerr <<
"Warning in line <" << current_line_n
2070 <<
"> of file <" << input_filename
2071 <<
">: You are using the deprecated spelling <"
2072 << entry_name <<
"> of the parameter <"
2075 <<
">." << std::endl;
2089 if (entry_value.find(
'{') == std::string::npos)
2092 const unsigned int pattern_index =
2100 patterns[pattern_index]->description()));
2104 const boost::optional<std::string> action_indices_as_string =
2107 if (action_indices_as_string)
2109 std::vector<int> action_indices =
2111 action_indices_as_string.get()));
2112 for (
const unsigned int index : action_indices)
2113 if (
actions.size() >= index + 1)
2125 std::pair<bool, bool>(map_iter->second.first,
true);
2128 ExcMessage(
"Could not find parameter " + path +
2129 " in map entries_set_status."));
2134 "deprecation_status") &&
2136 "deprecation_status") ==
"true")
2150 (
"No entry with name <" + entry_name +
2151 "> was declared in the current subsection.")));
2160 while ((line.size() > 0) && (line[0] ==
' '))
2167 "The current line is an 'include' or "
2168 "'INCLUDE' statement, but it does not "
2169 "name a file for inclusion."));
2171 std::ifstream input(line);
2188 "could not be parsed: please check to "
2189 "make sure that the file is not missing a "
2190 "'set', 'include', 'subsection', or 'end' "
2212 for (
unsigned int j = 0; j <
patterns.size(); ++j)
2223 std::ostringstream o1, o2;
2225 write_json(o2, *prm2.
entries);
2226 return (o1.str() == o2.str());
2231std::set<std::string>
2234 std::set<std::string> entries_wrongly_not_set;
2237 if (it.second.first ==
true && it.second.second ==
false)
2238 entries_wrongly_not_set.insert(it.first);
2240 return entries_wrongly_not_set;
2248 const std::set<std::string> entries_wrongly_not_set =
2251 if (entries_wrongly_not_set.size() > 0)
2253 std::string list_of_missing_parameters =
"\n\n";
2254 for (
const auto &it : entries_wrongly_not_set)
2255 list_of_missing_parameters +=
" " + it +
"\n";
2256 list_of_missing_parameters +=
"\n";
2259 entries_wrongly_not_set.empty(),
2261 "Not all entries of the parameter handler that were declared with "
2262 "`has_to_be_set = true` have been set. The following parameters " +
2263 list_of_missing_parameters +
2264 " have not been set. "
2265 "A possible reason might be that you did not add these parameter to "
2266 "the input file or that their spelling is not correct."));
2280 const std::string &filename,
2281 const std::string &last_line,
2282 const bool skip_undefined)
2298 for (
unsigned int run_no = 0; run_no <
n_branches; ++run_no)
2317 multiple_choice.split_different_values();
2323 n_branches *= multiple_choice.different_values.size();
2329 if (multiple_choice.different_values.size() !=
n_branches)
2330 std::cerr <<
" The entry value" << std::endl
2331 <<
" " << multiple_choice.entry_value << std::endl
2332 <<
" for the entry named" << std::endl
2333 <<
" " << multiple_choice.entry_name << std::endl
2334 <<
" does not have the right number of entries for the "
2337 <<
" variant runs that will be performed." << std::endl;
2344 for (
unsigned int i = 0; i <
n_branches; ++i)
2353 const boost::property_tree::ptree ¤t_section =
2359 for (
const auto &p : current_section)
2360 if (is_parameter_node(p.second) ==
true)
2362 const std::string value = p.second.get<std::string>(
"value");
2363 if (value.find(
'{') != std::string::npos)
2370 for (
const auto &p : current_section)
2371 if (is_parameter_node(p.second) ==
false)
2384 unsigned int possibilities = 1;
2386 std::vector<Entry>::iterator choice;
2390 const unsigned int selection =
2391 (run_no / possibilities) % choice->different_values.size();
2392 std::string entry_value;
2394 entry_value = choice->different_values[selection];
2397 if (run_no >= choice->different_values.size())
2400 <<
"The given array for entry <" << choice->entry_name
2401 <<
"> does not contain enough elements! Taking empty string instead."
2406 entry_value = choice->different_values[run_no];
2418 set(choice->entry_name, entry_value);
2423 possibilities *= choice->different_values.size();
2434 mem += multiple_choice.memory_consumption();
2442 const std::string &Name,
2443 const std::string &Value)
2444 : subsection_path(ssp)
2446 , entry_value(Value)
2447 , type(
Entry::array)
2459 std::string prefix(entry_value, 0, entry_value.find(
'{'));
2460 std::string multiple(entry_value,
2461 entry_value.find(
'{') + 1,
2462 entry_value.rfind(
'}') - entry_value.find(
'{') - 1);
2463 std::string postfix(entry_value,
2464 entry_value.rfind(
'}') + 1,
2468 if (multiple[0] ==
'{')
2469 multiple.erase(0, 1);
2470 if (multiple.back() ==
'}')
2471 multiple.erase(multiple.size() - 1, 1);
2474 while (std::isspace(multiple[0]) != 0)
2475 multiple.erase(0, 1);
2476 while (std::isspace(multiple.back()) != 0)
2477 multiple.erase(multiple.size() - 1, 1);
2480 while (multiple.find(
" |") != std::string::npos)
2481 multiple.replace(multiple.find(
" |"), 2,
"|");
2482 while (multiple.find(
"| ") != std::string::npos)
2483 multiple.replace(multiple.find(
"| "), 2,
"|");
2485 while (multiple.find(
'|') != std::string::npos)
2487 different_values.push_back(
2488 prefix + std::string(multiple, 0, multiple.find(
'|')) + postfix);
2489 multiple.erase(0, multiple.find(
'|') + 1);
2493 different_values.push_back(prefix + multiple + postfix);
2496 if ((entry_value.find(
"{{") != std::string::npos) &&
2497 (entry_value.find(
"}}") != std::string::npos))
1016 "You are trying to declare an alias entry <" + alias_name + {
…}
void push(const std::string &text)
void split_different_values()
std::size_t memory_consumption() const
virtual void create_new(const unsigned int run_no)=0
virtual void run(ParameterHandler &prm)=0
void init_branches_current_section()
void fill_entry_values(const unsigned int run_no)
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="", const bool skip_undefined=false) override
std::size_t memory_consumption() const
std::vector< Entry > multiple_choices
static const char path_separator
std::size_t memory_consumption() const
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="", const bool skip_undefined=false)
virtual void parse_input_from_xml(std::istream &input, const bool skip_undefined=false)
std::string get_current_path() const
std::vector< std::unique_ptr< const Patterns::PatternBase > > patterns
void enter_subsection(const std::string &subsection, const bool create_path_if_needed=true)
std::ostream & print_parameters(std::ostream &out, const OutputStyle style) const
void recursively_print_parameters(const boost::property_tree::ptree &tree, const std::vector< std::string > &target_subsection_path, const ParameterHandler::OutputStyle style, const unsigned int indent_level, std::ostream &out) const
void add_action(const std::string &entry, const std::function< void(const std::string &value)> &action, const bool execute_action=true)
long int get_integer(const std::string &entry_string) const
bool get_bool(const std::string &entry_name) const
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation="", const bool has_to_be_set=false)
virtual void parse_input_from_string(const std::string &s, const std::string &last_line="", const bool skip_undefined=false)
std::string get(const std::string &entry_string) const
std::set< std::string > get_entries_wrongly_not_set() const
void set(const std::string &entry_name, const std::string &new_value)
void log_parameters(LogStream &out, const OutputStyle style=DefaultStyle)
std::map< std::string, std::pair< bool, bool > > entries_set_status
std::string get_current_full_path(const std::string &name) const
void mark_as_deprecated(const std::string &entry, const bool is_deprecated=true)
std::vector< std::function< void(const std::string &)> > actions
void log_parameters_section(LogStream &out, const OutputStyle style=DefaultStyle)
std::unique_ptr< boost::property_tree::ptree > entries
bool subsection_path_exists(const std::vector< std::string > &sub_path) const
void scan_line(std::string line, const std::string &input_filename, const unsigned int current_line_n, const bool skip_undefined)
double get_double(const std::string &entry_name) const
void declare_alias(const std::string &existing_entry_name, const std::string &alias_name, const bool alias_is_deprecated=false)
bool operator==(const ParameterHandler &prm2) const
std::vector< std::string > subsection_path
void assert_that_entries_have_been_set() const
virtual void parse_input_from_json(std::istream &input, const bool skip_undefined=false)
virtual std::unique_ptr< PatternBase > clone() const =0
virtual std::string description(const OutputStyle style=Machine) const =0
virtual bool match(const std::string &test_string) const =0
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNoSubsection(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcCannotOpenIncludeStatementFile(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcFileNotOpen(std::string arg1)
static ::ExceptionBase & ExcEntryIsDeprecated(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcEncounteredDeprecatedEntries(std::string arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcAlreadyAtTopLevel()
static ::ExceptionBase & ExcInvalidEntryForPattern(int arg1, std::string arg2, std::string arg3, std::string arg4, std::string arg5)
static ::ExceptionBase & ExcEntryUndeclared(std::string arg1)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcValueDoesNotMatchPattern(std::string arg1, std::string arg2)
static ::ExceptionBase & ExcUnbalancedSubsections(std::string arg1, std::string arg2)
static ::ExceptionBase & ExcCannotParseLine(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcInvalidXMLParameterFile()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
std::string escape(const std::string &input, const PatternBase::OutputStyle style)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
bool match_at_string_start(const std::string &name, const std::string &pattern)
double string_to_double(const std::string &s)
std::string trim(const std::string &input)
int string_to_int(const std::string &s)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)