Reference documentation for deal.II version 9.1.0-pre
parameter_handler.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/logstream.h>
18 #include <deal.II/base/memory_consumption.h>
19 #include <deal.II/base/parameter_handler.h>
20 #include <deal.II/base/path_search.h>
21 #include <deal.II/base/utilities.h>
22 
23 #include <boost/io/ios_state.hpp>
24 #include <boost/property_tree/json_parser.hpp>
25 #include <boost/property_tree/ptree.hpp>
26 #include <boost/property_tree/xml_parser.hpp>
27 
28 #include <algorithm>
29 #include <cctype>
30 #include <cstdlib>
31 #include <cstring>
32 #include <fstream>
33 #include <iomanip>
34 #include <iostream>
35 #include <limits>
36 #include <sstream>
37 
38 
39 DEAL_II_NAMESPACE_OPEN
40 
41 
43  : entries(new boost::property_tree::ptree())
44 {}
45 
46 
47 namespace
48 {
49  std::string
50  mangle(const std::string &s)
51  {
52  std::string u;
53 
54  // reserve the minimum number of characters we will need. it may
55  // be more but this is the least we can do
56  u.reserve(s.size());
57 
58  // see if the name is special and if so mangle the whole thing
59  const bool mangle_whole_string = (s == "value");
60 
61  // for all parts of the string, see
62  // if it is an allowed character or
63  // not
64  for (unsigned int i = 0; i < s.size(); ++i)
65  {
66  static const std::string allowed_characters(
67  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
68 
69  if ((!mangle_whole_string) &&
70  (allowed_characters.find(s[i]) != std::string::npos))
71  u.push_back(s[i]);
72  else
73  {
74  u.push_back('_');
75  static const char hex[16] = {'0',
76  '1',
77  '2',
78  '3',
79  '4',
80  '5',
81  '6',
82  '7',
83  '8',
84  '9',
85  'a',
86  'b',
87  'c',
88  'd',
89  'e',
90  'f'};
91  u.push_back(hex[static_cast<unsigned char>(s[i]) / 16]);
92  u.push_back(hex[static_cast<unsigned char>(s[i]) % 16]);
93  }
94  }
95 
96  return u;
97  }
98 
99 
100 
101  std::string
102  demangle(const std::string &s)
103  {
104  std::string u;
105  u.reserve(s.size());
106 
107  for (unsigned int i = 0; i < s.size(); ++i)
108  if (s[i] != '_')
109  u.push_back(s[i]);
110  else
111  {
112  Assert(i + 2 < s.size(),
113  ExcMessage("Trying to demangle an invalid string."));
114 
115  unsigned char c = 0;
116  switch (s[i + 1])
117  {
118  case '0':
119  c = 0 * 16;
120  break;
121  case '1':
122  c = 1 * 16;
123  break;
124  case '2':
125  c = 2 * 16;
126  break;
127  case '3':
128  c = 3 * 16;
129  break;
130  case '4':
131  c = 4 * 16;
132  break;
133  case '5':
134  c = 5 * 16;
135  break;
136  case '6':
137  c = 6 * 16;
138  break;
139  case '7':
140  c = 7 * 16;
141  break;
142  case '8':
143  c = 8 * 16;
144  break;
145  case '9':
146  c = 9 * 16;
147  break;
148  case 'a':
149  c = 10 * 16;
150  break;
151  case 'b':
152  c = 11 * 16;
153  break;
154  case 'c':
155  c = 12 * 16;
156  break;
157  case 'd':
158  c = 13 * 16;
159  break;
160  case 'e':
161  c = 14 * 16;
162  break;
163  case 'f':
164  c = 15 * 16;
165  break;
166  default:
167  Assert(false, ExcInternalError());
168  }
169  switch (s[i + 2])
170  {
171  case '0':
172  c += 0;
173  break;
174  case '1':
175  c += 1;
176  break;
177  case '2':
178  c += 2;
179  break;
180  case '3':
181  c += 3;
182  break;
183  case '4':
184  c += 4;
185  break;
186  case '5':
187  c += 5;
188  break;
189  case '6':
190  c += 6;
191  break;
192  case '7':
193  c += 7;
194  break;
195  case '8':
196  c += 8;
197  break;
198  case '9':
199  c += 9;
200  break;
201  case 'a':
202  c += 10;
203  break;
204  case 'b':
205  c += 11;
206  break;
207  case 'c':
208  c += 12;
209  break;
210  case 'd':
211  c += 13;
212  break;
213  case 'e':
214  c += 14;
215  break;
216  case 'f':
217  c += 15;
218  break;
219  default:
220  Assert(false, ExcInternalError());
221  }
222 
223  u.push_back(static_cast<char>(c));
224 
225  // skip the two characters
226  i += 2;
227  }
228 
229  return u;
230  }
231 
236  bool
237  is_parameter_node(const boost::property_tree::ptree &p)
238  {
239  return static_cast<bool>(p.get_optional<std::string>("value"));
240  }
241 
242 
247  bool
248  is_alias_node(const boost::property_tree::ptree &p)
249  {
250  return static_cast<bool>(p.get_optional<std::string>("alias"));
251  }
252 } // namespace
253 
254 
255 
256 std::string
258  const std::vector<std::string> &subsection_path)
259 {
260  if (subsection_path.size() > 0)
261  {
262  std::string p = mangle(subsection_path[0]);
263  for (unsigned int i = 1; i < subsection_path.size(); ++i)
264  {
265  p += path_separator;
266  p += mangle(subsection_path[i]);
267  }
268  return p;
269  }
270  else
271  return "";
272 }
273 
274 
275 std::string
277 {
279 }
280 
281 
282 
283 std::string
284 ParameterHandler::get_current_full_path(const std::string &name) const
285 {
286  std::string path = get_current_path();
287  if (path.empty() == false)
288  path += path_separator;
289 
290  path += mangle(name);
291 
292  return path;
293 }
294 
295 
296 
297 void
298 ParameterHandler::parse_input(std::istream & input,
299  const std::string &filename,
300  const std::string &last_line)
301 {
302  AssertThrow(input, ExcIO());
303 
304  // store subsections we are currently in
305  const std::vector<std::string> saved_path = subsection_path;
306 
307  std::string input_line;
308  std::string fully_concatenated_line;
309  bool is_concatenated = false;
310  // Maintain both the current line number and the current logical line
311  // number, where the latter refers to the line number where (possibly) the
312  // current line continuation started.
313  unsigned int current_line_n = 0;
314  unsigned int current_logical_line_n = 0;
315 
316  // define an action that tries to scan a line.
317  //
318  // if that fails, i.e., if scan_line throws
319  // an exception either because a parameter doesn't match its
320  // pattern or because an associated action throws an exception,
321  // then try to rewind the set of subsections to the same
322  // point where we were when the current function was called.
323  // this at least allows to read parameters from a predictable
324  // state, rather than leave the subsection stack in some
325  // unknown state.
326  //
327  // after unwinding the subsection stack, just re-throw the exception
328  auto scan_line_or_cleanup = [this,
329  &saved_path](const std::string &line,
330  const std::string &filename,
331  const unsigned int line_number) {
332  try
333  {
334  scan_line(line, filename, line_number);
335  }
336  catch (...)
337  {
338  while ((saved_path != subsection_path) && (subsection_path.size() > 0))
340 
341  throw;
342  }
343  };
344 
345 
346  while (std::getline(input, input_line))
347  {
348  ++current_line_n;
349  if (!is_concatenated)
350  current_logical_line_n = current_line_n;
351  // Trim the whitespace at the ends of the line here instead of in
352  // scan_line. This makes the continuation line logic a lot simpler.
353  input_line = Utilities::trim(input_line);
354 
355  // If we see the line which is the same as @p last_line ,
356  // terminate the parsing.
357  if (last_line.length() != 0 && input_line == last_line)
358  break;
359 
360  // Check whether or not the current line should be joined with the next
361  // line before calling scan_line.
362  if (input_line.length() != 0 &&
363  input_line.find_last_of('\\') == input_line.length() - 1)
364  {
365  input_line.erase(input_line.length() - 1); // remove the last '\'
366  is_concatenated = true;
367 
368  fully_concatenated_line += input_line;
369  }
370  // If the previous line ended in a '\' but the current did not, then we
371  // should proceed to scan_line.
372  else if (is_concatenated)
373  {
374  fully_concatenated_line += input_line;
375  is_concatenated = false;
376  }
377  // Finally, if neither the previous nor current lines are continuations,
378  // then the current input line is entirely concatenated.
379  else
380  {
381  fully_concatenated_line = input_line;
382  }
383 
384  if (!is_concatenated)
385  {
386  scan_line_or_cleanup(fully_concatenated_line,
387  filename,
388  current_logical_line_n);
389 
390  fully_concatenated_line.clear();
391  }
392  }
393 
394  // While it does not make much sense for anyone to actually do this, allow
395  // the last line to end in a backslash. to do do, we need to parse
396  // whatever was left in the stash of concatenated lines
397  if (is_concatenated)
398  scan_line_or_cleanup(fully_concatenated_line, filename, current_line_n);
399 
400  if (saved_path != subsection_path)
401  {
402  std::stringstream paths_message;
403  if (saved_path.size() > 0)
404  {
405  paths_message << "Path before loading input:\n";
406  for (unsigned int i = 0; i < subsection_path.size(); ++i)
407  {
408  paths_message << std::setw(i * 2 + 4) << " "
409  << "subsection " << saved_path[i] << '\n';
410  }
411  paths_message << "Current path:\n";
412  for (unsigned int i = 0; i < subsection_path.size(); ++i)
413  {
414  paths_message << std::setw(i * 2 + 4) << " "
415  << "subsection " << subsection_path[i]
416  << (i == subsection_path.size() - 1 ? "" : "\n");
417  }
418  }
419  // restore subsection we started with before throwing the exception:
420  subsection_path = saved_path;
421  AssertThrow(false,
422  ExcUnbalancedSubsections(filename, paths_message.str()));
423  }
424 }
425 
426 
427 
428 void
429 ParameterHandler::parse_input(const std::string &filename,
430  const std::string &last_line)
431 {
432  PathSearch search("PARAMETERS");
433 
434  std::string openname = search.find(filename);
435  std::ifstream file_stream(openname.c_str());
436  parse_input(file_stream, filename, last_line);
437 }
438 
439 
440 
441 void
443  const std::string &last_line)
444 {
445  std::istringstream input_stream(s);
446  parse_input(input_stream, "input string", last_line);
447 }
448 
449 
450 
451 namespace
452 {
453  // Recursively go through the 'source' tree and see if we can find
454  // corresponding entries in the 'destination' tree. If not, error out
455  // (i.e. we have just read an XML file that has entries that weren't
456  // declared in the ParameterHandler object); if so, copy the value of these
457  // nodes into the destination object
458  void
459  read_xml_recursively(
460  const boost::property_tree::ptree &source,
461  const std::string & current_path,
462  const char path_separator,
463  const std::vector<std::unique_ptr<const Patterns::PatternBase>> &patterns,
464  boost::property_tree::ptree &destination)
465  {
466  for (boost::property_tree::ptree::const_iterator p = source.begin();
467  p != source.end();
468  ++p)
469  {
470  // a sub-tree must either be a parameter node or a subsection
471  if (p->second.get_optional<std::string>("value"))
472  {
473  // make sure we have a corresponding entry in the destination
474  // object as well
475  const std::string full_path =
476  (current_path == "" ? p->first :
477  current_path + path_separator + p->first);
478 
479  const std::string new_value = p->second.get<std::string>("value");
480  AssertThrow(destination.get_optional<std::string>(full_path) &&
481  destination.get_optional<std::string>(
482  full_path + path_separator + "value"),
484 
485  // first make sure that the new entry actually satisfies its
486  // constraints
487  const unsigned int pattern_index = destination.get<unsigned int>(
488  full_path + path_separator + "pattern");
489  AssertThrow(patterns[pattern_index]->match(new_value),
491  // XML entries sometimes have extra surrounding
492  // newlines
493  (Utilities::trim(new_value),
494  p->first,
495  patterns[pattern_index]->description()));
496 
497  // set the found parameter in the destination argument
498  destination.put(full_path + path_separator + "value", new_value);
499 
500  // this node might have sub-nodes in addition to "value", such as
501  // "default_value", "documentation", etc. we might at some point
502  // in the future want to make sure that if they exist that they
503  // match the ones in the 'destination' tree
504  }
505  else if (p->second.get_optional<std::string>("alias"))
506  {
507  // it is an alias node. alias nodes are static and there is
508  // nothing to do here (but the same applies as mentioned in the
509  // comment above about the static nodes inside parameter nodes
510  }
511  else
512  {
513  // it must be a subsection
514  read_xml_recursively(p->second,
515  (current_path == "" ?
516  p->first :
517  current_path + path_separator + p->first),
518  path_separator,
519  patterns,
520  destination);
521  }
522  }
523  }
524 } // namespace
525 
526 
527 
528 void
530 {
531  AssertThrow(in, ExcIO());
532  // read the XML tree assuming that (as we
533  // do in print_parameters(XML) it has only
534  // a single top-level node called
535  // "ParameterHandler"
536  boost::property_tree::ptree single_node_tree;
537  // This boost function will raise an exception if this is not a valid XML
538  // file.
539  read_xml(in, single_node_tree);
540 
541  // make sure there is a single top-level element
542  // called "ParameterHandler"
543  AssertThrow(single_node_tree.get_optional<std::string>("ParameterHandler"),
544  ExcInvalidXMLParameterFile("There is no top-level XML element "
545  "called \"ParameterHandler\"."));
546 
547  const std::size_t n_top_level_elements =
548  std::distance(single_node_tree.begin(), single_node_tree.end());
549  if (n_top_level_elements != 1)
550  {
551  std::ostringstream top_level_message;
552  top_level_message << "The ParameterHandler input parser found "
553  << n_top_level_elements
554  << " top level elements while reading\n "
555  << " an XML format input file, but there should be"
556  << " exactly one top level element.\n"
557  << " The top level elements are:\n";
558 
559  unsigned int entry_n = 0;
560  for (boost::property_tree::ptree::iterator it = single_node_tree.begin();
561  it != single_node_tree.end();
562  ++it, ++entry_n)
563  {
564  top_level_message
565  << " " << it->first
566  << (entry_n != n_top_level_elements - 1 ? "\n" : "");
567  }
568 
569  // repeat assertion condition to make the printed version easier to read
570  AssertThrow(n_top_level_elements == 1,
571  ExcInvalidXMLParameterFile(top_level_message.str()));
572  }
573 
574  // read the child elements recursively
575  const boost::property_tree::ptree &my_entries =
576  single_node_tree.get_child("ParameterHandler");
577 
578  read_xml_recursively(my_entries, "", path_separator, patterns, *entries);
579 }
580 
581 
582 void
584 {
585  AssertThrow(in, ExcIO());
586 
587  boost::property_tree::ptree node_tree;
588  // This boost function will raise an exception if this is not a valid JSON
589  // file.
590  read_json(in, node_tree);
591 
592  // The xml function is reused to read in the xml into the parameter file.
593  // This means that only mangled files can be read.
594  read_xml_recursively(node_tree, "", path_separator, patterns, *entries);
595 }
596 
597 
598 
599 void
601 {
602  entries = std_cxx14::make_unique<boost::property_tree::ptree>();
603 }
604 
605 
606 
607 void
608 ParameterHandler::declare_entry(const std::string & entry,
609  const std::string & default_value,
610  const Patterns::PatternBase &pattern,
611  const std::string & documentation)
612 {
613  entries->put(get_current_full_path(entry) + path_separator + "value",
614  default_value);
615  entries->put(get_current_full_path(entry) + path_separator + "default_value",
616  default_value);
617  entries->put(get_current_full_path(entry) + path_separator + "documentation",
618  documentation);
619 
620  patterns.reserve(patterns.size() + 1);
621  patterns.emplace_back(pattern.clone());
622  entries->put(get_current_full_path(entry) + path_separator + "pattern",
623  static_cast<unsigned int>(patterns.size() - 1));
624  // also store the description of
625  // the pattern. we do so because we
626  // may wish to export the whole
627  // thing as XML or any other format
628  // so that external tools can work
629  // on the parameter file; in that
630  // case, they will have to be able
631  // to re-create the patterns as far
632  // as possible
634  "pattern_description",
635  patterns.back()->description());
636 
637  // as documented, do the default value checking at the very end
638  AssertThrow(pattern.match(default_value),
639  ExcValueDoesNotMatchPattern(default_value,
640  pattern.description()));
641 }
642 
643 
644 
645 void
647  const std::string & entry,
648  const std::function<void(const std::string &)> &action)
649 {
650  actions.push_back(action);
651 
652  // get the current list of actions, if any
653  boost::optional<std::string> current_actions =
654  entries->get_optional<std::string>(get_current_full_path(entry) +
655  path_separator + "actions");
656 
657  // if there were actions already associated with this parameter, add
658  // the current one to it; otherwise, create a one-item list and use
659  // that
660  if (current_actions)
661  {
662  const std::string all_actions =
663  current_actions.get() + "," +
664  Utilities::int_to_string(actions.size() - 1);
665  entries->put(get_current_full_path(entry) + path_separator + "actions",
666  all_actions);
667  }
668  else
669  entries->put(get_current_full_path(entry) + path_separator + "actions",
670  Utilities::int_to_string(actions.size() - 1));
671 
672 
673  // as documented, run the action on the default value at the very end
674  const std::string default_value = entries->get<std::string>(
675  get_current_full_path(entry) + path_separator + "default_value");
676  action(default_value);
677 }
678 
679 
680 
681 void
682 ParameterHandler::declare_alias(const std::string &existing_entry_name,
683  const std::string &alias_name,
684  const bool alias_is_deprecated)
685 {
686  // see if there is anything to refer to already
687  Assert(entries->get_optional<std::string>(
688  get_current_full_path(existing_entry_name)),
689  ExcMessage("You are trying to declare an alias entry <" + alias_name +
690  "> that references an entry <" + existing_entry_name +
691  ">, but the latter does not exist."));
692  // then also make sure that what is being referred to is in
693  // fact a parameter (not an alias or subsection)
694  Assert(entries->get_optional<std::string>(
695  get_current_full_path(existing_entry_name) + path_separator +
696  "value"),
697  ExcMessage("You are trying to declare an alias entry <" + alias_name +
698  "> that references an entry <" + existing_entry_name +
699  ">, but the latter does not seem to be a "
700  "parameter declaration."));
701 
702 
703  // now also make sure that if the alias has already been
704  // declared, that it is also an alias and refers to the same
705  // entry
706  if (entries->get_optional<std::string>(get_current_full_path(alias_name)))
707  {
708  Assert(entries->get_optional<std::string>(
709  get_current_full_path(alias_name) + path_separator + "alias"),
710  ExcMessage("You are trying to declare an alias entry <" +
711  alias_name +
712  "> but a non-alias entry already exists in this "
713  "subsection (i.e., there is either a preexisting "
714  "further subsection, or a parameter entry, with "
715  "the same name as the alias)."));
716  Assert(entries->get<std::string>(get_current_full_path(alias_name) +
717  path_separator + "alias") ==
718  existing_entry_name,
719  ExcMessage(
720  "You are trying to declare an alias entry <" + alias_name +
721  "> but an alias entry already exists in this "
722  "subsection and this existing alias references a "
723  "different parameter entry. Specifically, "
724  "you are trying to reference the entry <" +
725  existing_entry_name +
726  "> whereas the existing alias references "
727  "the entry <" +
728  entries->get<std::string>(get_current_full_path(alias_name) +
729  path_separator + "alias") +
730  ">."));
731  }
732 
733  entries->put(get_current_full_path(alias_name) + path_separator + "alias",
734  existing_entry_name);
735  entries->put(get_current_full_path(alias_name) + path_separator +
736  "deprecation_status",
737  (alias_is_deprecated ? "true" : "false"));
738 }
739 
740 
741 
742 void
743 ParameterHandler::enter_subsection(const std::string &subsection)
744 {
745  // if necessary create subsection
746  if (!entries->get_child_optional(get_current_full_path(subsection)))
747  entries->add_child(get_current_full_path(subsection),
748  boost::property_tree::ptree());
749 
750  // then enter it
751  subsection_path.push_back(subsection);
752 }
753 
754 
755 
756 void
758 {
759  // assert there is a subsection that
760  // we may leave
762 
763  if (subsection_path.size() > 0)
764  subsection_path.pop_back();
765 }
766 
767 
768 
769 std::string
770 ParameterHandler::get(const std::string &entry_string) const
771 {
772  // assert that the entry is indeed
773  // declared
774  if (boost::optional<std::string> value = entries->get_optional<std::string>(
775  get_current_full_path(entry_string) + path_separator + "value"))
776  return value.get();
777  else
778  {
779  Assert(false, ExcEntryUndeclared(entry_string));
780  return "";
781  }
782 }
783 
784 
785 
786 long int
787 ParameterHandler::get_integer(const std::string &entry_string) const
788 {
789  try
790  {
791  return Utilities::string_to_int(get(entry_string));
792  }
793  catch (...)
794  {
795  AssertThrow(false,
796  ExcMessage("Can't convert the parameter value <" +
797  get(entry_string) + "> for entry <" +
798  entry_string + " to an integer."));
799  return 0;
800  }
801 }
802 
803 
804 
805 double
806 ParameterHandler::get_double(const std::string &entry_string) const
807 {
808  try
809  {
810  return Utilities::string_to_double(get(entry_string));
811  }
812  catch (...)
813  {
814  AssertThrow(false,
815  ExcMessage("Can't convert the parameter value <" +
816  get(entry_string) + "> for entry <" +
817  entry_string +
818  " to a double precision variable."));
819  return 0;
820  }
821 }
822 
823 
824 
825 bool
826 ParameterHandler::get_bool(const std::string &entry_string) const
827 {
828  const std::string s = get(entry_string);
829 
830  AssertThrow((s == "true") || (s == "false") || (s == "yes") || (s == "no"),
831  ExcMessage("Can't convert the parameter value <" +
832  get(entry_string) + "> for entry <" + entry_string +
833  " to a boolean."));
834  if (s == "true" || s == "yes")
835  return true;
836  else
837  return false;
838 }
839 
840 
841 
842 void
843 ParameterHandler::set(const std::string &entry_string,
844  const std::string &new_value)
845 {
846  // resolve aliases before looking up the correct entry
847  std::string path = get_current_full_path(entry_string);
848  if (entries->get_optional<std::string>(path + path_separator + "alias"))
849  path = get_current_full_path(
850  entries->get<std::string>(path + path_separator + "alias"));
851 
852  // get the node for the entry. if it doesn't exist, then we end up
853  // in the else-branch below, which asserts that the entry is indeed
854  // declared
855  if (entries->get_optional<std::string>(path + path_separator + "value"))
856  {
857  // verify that the new value satisfies the provided pattern
858  const unsigned int pattern_index =
859  entries->get<unsigned int>(path + path_separator + "pattern");
860  AssertThrow(patterns[pattern_index]->match(new_value),
861  ExcValueDoesNotMatchPattern(new_value,
862  entries->get<std::string>(
863  path + path_separator +
864  "pattern_description")));
865 
866  // then also execute the actions associated with this
867  // parameter (if any have been provided)
868  const boost::optional<std::string> action_indices_as_string =
869  entries->get_optional<std::string>(path + path_separator + "actions");
870  if (action_indices_as_string)
871  {
872  std::vector<int> action_indices = Utilities::string_to_int(
873  Utilities::split_string_list(action_indices_as_string.get()));
874  for (unsigned int index : action_indices)
875  if (actions.size() >= index + 1)
876  actions[index](new_value);
877  }
878 
879  // finally write the new value into the database
880  entries->put(path + path_separator + "value", new_value);
881  }
882  else
883  AssertThrow(false, ExcEntryUndeclared(entry_string));
884 }
885 
886 
887 void
888 ParameterHandler::set(const std::string &entry_string, const char *new_value)
889 {
890  // simply forward
891  set(entry_string, std::string(new_value));
892 }
893 
894 
895 void
896 ParameterHandler::set(const std::string &entry_string, const double &new_value)
897 {
898  std::ostringstream s;
899  s << std::setprecision(16);
900  s << new_value;
901 
902  // hand this off to the function that
903  // actually sets the value as a string
904  set(entry_string, s.str());
905 }
906 
907 
908 
909 void
910 ParameterHandler::set(const std::string &entry_string,
911  const long int & new_value)
912 {
913  std::ostringstream s;
914  s << new_value;
915 
916  // hand this off to the function that
917  // actually sets the value as a string
918  set(entry_string, s.str());
919 }
920 
921 
922 
923 void
924 ParameterHandler::set(const std::string &entry_string, const bool &new_value)
925 {
926  // hand this off to the function that
927  // actually sets the value as a string
928  set(entry_string, (new_value ? "true" : "false"));
929 }
930 
931 
932 
933 std::ostream &
935  const OutputStyle style) const
936 {
937  AssertThrow(out, ExcIO());
938 
939  // we'll have to print some text that is padded with spaces;
940  // set the appropriate fill character, but also make sure that
941  // we will restore the previous setting (and all other stream
942  // flags) when we exit this function
943  boost::io::ios_flags_saver restore_flags(out);
944  boost::io::basic_ios_fill_saver<char> restore_fill_state(out);
945  out.fill(' ');
946 
947  // we treat XML and JSON is one step via BOOST, whereas all of the others are
948  // done recursively in our own code. take care of the two special formats
949  // first
950  if (style == XML)
951  {
952  // call the writer function and exit as there is nothing
953  // further to do down in this function
954  //
955  // XML has a requirement that there can only be one
956  // single top-level entry, but we may have multiple
957  // entries and sections. we work around this by
958  // creating a tree just for this purpose with the
959  // single top-level node "ParameterHandler" and
960  // assign the existing tree under it
961  boost::property_tree::ptree single_node_tree;
962  single_node_tree.add_child("ParameterHandler", *entries);
963 
964  write_xml(out, single_node_tree);
965  return out;
966  }
967 
968  if (style == JSON)
969  {
970  write_json(out, *entries);
971  return out;
972  }
973 
974  // for all of the other formats, print a preamble:
975  switch (style)
976  {
977  case Text:
978  out << "# Listing of Parameters" << std::endl
979  << "# ---------------------" << std::endl;
980  break;
981 
982  case LaTeX:
983  out << "\\subsection{Global parameters}" << std::endl;
984  out << "\\label{parameters:global}" << std::endl;
985  out << std::endl << std::endl;
986  break;
987 
988  case Description:
989  out << "Listing of Parameters:" << std::endl << std::endl;
990  break;
991 
992  case ShortText:
993  break;
994 
995  default:
996  Assert(false, ExcNotImplemented());
997  }
998 
999  // dive recursively into the subsections
1001  std::vector<std::string>(), // start at the top level
1002  style,
1003  0,
1004  out);
1005 
1006  return out;
1007 }
1008 
1009 
1010 
1011 void
1013  const std::vector<std::string> &target_subsection_path,
1014  const OutputStyle style,
1015  const unsigned int indent_level,
1016  std::ostream & out) const
1017 {
1018  AssertThrow(out, ExcIO());
1019 
1020  // this function should not be necessary for XML or JSON output...
1021  Assert((style != XML) && (style != JSON), ExcInternalError());
1022 
1023  const boost::property_tree::ptree &current_section =
1024  entries->get_child(collate_path_string(target_subsection_path));
1025 
1026  unsigned int overall_indent_level = indent_level;
1027 
1028  switch (style)
1029  {
1030  case Text:
1031  case ShortText:
1032  {
1033  // first find out the longest entry name to be able to align the
1034  // equal signs to do this loop over all nodes of the current
1035  // tree, select the parameter nodes (and discard sub-tree nodes)
1036  // and take the maximum of their lengths
1037  //
1038  // likewise find the longest actual value string to make sure we
1039  // can align the default and documentation strings
1040  std::size_t longest_name = 0;
1041  std::size_t longest_value = 0;
1042  for (boost::property_tree::ptree::const_iterator p =
1043  current_section.begin();
1044  p != current_section.end();
1045  ++p)
1046  if (is_parameter_node(p->second) == true)
1047  {
1048  longest_name =
1049  std::max(longest_name, demangle(p->first).length());
1050  longest_value =
1051  std::max(longest_value,
1052  p->second.get<std::string>("value").length());
1053  }
1054 
1055  // print entries one by one. make sure they are sorted by using
1056  // the appropriate iterators
1057  bool first_entry = true;
1058  for (boost::property_tree::ptree::const_assoc_iterator p =
1059  current_section.ordered_begin();
1060  p != current_section.not_found();
1061  ++p)
1062  if (is_parameter_node(p->second) == true)
1063  {
1064  const std::string value = p->second.get<std::string>("value");
1065 
1066  // if there is documentation, then add an empty line
1067  // (unless this is the first entry in a subsection), print
1068  // the documentation, and then the actual entry; break the
1069  // documentation into readable chunks such that the whole
1070  // thing is at most 78 characters wide
1071  if ((style == Text) &&
1072  !p->second.get<std::string>("documentation").empty())
1073  {
1074  if (first_entry == false)
1075  out << '\n';
1076  else
1077  first_entry = false;
1078 
1079  const std::vector<std::string> doc_lines =
1081  p->second.get<std::string>("documentation"),
1082  78 - overall_indent_level * 2 - 2);
1083 
1084  for (unsigned int i = 0; i < doc_lines.size(); ++i)
1085  out << std::setw(overall_indent_level * 2) << ""
1086  << "# " << doc_lines[i] << '\n';
1087  }
1088 
1089 
1090 
1091  // print name and value of this entry
1092  out << std::setw(overall_indent_level * 2) << ""
1093  << "set " << demangle(p->first)
1094  << std::setw(longest_name - demangle(p->first).length() + 1)
1095  << " "
1096  << "= " << value;
1097 
1098  // finally print the default value, but only if it differs
1099  // from the actual value
1100  if ((style == Text) &&
1101  value != p->second.get<std::string>("default_value"))
1102  {
1103  out << std::setw(longest_value - value.length() + 1) << ' '
1104  << "# ";
1105  out << "default: "
1106  << p->second.get<std::string>("default_value");
1107  }
1108 
1109  out << '\n';
1110  }
1111 
1112  break;
1113  }
1114 
1115  case LaTeX:
1116  {
1117  auto escape = [](const std::string &input) {
1118  return Patterns::internal::escape(input,
1120  };
1121 
1122  // if there are any parameters in this section then print them
1123  // as an itemized list
1124  bool parameters_exist_here = false;
1125  for (boost::property_tree::ptree::const_assoc_iterator p =
1126  current_section.ordered_begin();
1127  p != current_section.not_found();
1128  ++p)
1129  if ((is_parameter_node(p->second) == true) ||
1130  (is_alias_node(p->second) == true))
1131  {
1132  parameters_exist_here = true;
1133  break;
1134  }
1135 
1136  if (parameters_exist_here)
1137  {
1138  out << "\\begin{itemize}" << '\n';
1139 
1140  // print entries one by one. make sure they are sorted by
1141  // using the appropriate iterators
1142  for (boost::property_tree::ptree::const_assoc_iterator p =
1143  current_section.ordered_begin();
1144  p != current_section.not_found();
1145  ++p)
1146  if (is_parameter_node(p->second) == true)
1147  {
1148  const std::string value =
1149  p->second.get<std::string>("value");
1150 
1151  // print name
1152  out << "\\item {\\it Parameter name:} {\\tt "
1153  << escape(demangle(p->first)) << "}\n"
1154  << "\\phantomsection";
1155  {
1156  // create label: labels are not to be escaped but mangled
1157  std::string label = "parameters:";
1158  for (unsigned int i = 0;
1159  i < target_subsection_path.size();
1160  ++i)
1161  {
1162  label.append(mangle(target_subsection_path[i]));
1163  label.append("/");
1164  }
1165  label.append(p->first);
1166  // Backwards-compatibility. Output the label with and
1167  // without escaping whitespace:
1168  if (label.find("_20") != std::string::npos)
1169  out << "\\label{"
1170  << Utilities::replace_in_string(label, "_20", " ")
1171  << "}\n";
1172  out << "\\label{" << label << "}\n";
1173  }
1174  out << "\n\n";
1175 
1176  out << "\\index[prmindex]{" << escape(demangle(p->first))
1177  << "}\n";
1178  out << "\\index[prmindexfull]{";
1179  for (unsigned int i = 0; i < target_subsection_path.size();
1180  ++i)
1181  out << escape(target_subsection_path[i]) << "!";
1182  out << escape(demangle(p->first)) << "}\n";
1183 
1184  // finally print value and default
1185  out << "{\\it Value:} " << escape(value) << "\n\n"
1186  << '\n'
1187  << "{\\it Default:} "
1188  << escape(p->second.get<std::string>("default_value"))
1189  << "\n\n"
1190  << '\n';
1191 
1192  // if there is a documenting string, print it as well but
1193  // don't escape to allow formatting/formulas
1194  if (!p->second.get<std::string>("documentation").empty())
1195  out << "{\\it Description:} "
1196  << p->second.get<std::string>("documentation")
1197  << "\n\n"
1198  << '\n';
1199 
1200  // also output possible values, do not escape because the
1201  // description internally will use LaTeX formatting
1202  const unsigned int pattern_index =
1203  p->second.get<unsigned int>("pattern");
1204  const std::string desc_str =
1205  patterns[pattern_index]->description(
1207  out << "{\\it Possible values:} " << desc_str << '\n';
1208  }
1209  else if (is_alias_node(p->second) == true)
1210  {
1211  const std::string alias =
1212  p->second.get<std::string>("alias");
1213 
1214  // print name
1215  out << "\\item {\\it Parameter name:} {\\tt "
1216  << escape(demangle(p->first)) << "}\n"
1217  << "\\phantomsection";
1218  {
1219  // create label: labels are not to be escaped but mangled
1220  std::string label = "parameters:";
1221  for (unsigned int i = 0;
1222  i < target_subsection_path.size();
1223  ++i)
1224  {
1225  label.append(mangle(target_subsection_path[i]));
1226  label.append("/");
1227  }
1228  label.append(p->first);
1229  // Backwards-compatibility. Output the label with and
1230  // without escaping whitespace:
1231  if (label.find("_20") != std::string::npos)
1232  out << "\\label{"
1233  << Utilities::replace_in_string(label, "_20", " ")
1234  << "}\n";
1235  out << "\\label{" << label << "}\n";
1236  }
1237  out << "\n\n";
1238 
1239  out << "\\index[prmindex]{" << escape(demangle(p->first))
1240  << "}\n";
1241  out << "\\index[prmindexfull]{";
1242  for (unsigned int i = 0; i < target_subsection_path.size();
1243  ++i)
1244  out << escape(target_subsection_path[i]) << "!";
1245  out << escape(demangle(p->first)) << "}\n";
1246 
1247  // finally print alias and indicate if it is deprecated
1248  out
1249  << "This parameter is an alias for the parameter ``\\texttt{"
1250  << escape(alias) << "}''."
1251  << (p->second.get<std::string>("deprecation_status") ==
1252  "true" ?
1253  " Its use is deprecated." :
1254  "")
1255  << "\n\n"
1256  << '\n';
1257  }
1258  out << "\\end{itemize}" << '\n';
1259  }
1260 
1261  break;
1262  }
1263 
1264  case Description:
1265  {
1266  // first find out the longest entry name to be able to align the
1267  // equal signs
1268  std::size_t longest_name = 0;
1269  for (boost::property_tree::ptree::const_iterator p =
1270  current_section.begin();
1271  p != current_section.end();
1272  ++p)
1273  if (is_parameter_node(p->second) == true)
1274  longest_name =
1275  std::max(longest_name, demangle(p->first).length());
1276 
1277  // print entries one by one. make sure they are sorted by using
1278  // the appropriate iterators
1279  for (boost::property_tree::ptree::const_assoc_iterator p =
1280  current_section.ordered_begin();
1281  p != current_section.not_found();
1282  ++p)
1283  if (is_parameter_node(p->second) == true)
1284  {
1285  // print name and value
1286  out << std::setw(overall_indent_level * 2) << ""
1287  << "set " << demangle(p->first)
1288  << std::setw(longest_name - demangle(p->first).length() + 1)
1289  << " "
1290  << " = ";
1291 
1292  // print possible values:
1293  const unsigned int pattern_index =
1294  p->second.get<unsigned int>("pattern");
1295  const std::string full_desc_str =
1296  patterns[pattern_index]->description(
1298  const std::vector<std::string> description_str =
1300  full_desc_str, 78 - overall_indent_level * 2 - 2, '|');
1301  if (description_str.size() > 1)
1302  {
1303  out << '\n';
1304  for (unsigned int i = 0; i < description_str.size(); ++i)
1305  out << std::setw(overall_indent_level * 2 + 6) << ""
1306  << description_str[i] << '\n';
1307  }
1308  else if (description_str.empty() == false)
1309  out << " " << description_str[0] << '\n';
1310  else
1311  out << '\n';
1312 
1313  // if there is a documenting string, print it as well
1314  if (p->second.get<std::string>("documentation").length() != 0)
1315  out << std::setw(overall_indent_level * 2 + longest_name + 10)
1316  << ""
1317  << "(" << p->second.get<std::string>("documentation")
1318  << ")" << '\n';
1319  }
1320 
1321  break;
1322  }
1323 
1324  default:
1325  Assert(false, ExcNotImplemented());
1326  }
1327 
1328 
1329  // if there was text before and there are sections to come, put two
1330  // newlines between the last entry and the first subsection
1331  {
1332  unsigned int n_parameters = 0;
1333  unsigned int n_sections = 0;
1334  for (boost::property_tree::ptree::const_iterator p =
1335  current_section.begin();
1336  p != current_section.end();
1337  ++p)
1338  if (is_parameter_node(p->second) == true)
1339  ++n_parameters;
1340  else if (is_alias_node(p->second) == false)
1341  ++n_sections;
1342 
1343  if ((style != Description) && (style != ShortText) && (n_parameters != 0) &&
1344  (n_sections != 0))
1345  out << "\n\n";
1346  }
1347 
1348  // now traverse subsections tree, in alphabetical order
1349  for (boost::property_tree::ptree::const_assoc_iterator p =
1350  current_section.ordered_begin();
1351  p != current_section.not_found();
1352  ++p)
1353  if ((is_parameter_node(p->second) == false) &&
1354  (is_alias_node(p->second) == false))
1355  {
1356  // first print the subsection header
1357  switch (style)
1358  {
1359  case Text:
1360  case Description:
1361  case ShortText:
1362  out << std::setw(overall_indent_level * 2) << ""
1363  << "subsection " << demangle(p->first) << '\n';
1364  break;
1365 
1366  case LaTeX:
1367  {
1368  auto escape = [](const std::string &input) {
1369  return Patterns::internal::escape(
1371  };
1372 
1373  out << '\n' << "\\subsection{Parameters in section \\tt ";
1374 
1375  // find the path to the current section so that we can
1376  // print it in the \subsection{...} heading
1377  for (unsigned int i = 0; i < target_subsection_path.size(); ++i)
1378  out << escape(target_subsection_path[i]) << "/";
1379  out << escape(demangle(p->first));
1380 
1381  out << "}" << '\n';
1382  out << "\\label{parameters:";
1383  for (unsigned int i = 0; i < target_subsection_path.size(); ++i)
1384  out << mangle(target_subsection_path[i]) << "/";
1385  out << p->first << "}";
1386  out << '\n';
1387 
1388  out << '\n';
1389  break;
1390  }
1391 
1392  default:
1393  Assert(false, ExcNotImplemented());
1394  }
1395 
1396  // then the contents of the subsection
1397  const std::string subsection = demangle(p->first);
1398  std::vector<std::string> directory_path = target_subsection_path;
1399  directory_path.emplace_back(subsection);
1400 
1401  recursively_print_parameters(directory_path,
1402  style,
1403  overall_indent_level + 1,
1404  out);
1405 
1406  switch (style)
1407  {
1408  case Text:
1409  // write end of subsection. one blank line after each
1410  // subsection
1411  out << std::setw(overall_indent_level * 2) << ""
1412  << "end" << '\n'
1413  << '\n';
1414 
1415  // if this is a toplevel subsection, then have two
1416  // newlines
1417  if (overall_indent_level == 0)
1418  out << '\n';
1419 
1420  break;
1421 
1422  case Description:
1423  break;
1424 
1425  case ShortText:
1426  // write end of subsection.
1427  out << std::setw(overall_indent_level * 2) << ""
1428  << "end" << '\n';
1429  break;
1430 
1431  case LaTeX:
1432  break;
1433 
1434  default:
1435  Assert(false, ExcNotImplemented());
1436  }
1437  }
1438 }
1439 
1440 
1441 
1442 // Print a section in the desired style. The styles are separated into
1443 // several verbosity classes depending on the higher bits.
1444 //
1445 // If bit 7 (128) is set, comments are not printed.
1446 // If bit 6 (64) is set, default values after change are not printed.
1447 void
1449  std::ostream & out,
1450  const OutputStyle style,
1451  const unsigned int indent_level,
1452  const bool include_top_level_elements)
1453 {
1454  AssertThrow(out, ExcIO());
1455 
1456  const boost::property_tree::ptree &current_section =
1457  entries->get_child(get_current_path());
1458 
1459  unsigned int overall_indent_level = indent_level;
1460 
1461  switch (style)
1462  {
1463  case XML:
1464  {
1465  if (include_top_level_elements)
1466  {
1467  // call the writer function and exit as there is nothing
1468  // further to do down in this function
1469  //
1470  // XML has a requirement that there can only be one single
1471  // top-level entry, but a section has multiple entries and
1472  // sections. we work around this by creating a tree just for
1473  // this purpose with the single top-level node
1474  // "ParameterHandler" and assign the full path of down to
1475  // the current section under it
1476  boost::property_tree::ptree single_node_tree;
1477 
1478  // if there is no subsection selected, add the whole tree of
1479  // entries, otherwise add a root element and the selected
1480  // subsection under it
1481  if (subsection_path.size() == 0)
1482  {
1483  single_node_tree.add_child("ParameterHandler", *entries);
1484  }
1485  else
1486  {
1487  std::string path("ParameterHandler");
1488 
1489  single_node_tree.add_child(path,
1490  boost::property_tree::ptree());
1491 
1492  path += path_separator + get_current_path();
1493  single_node_tree.add_child(path, current_section);
1494  }
1495 
1496  write_xml(out, single_node_tree);
1497  }
1498  else
1499  Assert(false, ExcNotImplemented());
1500 
1501  break;
1502  }
1503  case Text:
1504  case ShortText:
1505  {
1506  // if there are top level elements to print, do it
1507  if (include_top_level_elements && (subsection_path.size() > 0))
1508  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1509  {
1510  out << std::setw(overall_indent_level * 2) << ""
1511  << "subsection " << demangle(subsection_path[i])
1512  << std::endl;
1513  overall_indent_level += 1;
1514  }
1515 
1516  // first find out the longest entry name to be able to align the
1517  // equal signs to do this loop over all nodes of the current
1518  // tree, select the parameter nodes (and discard sub-tree nodes)
1519  // and take the maximum of their lengths
1520  std::size_t longest_name = 0;
1521  for (boost::property_tree::ptree::const_iterator p =
1522  current_section.begin();
1523  p != current_section.end();
1524  ++p)
1525  if (is_parameter_node(p->second) == true)
1526  longest_name =
1527  std::max(longest_name, demangle(p->first).length());
1528 
1529  // likewise find the longest actual value string to make sure we
1530  // can align the default and documentation strings
1531  std::size_t longest_value = 0;
1532  for (boost::property_tree::ptree::const_iterator p =
1533  current_section.begin();
1534  p != current_section.end();
1535  ++p)
1536  if (is_parameter_node(p->second) == true)
1537  longest_value =
1538  std::max(longest_value,
1539  p->second.get<std::string>("value").length());
1540 
1541 
1542  // print entries one by one. make sure they are sorted by using
1543  // the appropriate iterators
1544  bool first_entry = true;
1545  for (boost::property_tree::ptree::const_assoc_iterator p =
1546  current_section.ordered_begin();
1547  p != current_section.not_found();
1548  ++p)
1549  if (is_parameter_node(p->second) == true)
1550  {
1551  const std::string value = p->second.get<std::string>("value");
1552 
1553  // if there is documentation, then add an empty line
1554  // (unless this is the first entry in a subsection), print
1555  // the documentation, and then the actual entry; break the
1556  // documentation into readable chunks such that the whole
1557  // thing is at most 78 characters wide
1558  if ((!(style & 128)) &&
1559  !p->second.get<std::string>("documentation").empty())
1560  {
1561  if (first_entry == false)
1562  out << std::endl;
1563  else
1564  first_entry = false;
1565 
1566  const std::vector<std::string> doc_lines =
1568  p->second.get<std::string>("documentation"),
1569  78 - overall_indent_level * 2 - 2);
1570 
1571  for (unsigned int i = 0; i < doc_lines.size(); ++i)
1572  out << std::setw(overall_indent_level * 2) << ""
1573  << "# " << doc_lines[i] << std::endl;
1574  }
1575 
1576 
1577 
1578  // print name and value of this entry
1579  out << std::setw(overall_indent_level * 2) << ""
1580  << "set " << demangle(p->first)
1581  << std::setw(longest_name - demangle(p->first).length() + 1)
1582  << " "
1583  << "= " << value;
1584 
1585  // finally print the default value, but only if it differs
1586  // from the actual value
1587  if ((!(style & 64)) &&
1588  value != p->second.get<std::string>("default_value"))
1589  {
1590  out << std::setw(longest_value - value.length() + 1) << ' '
1591  << "# ";
1592  out << "default: "
1593  << p->second.get<std::string>("default_value");
1594  }
1595 
1596  out << std::endl;
1597  }
1598 
1599  break;
1600  }
1601 
1602  case LaTeX:
1603  {
1604  auto escape = [](const std::string &input) {
1605  return Patterns::internal::escape(input,
1607  };
1608 
1609  // if there are any parameters in this section then print them
1610  // as an itemized list
1611  bool parameters_exist_here = false;
1612  for (boost::property_tree::ptree::const_assoc_iterator p =
1613  current_section.ordered_begin();
1614  p != current_section.not_found();
1615  ++p)
1616  if ((is_parameter_node(p->second) == true) ||
1617  (is_alias_node(p->second) == true))
1618  {
1619  parameters_exist_here = true;
1620  break;
1621  }
1622 
1623  if (parameters_exist_here)
1624  {
1625  out << "\\begin{itemize}" << std::endl;
1626 
1627  // print entries one by one. make sure they are sorted by
1628  // using the appropriate iterators
1629  for (boost::property_tree::ptree::const_assoc_iterator p =
1630  current_section.ordered_begin();
1631  p != current_section.not_found();
1632  ++p)
1633  if (is_parameter_node(p->second) == true)
1634  {
1635  const std::string value =
1636  p->second.get<std::string>("value");
1637 
1638  // print name
1639  out << "\\item {\\it Parameter name:} {\\tt "
1640  << escape(demangle(p->first)) << "}\n"
1641  << "\\phantomsection\\label{parameters:";
1642  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1643  out << mangle(subsection_path[i]) << "/";
1644  out << p->first;
1645  out << "}\n\n" << std::endl;
1646 
1647  out << "\\index[prmindex]{" << escape(demangle(p->first))
1648  << "}\n";
1649  out << "\\index[prmindexfull]{";
1650  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1651  out << escape(subsection_path[i]) << "!";
1652  out << escape(demangle(p->first)) << "}\n";
1653 
1654  // finally print value and default
1655  out << "{\\it Value:} " << escape(value) << "\n\n"
1656  << std::endl
1657  << "{\\it Default:} "
1658  << escape(p->second.get<std::string>("default_value"))
1659  << "\n\n"
1660  << std::endl;
1661 
1662  // if there is a documenting string, print it as well
1663  if (!p->second.get<std::string>("documentation").empty())
1664  out << "{\\it Description:} "
1665  << p->second.get<std::string>("documentation")
1666  << "\n\n"
1667  << std::endl;
1668 
1669  // also output possible values
1670  const unsigned int pattern_index =
1671  p->second.get<unsigned int>("pattern");
1672  const std::string desc_str =
1673  patterns[pattern_index]->description(
1675  out << "{\\it Possible values:} " << desc_str << std::endl;
1676  }
1677  else if (is_alias_node(p->second) == true)
1678  {
1679  const std::string alias =
1680  p->second.get<std::string>("alias");
1681 
1682  // print name
1683  out << "\\item {\\it Parameter name:} {\\tt "
1684  << escape(demangle(p->first)) << "}\n"
1685  << "\\phantomsection\\label{parameters:";
1686  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1687  out << mangle(subsection_path[i]) << "/";
1688  out << p->first;
1689  out << "}\n\n" << std::endl;
1690 
1691  out << "\\index[prmindex]{" << escape(demangle(p->first))
1692  << "}\n";
1693  out << "\\index[prmindexfull]{";
1694  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1695  out << escape(subsection_path[i]) << "!";
1696  out << escape(demangle(p->first)) << "}\n";
1697 
1698  // finally print alias and indicate if it is deprecated
1699  out
1700  << "This parameter is an alias for the parameter ``\\texttt{"
1701  << escape(alias) << "}''."
1702  << (p->second.get<std::string>("deprecation_status") ==
1703  "true" ?
1704  " Its use is deprecated." :
1705  "")
1706  << "\n\n"
1707  << std::endl;
1708  }
1709  out << "\\end{itemize}" << std::endl;
1710  }
1711 
1712  break;
1713  }
1714 
1715  case Description:
1716  {
1717  // if there are top level elements to print, do it
1718  if (include_top_level_elements && (subsection_path.size() > 0))
1719  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1720  {
1721  out << std::setw(overall_indent_level * 2) << ""
1722  << "subsection " << demangle(subsection_path[i])
1723  << std::endl;
1724  overall_indent_level += 1;
1725  };
1726 
1727  // first find out the longest entry name to be able to align the
1728  // equal signs
1729  std::size_t longest_name = 0;
1730  for (boost::property_tree::ptree::const_iterator p =
1731  current_section.begin();
1732  p != current_section.end();
1733  ++p)
1734  if (is_parameter_node(p->second) == true)
1735  longest_name =
1736  std::max(longest_name, demangle(p->first).length());
1737 
1738  // print entries one by one. make sure they are sorted by using
1739  // the appropriate iterators
1740  for (boost::property_tree::ptree::const_assoc_iterator p =
1741  current_section.ordered_begin();
1742  p != current_section.not_found();
1743  ++p)
1744  if (is_parameter_node(p->second) == true)
1745  {
1746  // print name and value
1747  out << std::setw(overall_indent_level * 2) << ""
1748  << "set " << demangle(p->first)
1749  << std::setw(longest_name - demangle(p->first).length() + 1)
1750  << " "
1751  << " = ";
1752 
1753  // print possible values:
1754  const unsigned int pattern_index =
1755  p->second.get<unsigned int>("pattern");
1756  const std::string full_desc_str =
1757  patterns[pattern_index]->description(
1759  const std::vector<std::string> description_str =
1761  full_desc_str, 78 - overall_indent_level * 2 - 2, '|');
1762  if (description_str.size() > 1)
1763  {
1764  out << std::endl;
1765  for (unsigned int i = 0; i < description_str.size(); ++i)
1766  out << std::setw(overall_indent_level * 2 + 6) << ""
1767  << description_str[i] << std::endl;
1768  }
1769  else if (description_str.empty() == false)
1770  out << " " << description_str[0] << std::endl;
1771  else
1772  out << std::endl;
1773 
1774  // if there is a documenting string, print it as well
1775  if (p->second.get<std::string>("documentation").length() != 0)
1776  out << std::setw(overall_indent_level * 2 + longest_name + 10)
1777  << ""
1778  << "(" << p->second.get<std::string>("documentation")
1779  << ")" << std::endl;
1780  }
1781 
1782  break;
1783  }
1784 
1785  default:
1786  Assert(false, ExcNotImplemented());
1787  }
1788 
1789 
1790  // if there was text before and there are sections to come, put two
1791  // newlines between the last entry and the first subsection
1792  if (style != XML)
1793  {
1794  unsigned int n_parameters = 0;
1795  unsigned int n_sections = 0;
1796  for (boost::property_tree::ptree::const_iterator p =
1797  current_section.begin();
1798  p != current_section.end();
1799  ++p)
1800  if (is_parameter_node(p->second) == true)
1801  ++n_parameters;
1802  else if (is_alias_node(p->second) == false)
1803  ++n_sections;
1804 
1805  if ((style != Description) && (!(style & 128)) && (n_parameters != 0) &&
1806  (n_sections != 0))
1807  out << std::endl << std::endl;
1808 
1809  // now traverse subsections tree, in alphabetical order
1810  for (boost::property_tree::ptree::const_assoc_iterator p =
1811  current_section.ordered_begin();
1812  p != current_section.not_found();
1813  ++p)
1814  if ((is_parameter_node(p->second) == false) &&
1815  (is_alias_node(p->second) == false))
1816  {
1817  // first print the subsection header
1818  switch (style)
1819  {
1820  case Text:
1821  case Description:
1822  case ShortText:
1823  out << std::setw(overall_indent_level * 2) << ""
1824  << "subsection " << demangle(p->first) << std::endl;
1825  break;
1826  case LaTeX:
1827  {
1828  auto escape = [](const std::string &input) {
1829  return Patterns::internal::escape(
1831  };
1832 
1833  out << std::endl
1834  << "\\subsection{Parameters in section \\tt ";
1835 
1836  // find the path to the current section so that we can
1837  // print it in the \subsection{...} heading
1838  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1839  out << escape(subsection_path[i]) << "/";
1840  out << escape(demangle(p->first));
1841 
1842  out << "}" << std::endl;
1843  out << "\\label{parameters:";
1844  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1845  out << mangle(subsection_path[i]) << "/";
1846  out << p->first << "}";
1847  out << std::endl;
1848 
1849  out << std::endl;
1850  break;
1851  }
1852 
1853  default:
1854  Assert(false, ExcNotImplemented());
1855  };
1856 
1857  // then the contents of the subsection
1858  enter_subsection(demangle(p->first));
1859  print_parameters_section(out, style, overall_indent_level + 1);
1860  leave_subsection();
1861  switch (style)
1862  {
1863  case Text:
1864  // write end of subsection. one blank line after each
1865  // subsection
1866  out << std::setw(overall_indent_level * 2) << ""
1867  << "end" << std::endl
1868  << std::endl;
1869 
1870  // if this is a toplevel subsection, then have two
1871  // newlines
1872  if (overall_indent_level == 0)
1873  out << std::endl;
1874 
1875  break;
1876  case Description:
1877  break;
1878  case ShortText:
1879  // write end of subsection.
1880  out << std::setw(overall_indent_level * 2) << ""
1881  << "end" << std::endl;
1882  break;
1883  case LaTeX:
1884  break;
1885  default:
1886  Assert(false, ExcNotImplemented());
1887  }
1888  }
1889  }
1890 
1891  // close top level elements, if there are any
1892  switch (style)
1893  {
1894  case XML:
1895  case LaTeX:
1896  case Description:
1897  break;
1898  case Text:
1899  case ShortText:
1900  {
1901  if (include_top_level_elements && (subsection_path.size() > 0))
1902  for (unsigned int i = 0; i < subsection_path.size(); ++i)
1903  {
1904  overall_indent_level -= 1;
1905  out << std::setw(overall_indent_level * 2) << ""
1906  << "end" << std::endl;
1907  };
1908 
1909  break;
1910  }
1911 
1912  default:
1913  Assert(false, ExcNotImplemented());
1914  }
1915 }
1916 
1917 
1918 
1919 void
1921 {
1922  out.push("parameters");
1923  // dive recursively into the subsections
1925 
1926  out.pop();
1927 }
1928 
1929 
1930 
1931 void
1933 {
1934  const boost::property_tree::ptree &current_section =
1935  entries->get_child(get_current_path());
1936 
1937  // print entries one by
1938  // one. make sure they are
1939  // sorted by using the
1940  // appropriate iterators
1941  for (boost::property_tree::ptree::const_assoc_iterator p =
1942  current_section.ordered_begin();
1943  p != current_section.not_found();
1944  ++p)
1945  if (is_parameter_node(p->second) == true)
1946  out << demangle(p->first) << ": " << p->second.get<std::string>("value")
1947  << std::endl;
1948 
1949  // now transverse subsections tree
1950  // now traverse subsections tree,
1951  // in alphabetical order
1952  for (boost::property_tree::ptree::const_assoc_iterator p =
1953  current_section.ordered_begin();
1954  p != current_section.not_found();
1955  ++p)
1956  if (is_parameter_node(p->second) == false)
1957  {
1958  out.push(demangle(p->first));
1959  enter_subsection(demangle(p->first));
1961  leave_subsection();
1962  out.pop();
1963  }
1964 }
1965 
1966 
1967 
1968 void
1970  const std::string &input_filename,
1971  const unsigned int current_line_n)
1972 {
1973  // save a copy for some error messages
1974  const std::string original_line = line;
1975 
1976  // if there is a comment, delete it
1977  if (line.find('#') != std::string::npos)
1978  line.erase(line.find('#'), std::string::npos);
1979 
1980  // replace \t by space:
1981  while (line.find('\t') != std::string::npos)
1982  line.replace(line.find('\t'), 1, " ");
1983 
1984  // trim start and end:
1985  line = Utilities::trim(line);
1986 
1987  // if line is now empty: leave
1988  if (line.length() == 0)
1989  {
1990  return;
1991  }
1992  // enter subsection
1993  else if (Utilities::match_at_string_start(line, "SUBSECTION ") ||
1994  Utilities::match_at_string_start(line, "subsection "))
1995  {
1996  // delete this prefix
1997  line.erase(0, std::string("subsection").length() + 1);
1998 
1999  const std::string subsection = Utilities::trim(line);
2000 
2001  // check whether subsection exists
2002  AssertThrow(entries->get_child_optional(
2003  get_current_full_path(subsection)),
2004  ExcNoSubsection(current_line_n,
2005  input_filename,
2006  demangle(get_current_full_path(subsection))));
2007 
2008  // subsection exists
2009  subsection_path.push_back(subsection);
2010  }
2011  // exit subsection
2012  else if (Utilities::match_at_string_start(line, "END") ||
2013  Utilities::match_at_string_start(line, "end"))
2014  {
2015  line.erase(0, 3);
2016  while ((line.size() > 0) && (std::isspace(line[0])))
2017  line.erase(0, 1);
2018 
2019  AssertThrow(
2020  line.size() == 0,
2021  ExcCannotParseLine(current_line_n,
2022  input_filename,
2023  "Invalid content after 'end' or 'END' statement."));
2024  AssertThrow(subsection_path.size() != 0,
2025  ExcCannotParseLine(current_line_n,
2026  input_filename,
2027  "There is no subsection to leave here."));
2028  leave_subsection();
2029  }
2030  // regular entry
2031  else if (Utilities::match_at_string_start(line, "SET ") ||
2032  Utilities::match_at_string_start(line, "set "))
2033  {
2034  // erase "set" statement
2035  line.erase(0, 4);
2036 
2037  std::string::size_type pos = line.find('=');
2038  AssertThrow(
2039  pos != std::string::npos,
2040  ExcCannotParseLine(current_line_n,
2041  input_filename,
2042  "Invalid format of 'set' or 'SET' statement."));
2043 
2044  // extract entry name and value and trim
2045  std::string entry_name = Utilities::trim(std::string(line, 0, pos));
2046  std::string entry_value =
2047  Utilities::trim(std::string(line, pos + 1, std::string::npos));
2048 
2049  // resolve aliases before we look up the entry. if necessary, print
2050  // a warning that the alias is deprecated
2051  std::string path = get_current_full_path(entry_name);
2052  if (entries->get_optional<std::string>(path + path_separator + "alias"))
2053  {
2054  if (entries->get<std::string>(path + path_separator +
2055  "deprecation_status") == "true")
2056  {
2057  std::cerr << "Warning in line <" << current_line_n
2058  << "> of file <" << input_filename
2059  << ">: You are using the deprecated spelling <"
2060  << entry_name << "> of the parameter <"
2061  << entries->get<std::string>(path + path_separator +
2062  "alias")
2063  << ">." << std::endl;
2064  }
2065  path = get_current_full_path(
2066  entries->get<std::string>(path + path_separator + "alias"));
2067  }
2068 
2069  // get the node for the entry. if it doesn't exist, then we end up
2070  // in the else-branch below, which asserts that the entry is indeed
2071  // declared
2072  if (entries->get_optional<std::string>(path + path_separator + "value"))
2073  {
2074  // if entry was declared:
2075  // does it match the regex? if not,
2076  // don't enter it into the database
2077  // exception: if it contains characters
2078  // which specify it as a multiple loop
2079  // entry, then ignore content
2080  if (entry_value.find('{') == std::string::npos)
2081  {
2082  // verify that the new value satisfies the provided pattern
2083  const unsigned int pattern_index =
2084  entries->get<unsigned int>(path + path_separator + "pattern");
2085  AssertThrow(patterns[pattern_index]->match(entry_value),
2087  current_line_n,
2088  input_filename,
2089  entry_value,
2090  entry_name,
2091  patterns[pattern_index]->description()));
2092 
2093  // then also execute the actions associated with this
2094  // parameter (if any have been provided)
2095  const boost::optional<std::string> action_indices_as_string =
2096  entries->get_optional<std::string>(path + path_separator +
2097  "actions");
2098  if (action_indices_as_string)
2099  {
2100  std::vector<int> action_indices =
2102  action_indices_as_string.get()));
2103  for (unsigned int index : action_indices)
2104  if (actions.size() >= index + 1)
2105  actions[index](entry_value);
2106  }
2107  }
2108 
2109  // finally write the new value into the database
2110  entries->put(path + path_separator + "value", entry_value);
2111  }
2112  else
2113  {
2114  AssertThrow(
2115  false,
2116  ExcCannotParseLine(current_line_n,
2117  input_filename,
2118  ("No entry with name <" + entry_name +
2119  "> was declared in the current subsection.")));
2120  }
2121  }
2122  // an include statement?
2123  else if (Utilities::match_at_string_start(line, "include ") ||
2124  Utilities::match_at_string_start(line, "INCLUDE "))
2125  {
2126  // erase "include " statement and eliminate spaces
2127  line.erase(0, 7);
2128  while ((line.size() > 0) && (line[0] == ' '))
2129  line.erase(0, 1);
2130 
2131  // the remainder must then be a filename
2132  AssertThrow(line.size() != 0,
2133  ExcCannotParseLine(current_line_n,
2134  input_filename,
2135  "The current line is an 'include' or "
2136  "'INCLUDE' statement, but it does not "
2137  "name a file for inclusion."));
2138 
2139  std::ifstream input(line.c_str());
2140  AssertThrow(input,
2141  ExcCannotOpenIncludeStatementFile(current_line_n,
2142  input_filename,
2143  line));
2144  parse_input(input);
2145  }
2146  else
2147  {
2148  AssertThrow(
2149  false,
2150  ExcCannotParseLine(current_line_n,
2151  input_filename,
2152  "The line\n\n"
2153  " <" +
2154  original_line +
2155  ">\n\n"
2156  "could not be parsed: please check to "
2157  "make sure that the file is not missing a "
2158  "'set', 'include', 'subsection', or 'end' "
2159  "statement."));
2160  }
2161 }
2162 
2163 
2164 
2165 std::size_t
2167 {
2168  // TODO: add to this an estimate of the memory in the property_tree
2170 }
2171 
2172 
2173 
2174 bool
2176 {
2177  if (patterns.size() != prm2.patterns.size())
2178  return false;
2179 
2180  for (unsigned int j = 0; j < patterns.size(); ++j)
2181  if (patterns[j]->description() != prm2.patterns[j]->description())
2182  return false;
2183 
2184  // instead of walking through all
2185  // the nodes of the two trees
2186  // entries and prm2.entries and
2187  // comparing them for equality,
2188  // simply dump the content of the
2189  // entire structure into a string
2190  // and compare those for equality
2191  std::ostringstream o1, o2;
2192  write_json(o1, *entries);
2193  write_json(o2, *prm2.entries);
2194  return (o1.str() == o2.str());
2195 }
2196 
2197 
2198 
2200  : n_branches(0)
2201 {}
2202 
2203 
2204 
2205 void
2207  const std::string &filename,
2208  const std::string &last_line)
2209 {
2210  AssertThrow(input, ExcIO());
2211 
2212  // Note that (to avoid infinite recursion) we have to explicitly call the
2213  // base class version of parse_input and *not* a wrapper (which may be
2214  // virtual and lead us back here)
2215  ParameterHandler::parse_input(input, filename, last_line);
2216  init_branches();
2217 }
2218 
2219 
2220 
2221 void
2223 {
2224  for (unsigned int run_no = 0; run_no < n_branches; ++run_no)
2225  {
2226  // give create_new one-based numbers
2227  uc.create_new(run_no + 1);
2228  fill_entry_values(run_no);
2229  uc.run(*this);
2230  };
2231 }
2232 
2233 
2234 
2235 void
2237 {
2238  multiple_choices.clear();
2240 
2241  // split up different values
2242  for (unsigned int i = 0; i < multiple_choices.size(); ++i)
2243  multiple_choices[i].split_different_values();
2244 
2245  // finally calculate number of branches
2246  n_branches = 1;
2247  for (unsigned int i = 0; i < multiple_choices.size(); ++i)
2248  if (multiple_choices[i].type == Entry::variant)
2249  n_branches *= multiple_choices[i].different_values.size();
2250 
2251  // check whether array entries have the correct
2252  // number of entries
2253  for (unsigned int i = 0; i < multiple_choices.size(); ++i)
2254  if (multiple_choices[i].type == Entry::array)
2255  if (multiple_choices[i].different_values.size() != n_branches)
2256  std::cerr << " The entry value" << std::endl
2257  << " " << multiple_choices[i].entry_value << std::endl
2258  << " for the entry named" << std::endl
2259  << " " << multiple_choices[i].entry_name << std::endl
2260  << " does not have the right number of entries for the "
2261  << std::endl
2262  << " " << n_branches
2263  << " variant runs that will be performed." << std::endl;
2264 
2265 
2266  // do a first run on filling the values to
2267  // check for the conformance with the regexp
2268  // (later on, this will be lost in the whole
2269  // other output)
2270  for (unsigned int i = 0; i < n_branches; ++i)
2271  fill_entry_values(i);
2272 }
2273 
2274 
2275 
2276 void
2278 {
2279  const boost::property_tree::ptree &current_section =
2280  entries->get_child(get_current_path());
2281 
2282  // check all entries in the present
2283  // subsection whether they are
2284  // multiple entries
2285  //
2286  // we loop over entries in sorted
2287  // order to guarantee backward
2288  // compatibility to an earlier
2289  // implementation
2290  for (boost::property_tree::ptree::const_assoc_iterator p =
2291  current_section.ordered_begin();
2292  p != current_section.not_found();
2293  ++p)
2294  if (is_parameter_node(p->second) == true)
2295  {
2296  const std::string value = p->second.get<std::string>("value");
2297  if (value.find('{') != std::string::npos)
2298  multiple_choices.emplace_back(subsection_path,
2299  demangle(p->first),
2300  value);
2301  }
2302 
2303  // then loop over all subsections
2304  for (boost::property_tree::ptree::const_iterator p = current_section.begin();
2305  p != current_section.end();
2306  ++p)
2307  if (is_parameter_node(p->second) == false)
2308  {
2309  enter_subsection(demangle(p->first));
2311  leave_subsection();
2312  }
2313 }
2314 
2315 
2316 
2317 void
2319 {
2320  unsigned int possibilities = 1;
2321 
2322  std::vector<Entry>::iterator choice;
2323  for (choice = multiple_choices.begin(); choice != multiple_choices.end();
2324  ++choice)
2325  {
2326  const unsigned int selection =
2327  (run_no / possibilities) % choice->different_values.size();
2328  std::string entry_value;
2329  if (choice->type == Entry::variant)
2330  entry_value = choice->different_values[selection];
2331  else
2332  {
2333  if (run_no >= choice->different_values.size())
2334  {
2335  std::cerr
2336  << "The given array for entry <" << choice->entry_name
2337  << "> does not contain enough elements! Taking empty string instead."
2338  << std::endl;
2339  entry_value = "";
2340  }
2341  else
2342  entry_value = choice->different_values[run_no];
2343  }
2344 
2345  // temporarily enter the
2346  // subsection tree of this
2347  // multiple entry, set the
2348  // value, and get out
2349  // again. the set() operation
2350  // also tests for the
2351  // correctness of the value
2352  // with regard to the pattern
2353  subsection_path.swap(choice->subsection_path);
2354  set(choice->entry_name, entry_value);
2355  subsection_path.swap(choice->subsection_path);
2356 
2357  // move ahead if it was a variant entry
2358  if (choice->type == Entry::variant)
2359  possibilities *= choice->different_values.size();
2360  }
2361 }
2362 
2363 
2364 
2365 std::size_t
2367 {
2368  std::size_t mem = ParameterHandler::memory_consumption();
2369  for (unsigned int i = 0; i < multiple_choices.size(); ++i)
2371 
2372  return mem;
2373 }
2374 
2375 
2376 
2377 MultipleParameterLoop::Entry::Entry(const std::vector<std::string> &ssp,
2378  const std::string & Name,
2379  const std::string & Value)
2380  : subsection_path(ssp)
2381  , entry_name(Name)
2382  , entry_value(Value)
2383  , type(Entry::array)
2384 {}
2385 
2386 
2387 
2388 void
2390 {
2391  // split string into three parts:
2392  // part before the opening "{",
2393  // the selection itself, final
2394  // part after "}"
2395  std::string prefix(entry_value, 0, entry_value.find('{'));
2396  std::string multiple(entry_value,
2397  entry_value.find('{') + 1,
2398  entry_value.rfind('}') - entry_value.find('{') - 1);
2399  std::string postfix(entry_value,
2400  entry_value.rfind('}') + 1,
2401  std::string::npos);
2402  // if array entry {{..}}: delete inner
2403  // pair of braces
2404  if (multiple[0] == '{')
2405  multiple.erase(0, 1);
2406  if (multiple[multiple.size() - 1] == '}')
2407  multiple.erase(multiple.size() - 1, 1);
2408  // erase leading and trailing spaces
2409  // in multiple
2410  while (std::isspace(multiple[0]))
2411  multiple.erase(0, 1);
2412  while (std::isspace(multiple[multiple.size() - 1]))
2413  multiple.erase(multiple.size() - 1, 1);
2414 
2415  // delete spaces around '|'
2416  while (multiple.find(" |") != std::string::npos)
2417  multiple.replace(multiple.find(" |"), 2, "|");
2418  while (multiple.find("| ") != std::string::npos)
2419  multiple.replace(multiple.find("| "), 2, "|");
2420 
2421  while (multiple.find('|') != std::string::npos)
2422  {
2423  different_values.push_back(
2424  prefix + std::string(multiple, 0, multiple.find('|')) + postfix);
2425  multiple.erase(0, multiple.find('|') + 1);
2426  };
2427  // make up the last selection ("while" broke
2428  // because there was no '|' any more
2429  different_values.push_back(prefix + multiple + postfix);
2430  // finally check whether this was a variant
2431  // entry ({...}) or an array ({{...}})
2432  if ((entry_value.find("{{") != std::string::npos) &&
2433  (entry_value.find("}}") != std::string::npos))
2434  type = Entry::array;
2435  else
2436  type = Entry::variant;
2437 }
2438 
2439 
2440 std::size_t
2442 {
2447  sizeof(type));
2448 }
2449 
2450 DEAL_II_NAMESPACE_CLOSE
bool operator==(const ParameterHandler &prm2) const
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:279
std::vector< Entry > multiple_choices
void pop()
Definition: logstream.cc:313
static const char path_separator
static std::string collate_path_string(const std::vector< std::string > &subsection_path)
void loop(UserClass &uc)
std::string get_current_full_path(const std::string &name) const
static::ExceptionBase & ExcInvalidEntryForPatternXML(std::string arg1, std::string arg2, std::string arg3)
static::ExceptionBase & ExcCannotOpenIncludeStatementFile(int arg1, std::string arg2, std::string arg3)
static::ExceptionBase & ExcIO()
virtual void run(ParameterHandler &prm)=0
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="") override
static::ExceptionBase & ExcEntryUndeclared(std::string arg1)
std::size_t memory_consumption() const
std::string trim(const std::string &input)
Definition: utilities.cc:143
static::ExceptionBase & ExcUnbalancedSubsections(std::string arg1, std::string arg2)
void log_parameters(LogStream &out)
virtual std::unique_ptr< PatternBase > clone() const =0
void set(const std::string &entry_name, const std::string &new_value)
virtual void parse_input_from_json(std::istream &input)
void log_parameters_section(LogStream &out)
std::vector< std::string > subsection_path
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
std::string get(const std::string &entry_string) const
static::ExceptionBase & ExcValueDoesNotMatchPattern(std::string arg1, std::string arg2)
std::vector< std::string > subsection_path
double string_to_double(const std::string &s)
Definition: utilities.cc:240
std::size_t memory_consumption() const
void enter_subsection(const std::string &subsection)
virtual void parse_input_from_xml(std::istream &input)
static::ExceptionBase & ExcInvalidXMLParameterFile()
static::ExceptionBase & ExcMessage(std::string arg1)
virtual void create_new(const unsigned int run_no)=0
static::ExceptionBase & ExcCannotParseLine(int arg1, std::string arg2, std::string arg3)
std::ostream & print_parameters(std::ostream &out, const OutputStyle style) const
#define Assert(cond, exc)
Definition: exceptions.h:1227
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition: utilities.cc:413
std::string get_current_path() const
std::unique_ptr< boost::property_tree::ptree > entries
void fill_entry_values(const unsigned int run_no)
virtual void parse_input_from_string(const char *s, const std::string &last_line="")
static::ExceptionBase & ExcAlreadyAtTopLevel()
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:96
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition: utilities.cc:124
std::vector< std::unique_ptr< const Patterns::PatternBase > > patterns
virtual bool match(const std::string &test_string) const =0
bool get_bool(const std::string &entry_name) const
std::string find(const std::string &filename, const char *open_mode="r")
Definition: path_search.cc:171
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter= ' ')
Definition: utilities.cc:333
void push(const std::string &text)
Definition: logstream.cc:299
virtual std::string description(const OutputStyle style=Machine) const =0
void add_action(const std::string &entry, const std::function< void(const std::string &value)> &action)
double get_double(const std::string &entry_name) const
void print_parameters_section(std::ostream &out, const OutputStyle style, const unsigned int indent_level, const bool include_top_level_elements=false)
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
int string_to_int(const std::string &s)
Definition: utilities.cc:201
static::ExceptionBase & ExcNotImplemented()
std::vector< std::string > different_values
void scan_line(std::string line, const std::string &input_filename, const unsigned int current_line_n)
static::ExceptionBase & ExcInvalidEntryForPattern(int arg1, std::string arg2, std::string arg3, std::string arg4, std::string arg5)
std::vector< std::function< void(const std::string &)> > actions
void recursively_print_parameters(const std::vector< std::string > &target_subsection_path, const OutputStyle style, const unsigned int indent_level, std::ostream &out) const
static::ExceptionBase & ExcNoSubsection(int arg1, std::string arg2, std::string arg3)
void declare_alias(const std::string &existing_entry_name, const std::string &alias_name, const bool alias_is_deprecated=false)
std::size_t memory_consumption() const
long int get_integer(const std::string &entry_string) const
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static::ExceptionBase & ExcInternalError()
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="")