Reference documentation for deal.II version Git 2618e0f 2017-11-23 17:25:26 +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 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  auto escape = [] (const std::string &input)
1108  {
1109  return Patterns::internal::escape(input, Patterns::PatternBase::LaTeX);
1110  };
1111 
1112  // if there are any parameters in this section then print them
1113  // as an itemized list
1114  bool parameters_exist_here = false;
1115  for (boost::property_tree::ptree::const_assoc_iterator
1116  p = current_section.ordered_begin();
1117  p != current_section.not_found(); ++p)
1118  if ((is_parameter_node (p->second) == true)
1119  ||
1120  (is_alias_node (p->second) == true))
1121  {
1122  parameters_exist_here = true;
1123  break;
1124  }
1125 
1126  if (parameters_exist_here)
1127  {
1128  out << "\\begin{itemize}"
1129  << '\n';
1130 
1131  // print entries one by one. make sure they are sorted by
1132  // using the appropriate iterators
1133  for (boost::property_tree::ptree::const_assoc_iterator
1134  p = current_section.ordered_begin();
1135  p != current_section.not_found(); ++p)
1136  if (is_parameter_node (p->second) == true)
1137  {
1138  const std::string value = p->second.get<std::string>("value");
1139 
1140  // print name
1141  out << "\\item {\\it Parameter name:} {\\tt "
1142  << escape(demangle(p->first)) << "}\n"
1143  << "\\phantomsection";
1144  {
1145  // create label: labels are not to be escaped but mangled
1146  std::string label = "parameters:";
1147  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1148  {
1149  label.append(mangle(target_subsection_path[i]));
1150  label.append("/");
1151  }
1152  label.append(p->first);
1153  // Backwards-compatibility. Output the label with and without
1154  // escaping whitespace:
1155  if (label.find("_20")!=std::string::npos)
1156  out << "\\label{" << Utilities::replace_in_string(label,"_20", " ") << "}\n";
1157  out << "\\label{" << label << "}\n";
1158  }
1159  out << "\n\n";
1160 
1161  out << "\\index[prmindex]{"
1162  << escape(demangle(p->first))
1163  << "}\n";
1164  out << "\\index[prmindexfull]{";
1165  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1166  out << escape(target_subsection_path[i]) << "!";
1167  out << escape(demangle(p->first))
1168  << "}\n";
1169 
1170  // finally print value and default
1171  out << "{\\it Value:} " << escape(value) << "\n\n"
1172  << '\n'
1173  << "{\\it Default:} "
1174  << escape(p->second.get<std::string>("default_value"))
1175  << "\n\n"
1176  << '\n';
1177 
1178  // if there is a documenting string, print it as well but
1179  // don't escape to allow formatting/formulas
1180  if (!p->second.get<std::string>("documentation").empty())
1181  out << "{\\it Description:} "
1182  << p->second.get<std::string>("documentation") << "\n\n"
1183  << '\n';
1184 
1185  // also output possible values, do not escape because the
1186  // description internally will use LaTeX formatting
1187  const unsigned int pattern_index = p->second.get<unsigned int> ("pattern");
1188  const std::string desc_str = patterns[pattern_index]->description (Patterns::PatternBase::LaTeX);
1189  out << "{\\it Possible values:} "
1190  << desc_str
1191  << '\n';
1192  }
1193  else if (is_alias_node (p->second) == true)
1194  {
1195  const std::string alias = p->second.get<std::string>("alias");
1196 
1197  // print name
1198  out << "\\item {\\it Parameter name:} {\\tt "
1199  << escape(demangle(p->first)) << "}\n"
1200  << "\\phantomsection";
1201  {
1202  // create label: labels are not to be escaped but mangled
1203  std::string label = "parameters:";
1204  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1205  {
1206  label.append(mangle(target_subsection_path[i]));
1207  label.append("/");
1208  }
1209  label.append(p->first);
1210  // Backwards-compatibility. Output the label with and without
1211  // escaping whitespace:
1212  if (label.find("_20")!=std::string::npos)
1213  out << "\\label{" << Utilities::replace_in_string(label,"_20", " ") << "}\n";
1214  out << "\\label{" << label << "}\n";
1215  }
1216  out << "\n\n";
1217 
1218  out << "\\index[prmindex]{"
1219  << escape(demangle(p->first))
1220  << "}\n";
1221  out << "\\index[prmindexfull]{";
1222  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1223  out << escape(target_subsection_path[i]) << "!";
1224  out << escape(demangle(p->first))
1225  << "}\n";
1226 
1227  // finally print alias and indicate if it is deprecated
1228  out << "This parameter is an alias for the parameter ``\\texttt{"
1229  << escape(alias) << "}''."
1230  << (p->second.get<std::string>("deprecation_status") == "true"
1231  ?
1232  " Its use is deprecated."
1233  :
1234  "")
1235  << "\n\n"
1236  << '\n';
1237  }
1238  out << "\\end{itemize}"
1239  << '\n';
1240  }
1241 
1242  break;
1243  }
1244 
1245  case Description:
1246  {
1247  // first find out the longest entry name to be able to align the
1248  // equal signs
1249  std::size_t longest_name = 0;
1250  for (boost::property_tree::ptree::const_iterator
1251  p = current_section.begin();
1252  p != current_section.end(); ++p)
1253  if (is_parameter_node (p->second) == true)
1254  longest_name = std::max (longest_name,
1255  demangle(p->first).length());
1256 
1257  // print entries one by one. make sure they are sorted by using
1258  // the appropriate iterators
1259  for (boost::property_tree::ptree::const_assoc_iterator
1260  p = current_section.ordered_begin();
1261  p != current_section.not_found(); ++p)
1262  if (is_parameter_node (p->second) == true)
1263  {
1264  // print name and value
1265  out << std::setw(overall_indent_level*2) << ""
1266  << "set "
1267  << demangle(p->first)
1268  << std::setw(longest_name-demangle(p->first).length()+1) << " "
1269  << " = ";
1270 
1271  // print possible values:
1272  const unsigned int pattern_index = p->second.get<unsigned int> ("pattern");
1273  const std::string full_desc_str = patterns[pattern_index]->description (Patterns::PatternBase::Text);
1274  const std::vector<std::string> description_str
1275  = Utilities::break_text_into_lines (full_desc_str,
1276  78 - overall_indent_level*2 - 2, '|');
1277  if (description_str.size() > 1)
1278  {
1279  out << '\n';
1280  for (unsigned int i=0; i<description_str.size(); ++i)
1281  out << std::setw(overall_indent_level*2+6) << ""
1282  << description_str[i] << '\n';
1283  }
1284  else if (description_str.empty() == false)
1285  out << " " << description_str[0] << '\n';
1286  else
1287  out << '\n';
1288 
1289  // if there is a documenting string, print it as well
1290  if (p->second.get<std::string>("documentation").length() != 0)
1291  out << std::setw(overall_indent_level*2 + longest_name + 10) << ""
1292  << "(" << p->second.get<std::string>("documentation") << ")"
1293  << '\n';
1294  }
1295 
1296  break;
1297  }
1298 
1299  default:
1300  Assert (false, ExcNotImplemented());
1301  }
1302 
1303 
1304  // if there was text before and there are sections to come, put two
1305  // newlines between the last entry and the first subsection
1306  {
1307  unsigned int n_parameters = 0;
1308  unsigned int n_sections = 0;
1309  for (boost::property_tree::ptree::const_iterator
1310  p = current_section.begin();
1311  p != current_section.end(); ++p)
1312  if (is_parameter_node (p->second) == true)
1313  ++n_parameters;
1314  else if (is_alias_node (p->second) == false)
1315  ++n_sections;
1316 
1317  if ((style != Description)
1318  &&
1319  (style != ShortText)
1320  &&
1321  (n_parameters != 0)
1322  &&
1323  (n_sections != 0))
1324  out << "\n\n";
1325  }
1326 
1327  // now traverse subsections tree, in alphabetical order
1328  for (boost::property_tree::ptree::const_assoc_iterator
1329  p = current_section.ordered_begin();
1330  p != current_section.not_found(); ++p)
1331  if ((is_parameter_node (p->second) == false)
1332  &&
1333  (is_alias_node (p->second) == false))
1334  {
1335  // first print the subsection header
1336  switch (style)
1337  {
1338  case Text:
1339  case Description:
1340  case ShortText:
1341  out << std::setw(overall_indent_level*2) << ""
1342  << "subsection " << demangle(p->first)
1343  << '\n';
1344  break;
1345 
1346  case LaTeX:
1347  {
1348  auto escape = [] (const std::string &input)
1349  {
1350  return Patterns::internal::escape(input, Patterns::PatternBase::LaTeX);
1351  };
1352 
1353  out << '\n'
1354  << "\\subsection{Parameters in section \\tt ";
1355 
1356  // find the path to the current section so that we can
1357  // print it in the \subsection{...} heading
1358  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1359  out << escape(target_subsection_path[i]) << "/";
1360  out << escape(demangle(p->first));
1361 
1362  out << "}" << '\n';
1363  out << "\\label{parameters:";
1364  for (unsigned int i=0; i<target_subsection_path.size(); ++i)
1365  out << mangle(target_subsection_path[i]) << "/";
1366  out << p->first << "}";
1367  out << '\n';
1368 
1369  out << '\n';
1370  break;
1371  }
1372 
1373  default:
1374  Assert (false, ExcNotImplemented());
1375  }
1376 
1377  // then the contents of the subsection
1378  const std::string subsection = demangle(p->first);
1379  std::vector<std::string> directory_path = target_subsection_path;
1380  directory_path.emplace_back (subsection);
1381 
1382  recursively_print_parameters (directory_path, style,
1383  overall_indent_level+1,
1384  out);
1385 
1386  switch (style)
1387  {
1388  case Text:
1389  // write end of subsection. one blank line after each
1390  // subsection
1391  out << std::setw(overall_indent_level*2) << ""
1392  << "end" << '\n'
1393  << '\n';
1394 
1395  // if this is a toplevel subsection, then have two
1396  // newlines
1397  if (overall_indent_level == 0)
1398  out << '\n';
1399 
1400  break;
1401 
1402  case Description:
1403  break;
1404 
1405  case ShortText:
1406  // write end of subsection.
1407  out << std::setw(overall_indent_level*2) << ""
1408  << "end" << '\n';
1409  break;
1410 
1411  case LaTeX:
1412  break;
1413 
1414  default:
1415  Assert (false, ExcNotImplemented());
1416  }
1417  }
1418 }
1419 
1420 
1421 
1422 // Print a section in the desired style. The styles are separated into
1423 // several verbosity classes depending on the higher bits.
1424 //
1425 // If bit 7 (128) is set, comments are not printed.
1426 // If bit 6 (64) is set, default values after change are not printed.
1427 void
1429  const OutputStyle style,
1430  const unsigned int indent_level,
1431  const bool include_top_level_elements)
1432 {
1433  AssertThrow (out, ExcIO());
1434 
1435  const boost::property_tree::ptree &current_section
1436  = entries->get_child (get_current_path());
1437 
1438  unsigned int overall_indent_level = indent_level;
1439 
1440  switch (style)
1441  {
1442  case XML:
1443  {
1444  if (include_top_level_elements)
1445  {
1446  // call the writer function and exit as there is nothing
1447  // further to do down in this function
1448  //
1449  // XML has a requirement that there can only be one single
1450  // top-level entry, but a section has multiple entries and
1451  // sections. we work around this by creating a tree just for
1452  // this purpose with the single top-level node
1453  // "ParameterHandler" and assign the full path of down to
1454  // the current section under it
1455  boost::property_tree::ptree single_node_tree;
1456 
1457  // if there is no subsection selected, add the whole tree of entries,
1458  // otherwise add a root element and the selected subsection under it
1459  if (subsection_path.size() == 0)
1460  {
1461  single_node_tree.add_child("ParameterHandler",
1462  *entries);
1463  }
1464  else
1465  {
1466  std::string path ("ParameterHandler");
1467 
1468  single_node_tree.add_child(path,
1469  boost::property_tree::ptree());
1470 
1471  path += path_separator + get_current_path ();
1472  single_node_tree.add_child (path, current_section);
1473  }
1474 
1475  write_xml (out, single_node_tree);
1476  }
1477  else
1478  Assert (false, ExcNotImplemented());
1479 
1480  break;
1481  }
1482  case Text:
1483  case ShortText:
1484  {
1485  // if there are top level elements to print, do it
1486  if (include_top_level_elements && (subsection_path.size() > 0))
1487  for (unsigned int i=0; i<subsection_path.size(); ++i)
1488  {
1489  out << std::setw(overall_indent_level*2) << ""
1490  << "subsection " << demangle (subsection_path[i]) << std::endl;
1491  overall_indent_level += 1;
1492  }
1493 
1494  // first find out the longest entry name to be able to align the
1495  // equal signs to do this loop over all nodes of the current
1496  // tree, select the parameter nodes (and discard sub-tree nodes)
1497  // and take the maximum of their lengths
1498  std::size_t longest_name = 0;
1499  for (boost::property_tree::ptree::const_iterator
1500  p = current_section.begin();
1501  p != current_section.end(); ++p)
1502  if (is_parameter_node (p->second) == true)
1503  longest_name = std::max (longest_name,
1504  demangle(p->first).length());
1505 
1506  // likewise find the longest actual value string to make sure we
1507  // can align the default and documentation strings
1508  std::size_t longest_value = 0;
1509  for (boost::property_tree::ptree::const_iterator
1510  p = current_section.begin();
1511  p != current_section.end(); ++p)
1512  if (is_parameter_node (p->second) == true)
1513  longest_value = std::max (longest_value,
1514  p->second.get<std::string>("value").length());
1515 
1516 
1517  // print entries one by one. make sure they are sorted by using
1518  // the appropriate iterators
1519  bool first_entry = true;
1520  for (boost::property_tree::ptree::const_assoc_iterator
1521  p = current_section.ordered_begin();
1522  p != current_section.not_found(); ++p)
1523  if (is_parameter_node (p->second) == true)
1524  {
1525  const std::string value = p->second.get<std::string>("value");
1526 
1527  // if there is documentation, then add an empty line
1528  // (unless this is the first entry in a subsection), print
1529  // the documentation, and then the actual entry; break the
1530  // documentation into readable chunks such that the whole
1531  // thing is at most 78 characters wide
1532  if ((!(style & 128)) &&
1533  !p->second.get<std::string>("documentation").empty())
1534  {
1535  if (first_entry == false)
1536  out << std::endl;
1537  else
1538  first_entry = false;
1539 
1540  const std::vector<std::string> doc_lines
1541  = Utilities::
1542  break_text_into_lines (p->second.get<std::string>("documentation"),
1543  78 - overall_indent_level*2 - 2);
1544 
1545  for (unsigned int i=0; i<doc_lines.size(); ++i)
1546  out << std::setw(overall_indent_level*2) << ""
1547  << "# "
1548  << doc_lines[i]
1549  << std::endl;
1550  }
1551 
1552 
1553 
1554  // print name and value of this entry
1555  out << std::setw(overall_indent_level*2) << ""
1556  << "set "
1557  << demangle(p->first)
1558  << std::setw(longest_name-demangle(p->first).length()+1) << " "
1559  << "= " << value;
1560 
1561  // finally print the default value, but only if it differs
1562  // from the actual value
1563  if ((!(style & 64)) && value != p->second.get<std::string>("default_value"))
1564  {
1565  out << std::setw(longest_value-value.length()+1) << ' '
1566  << "# ";
1567  out << "default: " << p->second.get<std::string>("default_value");
1568  }
1569 
1570  out << std::endl;
1571  }
1572 
1573  break;
1574  }
1575 
1576  case LaTeX:
1577  {
1578  auto escape = [] (const std::string &input)
1579  {
1580  return Patterns::internal::escape(input, Patterns::PatternBase::LaTeX);
1581  };
1582 
1583  // if there are any parameters in this section then print them
1584  // as an itemized list
1585  bool parameters_exist_here = false;
1586  for (boost::property_tree::ptree::const_assoc_iterator
1587  p = current_section.ordered_begin();
1588  p != current_section.not_found(); ++p)
1589  if ((is_parameter_node (p->second) == true)
1590  ||
1591  (is_alias_node (p->second) == true))
1592  {
1593  parameters_exist_here = true;
1594  break;
1595  }
1596 
1597  if (parameters_exist_here)
1598  {
1599  out << "\\begin{itemize}"
1600  << std::endl;
1601 
1602  // print entries one by one. make sure they are sorted by
1603  // using the appropriate iterators
1604  for (boost::property_tree::ptree::const_assoc_iterator
1605  p = current_section.ordered_begin();
1606  p != current_section.not_found(); ++p)
1607  if (is_parameter_node (p->second) == true)
1608  {
1609  const std::string value = p->second.get<std::string>("value");
1610 
1611  // print name
1612  out << "\\item {\\it Parameter name:} {\\tt " << escape(demangle(p->first)) << "}\n"
1613  << "\\phantomsection\\label{parameters:";
1614  for (unsigned int i=0; i<subsection_path.size(); ++i)
1615  out << mangle(subsection_path[i]) << "/";
1616  out << p->first;
1617  out << "}\n\n"
1618  << std::endl;
1619 
1620  out << "\\index[prmindex]{"
1621  << escape(demangle(p->first))
1622  << "}\n";
1623  out << "\\index[prmindexfull]{";
1624  for (unsigned int i=0; i<subsection_path.size(); ++i)
1625  out << escape(subsection_path[i]) << "!";
1626  out << escape(demangle(p->first))
1627  << "}\n";
1628 
1629  // finally print value and default
1630  out << "{\\it Value:} " << escape(value) << "\n\n"
1631  << std::endl
1632  << "{\\it Default:} "
1633  << escape(p->second.get<std::string>("default_value")) << "\n\n"
1634  << std::endl;
1635 
1636  // if there is a documenting string, print it as well
1637  if (!p->second.get<std::string>("documentation").empty())
1638  out << "{\\it Description:} "
1639  << p->second.get<std::string>("documentation") << "\n\n"
1640  << std::endl;
1641 
1642  // also output possible values
1643  const unsigned int pattern_index = p->second.get<unsigned int> ("pattern");
1644  const std::string desc_str = patterns[pattern_index]->description (Patterns::PatternBase::LaTeX);
1645  out << "{\\it Possible values:} "
1646  << desc_str
1647  << std::endl;
1648  }
1649  else if (is_alias_node (p->second) == true)
1650  {
1651  const std::string alias = p->second.get<std::string>("alias");
1652 
1653  // print name
1654  out << "\\item {\\it Parameter name:} {\\tt " << escape(demangle(p->first)) << "}\n"
1655  << "\\phantomsection\\label{parameters:";
1656  for (unsigned int i=0; i<subsection_path.size(); ++i)
1657  out << mangle(subsection_path[i]) << "/";
1658  out << p->first;
1659  out << "}\n\n"
1660  << std::endl;
1661 
1662  out << "\\index[prmindex]{"
1663  << escape(demangle(p->first))
1664  << "}\n";
1665  out << "\\index[prmindexfull]{";
1666  for (unsigned int i=0; i<subsection_path.size(); ++i)
1667  out << escape(subsection_path[i]) << "!";
1668  out << escape(demangle(p->first))
1669  << "}\n";
1670 
1671  // finally print alias and indicate if it is deprecated
1672  out << "This parameter is an alias for the parameter ``\\texttt{"
1673  << escape(alias) << "}''."
1674  << (p->second.get<std::string>("deprecation_status") == "true"
1675  ?
1676  " Its use is deprecated."
1677  :
1678  "")
1679  << "\n\n"
1680  << std::endl;
1681  }
1682  out << "\\end{itemize}" << std::endl;
1683  }
1684 
1685  break;
1686  }
1687 
1688  case Description:
1689  {
1690  // if there are top level elements to print, do it
1691  if (include_top_level_elements && (subsection_path.size() > 0))
1692  for (unsigned int i=0; i<subsection_path.size(); ++i)
1693  {
1694  out << std::setw(overall_indent_level*2) << ""
1695  << "subsection " << demangle (subsection_path[i]) << std::endl;
1696  overall_indent_level += 1;
1697  };
1698 
1699  // first find out the longest entry name to be able to align the
1700  // equal signs
1701  std::size_t longest_name = 0;
1702  for (boost::property_tree::ptree::const_iterator
1703  p = current_section.begin();
1704  p != current_section.end(); ++p)
1705  if (is_parameter_node (p->second) == true)
1706  longest_name = std::max (longest_name,
1707  demangle(p->first).length());
1708 
1709  // print entries one by one. make sure they are sorted by using
1710  // the appropriate iterators
1711  for (boost::property_tree::ptree::const_assoc_iterator
1712  p = current_section.ordered_begin();
1713  p != current_section.not_found(); ++p)
1714  if (is_parameter_node (p->second) == true)
1715  {
1716  // print name and value
1717  out << std::setw(overall_indent_level*2) << ""
1718  << "set "
1719  << demangle(p->first)
1720  << std::setw(longest_name-demangle(p->first).length()+1) << " "
1721  << " = ";
1722 
1723  // print possible values:
1724  const unsigned int pattern_index = p->second.get<unsigned int> ("pattern");
1725  const std::string full_desc_str = patterns[pattern_index]->description (Patterns::PatternBase::Text);
1726  const std::vector<std::string> description_str
1727  = Utilities::break_text_into_lines (full_desc_str,
1728  78 - overall_indent_level*2 - 2, '|');
1729  if (description_str.size() > 1)
1730  {
1731  out << std::endl;
1732  for (unsigned int i=0; i<description_str.size(); ++i)
1733  out << std::setw(overall_indent_level*2+6) << ""
1734  << description_str[i] << std::endl;
1735  }
1736  else if (description_str.empty() == false)
1737  out << " " << description_str[0] << std::endl;
1738  else
1739  out << std::endl;
1740 
1741  // if there is a documenting string, print it as well
1742  if (p->second.get<std::string>("documentation").length() != 0)
1743  out << std::setw(overall_indent_level*2 + longest_name + 10) << ""
1744  << "(" << p->second.get<std::string>("documentation") << ")" << std::endl;
1745  }
1746 
1747  break;
1748  }
1749 
1750  default:
1751  Assert (false, ExcNotImplemented());
1752  }
1753 
1754 
1755  // if there was text before and there are sections to come, put two
1756  // newlines between the last entry and the first subsection
1757  if (style != XML)
1758  {
1759  unsigned int n_parameters = 0;
1760  unsigned int n_sections = 0;
1761  for (boost::property_tree::ptree::const_iterator
1762  p = current_section.begin();
1763  p != current_section.end(); ++p)
1764  if (is_parameter_node (p->second) == true)
1765  ++n_parameters;
1766  else if (is_alias_node (p->second) == false)
1767  ++n_sections;
1768 
1769  if ((style != Description)
1770  &&
1771  (!(style & 128))
1772  &&
1773  (n_parameters != 0)
1774  &&
1775  (n_sections != 0))
1776  out << std::endl << std::endl;
1777 
1778  // now traverse subsections tree, in alphabetical order
1779  for (boost::property_tree::ptree::const_assoc_iterator
1780  p = current_section.ordered_begin();
1781  p != current_section.not_found(); ++p)
1782  if ((is_parameter_node (p->second) == false)
1783  &&
1784  (is_alias_node (p->second) == false))
1785  {
1786  // first print the subsection header
1787  switch (style)
1788  {
1789  case Text:
1790  case Description:
1791  case ShortText:
1792  out << std::setw(overall_indent_level*2) << ""
1793  << "subsection " << demangle(p->first) << std::endl;
1794  break;
1795  case LaTeX:
1796  {
1797  auto escape = [] (const std::string &input)
1798  {
1799  return Patterns::internal::escape(input, Patterns::PatternBase::LaTeX);
1800  };
1801 
1802  out << std::endl
1803  << "\\subsection{Parameters in section \\tt ";
1804 
1805  // find the path to the current section so that we can
1806  // print it in the \subsection{...} heading
1807  for (unsigned int i=0; i<subsection_path.size(); ++i)
1808  out << escape(subsection_path[i]) << "/";
1809  out << escape(demangle(p->first));
1810 
1811  out << "}" << std::endl;
1812  out << "\\label{parameters:";
1813  for (unsigned int i=0; i<subsection_path.size(); ++i)
1814  out << mangle(subsection_path[i]) << "/";
1815  out << p->first << "}";
1816  out << std::endl;
1817 
1818  out << std::endl;
1819  break;
1820  }
1821 
1822  default:
1823  Assert (false, ExcNotImplemented());
1824  };
1825 
1826  // then the contents of the subsection
1827  enter_subsection (demangle(p->first));
1828  print_parameters_section (out, style, overall_indent_level+1);
1829  leave_subsection ();
1830  switch (style)
1831  {
1832  case Text:
1833  // write end of subsection. one blank line after each
1834  // subsection
1835  out << std::setw(overall_indent_level*2) << ""
1836  << "end" << std::endl
1837  << std::endl;
1838 
1839  // if this is a toplevel subsection, then have two
1840  // newlines
1841  if (overall_indent_level == 0)
1842  out << std::endl;
1843 
1844  break;
1845  case Description:
1846  break;
1847  case ShortText:
1848  // write end of subsection.
1849  out << std::setw(overall_indent_level*2) << ""
1850  << "end" << std::endl;
1851  break;
1852  case LaTeX:
1853  break;
1854  default:
1855  Assert (false, ExcNotImplemented());
1856  }
1857  }
1858  }
1859 
1860  // close top level elements, if there are any
1861  switch (style)
1862  {
1863  case XML:
1864  case LaTeX:
1865  case Description:
1866  break;
1867  case Text:
1868  case ShortText:
1869  {
1870  if (include_top_level_elements && (subsection_path.size() > 0))
1871  for (unsigned int i=0; i<subsection_path.size(); ++i)
1872  {
1873  overall_indent_level -= 1;
1874  out << std::setw(overall_indent_level*2) << ""
1875  << "end" << std::endl;
1876  };
1877 
1878  break;
1879  }
1880 
1881  default:
1882  Assert (false, ExcNotImplemented());
1883  }
1884 
1885 }
1886 
1887 
1888 
1889 void
1891 {
1892  out.push("parameters");
1893  // dive recursively into the subsections
1894  log_parameters_section (out);
1895 
1896  out.pop();
1897 }
1898 
1899 
1900 
1901 void
1903 {
1904  const boost::property_tree::ptree &current_section
1905  = entries->get_child (get_current_path());
1906 
1907  // print entries one by
1908  // one. make sure they are
1909  // sorted by using the
1910  // appropriate iterators
1911  for (boost::property_tree::ptree::const_assoc_iterator
1912  p = current_section.ordered_begin();
1913  p != current_section.not_found(); ++p)
1914  if (is_parameter_node (p->second) == true)
1915  out << demangle(p->first) << ": "
1916  << p->second.get<std::string>("value") << std::endl;
1917 
1918  // now transverse subsections tree
1919  // now traverse subsections tree,
1920  // in alphabetical order
1921  for (boost::property_tree::ptree::const_assoc_iterator
1922  p = current_section.ordered_begin();
1923  p != current_section.not_found(); ++p)
1924  if (is_parameter_node (p->second) == false)
1925  {
1926  out.push (demangle(p->first));
1927  enter_subsection (demangle(p->first));
1928  log_parameters_section (out);
1929  leave_subsection ();
1930  out.pop ();
1931  }
1932 }
1933 
1934 
1935 
1936 void
1938  const std::string &input_filename,
1939  const unsigned int current_line_n)
1940 {
1941  // save a copy for some error messages
1942  const std::string original_line = line;
1943 
1944  // if there is a comment, delete it
1945  if (line.find('#') != std::string::npos)
1946  line.erase (line.find('#'), std::string::npos);
1947 
1948  // replace \t by space:
1949  while (line.find('\t') != std::string::npos)
1950  line.replace (line.find('\t'), 1, " ");
1951 
1952  //trim start and end:
1953  line = Utilities::trim(line);
1954 
1955  // if line is now empty: leave
1956  if (line.length() == 0)
1957  {
1958  return;
1959  }
1960  // enter subsection
1961  else if (Utilities::match_at_string_start(line, "SUBSECTION ") ||
1962  Utilities::match_at_string_start(line, "subsection "))
1963  {
1964  // delete this prefix
1965  line.erase (0, std::string("subsection").length()+1);
1966 
1967  const std::string subsection = Utilities::trim(line);
1968 
1969  // check whether subsection exists
1970  AssertThrow (entries->get_child_optional (get_current_full_path(subsection)),
1971  ExcNoSubsection (current_line_n,
1972  input_filename,
1973  demangle(get_current_full_path(subsection))));
1974 
1975  // subsection exists
1976  subsection_path.push_back (subsection);
1977  }
1978  // exit subsection
1979  else if (Utilities::match_at_string_start(line, "END") ||
1980  Utilities::match_at_string_start(line, "end"))
1981  {
1982  line.erase (0, 3);
1983  while ((line.size() > 0) && (std::isspace(line[0])))
1984  line.erase (0, 1);
1985 
1986  AssertThrow (line.size() == 0,
1987  ExcCannotParseLine (current_line_n,
1988  input_filename,
1989  "Invalid content after 'end' or 'END' statement."));
1990  AssertThrow (subsection_path.size() != 0,
1991  ExcCannotParseLine (current_line_n,
1992  input_filename,
1993  "There is no subsection to leave here."));
1994  leave_subsection ();
1995  }
1996  // regular entry
1997  else if (Utilities::match_at_string_start(line, "SET ") ||
1998  Utilities::match_at_string_start(line, "set "))
1999  {
2000  // erase "set" statement
2001  line.erase (0, 4);
2002 
2003  std::string::size_type pos = line.find('=');
2004  AssertThrow (pos != std::string::npos,
2005  ExcCannotParseLine (current_line_n,
2006  input_filename,
2007  "Invalid format of 'set' or 'SET' statement."));
2008 
2009  // extract entry name and value and trim
2010  std::string entry_name = Utilities::trim(std::string(line, 0, pos));
2011  std::string entry_value = Utilities::trim(std::string(line, pos+1, std::string::npos));
2012 
2013  // resolve aliases before we look up the entry. if necessary, print
2014  // a warning that the alias is deprecated
2015  std::string path = get_current_full_path(entry_name);
2016  if (entries->get_optional<std::string>(path + path_separator + "alias"))
2017  {
2018  if (entries->get<std::string>(path + path_separator + "deprecation_status") == "true")
2019  {
2020  std::cerr << "Warning in line <" << current_line_n
2021  << "> of file <" << input_filename
2022  << ">: You are using the deprecated spelling <"
2023  << entry_name
2024  << "> of the parameter <"
2025  << entries->get<std::string>(path + path_separator + "alias")
2026  << ">." << std::endl;
2027  }
2028  path = get_current_full_path(entries->get<std::string>(path + path_separator + "alias"));
2029  }
2030 
2031  // get the node for the entry. if it doesn't exist, then we end up
2032  // in the else-branch below, which asserts that the entry is indeed
2033  // declared
2034  if (entries->get_optional<std::string> (path + path_separator + "value"))
2035  {
2036  // if entry was declared:
2037  // does it match the regex? if not,
2038  // don't enter it into the database
2039  // exception: if it contains characters
2040  // which specify it as a multiple loop
2041  // entry, then ignore content
2042  if (entry_value.find ('{') == std::string::npos)
2043  {
2044  // verify that the new value satisfies the provided pattern
2045  const unsigned int pattern_index
2046  = entries->get<unsigned int> (path + path_separator + "pattern");
2047  AssertThrow (patterns[pattern_index]->match (entry_value),
2048  ExcInvalidEntryForPattern (current_line_n,
2049  input_filename,
2050  entry_value,
2051  entry_name,
2052  patterns[pattern_index]->description()));
2053 
2054  // then also execute the actions associated with this
2055  // parameter (if any have been provided)
2056  const boost::optional<std::string> action_indices_as_string
2057  = entries->get_optional<std::string> (path + path_separator + "actions");
2058  if (action_indices_as_string)
2059  {
2060  std::vector<int> action_indices
2061  = Utilities::string_to_int (Utilities::split_string_list (action_indices_as_string.get()));
2062  for (unsigned int index : action_indices)
2063  if (actions.size() >= index+1)
2064  actions[index](entry_value);
2065  }
2066  }
2067 
2068  // finally write the new value into the database
2069  entries->put (path + path_separator + "value",
2070  entry_value);
2071  }
2072  else
2073  {
2074  AssertThrow (false,
2075  ExcCannotParseLine(current_line_n,
2076  input_filename,
2077  ("No entry with name <" + entry_name +
2078  "> was declared in the current subsection.")));
2079  }
2080  }
2081  // an include statement?
2082  else if (Utilities::match_at_string_start(line, "include ") ||
2083  Utilities::match_at_string_start(line, "INCLUDE "))
2084  {
2085  // erase "include " statement and eliminate spaces
2086  line.erase (0, 7);
2087  while ((line.size() > 0) && (line[0] == ' '))
2088  line.erase (0, 1);
2089 
2090  // the remainder must then be a filename
2091  AssertThrow (line.size() !=0,
2092  ExcCannotParseLine (current_line_n,
2093  input_filename,
2094  "The current line is an 'include' or "
2095  "'INCLUDE' statement, but it does not "
2096  "name a file for inclusion."));
2097 
2098  std::ifstream input (line.c_str());
2099  AssertThrow (input, ExcCannotOpenIncludeStatementFile (current_line_n,
2100  input_filename,
2101  line));
2102  parse_input (input);
2103  }
2104  else
2105  {
2106  AssertThrow (false,
2107  ExcCannotParseLine (current_line_n,
2108  input_filename,
2109  "The line\n\n"
2110  " <"
2111  + original_line
2112  + ">\n\n"
2113  "could not be parsed: please check to "
2114  "make sure that the file is not missing a "
2115  "'set', 'include', 'subsection', or 'end' "
2116  "statement."));
2117  }
2118 }
2119 
2120 
2121 
2122 std::size_t
2124 {
2125 //TODO: add to this an estimate of the memory in the property_tree
2127 }
2128 
2129 
2130 
2131 bool
2133 {
2134  if (patterns.size() != prm2.patterns.size())
2135  return false;
2136 
2137  for (unsigned int j=0; j<patterns.size(); ++j)
2138  if (patterns[j]->description() != prm2.patterns[j]->description())
2139  return false;
2140 
2141  // instead of walking through all
2142  // the nodes of the two trees
2143  // entries and prm2.entries and
2144  // comparing them for equality,
2145  // simply dump the content of the
2146  // entire structure into a string
2147  // and compare those for equality
2148  std::ostringstream o1, o2;
2149  write_json (o1, *entries);
2150  write_json (o2, *prm2.entries);
2151  return (o1.str() == o2.str());
2152 }
2153 
2154 
2155 
2157  :
2158  n_branches(0)
2159 {}
2160 
2161 
2162 
2163 void
2165  const std::string &filename,
2166  const std::string &last_line)
2167 {
2168  AssertThrow (input, ExcIO());
2169 
2170  // Note that (to avoid infinite recursion) we have to explicitly call the
2171  // base class version of parse_input and *not* a wrapper (which may be
2172  // virtual and lead us back here)
2173  ParameterHandler::parse_input (input, filename, last_line);
2174  init_branches ();
2175 }
2176 
2177 
2178 
2180 {
2181  for (unsigned int run_no=0; run_no<n_branches; ++run_no)
2182  {
2183  // give create_new one-based numbers
2184  uc.create_new (run_no+1);
2185  fill_entry_values (run_no);
2186  uc.run (*this);
2187  };
2188 }
2189 
2190 
2191 
2193 {
2194  multiple_choices.clear ();
2196 
2197  // split up different values
2198  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2199  multiple_choices[i].split_different_values ();
2200 
2201  // finally calculate number of branches
2202  n_branches = 1;
2203  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2204  if (multiple_choices[i].type == Entry::variant)
2205  n_branches *= multiple_choices[i].different_values.size();
2206 
2207  // check whether array entries have the correct
2208  // number of entries
2209  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2210  if (multiple_choices[i].type == Entry::array)
2211  if (multiple_choices[i].different_values.size() != n_branches)
2212  std::cerr << " The entry value" << std::endl
2213  << " " << multiple_choices[i].entry_value << std::endl
2214  << " for the entry named" << std::endl
2215  << " " << multiple_choices[i].entry_name << std::endl
2216  << " does not have the right number of entries for the " << std::endl
2217  << " " << n_branches << " variant runs that will be performed."
2218  << std::endl;
2219 
2220 
2221  // do a first run on filling the values to
2222  // check for the conformance with the regexp
2223  // (later on, this will be lost in the whole
2224  // other output)
2225  for (unsigned int i=0; i<n_branches; ++i)
2226  fill_entry_values (i);
2227 }
2228 
2229 
2230 
2232 {
2233  const boost::property_tree::ptree &current_section
2234  = entries->get_child (get_current_path());
2235 
2236  // check all entries in the present
2237  // subsection whether they are
2238  // multiple entries
2239  //
2240  // we loop over entries in sorted
2241  // order to guarantee backward
2242  // compatibility to an earlier
2243  // implementation
2244  for (boost::property_tree::ptree::const_assoc_iterator
2245  p = current_section.ordered_begin();
2246  p != current_section.not_found(); ++p)
2247  if (is_parameter_node (p->second) == true)
2248  {
2249  const std::string value = p->second.get<std::string>("value");
2250  if (value.find('{') != std::string::npos)
2251  multiple_choices.emplace_back (subsection_path,
2252  demangle(p->first),
2253  value);
2254  }
2255 
2256  // then loop over all subsections
2257  for (boost::property_tree::ptree::const_iterator
2258  p = current_section.begin();
2259  p != current_section.end(); ++p)
2260  if (is_parameter_node (p->second) == false)
2261  {
2262  enter_subsection (demangle(p->first));
2264  leave_subsection ();
2265  }
2266 }
2267 
2268 
2269 
2270 
2271 void MultipleParameterLoop::fill_entry_values (const unsigned int run_no)
2272 {
2273  unsigned int possibilities = 1;
2274 
2275  std::vector<Entry>::iterator choice;
2276  for (choice = multiple_choices.begin();
2277  choice != multiple_choices.end();
2278  ++choice)
2279  {
2280  const unsigned int selection
2281  = (run_no/possibilities) % choice->different_values.size();
2282  std::string entry_value;
2283  if (choice->type == Entry::variant)
2284  entry_value = choice->different_values[selection];
2285  else
2286  {
2287  if (run_no>=choice->different_values.size())
2288  {
2289  std::cerr << "The given array for entry <"
2290  << choice->entry_name
2291  << "> does not contain enough elements! Taking empty string instead."
2292  << std::endl;
2293  entry_value = "";
2294  }
2295  else
2296  entry_value = choice->different_values[run_no];
2297  }
2298 
2299  // temporarily enter the
2300  // subsection tree of this
2301  // multiple entry, set the
2302  // value, and get out
2303  // again. the set() operation
2304  // also tests for the
2305  // correctness of the value
2306  // with regard to the pattern
2307  subsection_path.swap (choice->subsection_path);
2308  set (choice->entry_name, entry_value);
2309  subsection_path.swap (choice->subsection_path);
2310 
2311  // move ahead if it was a variant entry
2312  if (choice->type == Entry::variant)
2313  possibilities *= choice->different_values.size();
2314  }
2315 }
2316 
2317 
2318 
2319 
2320 std::size_t
2322 {
2323  std::size_t mem = ParameterHandler::memory_consumption ();
2324  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2325  mem += multiple_choices[i].memory_consumption ();
2326 
2327  return mem;
2328 }
2329 
2330 
2331 
2332 MultipleParameterLoop::Entry::Entry (const std::vector<std::string> &ssp,
2333  const std::string &Name,
2334  const std::string &Value)
2335  :
2336  subsection_path (ssp), entry_name(Name), entry_value(Value), type (Entry::array)
2337 {}
2338 
2339 
2340 
2342 {
2343  // split string into three parts:
2344  // part before the opening "{",
2345  // the selection itself, final
2346  // part after "}"
2347  std::string prefix (entry_value, 0, entry_value.find('{'));
2348  std::string multiple(entry_value, entry_value.find('{')+1,
2349  entry_value.rfind('}')-entry_value.find('{')-1);
2350  std::string postfix (entry_value, entry_value.rfind('}')+1, std::string::npos);
2351  // if array entry {{..}}: delete inner
2352  // pair of braces
2353  if (multiple[0]=='{')
2354  multiple.erase (0,1);
2355  if (multiple[multiple.size()-1] == '}')
2356  multiple.erase (multiple.size()-1, 1);
2357  // erase leading and trailing spaces
2358  // in multiple
2359  while (std::isspace (multiple[0])) multiple.erase (0,1);
2360  while (std::isspace (multiple[multiple.size()-1])) multiple.erase (multiple.size()-1,1);
2361 
2362  // delete spaces around '|'
2363  while (multiple.find(" |") != std::string::npos)
2364  multiple.replace (multiple.find(" |"), 2, "|");
2365  while (multiple.find("| ") != std::string::npos)
2366  multiple.replace (multiple.find("| "), 2, "|");
2367 
2368  while (multiple.find('|') != std::string::npos)
2369  {
2370  different_values.push_back (prefix +
2371  std::string(multiple, 0, multiple.find('|'))+
2372  postfix);
2373  multiple.erase (0, multiple.find('|')+1);
2374  };
2375  // make up the last selection ("while" broke
2376  // because there was no '|' any more
2377  different_values.push_back (prefix+multiple+postfix);
2378  // finally check whether this was a variant
2379  // entry ({...}) or an array ({{...}})
2380  if ((entry_value.find("{{") != std::string::npos) &&
2381  (entry_value.find("}}") != std::string::npos))
2382  type = Entry::array;
2383  else
2384  type = Entry::variant;
2385 }
2386 
2387 
2388 std::size_t
2390 {
2394  MemoryConsumption::memory_consumption (different_values) +
2395  sizeof (type));
2396 }
2397 
2398 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: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
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)
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
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition: utilities.cc:123
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: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())
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="")