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