Reference documentation for deal.II version 8.4.2
parameter_handler.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2016 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>
28 
29 #include <fstream>
30 #include <iostream>
31 #include <iomanip>
32 #include <cstdlib>
33 #include <algorithm>
34 #include <list>
35 #include <sstream>
36 #include <cctype>
37 #include <limits>
38 
39 
40 DEAL_II_NAMESPACE_OPEN
41 
42 
43 
44 //TODO[WB]: various functions here could be simplified by using namespace Utilities
45 
46 namespace Patterns
47 {
48 
49  namespace
50  {
57  bool has_only_whitespace (std::istream &in)
58  {
59  while (in)
60  {
61  char c;
62 
63  // skip if we've reached the end of
64  // the line
65  if (!(in >> c))
66  break;
67 
68  if ((c != ' ') && (c != '\t'))
69  return false;
70  }
71  return true;
72  }
73  }
74 
75 
76 
77  PatternBase *pattern_factory (const std::string &description)
78  {
79  PatternBase *p;
80 
81  p = Integer::create(description);
82  if (p != 0)
83  return p;
84 
85  p = Double::create(description);
86  if (p !=0 )
87  return p;
88 
89  p = Selection::create(description);
90  if (p !=0 )
91  return p;
92 
93  p = List::create(description);
94  if (p !=0 )
95  return p;
96 
97  p = MultipleSelection::create(description);
98  if (p !=0 )
99  return p;
100 
101  p = Bool::create(description);
102  if (p!=0 )
103  return p;
104 
105  p = Anything::create(description);
106  if (p !=0 )
107  return p;
108 
109  p = FileName::create(description);
110  if (p !=0 )
111  return p;
112 
113  p = DirectoryName::create(description);
114  if (p!=0 )
115  return p;
116 
117  Assert(false, ExcNotImplemented());
118 
119  return 0;
120  }
121 
122 
123 
125  {}
126 
127 
128  std::size_t
130  {
131  if (dynamic_cast<const Integer *>(this) != 0)
132  return sizeof(Integer);
133  else if (dynamic_cast<const Double *>(this) != 0)
134  return sizeof(Double);
135  else if (dynamic_cast<const Bool *>(this) != 0)
136  return sizeof(Bool);
137  else if (dynamic_cast<const Anything *>(this) != 0)
138  return sizeof(Anything);
139  else
140  return sizeof(*this) + 32;
141  }
142 
143 
144 
145  const int Integer::min_int_value = std::numeric_limits<int>::min();
146  const int Integer::max_int_value = std::numeric_limits<int>::max();
147 
148  const char *Integer::description_init = "[Integer";
149 
150  Integer::Integer (const int lower_bound,
151  const int upper_bound)
152  :
153  lower_bound (lower_bound),
154  upper_bound (upper_bound)
155  {}
156 
157 
158 
159  bool Integer::match (const std::string &test_string) const
160  {
161  std::istringstream str(test_string);
162 
163  int i;
164  if (!(str >> i))
165  return false;
166 
167  if (!has_only_whitespace (str))
168  return false;
169  // check whether valid bounds
170  // were specified, and if so
171  // enforce their values
172  if (lower_bound <= upper_bound)
173  return ((lower_bound <= i) &&
174  (upper_bound >= i));
175  else
176  return true;
177  }
178 
179 
180 
181  std::string Integer::description () const
182  {
183  // check whether valid bounds
184  // were specified, and if so
185  // output their values
186  if (lower_bound <= upper_bound)
187  {
188  std::ostringstream description;
189 
190  description << description_init
191  <<" range "
192  << lower_bound << "..." << upper_bound
193  << " (inclusive)]";
194  return description.str();
195  }
196  else
197  // if no bounds were given, then
198  // return generic string
199  return "[Integer]";
200  }
201 
202 
203 
204  PatternBase *
205  Integer::clone () const
206  {
207  return new Integer(lower_bound, upper_bound);
208  }
209 
210 
211 
212  Integer *Integer::create (const std::string &description)
213  {
214  if (description.compare(0, std::strlen(description_init), description_init) == 0)
215  {
216  std::istringstream is(description);
217 
218  if (is.str().size() > strlen(description_init) + 1)
219  {
220 //TODO: verify that description matches the pattern "^\[Integer range \d+\.\.\.\d+\]@f$"
222 
223  is.ignore(strlen(description_init) + strlen(" range "));
224 
225  if (!(is >> lower_bound))
226  return new Integer();
227 
228  is.ignore(strlen("..."));
229 
230  if (!(is >> upper_bound))
231  return new Integer();
232 
233  return new Integer(lower_bound, upper_bound);
234  }
235  else
236  return new Integer();
237  }
238  else
239  return 0;
240  }
241 
242 
243 
244  const double Double::min_double_value = -std::numeric_limits<double>::max();
245  const double Double::max_double_value = std::numeric_limits<double>::max();
246 
247  const char *Double::description_init = "[Double";
248 
250  const double upper_bound)
251  :
252  lower_bound (lower_bound),
253  upper_bound (upper_bound)
254  {}
255 
256 
257 
258  bool Double::match (const std::string &test_string) const
259  {
260  std::istringstream str(test_string);
261 
262  double d;
263  if (!(str >> d))
264  return false;
265 
266  if (!has_only_whitespace (str))
267  return false;
268  // check whether valid bounds
269  // were specified, and if so
270  // enforce their values
271  if (lower_bound <= upper_bound)
272  return ((lower_bound <= d) &&
273  (upper_bound >= d));
274  else
275  return true;
276  }
277 
278 
279 
280  std::string Double::description () const
281  {
282  std::ostringstream description;
283 
284  // check whether valid bounds
285  // were specified, and if so
286  // output their values
287  if (lower_bound <= upper_bound)
288  {
289  description << description_init
290  << " "
291  << lower_bound << "..." << upper_bound
292  << " (inclusive)]";
293  return description.str();
294  }
295  else
296  // if no bounds were given, then
297  // return generic string
298  {
299  description << description_init
300  << "]";
301  return description.str();
302  }
303  }
304 
305 
306  PatternBase *
307  Double::clone () const
308  {
309  return new Double(lower_bound, upper_bound);
310  }
311 
312 
313 
314  Double *Double::create (const std::string &description)
315  {
316  if (description.compare(0, std::strlen(description_init), description_init) == 0)
317  {
318  std::istringstream is(description);
319 
320  if (is.str().size() > strlen(description_init) + 1)
321  {
322  double lower_bound, upper_bound;
323 
324  is.ignore(strlen(description_init) + strlen(" range "));
325 
326  if (!(is >> lower_bound))
327  return new Double();
328 
329  is.ignore(strlen("..."));
330 
331  if (!(is >> upper_bound))
332  return new Double();
333 
334  return new Double(lower_bound, upper_bound);
335  }
336  else
337  return new Double();
338  }
339  else
340  return 0;
341  }
342 
343 
344 
345  const char *Selection::description_init = "[Selection";
346 
347 
348  Selection::Selection (const std::string &seq)
349  {
350  sequence = seq;
351 
352  while (sequence.find(" |") != std::string::npos)
353  sequence.replace (sequence.find(" |"), 2, "|");
354  while (sequence.find("| ") != std::string::npos)
355  sequence.replace (sequence.find("| "), 2, "|");
356  }
357 
358 
359 
360  bool Selection::match (const std::string &test_string) const
361  {
362  std::vector<std::string> choices;
363  std::string tmp(sequence);
364  // check the different possibilities
365  while (tmp.find('|') != std::string::npos)
366  {
367  if (test_string == std::string(tmp, 0, tmp.find('|')))
368  return true;
369 
370  tmp.erase (0, tmp.find('|')+1);
371  };
372  // check last choice, not finished by |
373  if (test_string == tmp)
374  return true;
375 
376  // not found
377  return false;
378  }
379 
380 
381 
382  std::string Selection::description () const
383  {
384  std::ostringstream description;
385 
386  description << description_init
387  << " "
388  << sequence
389  << " ]";
390 
391  return description.str();
392  }
393 
394 
395 
396  PatternBase *
398  {
399  return new Selection(sequence);
400  }
401 
402 
403  std::size_t
405  {
406  return (sizeof(PatternBase) +
408  }
409 
410 
411 
413  {
414  if (description.compare(0, std::strlen(description_init), description_init) == 0)
415  {
416  std::string sequence(description);
417 
418  sequence.erase(0, std::strlen(description_init) + 1);
419  sequence.erase(sequence.length()-2, 2);
420 
421  return new Selection(sequence);
422  }
423  else
424  return 0;
425  }
426 
427 
428 
429  const unsigned int List::max_int_value
430  = std::numeric_limits<unsigned int>::max();
431 
432  const char *List::description_init = "[List";
433 
434 
436  const unsigned int min_elements,
437  const unsigned int max_elements,
438  const std::string &separator)
439  :
440  pattern (p.clone()),
441  min_elements (min_elements),
442  max_elements (max_elements),
443  separator (separator)
444  {
445  Assert (min_elements <= max_elements,
446  ExcInvalidRange (min_elements, max_elements));
447  Assert (separator.size() > 0,
448  ExcMessage ("The separator must have a non-zero length."));
449  }
450 
451 
452 
454  {
455  delete pattern;
456  pattern = 0;
457  }
458 
459 
460 
461  bool List::match (const std::string &test_string_list) const
462  {
463  std::string tmp = test_string_list;
464  std::vector<std::string> split_list;
465 
466  // first split the input list
467  while (tmp.length() != 0)
468  {
469  std::string name;
470  name = tmp;
471 
472  if (name.find(separator) != std::string::npos)
473  {
474  name.erase (name.find(separator), std::string::npos);
475  tmp.erase (0, tmp.find(separator)+separator.size());
476  }
477  else
478  tmp = "";
479 
480  while ((name.length() != 0) &&
481  (std::isspace (name[0])))
482  name.erase (0,1);
483 
484  while (std::isspace (name[name.length()-1]))
485  name.erase (name.length()-1, 1);
486 
487  split_list.push_back (name);
488  }
489 
490  if ((split_list.size() < min_elements) ||
491  (split_list.size() > max_elements))
492  return false;
493 
494  // check the different possibilities
495  for (std::vector<std::string>::const_iterator
496  test_string = split_list.begin();
497  test_string != split_list.end(); ++test_string)
498  if (pattern->match (*test_string) == false)
499  return false;
500 
501  return true;
502  }
503 
504 
505 
506  std::string List::description () const
507  {
508  std::ostringstream description;
509 
510  description << description_init
511  << " list of <" << pattern->description() << ">"
512  << " of length " << min_elements << "..." << max_elements
513  << " (inclusive)";
514  if (separator != ",")
515  description << " separated by <" << separator << ">";
516  description << "]";
517 
518  return description.str();
519  }
520 
521 
522 
523  PatternBase *
524  List::clone () const
525  {
527  }
528 
529 
530  std::size_t
532  {
533  return (sizeof(*this) +
536  }
537 
538 
539 
540  List *List::create (const std::string &description)
541  {
542  if (description.compare(0, std::strlen(description_init), description_init) == 0)
543  {
545 
546  std::istringstream is(description);
547  is.ignore(strlen(description_init) + strlen(" list of <"));
548 
549  std::string str;
550  std::getline(is, str, '>');
551 
552  std_cxx11::shared_ptr<PatternBase> base_pattern (pattern_factory(str));
553 
554  is.ignore(strlen(" of length "));
555  if (!(is >> min_elements))
556  return new List(*base_pattern);
557 
558  is.ignore(strlen("..."));
559  if (!(is >> max_elements))
560  return new List(*base_pattern, min_elements);
561 
562  is.ignore(strlen(" separated by <"));
563  std::string separator;
564  if (!is)
565  std::getline(is, separator, '>');
566  else
567  separator = ",";
568 
569  return new List(*base_pattern, min_elements, max_elements, separator);
570  }
571  else
572  return 0;
573  }
574 
575 
576 
577  const unsigned int Map::max_int_value
578  = std::numeric_limits<unsigned int>::max();
579 
580  const char *Map::description_init = "[Map";
581 
582 
583  Map::Map (const PatternBase &p_key,
584  const PatternBase &p_value,
585  const unsigned int min_elements,
586  const unsigned int max_elements,
587  const std::string &separator)
588  :
589  key_pattern (p_key.clone()),
590  value_pattern (p_value.clone()),
591  min_elements (min_elements),
592  max_elements (max_elements),
593  separator (separator)
594  {
595  Assert (min_elements <= max_elements,
596  ExcInvalidRange (min_elements, max_elements));
597  Assert (separator.size() > 0,
598  ExcMessage ("The separator must have a non-zero length."));
599  Assert (separator != ":",
600  ExcMessage ("The separator can not be a colon ':' since that "
601  "is the separator between the two elements of <key:value> pairs"));
602  }
603 
604 
605 
607  {
608  delete key_pattern;
609  key_pattern = 0;
610 
611  delete value_pattern;
612  value_pattern = 0;
613  }
614 
615 
616 
617  bool Map::match (const std::string &test_string_list) const
618  {
619  std::string tmp = test_string_list;
620  std::vector<std::string> split_list;
621 
622  // first split the input list at comma sites
623  while (tmp.length() != 0)
624  {
625  std::string map_entry;
626  map_entry = tmp;
627 
628  if (map_entry.find(separator) != std::string::npos)
629  {
630  map_entry.erase (map_entry.find(separator), std::string::npos);
631  tmp.erase (0, tmp.find(separator)+separator.size());
632  }
633  else
634  tmp = "";
635 
636  while ((map_entry.length() != 0) &&
637  (std::isspace (map_entry[0])))
638  map_entry.erase (0,1);
639 
640  while (std::isspace (map_entry[map_entry.length()-1]))
641  map_entry.erase (map_entry.length()-1, 1);
642 
643  split_list.push_back (map_entry);
644  }
645 
646  if ((split_list.size() < min_elements) ||
647  (split_list.size() > max_elements))
648  return false;
649 
650  // check the different possibilities
651  for (std::vector<std::string>::const_iterator
652  test_string = split_list.begin();
653  test_string != split_list.end(); ++test_string)
654  {
655  // separate key and value from the test_string
656  if (test_string->find(":") == std::string::npos)
657  return false;
658 
659  // we know now that there is a ':', so split the string there
660  // and trim spaces
661  std::string key = *test_string;
662  key.erase (key.find(":"), std::string::npos);
663  while ((key.length() > 0) && (std::isspace (key[key.length()-1])))
664  key.erase (key.length()-1, 1);
665 
666  std::string value = *test_string;
667  value.erase (0, value.find(":")+1);
668  while ((value.length() > 0) && (std::isspace (value[0])))
669  value.erase (0, 1);
670 
671  // then verify that the patterns are satisfied
672  if (key_pattern->match (key) == false)
673  return false;
674  if (value_pattern->match (value) == false)
675  return false;
676  }
677 
678  return true;
679  }
680 
681 
682 
683  std::string Map::description () const
684  {
685  std::ostringstream description;
686 
687  description << description_init
688  << " map of <"
689  << key_pattern->description() << ":"
690  << value_pattern->description() << ">"
691  << " of length " << min_elements << "..." << max_elements
692  << " (inclusive)";
693  if (separator != ",")
694  description << " separated by <" << separator << ">";
695  description << "]";
696 
697  return description.str();
698  }
699 
700 
701 
702  PatternBase *
703  Map::clone () const
704  {
705  return new Map(*key_pattern, *value_pattern,
707  separator);
708  }
709 
710 
711  std::size_t
713  {
714  return (sizeof(*this) +
716  MemoryConsumption::memory_consumption (*value_pattern) +
718  }
719 
720 
721 
722  Map *Map::create (const std::string &description)
723  {
724  if (description.compare(0, std::strlen(description_init), description_init) == 0)
725  {
727 
728  std::istringstream is(description);
729  is.ignore(strlen(description_init) + strlen(" map of <"));
730 
731  std::string str;
732  std::getline(is, str, '>');
733 
734  // split 'str' into key and value
735  std::string key = str;
736  key.erase (key.find(":"), std::string::npos);
737 
738  std::string value = str;
739  value.erase (0, value.find(":")+1);
740 
741  std_cxx11::shared_ptr<PatternBase> key_pattern (pattern_factory(key));
742  std_cxx11::shared_ptr<PatternBase> value_pattern (pattern_factory(value));
743 
744  is.ignore(strlen(" of length "));
745  if (!(is >> min_elements))
746  return new Map(*key_pattern, *value_pattern);
747 
748  is.ignore(strlen("..."));
749  if (!(is >> max_elements))
750  return new Map(*key_pattern, *value_pattern, min_elements);
751 
752  is.ignore(strlen(" separated by <"));
753  std::string separator;
754  if (!is)
755  std::getline(is, separator, '>');
756  else
757  separator = ",";
758 
759  return new Map(*key_pattern, *value_pattern,
760  min_elements, max_elements,
761  separator);
762  }
763  else
764  return 0;
765  }
766 
767 
768 
769  const char *MultipleSelection::description_init = "[MultipleSelection";
770 
771 
772  MultipleSelection::MultipleSelection (const std::string &seq)
773  {
774  Assert (seq.find (",") == std::string::npos, ExcCommasNotAllowed(seq.find(",")));
775 
776  sequence = seq;
777  while (sequence.find(" |") != std::string::npos)
778  sequence.replace (sequence.find(" |"), 2, "|");
779  while (sequence.find("| ") != std::string::npos)
780  sequence.replace (sequence.find("| "), 2, "|");
781  }
782 
783 
784 
785  bool MultipleSelection::match (const std::string &test_string_list) const
786  {
787  std::string tmp = test_string_list;
788  std::list<std::string> split_list;
789 
790  // first split the input list
791  while (tmp.length() != 0)
792  {
793  std::string name;
794  name = tmp;
795 
796  if (name.find(",") != std::string::npos)
797  {
798  name.erase (name.find(","), std::string::npos);
799  tmp.erase (0, tmp.find(",")+1);
800  }
801  else
802  tmp = "";
803 
804  while ((name.length() != 0) &&
805  (std::isspace (name[0])))
806  name.erase (0,1);
807  while (std::isspace (name[name.length()-1]))
808  name.erase (name.length()-1, 1);
809 
810  split_list.push_back (name);
811  };
812 
813 
814  // check the different possibilities
815  for (std::list<std::string>::const_iterator test_string = split_list.begin();
816  test_string != split_list.end(); ++test_string)
817  {
818  bool string_found = false;
819 
820  tmp = sequence;
821  while (tmp.find('|') != std::string::npos)
822  {
823  if (*test_string == std::string(tmp, 0, tmp.find('|')))
824  {
825  // string found, quit
826  // loop. don't change
827  // tmp, since we don't
828  // need it anymore.
829  string_found = true;
830  break;
831  };
832 
833  tmp.erase (0, tmp.find('|')+1);
834  };
835  // check last choice, not finished by |
836  if (!string_found)
837  if (*test_string == tmp)
838  string_found = true;
839 
840  if (!string_found)
841  return false;
842  };
843 
844  return true;
845  }
846 
847 
848 
849  std::string MultipleSelection::description () const
850  {
851  std::ostringstream description;
852 
853  description << description_init
854  << " "
855  << sequence
856  << " ]";
857 
858  return description.str();
859  }
860 
861 
862 
863  PatternBase *
865  {
866  return new MultipleSelection(sequence);
867  }
868 
869 
870  std::size_t
872  {
873  return (sizeof(PatternBase) +
875  }
876 
877 
878 
880  {
881  if (description.compare(0, std::strlen(description_init), description_init) == 0)
882  {
883  std::string sequence(description);
884 
885  sequence.erase(0, std::strlen(description_init) + 1);
886  sequence.erase(sequence.length()-2, 2);
887 
888  return new MultipleSelection(sequence);
889  }
890  else
891  return 0;
892  }
893 
894 
895 
896  const char *Bool::description_init = "[Bool";
897 
898 
900  :
901  Selection ("true|false")
902  {}
903 
904 
905 
906  std::string Bool::description () const
907  {
908  std::ostringstream description;
909 
910  description << description_init
911  << "]";
912 
913  return description.str();
914  }
915 
916 
917 
918  PatternBase *
919  Bool::clone () const
920  {
921  return new Bool();
922  }
923 
924 
925 
926  Bool *Bool::create (const std::string &description)
927  {
928  if (description.compare(0, std::strlen(description_init), description_init) == 0)
929  return new Bool();
930  else
931  return 0;
932  }
933 
934 
935 
936  const char *Anything::description_init = "[Anything";
937 
938 
940  {}
941 
942 
943 
944  bool Anything::match (const std::string &) const
945  {
946  return true;
947  }
948 
949 
950 
951  std::string Anything::description () const
952  {
953  std::ostringstream description;
954 
955  description << description_init
956  << "]";
957 
958  return description.str();
959  }
960 
961 
962 
963  PatternBase *
965  {
966  return new Anything();
967  }
968 
969 
970 
971  Anything *Anything::create (const std::string &description)
972  {
973  if (description.compare(0, std::strlen(description_init), description_init) == 0)
974  return new Anything();
975  else
976  return 0;
977  }
978 
979 
980 
981  const char *FileName::description_init = "[FileName";
982 
983 
985  : file_type (type)
986  {}
987 
988 
989 
990  bool FileName::match (const std::string &) const
991  {
992  return true;
993  }
994 
995 
996 
997  std::string FileName::description () const
998  {
999  std::ostringstream description;
1000 
1001  description << description_init;
1002 
1003  if (file_type == input)
1004  description << " (Type: input)]";
1005  else
1006  description << " (Type: output)]";
1007 
1008  return description.str();
1009  }
1010 
1011 
1012 
1013  PatternBase *
1015  {
1016  return new FileName(file_type);
1017  }
1018 
1019 
1020 
1021  FileName *FileName::create (const std::string &description)
1022  {
1023  if (description.compare(0, std::strlen(description_init), description_init) == 0)
1024  {
1025  std::istringstream is(description);
1026  std::string file_type;
1027  FileType type;
1028 
1029  is.ignore(strlen(description_init) + strlen(" (Type:"));
1030 
1031  is >> file_type;
1032 
1033  if (file_type == "input)]")
1034  type = input;
1035  else
1036  type = output;
1037 
1038  return new FileName(type);
1039  }
1040  else
1041  return 0;
1042  }
1043 
1044 
1045 
1046  const char *DirectoryName::description_init = "[DirectoryName";
1047 
1048 
1050  {}
1051 
1052 
1053 
1054  bool DirectoryName::match (const std::string &) const
1055  {
1056  return true;
1057  }
1058 
1059 
1060 
1061  std::string DirectoryName::description () const
1062  {
1063  std::ostringstream description;
1064 
1065  description << description_init << "]";
1066 
1067  return description.str();
1068  }
1069 
1070 
1071 
1072  PatternBase *
1074  {
1075  return new DirectoryName();
1076  }
1077 
1078 
1079 
1081  {
1082  if (description.compare(0, std::strlen(description_init), description_init) == 0)
1083  return new DirectoryName();
1084  else
1085  return 0;
1086  }
1087 
1088 } // end namespace Patterns
1089 
1090 
1091 
1093  :
1094  entries (new boost::property_tree::ptree())
1095 {}
1096 
1097 
1098 
1100 {}
1101 
1102 
1103 
1104 std::string
1105 ParameterHandler::mangle (const std::string &s)
1106 {
1107  std::string u;
1108 
1109  // reserve the minimum number of characters we will need. it may
1110  // be more but this is the least we can do
1111  u.reserve (s.size());
1112 
1113  // see if the name is special and if so mangle the whole thing
1114  const bool mangle_whole_string = (s == "value");
1115 
1116  // for all parts of the string, see
1117  // if it is an allowed character or
1118  // not
1119  for (unsigned int i=0; i<s.size(); ++i)
1120  {
1121  static const std::string allowed_characters
1122  ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
1123 
1124  if ((! mangle_whole_string)
1125  &&
1126  (allowed_characters.find (s[i]) != std::string::npos))
1127  u.push_back (s[i]);
1128  else
1129  {
1130  u.push_back ('_');
1131  static const char hex[16]
1132  = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1133  u.push_back (hex[static_cast<unsigned char>(s[i])/16]);
1134  u.push_back (hex[static_cast<unsigned char>(s[i])%16]);
1135  }
1136  }
1137 
1138  return u;
1139 }
1140 
1141 
1142 
1143 std::string
1144 ParameterHandler::demangle (const std::string &s)
1145 {
1146  std::string u;
1147  u.reserve (s.size());
1148 
1149  for (unsigned int i=0; i<s.size(); ++i)
1150  if (s[i] != '_')
1151  u.push_back (s[i]);
1152  else
1153  {
1154  Assert (i+2 < s.size(),
1155  ExcMessage ("Trying to demangle an invalid string."));
1156 
1157  unsigned char c = 0;
1158  switch (s[i+1])
1159  {
1160  case '0':
1161  c = 0 * 16;
1162  break;
1163  case '1':
1164  c = 1 * 16;
1165  break;
1166  case '2':
1167  c = 2 * 16;
1168  break;
1169  case '3':
1170  c = 3 * 16;
1171  break;
1172  case '4':
1173  c = 4 * 16;
1174  break;
1175  case '5':
1176  c = 5 * 16;
1177  break;
1178  case '6':
1179  c = 6 * 16;
1180  break;
1181  case '7':
1182  c = 7 * 16;
1183  break;
1184  case '8':
1185  c = 8 * 16;
1186  break;
1187  case '9':
1188  c = 9 * 16;
1189  break;
1190  case 'a':
1191  c = 10 * 16;
1192  break;
1193  case 'b':
1194  c = 11 * 16;
1195  break;
1196  case 'c':
1197  c = 12 * 16;
1198  break;
1199  case 'd':
1200  c = 13 * 16;
1201  break;
1202  case 'e':
1203  c = 14 * 16;
1204  break;
1205  case 'f':
1206  c = 15 * 16;
1207  break;
1208  default:
1209  Assert (false, ExcInternalError());
1210  }
1211  switch (s[i+2])
1212  {
1213  case '0':
1214  c += 0;
1215  break;
1216  case '1':
1217  c += 1;
1218  break;
1219  case '2':
1220  c += 2;
1221  break;
1222  case '3':
1223  c += 3;
1224  break;
1225  case '4':
1226  c += 4;
1227  break;
1228  case '5':
1229  c += 5;
1230  break;
1231  case '6':
1232  c += 6;
1233  break;
1234  case '7':
1235  c += 7;
1236  break;
1237  case '8':
1238  c += 8;
1239  break;
1240  case '9':
1241  c += 9;
1242  break;
1243  case 'a':
1244  c += 10;
1245  break;
1246  case 'b':
1247  c += 11;
1248  break;
1249  case 'c':
1250  c += 12;
1251  break;
1252  case 'd':
1253  c += 13;
1254  break;
1255  case 'e':
1256  c += 14;
1257  break;
1258  case 'f':
1259  c += 15;
1260  break;
1261  default:
1262  Assert (false, ExcInternalError());
1263  }
1264 
1265  u.push_back (static_cast<char>(c));
1266 
1267  // skip the two characters
1268  i += 2;
1269  }
1270 
1271  return u;
1272 }
1273 
1274 
1275 
1276 namespace
1277 {
1282  bool
1283  is_parameter_node (const boost::property_tree::ptree &p)
1284  {
1285  return static_cast<bool>(p.get_optional<std::string>("value"));
1286  }
1287 
1288 
1293  bool
1294  is_alias_node (const boost::property_tree::ptree &p)
1295  {
1296  return static_cast<bool>(p.get_optional<std::string>("alias"));
1297  }
1298 }
1299 
1300 
1301 std::string
1303 {
1304  if (subsection_path.size() > 0)
1305  {
1306  std::string p = mangle(subsection_path[0]);
1307  for (unsigned int i=1; i<subsection_path.size(); ++i)
1308  {
1309  p += path_separator;
1310  p += mangle(subsection_path[i]);
1311  }
1312  return p;
1313  }
1314  else
1315  return "";
1316 }
1317 
1318 
1319 
1320 std::string
1321 ParameterHandler::get_current_full_path (const std::string &name) const
1322 {
1323  std::string path = get_current_path ();
1324  if (path.empty() == false)
1325  path += path_separator;
1326 
1327  path += mangle(name);
1328 
1329  return path;
1330 }
1331 
1332 
1333 
1334 bool ParameterHandler::read_input (std::istream &input,
1335  const std::string &filename)
1336 {
1337  AssertThrow (input, ExcIO());
1338 
1339  // store subsections we are currently in
1340  std::vector<std::string> saved_path = subsection_path;
1341 
1342  std::string input_line;
1343  std::string fully_concatenated_line;
1344  bool is_concatenated = false;
1345  unsigned int current_line_n = 0;
1346  bool status = true;
1347 
1348  while (std::getline (input, input_line))
1349  {
1350  ++current_line_n;
1351  // Trim the whitespace at the ends of the line here instead of in
1352  // scan_line. This makes the continuation line logic a lot simpler.
1353  input_line = Utilities::trim (input_line);
1354 
1355  // Check whether or not the current line should be joined with the next
1356  // line before calling scan_line.
1357  if (input_line.length() != 0 &&
1358  input_line.find_last_of('\\') == input_line.length() - 1)
1359  {
1360  input_line.erase (input_line.length() - 1); // remove the last '\'
1361  is_concatenated = true;
1362 
1363  fully_concatenated_line += input_line;
1364  }
1365  // If the previous line ended in a '\' but the current did not, then we
1366  // should proceed to scan_line.
1367  else if (is_concatenated)
1368  {
1369  fully_concatenated_line += input_line;
1370  is_concatenated = false;
1371  }
1372  // Finally, if neither the previous nor current lines are continuations,
1373  // then the current input line is entirely concatenated.
1374  else
1375  {
1376  fully_concatenated_line = input_line;
1377  }
1378 
1379  if (!is_concatenated)
1380  {
1381  status &= scan_line (fully_concatenated_line, filename, current_line_n);
1382  fully_concatenated_line.clear();
1383  }
1384  }
1385 
1386  // While it does not make much sense for anyone to actually do this, allow
1387  // the last line to end in a backslash.
1388  if (is_concatenated)
1389  {
1390  status &= scan_line (fully_concatenated_line, filename, current_line_n);
1391  }
1392 
1393  if (status && (saved_path != subsection_path))
1394  {
1395  std::cerr << "Unbalanced 'subsection'/'end' in file <" << filename
1396  << ">." << std::endl;
1397  if (saved_path.size()>0)
1398  {
1399  std::cerr << "Path before loading input:" << std::endl;
1400  for (unsigned int i=0; i<saved_path.size(); ++i)
1401  std::cerr << std::setw(i*2+4) << " "
1402  << "subsection " << saved_path[i] << std::endl;
1403  }
1404  std::cerr << "Current path:" << std::endl;
1405  for (unsigned int i=0; i<subsection_path.size(); ++i)
1406  std::cerr << std::setw(i*2+4) << " "
1407  << "subsection " << subsection_path[i] << std::endl;
1408 
1409  // restore subsection we started with and return failure:
1410  subsection_path = saved_path;
1411  return false;
1412  }
1413 
1414  return status;
1415 }
1416 
1417 
1418 
1419 bool ParameterHandler::read_input (const std::string &filename,
1420  const bool optional,
1421  const bool write_compact)
1422 {
1423  PathSearch search("PARAMETERS");
1424 
1425  try
1426  {
1427  std::string openname = search.find(filename);
1428  std::ifstream file_stream (openname.c_str());
1429  AssertThrow(file_stream, ExcIO());
1430 
1431  return read_input (file_stream, filename);
1432  }
1433  catch (const PathSearch::ExcFileNotFound &)
1434  {
1435  std::cerr << "ParameterHandler::read_input: could not open file <"
1436  << filename << "> for reading." << std::endl;
1437  if (!optional)
1438  {
1439  std:: cerr << "Trying to make file <"
1440  << filename << "> with default values for you." << std::endl;
1441  std::ofstream output (filename.c_str());
1442  if (output)
1443  print_parameters (output, (write_compact ? ShortText : Text));
1444  }
1445  }
1446  return false;
1447 }
1448 
1449 
1450 
1452 {
1453  std::istringstream input_stream (s);
1454  return read_input (input_stream, "input string");
1455 }
1456 
1457 
1458 
1459 namespace
1460 {
1461  // Recursively go through the 'source' tree
1462  // and see if we can find corresponding
1463  // entries in the 'destination' tree. If
1464  // not, error out (i.e. we have just read
1465  // an XML file that has entries that
1466  // weren't declared in the ParameterHandler
1467  // object); if so, copy the value of these
1468  // nodes into the destination object
1469  bool
1470  read_xml_recursively (const boost::property_tree::ptree &source,
1471  const std::string &current_path,
1472  const char path_separator,
1473  const std::vector<std_cxx11::shared_ptr<const Patterns::PatternBase> > &
1474  patterns,
1475  boost::property_tree::ptree &destination)
1476  {
1477  for (boost::property_tree::ptree::const_iterator p = source.begin();
1478  p != source.end(); ++p)
1479  {
1480  // a sub-tree must either be a
1481  // parameter node or a subsection
1482  if (p->second.get_optional<std::string>("value"))
1483  {
1484  // make sure we have a
1485  // corresponding entry in the
1486  // destination object as well
1487  const std::string full_path
1488  = (current_path == ""
1489  ?
1490  p->first
1491  :
1492  current_path + path_separator + p->first);
1493  if (destination.get_optional<std::string> (full_path)
1494  &&
1495  destination.get_optional<std::string> (full_path +
1496  path_separator +
1497  "value"))
1498  {
1499  // first make sure that the
1500  // new entry actually
1501  // satisfies its constraints
1502  const std::string new_value
1503  = p->second.get<std::string>("value");
1504 
1505  const unsigned int pattern_index
1506  = destination.get<unsigned int> (full_path +
1507  path_separator +
1508  "pattern");
1509  if (patterns[pattern_index]->match(new_value) == false)
1510  {
1511  std::cerr << " The entry value" << std::endl
1512  << " " << new_value << std::endl
1513  << " for the entry named" << std::endl
1514  << " " << full_path << std::endl
1515  << " does not match the given pattern" << std::endl
1516  << " " << patterns[pattern_index]->description()
1517  << std::endl;
1518  return false;
1519  }
1520 
1521  // set the found parameter in
1522  // the destination argument
1523  destination.put (full_path + path_separator + "value",
1524  new_value);
1525 
1526  // this node might have
1527  // sub-nodes in addition to
1528  // "value", such as
1529  // "default_value",
1530  // "documentation", etc. we
1531  // might at some point in the
1532  // future want to make sure
1533  // that if they exist that
1534  // they match the ones in the
1535  // 'destination' tree
1536  }
1537  else
1538  {
1539  std::cerr << "The entry <" << full_path
1540  << "> with value <"
1541  << p->second.get<std::string>("value")
1542  << "> has not been declared."
1543  << std::endl;
1544  return false;
1545  }
1546  }
1547  else if (p->second.get_optional<std::string>("alias"))
1548  {
1549  // it is an alias node. alias nodes are static and
1550  // there is nothing to do here (but the same applies as
1551  // mentioned in the comment above about the static
1552  // nodes inside parameter nodes
1553  }
1554  else
1555  {
1556  // it must be a subsection
1557  const bool result
1558  = read_xml_recursively (p->second,
1559  (current_path == "" ?
1560  p->first :
1561  current_path + path_separator + p->first),
1562  path_separator,
1563  patterns,
1564  destination);
1565 
1566  // see if the recursive read
1567  // succeeded. if yes, continue,
1568  // otherwise exit now
1569  if (result == false)
1570  return false;
1571  }
1572  }
1573 
1574  return true;
1575  }
1576 }
1577 
1578 
1579 
1581 {
1582  // read the XML tree assuming that (as we
1583  // do in print_parameters(XML) it has only
1584  // a single top-level node called
1585  // "ParameterHandler"
1586  boost::property_tree::ptree single_node_tree;
1587  try
1588  {
1589  read_xml (in, single_node_tree);
1590  }
1591  catch (...)
1592  {
1593  std::cerr << "This input stream appears not to be valid XML"
1594  << std::endl;
1595  return false;
1596  }
1597 
1598  // make sure there is a top-level element
1599  // called "ParameterHandler"
1600  if (!single_node_tree.get_optional<std::string>("ParameterHandler"))
1601  {
1602  std::cerr << "There is no top-level XML element called \"ParameterHandler\"."
1603  << std::endl;
1604  return false;
1605  }
1606 
1607  // ensure that there is only a single
1608  // top-level element
1609  if (std::distance (single_node_tree.begin(), single_node_tree.end()) != 1)
1610  {
1611  std::cerr << "The top-level XML element \"ParameterHandler\" is "
1612  << "not the only one."
1613  << std::endl;
1614  std::cerr << "(There are "
1615  << std::distance (single_node_tree.begin(),
1616  single_node_tree.end())
1617  << " top-level elements.)"
1618  << std::endl;
1619  return false;
1620  }
1621 
1622  // read the child elements recursively
1623  const boost::property_tree::ptree
1624  &my_entries = single_node_tree.get_child("ParameterHandler");
1625 
1626  return read_xml_recursively (my_entries, "", path_separator, patterns,
1627  *entries);
1628 }
1629 
1630 
1631 
1633 {
1634  entries.reset (new boost::property_tree::ptree());
1635 }
1636 
1637 
1638 
1639 void
1640 ParameterHandler::declare_entry (const std::string &entry,
1641  const std::string &default_value,
1642  const Patterns::PatternBase &pattern,
1643  const std::string &documentation)
1644 {
1645  entries->put (get_current_full_path(entry) + path_separator + "value",
1646  default_value);
1647  entries->put (get_current_full_path(entry) + path_separator + "default_value",
1648  default_value);
1649  entries->put (get_current_full_path(entry) + path_separator + "documentation",
1650  documentation);
1651 
1652  // clone the pattern and store its
1653  // index in the node
1654  patterns.push_back (std_cxx11::shared_ptr<const Patterns::PatternBase>
1655  (pattern.clone()));
1656  entries->put (get_current_full_path(entry) + path_separator + "pattern",
1657  static_cast<unsigned int>(patterns.size()-1));
1658  // also store the description of
1659  // the pattern. we do so because we
1660  // may wish to export the whole
1661  // thing as XML or any other format
1662  // so that external tools can work
1663  // on the parameter file; in that
1664  // case, they will have to be able
1665  // to re-create the patterns as far
1666  // as possible
1668  "pattern_description",
1669  patterns.back()->description());
1670 
1671  // as documented, do the default value checking at the very end
1672  AssertThrow (pattern.match (default_value),
1673  ExcValueDoesNotMatchPattern (default_value, pattern.description()));
1674 }
1675 
1676 
1677 
1678 void
1679 ParameterHandler::declare_alias(const std::string &existing_entry_name,
1680  const std::string &alias_name,
1681  const bool alias_is_deprecated)
1682 {
1683  // see if there is anything to refer to already
1684  Assert (entries->get_optional<std::string>(get_current_full_path(existing_entry_name)),
1685  ExcMessage ("You are trying to declare an alias entry <"
1686  + alias_name +
1687  "> that references an entry <"
1688  + existing_entry_name +
1689  ">, but the latter does not exist."));
1690  // then also make sure that what is being referred to is in
1691  // fact a parameter (not an alias or subsection)
1692  Assert (entries->get_optional<std::string>(get_current_full_path(existing_entry_name) + path_separator + "value"),
1693  ExcMessage ("You are trying to declare an alias entry <"
1694  + alias_name +
1695  "> that references an entry <"
1696  + existing_entry_name +
1697  ">, but the latter does not seem to be a "
1698  "parameter declaration."));
1699 
1700 
1701  // now also make sure that if the alias has already been
1702  // declared, that it is also an alias and refers to the same
1703  // entry
1704  if (entries->get_optional<std::string>(get_current_full_path(alias_name)))
1705  {
1706  Assert (entries->get_optional<std::string> (get_current_full_path(alias_name) + path_separator + "alias"),
1707  ExcMessage ("You are trying to declare an alias entry <"
1708  + alias_name +
1709  "> but a non-alias entry already exists in this "
1710  "subsection (i.e., there is either a preexisting "
1711  "further subsection, or a parameter entry, with "
1712  "the same name as the alias)."));
1713  Assert (entries->get<std::string> (get_current_full_path(alias_name) + path_separator + "alias")
1714  ==
1715  existing_entry_name,
1716  ExcMessage ("You are trying to declare an alias entry <"
1717  + alias_name +
1718  "> but an alias entry already exists in this "
1719  "subsection and this existing alias references a "
1720  "different parameter entry. Specifically, "
1721  "you are trying to reference the entry <"
1722  + existing_entry_name +
1723  "> whereas the existing alias references "
1724  "the entry <"
1725  + entries->get<std::string> (get_current_full_path(alias_name) + path_separator + "alias") +
1726  ">."));
1727  }
1728 
1729  entries->put (get_current_full_path(alias_name) + path_separator + "alias",
1730  existing_entry_name);
1731  entries->put (get_current_full_path(alias_name) + path_separator + "deprecation_status",
1732  (alias_is_deprecated ? "true" : "false"));
1733 }
1734 
1735 
1736 
1737 void ParameterHandler::enter_subsection (const std::string &subsection)
1738 {
1739  const std::string current_path = get_current_path ();
1740 
1741  // if necessary create subsection
1742  if (!entries->get_child_optional (get_current_full_path(subsection)))
1743  entries->add_child (get_current_full_path(subsection),
1744  boost::property_tree::ptree());
1745 
1746  // then enter it
1747  subsection_path.push_back (subsection);
1748 }
1749 
1750 
1751 
1753 {
1754  // assert there is a subsection that
1755  // we may leave
1756  Assert (subsection_path.size() != 0, ExcAlreadyAtTopLevel());
1757 
1758  if (subsection_path.size() > 0)
1759  subsection_path.pop_back ();
1760 }
1761 
1762 
1763 
1764 std::string
1765 ParameterHandler::get (const std::string &entry_string) const
1766 {
1767  // assert that the entry is indeed
1768  // declared
1769  if (boost::optional<std::string> value
1770  = entries->get_optional<std::string> (get_current_full_path(entry_string) + path_separator + "value"))
1771  return value.get();
1772  else
1773  {
1774  Assert (false, ExcEntryUndeclared(entry_string));
1775  return "";
1776  }
1777 }
1778 
1779 
1780 
1781 long int ParameterHandler::get_integer (const std::string &entry_string) const
1782 {
1783  try
1784  {
1785  return Utilities::string_to_int (get (entry_string));
1786  }
1787  catch (...)
1788  {
1789  AssertThrow (false,
1790  ExcMessage("Can't convert the parameter value <"
1791  + get(entry_string) +
1792  "> for entry <"
1793  + entry_string +
1794  " to an integer."));
1795  return 0;
1796  }
1797 }
1798 
1799 
1800 
1801 double ParameterHandler::get_double (const std::string &entry_string) const
1802 {
1803  try
1804  {
1805  return Utilities::string_to_double (get (entry_string));
1806  }
1807  catch (...)
1808  {
1809  AssertThrow (false,
1810  ExcMessage("Can't convert the parameter value <"
1811  + get(entry_string) +
1812  "> for entry <"
1813  + entry_string +
1814  " to a double precision variable."));
1815  return 0;
1816  }
1817 }
1818 
1819 
1820 
1821 bool ParameterHandler::get_bool (const std::string &entry_string) const
1822 {
1823  const std::string s = get(entry_string);
1824 
1825  AssertThrow ((s=="true") || (s=="false") ||
1826  (s=="yes") || (s=="no"),
1827  ExcMessage("Can't convert the parameter value <"
1828  + get(entry_string) +
1829  "> for entry <"
1830  + entry_string +
1831  " to a boolean."));
1832  if (s=="true" || s=="yes")
1833  return true;
1834  else
1835  return false;
1836 }
1837 
1838 
1839 
1840 void
1841 ParameterHandler::set (const std::string &entry_string,
1842  const std::string &new_value)
1843 {
1844  // resolve aliases before looking up the correct entry
1845  std::string path = get_current_full_path(entry_string);
1846  if (entries->get_optional<std::string>(path + path_separator + "alias"))
1847  path = get_current_full_path(entries->get<std::string>(path + path_separator + "alias"));
1848 
1849  // assert that the entry is indeed declared
1850  if (entries->get_optional<std::string>(path + path_separator + "value"))
1851  {
1852  const unsigned int pattern_index
1853  = entries->get<unsigned int> (path + path_separator + "pattern");
1854  AssertThrow (patterns[pattern_index]->match(new_value),
1855  ExcValueDoesNotMatchPattern (new_value,
1856  entries->get<std::string>
1857  (path +
1858  path_separator +
1859  "pattern_description")));
1860 
1861  entries->put (path + path_separator + "value",
1862  new_value);
1863  }
1864  else
1865  AssertThrow (false, ExcEntryUndeclared(entry_string));
1866 }
1867 
1868 
1869 void
1870 ParameterHandler::set (const std::string &entry_string,
1871  const char *new_value)
1872 {
1873  // simply forward
1874  set (entry_string, std::string(new_value));
1875 }
1876 
1877 
1878 void
1879 ParameterHandler::set (const std::string &entry_string,
1880  const double &new_value)
1881 {
1882  std::ostringstream s;
1883  s << std::setprecision(16);
1884  s << new_value;
1885 
1886  // hand this off to the function that
1887  // actually sets the value as a string
1888  set (entry_string, s.str());
1889 }
1890 
1891 
1892 
1893 void
1894 ParameterHandler::set (const std::string &entry_string,
1895  const long int &new_value)
1896 {
1897  std::ostringstream s;
1898  s << new_value;
1899 
1900  // hand this off to the function that
1901  // actually sets the value as a string
1902  set (entry_string, s.str());
1903 }
1904 
1905 
1906 
1907 void
1908 ParameterHandler::set (const std::string &entry_string,
1909  const bool &new_value)
1910 {
1911  // hand this off to the function that
1912  // actually sets the value as a string
1913  set (entry_string,
1914  (new_value ? "true" : "false"));
1915 }
1916 
1917 
1918 
1919 std::ostream &
1921  const OutputStyle style)
1922 {
1923  AssertThrow (out, ExcIO());
1924 
1925  switch (style)
1926  {
1927  case XML:
1928  {
1929  // call the writer
1930  // function and exit as
1931  // there is nothing
1932  // further to do down in
1933  // this function
1934  //
1935  // XML has a requirement that
1936  // there can only be one
1937  // single top-level entry,
1938  // but we may have multiple
1939  // entries and sections. we
1940  // work around this by
1941  // creating a tree just for
1942  // this purpose with the
1943  // single top-level node
1944  // "ParameterHandler" and
1945  // assign the existing tree
1946  // under it
1947  boost::property_tree::ptree single_node_tree;
1948  single_node_tree.add_child("ParameterHandler",
1949  *entries);
1950 
1951  write_xml (out, single_node_tree);
1952  return out;
1953  }
1954 
1955 
1956  case JSON:
1957  // call the writer
1958  // function and exit as
1959  // there is nothing
1960  // further to do down in
1961  // this function
1962  write_json (out, *entries);
1963  return out;
1964 
1965  case Text:
1966  out << "# Listing of Parameters" << std::endl
1967  << "# ---------------------" << std::endl;
1968  break;
1969  case LaTeX:
1970  out << "\\subsection{Global parameters}" << std::endl;
1971  out << "\\label{parameters:global}" << std::endl;
1972  out << std::endl << std::endl;
1973  break;
1974  case Description:
1975  out << "Listing of Parameters:" << std::endl << std::endl;
1976  break;
1977  case ShortText:
1978  break;
1979  default:
1980  Assert (false, ExcNotImplemented());
1981  };
1982 
1983  // dive recursively into the subsections
1984  print_parameters_section (out, style, 0);
1985 
1986  switch (style)
1987  {
1988  case Text:
1989  case Description:
1990  case ShortText:
1991  break;
1992  case LaTeX:
1993  break;
1994  default:
1995  Assert (false, ExcNotImplemented());
1996  };
1997 
1998  return out;
1999 }
2000 
2001 
2002 
2003 // Print a section in the desired style. The styles are separated into
2004 // several verbosity classes depending on the higher bits.
2005 //
2006 // If bit 7 (128) is set, comments are not printed.
2007 // If bit 6 (64) is set, default values after change are not printed.
2008 void
2010  const OutputStyle style,
2011  const unsigned int indent_level,
2012  const bool include_top_level_elements)
2013 {
2014  AssertThrow (out, ExcIO());
2015 
2016  const boost::property_tree::ptree &current_section
2017  = entries->get_child (get_current_path());
2018 
2019  unsigned int overall_indent_level = indent_level;
2020 
2021  switch (style)
2022  {
2023  case XML:
2024  {
2025  if (include_top_level_elements)
2026  {
2027  // call the writer
2028  // function and exit as
2029  // there is nothing
2030  // further to do down in
2031  // this function
2032  //
2033  // XML has a requirement that
2034  // there can only be one
2035  // single top-level entry,
2036  // but a section has multiple
2037  // entries and sections. we
2038  // work around this by
2039  // creating a tree just for
2040  // this purpose with the
2041  // single top-level node
2042  // "ParameterHandler" and
2043  // assign the full path of
2044  // down to the current section
2045  // under it
2046  boost::property_tree::ptree single_node_tree;
2047 
2048  // if there is no subsection selected,
2049  // add the whole tree of entries,
2050  // otherwise add a root element
2051  // and the selected subsection under it
2052  if (subsection_path.size() == 0)
2053  {
2054  single_node_tree.add_child("ParameterHandler",
2055  *entries);
2056  }
2057  else
2058  {
2059  std::string path ("ParameterHandler");
2060 
2061  single_node_tree.add_child(path,
2062  boost::property_tree::ptree());
2063 
2064  path += path_separator + get_current_path ();
2065  single_node_tree.add_child (path, current_section);
2066  };
2067 
2068  write_xml (out, single_node_tree);
2069  }
2070  else
2071  Assert (false, ExcNotImplemented());
2072 
2073  break;
2074  }
2075  case Text:
2076  case ShortText:
2077  {
2078  // if there are top level elements to print, do it
2079  if (include_top_level_elements && (subsection_path.size() > 0))
2080  for (unsigned int i=0; i<subsection_path.size(); ++i)
2081  {
2082  out << std::setw(overall_indent_level*2) << ""
2083  << "subsection " << demangle (subsection_path[i]) << std::endl;
2084  overall_indent_level += 1;
2085  };
2086 
2087  // first find out the longest
2088  // entry name to be able to
2089  // align the equal signs
2090  //
2091  // to do this loop over all
2092  // nodes of the current tree,
2093  // select the parameter nodes
2094  // (and discard sub-tree
2095  // nodes) and take the
2096  // maximum of their lengths
2097  std::size_t longest_name = 0;
2098  for (boost::property_tree::ptree::const_iterator
2099  p = current_section.begin();
2100  p != current_section.end(); ++p)
2101  if (is_parameter_node (p->second) == true)
2102  longest_name = std::max (longest_name,
2103  demangle(p->first).length());
2104 
2105  // likewise find the longest
2106  // actual value string to
2107  // make sure we can align the
2108  // default and documentation
2109  // strings
2110  std::size_t longest_value = 0;
2111  for (boost::property_tree::ptree::const_iterator
2112  p = current_section.begin();
2113  p != current_section.end(); ++p)
2114  if (is_parameter_node (p->second) == true)
2115  longest_value = std::max (longest_value,
2116  p->second.get<std::string>("value").length());
2117 
2118 
2119  // print entries one by
2120  // one. make sure they are
2121  // sorted by using the
2122  // appropriate iterators
2123  bool first_entry = true;
2124  for (boost::property_tree::ptree::const_assoc_iterator
2125  p = current_section.ordered_begin();
2126  p != current_section.not_found(); ++p)
2127  if (is_parameter_node (p->second) == true)
2128  {
2129  const std::string value = p->second.get<std::string>("value");
2130 
2131  // if there is documentation,
2132  // then add an empty line (unless
2133  // this is the first entry in a
2134  // subsection), print the
2135  // documentation, and then the
2136  // actual entry; break the
2137  // documentation into readable
2138  // chunks such that the whole
2139  // thing is at most 78 characters
2140  // wide
2141  if ((!(style & 128)) &&
2142  !p->second.get<std::string>("documentation").empty())
2143  {
2144  if (first_entry == false)
2145  out << std::endl;
2146  else
2147  first_entry = false;
2148 
2149  const std::vector<std::string> doc_lines
2150  = Utilities::
2151  break_text_into_lines (p->second.get<std::string>("documentation"),
2152  78 - overall_indent_level*2 - 2);
2153 
2154  for (unsigned int i=0; i<doc_lines.size(); ++i)
2155  out << std::setw(overall_indent_level*2) << ""
2156  << "# "
2157  << doc_lines[i]
2158  << std::endl;
2159  }
2160 
2161 
2162 
2163  // print name and value
2164  // of this entry
2165  out << std::setw(overall_indent_level*2) << ""
2166  << "set "
2167  << demangle(p->first)
2168  << std::setw(longest_name-demangle(p->first).length()+1) << " "
2169  << "= " << value;
2170 
2171  // finally print the
2172  // default value, but
2173  // only if it differs
2174  // from the actual value
2175  if ((!(style & 64)) && value != p->second.get<std::string>("default_value"))
2176  {
2177  out << std::setw(longest_value-value.length()+1) << ' '
2178  << "# ";
2179  out << "default: " << p->second.get<std::string>("default_value");
2180  }
2181 
2182  out << std::endl;
2183  }
2184 
2185  break;
2186  }
2187 
2188  case LaTeX:
2189  {
2190  // if there are any parameters in
2191  // this section then print them as an
2192  // itemized list
2193  bool parameters_exist_here = false;
2194  for (boost::property_tree::ptree::const_assoc_iterator
2195  p = current_section.ordered_begin();
2196  p != current_section.not_found(); ++p)
2197  if ((is_parameter_node (p->second) == true)
2198  ||
2199  (is_alias_node (p->second) == true))
2200  {
2201  parameters_exist_here = true;
2202  break;
2203  }
2204 
2205  if (parameters_exist_here)
2206  {
2207  out << "\\begin{itemize}"
2208  << std::endl;
2209 
2210  // print entries one by
2211  // one. make sure they are
2212  // sorted by using the
2213  // appropriate iterators
2214  for (boost::property_tree::ptree::const_assoc_iterator
2215  p = current_section.ordered_begin();
2216  p != current_section.not_found(); ++p)
2217  if (is_parameter_node (p->second) == true)
2218  {
2219  const std::string value = p->second.get<std::string>("value");
2220 
2221  // print name
2222  out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n"
2223  << "\\phantomsection\\label{parameters:";
2224  for (unsigned int i=0; i<subsection_path.size(); ++i)
2225  out << subsection_path[i] << "/";
2226  out << demangle(p->first);
2227  out << "}\n\n"
2228  << std::endl;
2229 
2230  out << "\\index[prmindex]{"
2231  << demangle(p->first)
2232  << "}\n";
2233  out << "\\index[prmindexfull]{";
2234  for (unsigned int i=0; i<subsection_path.size(); ++i)
2235  out << subsection_path[i] << "!";
2236  out << demangle(p->first)
2237  << "}\n";
2238 
2239  // finally print value and default
2240  out << "{\\it Value:} " << value << "\n\n"
2241  << std::endl
2242  << "{\\it Default:} "
2243  << p->second.get<std::string>("default_value") << "\n\n"
2244  << std::endl;
2245 
2246  // if there is a
2247  // documenting string,
2248  // print it as well
2249  if (!p->second.get<std::string>("documentation").empty())
2250  out << "{\\it Description:} "
2251  << p->second.get<std::string>("documentation") << "\n\n"
2252  << std::endl;
2253 
2254  // also output possible values
2255  out << "{\\it Possible values:} "
2256  << p->second.get<std::string> ("pattern_description")
2257  << std::endl;
2258  }
2259  else if (is_alias_node (p->second) == true)
2260  {
2261  const std::string alias = p->second.get<std::string>("alias");
2262 
2263  // print name
2264  out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n"
2265  << "\\phantomsection\\label{parameters:";
2266  for (unsigned int i=0; i<subsection_path.size(); ++i)
2267  out << subsection_path[i] << "/";
2268  out << demangle(p->first);
2269  out << "}\n\n"
2270  << std::endl;
2271 
2272  out << "\\index[prmindex]{"
2273  << demangle(p->first)
2274  << "}\n";
2275  out << "\\index[prmindexfull]{";
2276  for (unsigned int i=0; i<subsection_path.size(); ++i)
2277  out << subsection_path[i] << "!";
2278  out << demangle(p->first)
2279  << "}\n";
2280 
2281  // finally print alias and indicate if it is deprecated
2282  out << "This parameter is an alias for the parameter ``\\texttt{"
2283  << alias << "}''."
2284  << (p->second.get<std::string>("deprecation_status") == "true"
2285  ?
2286  " Its use is deprecated."
2287  :
2288  "")
2289  << "\n\n"
2290  << std::endl;
2291  }
2292  out << "\\end{itemize}" << std::endl;
2293  }
2294 
2295  break;
2296  }
2297 
2298  case Description:
2299  {
2300  // if there are top level elements to print, do it
2301  if (include_top_level_elements && (subsection_path.size() > 0))
2302  for (unsigned int i=0; i<subsection_path.size(); ++i)
2303  {
2304  out << std::setw(overall_indent_level*2) << ""
2305  << "subsection " << demangle (subsection_path[i]) << std::endl;
2306  overall_indent_level += 1;
2307  };
2308 
2309  // first find out the longest
2310  // entry name to be able to
2311  // align the equal signs
2312  std::size_t longest_name = 0;
2313  for (boost::property_tree::ptree::const_iterator
2314  p = current_section.begin();
2315  p != current_section.end(); ++p)
2316  if (is_parameter_node (p->second) == true)
2317  longest_name = std::max (longest_name,
2318  demangle(p->first).length());
2319 
2320  // print entries one by
2321  // one. make sure they are
2322  // sorted by using the
2323  // appropriate iterators
2324  for (boost::property_tree::ptree::const_assoc_iterator
2325  p = current_section.ordered_begin();
2326  p != current_section.not_found(); ++p)
2327  if (is_parameter_node (p->second) == true)
2328  {
2329  const std::string value = p->second.get<std::string>("value");
2330 
2331  // print name and value
2332  out << std::setw(overall_indent_level*2) << ""
2333  << "set "
2334  << demangle(p->first)
2335  << std::setw(longest_name-demangle(p->first).length()+1) << " "
2336  << " = ";
2337 
2338  // print possible values:
2339  const std::vector<std::string> description_str
2340  = Utilities::break_text_into_lines (p->second.get<std::string>
2341  ("pattern_description"),
2342  78 - overall_indent_level*2 - 2, '|');
2343  if (description_str.size() > 1)
2344  {
2345  out << std::endl;
2346  for (unsigned int i=0; i<description_str.size(); ++i)
2347  out << std::setw(overall_indent_level*2+6) << ""
2348  << description_str[i] << std::endl;
2349  }
2350  else if (description_str.empty() == false)
2351  out << " " << description_str[0] << std::endl;
2352  else
2353  out << std::endl;
2354 
2355  // if there is a
2356  // documenting string,
2357  // print it as well
2358  if (p->second.get<std::string>("documentation").length() != 0)
2359  out << std::setw(overall_indent_level*2 + longest_name + 10) << ""
2360  << "(" << p->second.get<std::string>("documentation") << ")" << std::endl;
2361  }
2362 
2363  break;
2364  }
2365 
2366  default:
2367  Assert (false, ExcNotImplemented());
2368  }
2369 
2370 
2371  // if there was text before and there are
2372  // sections to come, put two newlines
2373  // between the last entry and the first
2374  // subsection
2375  if (style != XML)
2376  {
2377  unsigned int n_parameters = 0;
2378  unsigned int n_sections = 0;
2379  for (boost::property_tree::ptree::const_iterator
2380  p = current_section.begin();
2381  p != current_section.end(); ++p)
2382  if (is_parameter_node (p->second) == true)
2383  ++n_parameters;
2384  else if (is_alias_node (p->second) == false)
2385  ++n_sections;
2386 
2387  if ((style != Description)
2388  &&
2389  (!(style & 128))
2390  &&
2391  (n_parameters != 0)
2392  &&
2393  (n_sections != 0))
2394  out << std::endl << std::endl;
2395 
2396  // now traverse subsections tree,
2397  // in alphabetical order
2398  for (boost::property_tree::ptree::const_assoc_iterator
2399  p = current_section.ordered_begin();
2400  p != current_section.not_found(); ++p)
2401  if ((is_parameter_node (p->second) == false)
2402  &&
2403  (is_alias_node (p->second) == false))
2404  {
2405  // first print the subsection header
2406  switch (style)
2407  {
2408  case Text:
2409  case Description:
2410  case ShortText:
2411  out << std::setw(overall_indent_level*2) << ""
2412  << "subsection " << demangle(p->first) << std::endl;
2413  break;
2414  case LaTeX:
2415  {
2416  out << std::endl
2417  << "\\subsection{Parameters in section \\tt ";
2418 
2419  // find the path to the
2420  // current section so that we
2421  // can print it in the
2422  // \subsection{...} heading
2423  for (unsigned int i=0; i<subsection_path.size(); ++i)
2424  out << subsection_path[i] << "/";
2425  out << demangle(p->first);
2426 
2427  out << "}" << std::endl;
2428  out << "\\label{parameters:";
2429  for (unsigned int i=0; i<subsection_path.size(); ++i)
2430  out << mangle(subsection_path[i]) << "/";
2431  out << p->first << "}";
2432  out << std::endl;
2433 
2434  out << std::endl;
2435  break;
2436  }
2437 
2438  default:
2439  Assert (false, ExcNotImplemented());
2440  };
2441 
2442  // then the contents of the
2443  // subsection
2444  enter_subsection (demangle(p->first));
2445  print_parameters_section (out, style, overall_indent_level+1);
2446  leave_subsection ();
2447  switch (style)
2448  {
2449  case Text:
2450  // write end of
2451  // subsection. one
2452  // blank line after
2453  // each subsection
2454  out << std::setw(overall_indent_level*2) << ""
2455  << "end" << std::endl
2456  << std::endl;
2457 
2458  // if this is a toplevel
2459  // subsection, then have two
2460  // newlines
2461  if (overall_indent_level == 0)
2462  out << std::endl;
2463 
2464  break;
2465  case Description:
2466  break;
2467  case ShortText:
2468  // write end of
2469  // subsection.
2470  out << std::setw(overall_indent_level*2) << ""
2471  << "end" << std::endl;
2472  break;
2473  case LaTeX:
2474  break;
2475  default:
2476  Assert (false, ExcNotImplemented());
2477  }
2478  }
2479  }
2480 
2481  // close top level elements, if there are any
2482  switch (style)
2483  {
2484  case XML:
2485  case LaTeX:
2486  case Description:
2487  break;
2488  case Text:
2489  case ShortText:
2490  {
2491  if (include_top_level_elements && (subsection_path.size() > 0))
2492  for (unsigned int i=0; i<subsection_path.size(); ++i)
2493  {
2494  overall_indent_level -= 1;
2495  out << std::setw(overall_indent_level*2) << ""
2496  << "end" << std::endl;
2497  };
2498 
2499  break;
2500  }
2501 
2502  default:
2503  Assert (false, ExcNotImplemented());
2504  }
2505 
2506 }
2507 
2508 
2509 
2510 void
2512 {
2513  out.push("parameters");
2514  // dive recursively into the
2515  // subsections
2516  log_parameters_section (out);
2517 
2518  out.pop();
2519 }
2520 
2521 
2522 
2523 void
2525 {
2526  const boost::property_tree::ptree &current_section
2527  = entries->get_child (get_current_path());
2528 
2529  // print entries one by
2530  // one. make sure they are
2531  // sorted by using the
2532  // appropriate iterators
2533  for (boost::property_tree::ptree::const_assoc_iterator
2534  p = current_section.ordered_begin();
2535  p != current_section.not_found(); ++p)
2536  if (is_parameter_node (p->second) == true)
2537  out << demangle(p->first) << ": "
2538  << p->second.get<std::string>("value") << std::endl;
2539 
2540  // now transverse subsections tree
2541  // now traverse subsections tree,
2542  // in alphabetical order
2543  for (boost::property_tree::ptree::const_assoc_iterator
2544  p = current_section.ordered_begin();
2545  p != current_section.not_found(); ++p)
2546  if (is_parameter_node (p->second) == false)
2547  {
2548  out.push (demangle(p->first));
2549  enter_subsection (demangle(p->first));
2550  log_parameters_section (out);
2551  leave_subsection ();
2552  out.pop ();
2553  }
2554 }
2555 
2556 
2557 
2558 bool
2560  const std::string &input_filename,
2561  const unsigned int current_line_n)
2562 {
2563  // if there is a comment, delete it
2564  if (line.find('#') != std::string::npos)
2565  line.erase (line.find("#"), std::string::npos);
2566 
2567  // replace \t by space:
2568  while (line.find('\t') != std::string::npos)
2569  line.replace (line.find('\t'), 1, " ");
2570 
2571  //trim start and end:
2572  line = Utilities::trim(line);
2573 
2574  // if line is now empty: leave
2575  if (line.length() == 0)
2576  return true;
2577 
2578  // enter subsection
2579  if ((line.find ("SUBSECTION ") == 0) ||
2580  (line.find ("subsection ") == 0))
2581  {
2582  // delete this prefix
2583  line.erase (0, std::string("subsection").length()+1);
2584 
2585  const std::string subsection = Utilities::trim(line);
2586 
2587  // check whether subsection exists
2588  if (!entries->get_child_optional (get_current_full_path(subsection)))
2589  {
2590  std::cerr << "Line <" << current_line_n
2591  << "> of file <" << input_filename
2592  << ">: There is no such subsection to be entered: "
2593  << demangle(get_current_full_path(subsection)) << std::endl;
2594  for (unsigned int i=0; i<subsection_path.size(); ++i)
2595  std::cerr << std::setw(i*2+4) << " "
2596  << "subsection " << subsection_path[i] << std::endl;
2597  std::cerr << std::setw(subsection_path.size()*2+4) << " "
2598  << "subsection " << subsection << std::endl;
2599  return false;
2600  }
2601 
2602  // subsection exists
2603  subsection_path.push_back (subsection);
2604  return true;
2605  }
2606 
2607  // exit subsection
2608  if ((line.find ("END") == 0) ||
2609  (line.find ("end") == 0))
2610  {
2611  line.erase (0, 3);
2612  while ((line.size() > 0) && (std::isspace(line[0])))
2613  line.erase (0, 1);
2614 
2615  if (line.size()>0)
2616  {
2617  std::cerr << "Line <" << current_line_n
2618  << "> of file <" << input_filename
2619  << ">: invalid content after 'end'!" << std::endl;
2620  return false;
2621  }
2622 
2623  if (subsection_path.size() == 0)
2624  {
2625  std::cerr << "Line <" << current_line_n
2626  << "> of file <" << input_filename
2627  << ">: There is no subsection to leave here!" << std::endl;
2628  return false;
2629  }
2630  else
2631  {
2632  leave_subsection ();
2633  return true;
2634  }
2635 
2636  }
2637 
2638  // regular entry
2639  if ((line.find ("SET ") == 0) ||
2640  (line.find ("set ") == 0))
2641  {
2642  // erase "set" statement
2643  line.erase (0, 4);
2644 
2645  std::string::size_type pos = line.find("=");
2646  if (pos == std::string::npos)
2647  {
2648  std::cerr << "Line <" << current_line_n
2649  << "> of file <" << input_filename
2650  << ">: invalid format of set expression!" << std::endl;
2651  return false;
2652  }
2653 
2654  // extract entry name and value and trim
2655  std::string entry_name = Utilities::trim(std::string(line, 0, pos));
2656  std::string entry_value = Utilities::trim(std::string(line, pos+1, std::string::npos));
2657 
2658  // resolve aliases before we look up the entry. if necessary, print
2659  // a warning that the alias is deprecated
2660  std::string path = get_current_full_path(entry_name);
2661  if (entries->get_optional<std::string>(path + path_separator + "alias"))
2662  {
2663  if (entries->get<std::string>(path + path_separator + "deprecation_status") == "true")
2664  {
2665  std::cerr << "Warning in line <" << current_line_n
2666  << "> of file <" << input_filename
2667  << ">: You are using the deprecated spelling <"
2668  << entry_name
2669  << "> of the parameter <"
2670  << entries->get<std::string>(path + path_separator + "alias")
2671  << ">." << std::endl;
2672  }
2673  path = get_current_full_path(entries->get<std::string>(path + path_separator + "alias"));
2674  }
2675 
2676  // assert that the entry is indeed declared
2677  if (entries->get_optional<std::string> (path + path_separator + "value"))
2678  {
2679  // if entry was declared:
2680  // does it match the regex? if not,
2681  // don't enter it into the database
2682  // exception: if it contains characters
2683  // which specify it as a multiple loop
2684  // entry, then ignore content
2685  if (entry_value.find ('{') == std::string::npos)
2686  {
2687  const unsigned int pattern_index
2688  = entries->get<unsigned int> (path + path_separator + "pattern");
2689  if (!patterns[pattern_index]->match(entry_value))
2690  {
2691  std::cerr << "Line <" << current_line_n
2692  << "> of file <" << input_filename
2693  << ">:" << std::endl
2694  << " The entry value" << std::endl
2695  << " " << entry_value << std::endl
2696  << " for the entry named" << std::endl
2697  << " " << entry_name << std::endl
2698  << " does not match the given pattern" << std::endl
2699  << " " << patterns[pattern_index]->description()
2700  << std::endl;
2701  return false;
2702  }
2703  }
2704 
2705  entries->put (path + path_separator + "value",
2706  entry_value);
2707  return true;
2708  }
2709  else
2710  {
2711  std::cerr << "Line <" << current_line_n
2712  << "> of file <" << input_filename
2713  << ">: No such entry was declared:" << std::endl
2714  << " " << entry_name << std::endl
2715  << " <Present subsection:" << std::endl;
2716  for (unsigned int i=0; i<subsection_path.size(); ++i)
2717  std::cerr << std::setw(i*2+8) << " "
2718  << "subsection " << subsection_path[i] << std::endl;
2719  std::cerr << " >" << std::endl;
2720 
2721  return false;
2722  }
2723  }
2724 
2725  // an include statement?
2726  if ((line.find ("INCLUDE ") == 0) ||
2727  (line.find ("include ") == 0))
2728  {
2729  // erase "include " statement and eliminate spaces
2730  line.erase (0, 7);
2731  while ((line.size() > 0) && (line[0] == ' '))
2732  line.erase (0, 1);
2733 
2734  // the remainder must then be a filename
2735  if (line.size() == 0)
2736  {
2737  std::cerr << "Line <" << current_line_n
2738  << "> of file <" << input_filename
2739  << "> is an include statement but does not name a file!"
2740  << std::endl;
2741 
2742  return false;
2743  }
2744 
2745  std::ifstream input (line.c_str());
2746  if (!input)
2747  {
2748  std::cerr << "Line <" << current_line_n
2749  << "> of file <" << input_filename
2750  << "> is an include statement but the file <"
2751  << line << "> could not be opened!"
2752  << std::endl;
2753 
2754  return false;
2755  }
2756  else
2757  return read_input (input);
2758  }
2759 
2760  // this line matched nothing known
2761  std::cerr << "Line <" << current_line_n
2762  << "> of file <" << input_filename
2763  << ">: This line matched nothing known ('set' or 'subsection' missing!?):" << std::endl
2764  << " " << line << std::endl;
2765  return false;
2766 }
2767 
2768 
2769 
2770 std::size_t
2772 {
2773 //TODO: add to this an estimate of the memory in the property_tree
2775 }
2776 
2777 
2778 
2779 bool
2781 {
2782  if (patterns.size() != prm2.patterns.size())
2783  return false;
2784 
2785  for (unsigned int j=0; j<patterns.size(); ++j)
2786  if (patterns[j]->description() != prm2.patterns[j]->description())
2787  return false;
2788 
2789  // instead of walking through all
2790  // the nodes of the two trees
2791  // entries and prm2.entries and
2792  // comparing them for equality,
2793  // simply dump the content of the
2794  // entire structure into a string
2795  // and compare those for equality
2796  std::ostringstream o1, o2;
2797  write_json (o1, *entries);
2798  write_json (o2, *prm2.entries);
2799  return (o1.str() == o2.str());
2800 }
2801 
2802 
2803 
2804 
2806 {}
2807 
2808 
2809 
2811  :
2812  n_branches(0)
2813 {}
2814 
2815 
2816 
2818 {}
2819 
2820 
2821 
2822 bool MultipleParameterLoop::read_input (std::istream &input,
2823  const std::string &filename)
2824 {
2825  AssertThrow (input, ExcIO());
2826 
2827  bool x = ParameterHandler::read_input (input, filename);
2828  if (x)
2829  init_branches ();
2830  return x;
2831 }
2832 
2833 
2834 
2836 {
2837  for (unsigned int run_no=0; run_no<n_branches; ++run_no)
2838  {
2839  // give create_new one-based numbers
2840  uc.create_new (run_no+1);
2841  fill_entry_values (run_no);
2842  uc.run (*this);
2843  };
2844 }
2845 
2846 
2847 
2849 {
2850  multiple_choices.clear ();
2852 
2853  // split up different values
2854  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2855  multiple_choices[i].split_different_values ();
2856 
2857  // finally calculate number of branches
2858  n_branches = 1;
2859  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2860  if (multiple_choices[i].type == Entry::variant)
2861  n_branches *= multiple_choices[i].different_values.size();
2862 
2863  // check whether array entries have the correct
2864  // number of entries
2865  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2866  if (multiple_choices[i].type == Entry::array)
2867  if (multiple_choices[i].different_values.size() != n_branches)
2868  std::cerr << " The entry value" << std::endl
2869  << " " << multiple_choices[i].entry_value << std::endl
2870  << " for the entry named" << std::endl
2871  << " " << multiple_choices[i].entry_name << std::endl
2872  << " does not have the right number of entries for the " << std::endl
2873  << " " << n_branches << " variant runs that will be performed."
2874  << std::endl;
2875 
2876 
2877  // do a first run on filling the values to
2878  // check for the conformance with the regexp
2879  // (later on, this will be lost in the whole
2880  // other output)
2881  for (unsigned int i=0; i<n_branches; ++i)
2882  fill_entry_values (i);
2883 }
2884 
2885 
2886 
2888 {
2889  const boost::property_tree::ptree &current_section
2890  = entries->get_child (get_current_path());
2891 
2892  // check all entries in the present
2893  // subsection whether they are
2894  // multiple entries
2895  //
2896  // we loop over entries in sorted
2897  // order to guarantee backward
2898  // compatibility to an earlier
2899  // implementation
2900  for (boost::property_tree::ptree::const_assoc_iterator
2901  p = current_section.ordered_begin();
2902  p != current_section.not_found(); ++p)
2903  if (is_parameter_node (p->second) == true)
2904  {
2905  const std::string value = p->second.get<std::string>("value");
2906  if (value.find('{') != std::string::npos)
2908  demangle(p->first),
2909  value));
2910  }
2911 
2912  // then loop over all subsections
2913  for (boost::property_tree::ptree::const_iterator
2914  p = current_section.begin();
2915  p != current_section.end(); ++p)
2916  if (is_parameter_node (p->second) == false)
2917  {
2918  enter_subsection (demangle(p->first));
2920  leave_subsection ();
2921  }
2922 }
2923 
2924 
2925 
2926 
2927 void MultipleParameterLoop::fill_entry_values (const unsigned int run_no)
2928 {
2929  unsigned int possibilities = 1;
2930 
2931  std::vector<Entry>::iterator choice;
2932  for (choice = multiple_choices.begin();
2933  choice != multiple_choices.end();
2934  ++choice)
2935  {
2936  const unsigned int selection
2937  = (run_no/possibilities) % choice->different_values.size();
2938  std::string entry_value;
2939  if (choice->type == Entry::variant)
2940  entry_value = choice->different_values[selection];
2941  else
2942  {
2943  if (run_no>=choice->different_values.size())
2944  {
2945  std::cerr << "The given array for entry <"
2946  << choice->entry_name
2947  << "> does not contain enough elements! Taking empty string instead."
2948  << std::endl;
2949  entry_value = "";
2950  }
2951  else
2952  entry_value = choice->different_values[run_no];
2953  }
2954 
2955  // temporarily enter the
2956  // subsection tree of this
2957  // multiple entry, set the
2958  // value, and get out
2959  // again. the set() operation
2960  // also tests for the
2961  // correctness of the value
2962  // with regard to the pattern
2963  subsection_path.swap (choice->subsection_path);
2964  set (choice->entry_name, entry_value);
2965  subsection_path.swap (choice->subsection_path);
2966 
2967  // move ahead if it was a variant entry
2968  if (choice->type == Entry::variant)
2969  possibilities *= choice->different_values.size();
2970  }
2971 }
2972 
2973 
2974 
2975 
2976 std::size_t
2978 {
2979  std::size_t mem = ParameterHandler::memory_consumption ();
2980  for (unsigned int i=0; i<multiple_choices.size(); ++i)
2981  mem += multiple_choices[i].memory_consumption ();
2982 
2983  return mem;
2984 }
2985 
2986 
2987 
2988 MultipleParameterLoop::Entry::Entry (const std::vector<std::string> &ssp,
2989  const std::string &Name,
2990  const std::string &Value)
2991  :
2992  subsection_path (ssp), entry_name(Name), entry_value(Value), type (Entry::array)
2993 {}
2994 
2995 
2996 
2998 {
2999  // split string into three parts:
3000  // part before the opening "{",
3001  // the selection itself, final
3002  // part after "}"
3003  std::string prefix (entry_value, 0, entry_value.find('{'));
3004  std::string multiple(entry_value, entry_value.find('{')+1,
3005  entry_value.rfind('}')-entry_value.find('{')-1);
3006  std::string postfix (entry_value, entry_value.rfind('}')+1, std::string::npos);
3007  // if array entry {{..}}: delete inner
3008  // pair of braces
3009  if (multiple[0]=='{')
3010  multiple.erase (0,1);
3011  if (multiple[multiple.size()-1] == '}')
3012  multiple.erase (multiple.size()-1, 1);
3013  // erase leading and trailing spaces
3014  // in multiple
3015  while (std::isspace (multiple[0])) multiple.erase (0,1);
3016  while (std::isspace (multiple[multiple.size()-1])) multiple.erase (multiple.size()-1,1);
3017 
3018  // delete spaces around '|'
3019  while (multiple.find(" |") != std::string::npos)
3020  multiple.replace (multiple.find(" |"), 2, "|");
3021  while (multiple.find("| ") != std::string::npos)
3022  multiple.replace (multiple.find("| "), 2, "|");
3023 
3024  while (multiple.find('|') != std::string::npos)
3025  {
3026  different_values.push_back (prefix +
3027  std::string(multiple, 0, multiple.find('|'))+
3028  postfix);
3029  multiple.erase (0, multiple.find('|')+1);
3030  };
3031  // make up the last selection ("while" broke
3032  // because there was no '|' any more
3033  different_values.push_back (prefix+multiple+postfix);
3034  // finally check whether this was a variant
3035  // entry ({...}) or an array ({{...}})
3036  if ((entry_value.find("{{") != std::string::npos) &&
3037  (entry_value.find("}}") != std::string::npos))
3038  type = Entry::array;
3039  else
3040  type = Entry::variant;
3041 }
3042 
3043 
3044 std::size_t
3046 {
3051  sizeof (type));
3052 }
3053 
3054 DEAL_II_NAMESPACE_CLOSE
std::vector< Entry > multiple_choices
std::size_t memory_consumption() const
long int get_integer(const std::string &entry_string) const
virtual bool match(const std::string &test_string) const
void pop()
Definition: logstream.cc:300
static const char path_separator
PatternBase * key_pattern
virtual bool match(const std::string &test_string) const
const double upper_bound
virtual std::string description() const
static const char * description_init
void loop(UserClass &uc)
static const char * description_init
virtual std::string description() const
virtual void run(ParameterHandler &prm)=0
std::string get_current_path() const
virtual bool match(const std::string &test_string) const
::ExceptionBase & ExcMessage(std::string arg1)
std::string trim(const std::string &input)
Definition: utilities.cc:131
virtual std::string description() const =0
std::string get(const std::string &entry_string) const
std::size_t memory_consumption() const
const std::string separator
static Map * create(const std::string &description)
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:313
static const unsigned int max_int_value
static const char * description_init
void set(const std::string &entry_name, const std::string &new_value)
virtual PatternBase * clone() const
virtual bool match(const std::string &test_string) const
void log_parameters_section(LogStream &out)
static Double * create(const std::string &description)
std::vector< std::string > subsection_path
static const int max_int_value
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
const unsigned int max_elements
static const char * description_init
std::vector< std::string > subsection_path
static const int min_int_value
virtual std::string description() const
virtual std::string description() const
double string_to_double(const std::string &s)
Definition: utilities.cc:227
const double lower_bound
virtual PatternBase * clone() const =0
void enter_subsection(const std::string &subsection)
FileName(const FileType type=input)
static const char * description_init
virtual PatternBase * clone() const
static const char * description_init
static Integer * create(const std::string &description)
virtual void create_new(const unsigned int run_no)=0
PatternBase * pattern
double get_double(const std::string &entry_name) const
std::size_t memory_consumption() const
static const char * description_init
static Bool * create(const std::string &description)
Double(const double lower_bound=min_double_value, const double upper_bound=max_double_value)
#define Assert(cond, exc)
Definition: exceptions.h:294
std::string get_current_full_path(const std::string &name) const
List(const PatternBase &base_pattern, const unsigned int min_elements=0, const unsigned int max_elements=max_int_value, const std::string &separator=",")
MultipleSelection(const std::string &seq)
virtual std::size_t memory_consumption() const
static const char * description_init
virtual std::string description() const
static Anything * create(const std::string &description)
Map(const PatternBase &key_pattern, const PatternBase &value_pattern, const unsigned int min_elements=0, const unsigned int max_elements=max_int_value, const std::string &separator=",")
PatternBase * pattern_factory(const std::string &description)
static std::string mangle(const std::string &s)
virtual PatternBase * clone() const
virtual bool read_input_from_string(const char *s)
std::size_t memory_consumption() const
static const double min_double_value
void fill_entry_values(const unsigned int run_no)
virtual bool read_input(std::istream &input, const std::string &filename="input file")
bool get_bool(const std::string &entry_name) const
virtual bool match(const std::string &test_string) const
static const char * description_init
virtual PatternBase * clone() const
virtual bool match(const std::string &test_string) const =0
virtual PatternBase * clone() const
bool operator==(const ParameterHandler &prm2) const
std::string find(const std::string &filename, const char *open_mode="r")
Definition: path_search.cc:172
virtual bool match(const std::string &test_string) const
virtual std::string description() const
static const char * description_init
std::size_t memory_consumption() const
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
std::size_t memory_consumption() const
virtual std::string description() const
virtual PatternBase * clone() const
static const double max_double_value
void push(const std::string &text)
Definition: logstream.cc:288
virtual bool match(const std::string &test_string) const
virtual PatternBase * clone() const
bool scan_line(std::string line, const std::string &input_filename, const unsigned int current_line_n)
virtual std::string description() const
static std::string demangle(const std::string &s)
std::ostream & print_parameters(std::ostream &out, const OutputStyle style)
Integer(const int lower_bound=min_int_value, const int upper_bound=max_int_value)
void print_parameters_section(std::ostream &out, const OutputStyle style, const unsigned int indent_level, const bool include_top_level_elements=false)
virtual PatternBase * clone() const
std_cxx11::unique_ptr< boost::property_tree::ptree > entries
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:189
Selection(const std::string &seq)
virtual std::string description() const
static DirectoryName * create(const std::string &description)
static FileName * create(const std::string &description)
static MultipleSelection * create(const std::string &description)
virtual bool match(const std::string &test_string) const
std::vector< std::string > different_values
const unsigned int min_elements
std::size_t memory_consumption() const
virtual bool read_input_from_xml(std::istream &input)
static List * create(const std::string &description)
static const unsigned int max_int_value
static Selection * create(const std::string &description)
virtual PatternBase * clone() const
virtual std::string description() const
const std::string separator
void declare_alias(const std::string &existing_entry_name, const std::string &alias_name, const bool alias_is_deprecated=false)
const unsigned int max_elements
virtual bool match(const std::string &test_string) const
const unsigned int min_elements
virtual bool read_input(std::istream &input, const std::string &filename="input file")
std::vector< std_cxx11::shared_ptr< const Patterns::PatternBase > > patterns
virtual PatternBase * clone() const