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