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