Reference documentation for deal.II version GIT 92344eb39a 2023-03-23 02:40:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
patterns.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2022 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/logstream.h>
20 #include <deal.II/base/patterns.h>
21 #include <deal.II/base/utilities.h>
22 
23 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
24 #include <boost/io/ios_state.hpp>
25 #include <boost/property_tree/json_parser.hpp>
26 #include <boost/property_tree/ptree.hpp>
27 #include <boost/property_tree/xml_parser.hpp>
28 #undef BOOST_BIND_GLOBAL_PLACEHOLDERS
29 
30 #include <algorithm>
31 #include <cctype>
32 #include <cstdlib>
33 #include <cstring>
34 #include <fstream>
35 #include <iomanip>
36 #include <iostream>
37 #include <limits>
38 #include <sstream>
39 
40 
42 
43 
44 
45 // TODO[WB]: various functions here could be simplified by using namespace
46 // Utilities
47 
48 namespace Patterns
49 {
50  namespace internal
51  {
52  std::string
53  escape(const std::string &input, const PatternBase::OutputStyle style)
54  {
55  switch (style)
56  {
58  case PatternBase::Text:
59  return input;
60  case PatternBase::LaTeX:
61  {
62  std::string u;
63  u.reserve(input.size());
64  for (const auto c : input)
65  {
66  switch (c)
67  {
68  case '#':
69  case '@f$':
70  case '%':
71  case '&':
72  case '_':
73  case '{':
74  case '}':
75  // simple escaping:
76  u.push_back('\\');
77  u.push_back(c);
78  break;
79 
80  case '\\':
81  u.append("\\textbackslash{}");
82  break;
83 
84  case '^':
85  u.append("\\^{}");
86  break;
87 
88  case '~':
89  u.append("\\~{}");
90  break;
91 
92  default:
93  // all other chars are just copied:
94  u.push_back(c);
95  }
96  }
97  return u;
98  }
99  default:
100  Assert(false, ExcNotImplemented());
101  }
102  return "";
103  }
104 
105  } // namespace internal
106 
107 
108  namespace
109  {
116  bool
117  has_only_whitespace(std::istream &in)
118  {
119  while (in)
120  {
121  char c;
122 
123  // skip if we've reached the end of
124  // the line
125  if (!(in >> c))
126  break;
127 
128  if ((c != ' ') && (c != '\t'))
129  return false;
130  }
131  return true;
132  }
133  } // namespace
134 
135 
136 
137  std::unique_ptr<PatternBase>
138  pattern_factory(const std::string &description)
139  {
140  std::unique_ptr<PatternBase> p;
141 
142  p = Integer::create(description);
143  if (p != nullptr)
144  return p;
145 
146  p = Double::create(description);
147  if (p != nullptr)
148  return p;
149 
150  p = Selection::create(description);
151  if (p != nullptr)
152  return p;
153 
154  p = List::create(description);
155  if (p != nullptr)
156  return p;
157 
158  p = Map::create(description);
159  if (p != nullptr)
160  return p;
161 
162  p = MultipleSelection::create(description);
163  if (p != nullptr)
164  return p;
165 
166  p = Bool::create(description);
167  if (p != nullptr)
168  return p;
169 
170  p = Anything::create(description);
171  if (p != nullptr)
172  return p;
173 
174  p = FileName::create(description);
175  if (p != nullptr)
176  return p;
177 
178  p = DirectoryName::create(description);
179  if (p != nullptr)
180  return p;
181 
182  Assert(false, ExcNotImplemented());
183 
184  return p;
185  }
186 
187 
188 
189  std::size_t
191  {
192  if (dynamic_cast<const Integer *>(this) != nullptr)
193  return sizeof(Integer);
194  else if (dynamic_cast<const Double *>(this) != nullptr)
195  return sizeof(Double);
196  else if (dynamic_cast<const Bool *>(this) != nullptr)
197  return sizeof(Bool);
198  else if (dynamic_cast<const Anything *>(this) != nullptr)
199  return sizeof(Anything);
200  else
201  return sizeof(*this) + 32;
202  }
203 
204 
205 
208 
209  const char *Integer::description_init = "[Integer";
210 
211  Integer::Integer(const int lower_bound, const int upper_bound)
213  , upper_bound(upper_bound)
214  {}
215 
216 
217 
218  bool
219  Integer::match(const std::string &test_string) const
220  {
221  std::istringstream str(test_string);
222 
223  int i;
224  if (!(str >> i))
225  return false;
226 
227  if (!has_only_whitespace(str))
228  return false;
229  // check whether valid bounds
230  // were specified, and if so
231  // enforce their values
232  if (lower_bound <= upper_bound)
233  return ((lower_bound <= i) && (upper_bound >= i));
234  else
235  return true;
236  }
237 
238 
239 
240  std::string
242  {
243  switch (style)
244  {
245  case Machine:
246  {
247  // check whether valid bounds
248  // were specified, and if so
249  // output their values
250  if (lower_bound <= upper_bound)
251  {
252  std::ostringstream description;
253 
254  description << description_init << " range " << lower_bound
255  << "..." << upper_bound << " (inclusive)]";
256  return description.str();
257  }
258  else
259  // if no bounds were given, then
260  // return generic string
261  return "[Integer]";
262  }
263  case Text:
264  {
265  if (lower_bound <= upper_bound)
266  {
267  std::ostringstream description;
268 
269  description << "An integer n such that " << lower_bound
270  << " <= n <= " << upper_bound;
271 
272  return description.str();
273  }
274  else
275  return "An integer";
276  }
277  case LaTeX:
278  {
279  if (lower_bound <= upper_bound)
280  {
281  std::ostringstream description;
282 
283  description << "An integer @f$n@f$ such that @f$" << lower_bound
284  << "\\leq n \\leq " << upper_bound << "@f$";
285 
286  return description.str();
287  }
288  else
289  return "An integer";
290  }
291  default:
292  AssertThrow(false, ExcNotImplemented());
293  }
294  // Should never occur without an exception, but prevent compiler from
295  // complaining
296  return "";
297  }
298 
299 
300 
301  std::unique_ptr<PatternBase>
303  {
304  return std::unique_ptr<PatternBase>(new Integer(lower_bound, upper_bound));
305  }
306 
307 
308 
309  std::unique_ptr<Integer>
310  Integer::create(const std::string &description)
311  {
312  if (description.compare(0,
313  std::strlen(description_init),
314  description_init) == 0)
315  {
316  std::istringstream is(description);
317 
318  if (is.str().size() > strlen(description_init) + 1)
319  {
320  // TODO: verify that description matches the pattern "^\[Integer
321  // range \d+\.\.\.\d+\]@f$"
323 
324  is.ignore(strlen(description_init) + strlen(" range "));
325 
326  if (!(is >> lower_bound))
327  return std::make_unique<Integer>();
328 
329  is.ignore(strlen("..."));
330 
331  if (!(is >> upper_bound))
332  return std::make_unique<Integer>();
333 
334  return std::make_unique<Integer>(lower_bound, upper_bound);
335  }
336  else
337  return std::make_unique<Integer>();
338  }
339  else
340  return std::unique_ptr<Integer>();
341  }
342 
343 
344 
345  const double Double::min_double_value = std::numeric_limits<double>::lowest();
347 
348  const char *Double::description_init = "[Double";
349 
350  Double::Double(const double lower_bound, const double upper_bound)
352  , upper_bound(upper_bound)
353  {}
354 
355 
356 
357  bool
358  Double::match(const std::string &test_string) const
359  {
360  std::istringstream str(test_string);
361 
362  double d;
363  str >> d;
364  if (str.fail())
365  return false;
366 
367  if (!has_only_whitespace(str))
368  return false;
369  // check whether valid bounds
370  // were specified, and if so
371  // enforce their values
372  if (lower_bound <= upper_bound)
373  return ((lower_bound <= d) && (upper_bound >= d));
374  else
375  return true;
376  }
377 
378 
379 
380  std::string
381  Double::description(const OutputStyle style) const
382  {
383  switch (style)
384  {
385  case Machine:
386  {
387  std::ostringstream description;
388 
389  if (lower_bound <= upper_bound)
390  {
391  // bounds are valid
392  description << description_init << " ";
393  // We really want to compare with ==, but -Wfloat-equal would
394  // create a warning here, so work around it.
395  if (0 == std::memcmp(&lower_bound,
397  sizeof(lower_bound)))
398  description << "-MAX_DOUBLE";
399  else
401  description << "...";
402  if (0 == std::memcmp(&upper_bound,
404  sizeof(upper_bound)))
405  description << "MAX_DOUBLE";
406  else
408  description << " (inclusive)]";
409  return description.str();
410  }
411  else
412  {
413  // invalid bounds, assume unbounded double:
414  description << description_init << "]";
415  return description.str();
416  }
417  }
418  case Text:
419  {
420  if (lower_bound <= upper_bound)
421  {
422  std::ostringstream description;
423 
424  description << "A floating point number v such that ";
425  if (0 == std::memcmp(&lower_bound,
427  sizeof(lower_bound)))
428  description << "-MAX_DOUBLE";
429  else
431  description << " <= v <= ";
432  if (0 == std::memcmp(&upper_bound,
434  sizeof(upper_bound)))
435  description << "MAX_DOUBLE";
436  else
438 
439  return description.str();
440  }
441  else
442  return "A floating point number";
443  }
444  case LaTeX:
445  {
446  if (lower_bound <= upper_bound)
447  {
448  std::ostringstream description;
449 
450  description << "A floating point number @f$v@f$ such that @f$";
451  if (0 == std::memcmp(&lower_bound,
453  sizeof(lower_bound)))
454  description << "-\\text{MAX\\_DOUBLE}";
455  else
457  description << " \\leq v \\leq ";
458  if (0 == std::memcmp(&upper_bound,
460  sizeof(upper_bound)))
461  description << "\\text{MAX\\_DOUBLE}";
462  else
464  description << "@f$";
465 
466  return description.str();
467  }
468  else
469  return "A floating point number";
470  }
471  default:
472  AssertThrow(false, ExcNotImplemented());
473  }
474  // Should never occur without an exception, but prevent compiler from
475  // complaining
476  return "";
477  }
478 
479 
480  std::unique_ptr<PatternBase>
482  {
483  return std::unique_ptr<PatternBase>(new Double(lower_bound, upper_bound));
484  }
485 
486 
487 
488  std::unique_ptr<Double>
489  Double::create(const std::string &description)
490  {
491  const std::string description_init_str = description_init;
492  if (description.compare(0,
493  description_init_str.size(),
494  description_init_str) != 0)
495  return std::unique_ptr<Double>();
496  if (*description.rbegin() != ']')
497  return std::unique_ptr<Double>();
498 
499  std::string temp = description.substr(description_init_str.size());
500  if (temp == "]")
501  return std::make_unique<Double>(1.0,
502  -1.0); // return an invalid range
503 
504  if (temp.find("...") != std::string::npos)
505  temp.replace(temp.find("..."), 3, " ");
506 
508 
509  std::istringstream is(temp);
510  if (0 == temp.compare(0, std::strlen(" -MAX_DOUBLE"), " -MAX_DOUBLE"))
511  is.ignore(std::strlen(" -MAX_DOUBLE"));
512  else
513  {
514  // parse lower bound and give up if not a double
515  if (!(is >> lower_bound))
516  return std::unique_ptr<Double>();
517  }
518 
519  // ignore failure here and assume we got MAX_DOUBLE as upper bound:
520  is >> upper_bound;
521  if (is.fail())
523 
524  return std::make_unique<Double>(lower_bound, upper_bound);
525  }
526 
527 
528 
529  const char *Selection::description_init = "[Selection";
530 
531 
532  Selection::Selection(const std::string &seq)
533  : sequence(seq)
534  {
535  while (sequence.find(" |") != std::string::npos)
536  sequence.replace(sequence.find(" |"), 2, "|");
537  while (sequence.find("| ") != std::string::npos)
538  sequence.replace(sequence.find("| "), 2, "|");
539  }
540 
541 
542 
543  bool
544  Selection::match(const std::string &test_string) const
545  {
546  std::string tmp(sequence);
547 
548  // remove whitespace at beginning
549  while ((tmp.size() != 0) && (std::isspace(tmp.front()) != 0))
550  tmp.erase(0, 1);
551 
552  // check the different possibilities
553  while (tmp.find('|') != std::string::npos)
554  {
555  if (test_string == std::string(tmp, 0, tmp.find('|')))
556  return true;
557 
558  tmp.erase(0, tmp.find('|') + 1);
559  }
560 
561  // remove whitespace at the end
562  while ((tmp.size() != 0) && (std::isspace(tmp.back()) != 0))
563  tmp.erase(tmp.end() - 1);
564 
565  // check last choice, not finished by |
566  if (test_string == tmp)
567  return true;
568 
569  // not found
570  return false;
571  }
572 
573 
574 
575  std::string
577  {
578  switch (style)
579  {
580  case Machine:
581  {
582  std::ostringstream description;
583 
584  description << description_init << " " << sequence << " ]";
585 
586  return description.str();
587  }
588  case Text:
589  case LaTeX:
590  {
591  std::ostringstream description;
592 
593  description << "Any one of "
594  << internal::escape(
596  style);
597 
598  return description.str();
599  }
600  default:
601  AssertThrow(false, ExcNotImplemented());
602  }
603  // Should never occur without an exception, but prevent compiler from
604  // complaining
605  return "";
606  }
607 
608 
609 
610  std::unique_ptr<PatternBase>
612  {
613  return std::unique_ptr<PatternBase>(new Selection(sequence));
614  }
615 
616 
617  std::size_t
619  {
620  return (sizeof(PatternBase) +
622  }
623 
624 
625 
626  std::unique_ptr<Selection>
627  Selection::create(const std::string &description)
628  {
629  if (description.compare(0,
630  std::strlen(description_init),
631  description_init) == 0)
632  {
633  std::string sequence(description);
634 
635  sequence.erase(0, std::strlen(description_init) + 1);
636  sequence.erase(sequence.size() - 2, 2);
637 
638  return std::make_unique<Selection>(sequence);
639  }
640  else
641  return std::unique_ptr<Selection>();
642  }
643 
644 
645 
646  const unsigned int List::max_int_value =
648 
649  const char *List::description_init = "[List";
650 
651 
653  const unsigned int min_elements,
654  const unsigned int max_elements,
655  const std::string &separator)
656  : pattern(p.clone())
657  , min_elements(min_elements)
658  , max_elements(max_elements)
659  , separator(separator)
660  {
663  Assert(separator.size() > 0,
664  ExcMessage("The separator must have a non-zero length."));
665  }
666 
667 
668 
669  List::List(const List &other)
670  : pattern(other.pattern->clone())
671  , min_elements(other.min_elements)
672  , max_elements(other.max_elements)
673  , separator(other.separator)
674  {}
675 
676 
677  const std::string &
679  {
680  return separator;
681  }
682 
683 
684 
685  const PatternBase &
687  {
688  return *pattern;
689  }
690 
691 
692 
693  bool
694  List::match(const std::string &test_string_list) const
695  {
696  const std::vector<std::string> split_list =
697  Utilities::split_string_list(test_string_list, separator);
698 
699  if ((split_list.size() < min_elements) ||
700  (split_list.size() > max_elements))
701  return false;
702 
703  // check the different possibilities
704  for (const std::string &string : split_list)
705  if (pattern->match(string) == false)
706  return false;
707 
708  return true;
709  }
710 
711 
712 
713  std::string
714  List::description(const OutputStyle style) const
715  {
716  switch (style)
717  {
718  case Machine:
719  {
720  std::ostringstream description;
721 
722  description << description_init << " of <"
723  << pattern->description(style) << ">"
724  << " of length " << min_elements << "..."
725  << max_elements << " (inclusive)";
726  if (separator != ",")
727  description << " separated by <" << separator << ">";
728  description << "]";
729 
730  return description.str();
731  }
732  case Text:
733  case LaTeX:
734  {
735  std::ostringstream description;
736 
737  description << "A list of " << min_elements << " to "
738  << max_elements << " elements ";
739  if (separator != ",")
740  description << "separated by <"
741  << internal::escape(separator, style) << "> ";
742  description << "where each element is ["
743  << pattern->description(style) << "]";
744 
745  return description.str();
746  }
747  default:
748  AssertThrow(false, ExcNotImplemented());
749  }
750  // Should never occur without an exception, but prevent compiler from
751  // complaining
752  return "";
753  }
754 
755 
756 
757  std::unique_ptr<PatternBase>
758  List::clone() const
759  {
760  return std::unique_ptr<PatternBase>(
762  }
763 
764 
765  std::size_t
767  {
768  return (sizeof(*this) + MemoryConsumption::memory_consumption(*pattern) +
770  }
771 
772 
773 
774  std::unique_ptr<List>
775  List::create(const std::string &description)
776  {
777  if (description.compare(0,
778  std::strlen(description_init),
779  description_init) == 0)
780  {
781  unsigned int min_elements = 0, max_elements = 0;
782 
783  std::istringstream is(description);
784  is.ignore(strlen(description_init) + strlen(" of <"));
785 
786  std::string str;
787  std::getline(is, str, '>');
788 
789  std::unique_ptr<PatternBase> base_pattern(pattern_factory(str));
790 
791  is.ignore(strlen(" of length "));
792  if (!(is >> min_elements))
793  return std::make_unique<List>(*base_pattern);
794 
795  is.ignore(strlen("..."));
796  if (!(is >> max_elements))
797  return std::make_unique<List>(*base_pattern, min_elements);
798 
799  is.ignore(strlen(" (inclusive) separated by <"));
800  std::string separator;
801  if (!is.eof())
802  std::getline(is, separator, '>');
803  else
804  separator = ",";
805 
806  return std::make_unique<List>(*base_pattern,
807  min_elements,
808  max_elements,
809  separator);
810  }
811  else
812  return std::unique_ptr<List>();
813  }
814 
815 
816 
817  const unsigned int Map::max_int_value =
819 
820  const char *Map::description_init = "[Map";
821 
822 
823  Map::Map(const PatternBase &p_key,
824  const PatternBase &p_value,
825  const unsigned int min_elements,
826  const unsigned int max_elements,
827  const std::string &separator,
828  const std::string &key_value_separator)
829  : key_pattern(p_key.clone())
830  , value_pattern(p_value.clone())
831  , min_elements(min_elements)
832  , max_elements(max_elements)
833  , separator(separator)
834  , key_value_separator(key_value_separator)
835  {
838  Assert(separator.size() > 0,
839  ExcMessage("The separator must have a non-zero length."));
840  Assert(key_value_separator.size() > 0,
841  ExcMessage("The key_value_separator must have a non-zero length."));
843  ExcMessage(
844  "The separator can not be the same of the key_value_separator "
845  "since that is used as the separator between the two elements "
846  "of <key:value> pairs"));
847  }
848 
849 
850 
851  Map::Map(const Map &other)
852  : key_pattern(other.key_pattern->clone())
853  , value_pattern(other.value_pattern->clone())
854  , min_elements(other.min_elements)
855  , max_elements(other.max_elements)
856  , separator(other.separator)
857  , key_value_separator(other.key_value_separator)
858  {}
859 
860 
861 
862  bool
863  Map::match(const std::string &test_string_list) const
864  {
865  std::vector<std::string> split_list =
866  Utilities::split_string_list(test_string_list, separator);
867  if ((split_list.size() < min_elements) ||
868  (split_list.size() > max_elements))
869  return false;
870 
871  for (const auto &key_value_pair : split_list)
872  {
873  std::vector<std::string> pair =
875 
876  // Check that we have in fact two matches
877  if (pair.size() != 2)
878  return false;
879 
880  // then verify that the patterns are satisfied
881  if (key_pattern->match(pair[0]) == false)
882  return false;
883  if (value_pattern->match(pair[1]) == false)
884  return false;
885  }
886 
887  return true;
888  }
889 
890 
891 
892  std::string
893  Map::description(const OutputStyle style) const
894  {
895  switch (style)
896  {
897  case Machine:
898  {
899  std::ostringstream description;
900 
901  description << description_init << " of <"
902  << key_pattern->description(style) << ">"
903  << key_value_separator << "<"
904  << value_pattern->description(style) << ">"
905  << " of length " << min_elements << "..."
906  << max_elements << " (inclusive)";
907  if (separator != ",")
908  description << " separated by <" << separator << ">";
909  description << "]";
910 
911  return description.str();
912  }
913  case Text:
914  case LaTeX:
915  {
916  std::ostringstream description;
917 
918  description << "A key"
920  << "value map of " << min_elements << " to "
921  << max_elements << " elements ";
922  if (separator != ",")
923  description << " separated by <"
924  << internal::escape(separator, style) << "> ";
925  description << " where each key is ["
926  << key_pattern->description(style) << "]"
927  << " and each value is ["
928  << value_pattern->description(style) << "]";
929 
930  return description.str();
931  }
932  default:
933  AssertThrow(false, ExcNotImplemented());
934  }
935  // Should never occur without an exception, but prevent compiler from
936  // complaining
937  return "";
938  }
939 
940 
941 
942  std::unique_ptr<PatternBase>
943  Map::clone() const
944  {
945  return std::unique_ptr<PatternBase>(new Map(*key_pattern,
946  *value_pattern,
947  min_elements,
948  max_elements,
949  separator,
951  }
952 
953 
954  std::size_t
956  {
957  return (sizeof(*this) +
962  }
963 
964 
965 
966  std::unique_ptr<Map>
967  Map::create(const std::string &description)
968  {
969  if (description.compare(0,
970  std::strlen(description_init),
971  description_init) == 0)
972  {
973  unsigned int min_elements = 0, max_elements = 0;
974 
975  std::istringstream is(description);
976  is.ignore(strlen(description_init) + strlen(" of <"));
977 
978  std::string key;
979  std::getline(is, key, '>');
980 
981  std::string key_value_separator;
982  std::getline(is, key_value_separator, '<');
983 
984  // split 'str' into key and value
985  std::string value;
986  std::getline(is, value, '>');
987 
988  std::unique_ptr<PatternBase> key_pattern(pattern_factory(key));
989  std::unique_ptr<PatternBase> value_pattern(pattern_factory(value));
990 
991  is.ignore(strlen(" of length "));
992  if (!(is >> min_elements))
993  return std::make_unique<Map>(*key_pattern, *value_pattern);
994 
995  is.ignore(strlen("..."));
996  if (!(is >> max_elements))
997  return std::make_unique<Map>(*key_pattern,
998  *value_pattern,
999  min_elements);
1000 
1001  is.ignore(strlen(" (inclusive) separated by <"));
1002  std::string separator;
1003  if (!is.eof())
1004  std::getline(is, separator, '>');
1005  else
1006  separator = ",";
1007 
1008  return std::make_unique<Map>(*key_pattern,
1009  *value_pattern,
1010  min_elements,
1011  max_elements,
1012  separator,
1014  }
1015  else
1016  return std::unique_ptr<Map>();
1017  }
1018 
1019 
1020 
1021  const PatternBase &
1023  {
1024  return *key_pattern;
1025  }
1026 
1027 
1028 
1029  const PatternBase &
1031  {
1032  return *value_pattern;
1033  }
1034 
1035 
1036 
1037  const std::string &
1039  {
1040  return separator;
1041  }
1042 
1043 
1044  const std::string &
1046  {
1047  return key_value_separator;
1048  }
1049 
1050 
1051 
1052  const char *Tuple::description_init = "[Tuple";
1053 
1054 
1055  Tuple::Tuple(const std::vector<std::unique_ptr<PatternBase>> &ps,
1056  const std::string & separator)
1057  : separator(separator)
1058  {
1059  Assert(ps.size() > 0,
1060  ExcMessage("The Patterns list must have a non-zero length."));
1061  Assert(separator.size() > 0,
1062  ExcMessage("The separator must have a non-zero length."));
1063  patterns.resize(ps.size());
1064  for (unsigned int i = 0; i < ps.size(); ++i)
1065  patterns[i] = ps[i]->clone();
1066  }
1067 
1068 
1069 
1070  Tuple::Tuple(const std::vector<std::unique_ptr<PatternBase>> &ps,
1071  const char * separator)
1072  : Tuple(ps, std::string(separator))
1073  {}
1074 
1075 
1076 
1077  Tuple::Tuple(const Tuple &other)
1078  : separator(other.separator)
1079  {
1080  patterns.resize(other.patterns.size());
1081  for (unsigned int i = 0; i < other.patterns.size(); ++i)
1082  patterns[i] = other.patterns[i]->clone();
1083  }
1084 
1085 
1086 
1087  bool
1088  Tuple::match(const std::string &test_string_list) const
1089  {
1090  std::vector<std::string> split_list =
1091  Utilities::split_string_list(test_string_list, separator);
1092  if (split_list.size() != patterns.size())
1093  return false;
1094 
1095  for (unsigned int i = 0; i < patterns.size(); ++i)
1096  {
1097  if (patterns[i]->match(split_list[i]) == false)
1098  return false;
1099  }
1100 
1101  return true;
1102  }
1103 
1104 
1105 
1106  std::string
1107  Tuple::description(const OutputStyle style) const
1108  {
1109  switch (style)
1110  {
1111  case Machine:
1112  {
1113  std::ostringstream description;
1114 
1115  description << description_init << " of <" << patterns.size()
1116  << "> elements <" << patterns[0]->description(style)
1117  << ">";
1118  for (unsigned int i = 1; i < patterns.size(); ++i)
1119  description << ", <" << patterns[i]->description(style) << ">";
1120 
1121  if (separator != ":")
1122  description << " separated by <" << separator << ">";
1123  description << "]";
1124 
1125  return description.str();
1126  }
1127  case Text:
1128  case LaTeX:
1129  {
1130  std::ostringstream description;
1131 
1132  description << "A Tuple of " << patterns.size() << " elements ";
1133  if (separator != ":")
1134  description << " separated by <"
1135  << internal::escape(separator, style) << "> ";
1136  description << " where each element is ["
1137  << patterns[0]->description(style) << "]";
1138  for (unsigned int i = 1; i < patterns.size(); ++i)
1139  {
1140  description << internal::escape(separator, style) << "["
1141  << patterns[i]->description(style) << "]";
1142  }
1143  return description.str();
1144  }
1145 
1146  default:
1147  AssertThrow(false, ExcNotImplemented());
1148  }
1149  // Should never occur without an exception, but prevent compiler from
1150  // complaining
1151  return "";
1152  }
1153 
1154 
1155 
1156  std::unique_ptr<PatternBase>
1158  {
1159  return std::unique_ptr<PatternBase>(new Tuple(patterns, separator));
1160  }
1161 
1162 
1163  std::size_t
1165  {
1166  return (sizeof(*this) + MemoryConsumption::memory_consumption(patterns) +
1168  }
1169 
1170 
1171 
1172  std::unique_ptr<Tuple>
1173  Tuple::create(const std::string &description)
1174  {
1175  if (description.compare(0,
1176  std::strlen(description_init),
1177  description_init) == 0)
1178  {
1179  std::vector<std::unique_ptr<PatternBase>> patterns;
1180 
1181  std::istringstream is(description);
1182  is.ignore(strlen(description_init) + strlen(" of <"));
1183 
1184  std::string len;
1185  std::getline(is, len, '>');
1186  const unsigned int n_elements = Utilities::string_to_int(len);
1187  Assert(n_elements > 0,
1188  ExcMessage("Provide at least 1 element in the tuple."));
1189  patterns.resize(n_elements);
1190 
1191  is.ignore(strlen(" elements <"));
1192 
1193  std::string element;
1194  std::getline(is, element, '>');
1195  patterns[0] = pattern_factory(element);
1196 
1197  for (unsigned int i = 1; i < n_elements; ++i)
1198  {
1199  is.ignore(strlen(", <"));
1200  std::getline(is, element, '>');
1201  patterns[i] = pattern_factory(element);
1202  }
1203 
1204  is.ignore(strlen(" separated by <"));
1205 
1206  std::string separator;
1207  if (!is.eof())
1208  std::getline(is, separator, '>');
1209  else
1210  separator = ":";
1211 
1212  return std::make_unique<Tuple>(patterns, separator);
1213  }
1214  else
1215  return std::unique_ptr<Tuple>();
1216  }
1217 
1218 
1219 
1220  const PatternBase &
1221  Tuple::get_pattern(const unsigned int i) const
1222  {
1223  return *patterns[i];
1224  }
1225 
1226 
1227 
1228  const std::string &
1230  {
1231  return separator;
1232  }
1233 
1234 
1235 
1236  const char *MultipleSelection::description_init = "[MultipleSelection";
1237 
1238 
1240  {
1241  Assert(seq.find(',') == std::string::npos,
1242  ExcCommasNotAllowed(seq.find(',')));
1243 
1244  sequence = seq;
1245  while (sequence.find(" |") != std::string::npos)
1246  sequence.replace(sequence.find(" |"), 2, "|");
1247  while (sequence.find("| ") != std::string::npos)
1248  sequence.replace(sequence.find("| "), 2, "|");
1249  }
1250 
1251 
1252 
1253  bool
1254  MultipleSelection::match(const std::string &test_string_list) const
1255  {
1256  std::string tmp = test_string_list;
1257  std::vector<std::string> split_names;
1258 
1259  // first split the input list
1260  while (tmp.size() != 0)
1261  {
1262  std::string name;
1263  name = tmp;
1264 
1265  if (name.find(',') != std::string::npos)
1266  {
1267  name.erase(name.find(','), std::string::npos);
1268  tmp.erase(0, tmp.find(',') + 1);
1269  }
1270  else
1271  tmp = "";
1272 
1273  while ((name.size() != 0) && (std::isspace(name.front()) != 0))
1274  name.erase(0, 1);
1275  while ((name.size() != 0) && (std::isspace(name.back()) != 0))
1276  name.erase(name.size() - 1, 1);
1277 
1278  split_names.push_back(name);
1279  }
1280 
1281 
1282  // check the different possibilities
1283  for (const auto &test_string : split_names)
1284  {
1285  bool string_found = false;
1286 
1287  tmp = sequence;
1288  while (tmp.find('|') != std::string::npos)
1289  {
1290  if (test_string == std::string(tmp, 0, tmp.find('|')))
1291  {
1292  // string found, quit
1293  // loop. don't change
1294  // tmp, since we don't
1295  // need it anymore.
1296  string_found = true;
1297  break;
1298  }
1299 
1300  tmp.erase(0, tmp.find('|') + 1);
1301  }
1302  // check last choice, not finished by |
1303  if (!string_found)
1304  if (test_string == tmp)
1305  string_found = true;
1306 
1307  if (!string_found)
1308  return false;
1309  }
1310 
1311  return true;
1312  }
1313 
1314 
1315 
1316  std::string
1318  {
1319  switch (style)
1320  {
1321  case Machine:
1322  {
1323  std::ostringstream description;
1324 
1325  description << description_init << " " << sequence << " ]";
1326 
1327  return description.str();
1328  }
1329  case Text:
1330  case LaTeX:
1331  {
1332  std::ostringstream description;
1333 
1334  description << "A comma-separated list of any of "
1335  << internal::escape(
1337  style);
1338 
1339  return description.str();
1340  }
1341  default:
1342  AssertThrow(false, ExcNotImplemented());
1343  }
1344  // Should never occur without an exception, but prevent compiler from
1345  // complaining
1346  return "";
1347  }
1348 
1349 
1350 
1351  std::unique_ptr<PatternBase>
1353  {
1354  return std::unique_ptr<PatternBase>(new MultipleSelection(sequence));
1355  }
1356 
1357 
1358  std::size_t
1360  {
1361  return (sizeof(PatternBase) +
1363  }
1364 
1365 
1366 
1367  std::unique_ptr<MultipleSelection>
1368  MultipleSelection::create(const std::string &description)
1369  {
1370  if (description.compare(0,
1371  std::strlen(description_init),
1372  description_init) == 0)
1373  {
1374  std::string sequence(description);
1375 
1376  sequence.erase(0, std::strlen(description_init) + 1);
1377  sequence.erase(sequence.size() - 2, 2);
1378 
1379  return std::make_unique<MultipleSelection>(sequence);
1380  }
1381  else
1382  return std::unique_ptr<MultipleSelection>();
1383  }
1384 
1385 
1386 
1387  const char *Bool::description_init = "[Bool";
1388 
1389 
1391  : Selection("true|false")
1392  {}
1393 
1394 
1395 
1396  std::string
1397  Bool::description(const OutputStyle style) const
1398  {
1399  switch (style)
1400  {
1401  case Machine:
1402  {
1403  std::ostringstream description;
1404 
1405  description << description_init << "]";
1406 
1407  return description.str();
1408  }
1409  case Text:
1410  case LaTeX:
1411  {
1412  return "A boolean value (true or false)";
1413  }
1414  default:
1415  AssertThrow(false, ExcNotImplemented());
1416  }
1417  // Should never occur without an exception, but prevent compiler from
1418  // complaining
1419  return "";
1420  }
1421 
1422 
1423 
1424  std::unique_ptr<PatternBase>
1425  Bool::clone() const
1426  {
1427  return std::unique_ptr<PatternBase>(new Bool());
1428  }
1429 
1430 
1431 
1432  std::unique_ptr<Bool>
1433  Bool::create(const std::string &description)
1434  {
1435  if (description.compare(0,
1436  std::strlen(description_init),
1437  description_init) == 0)
1438  return std::make_unique<Bool>();
1439  else
1440  return std::unique_ptr<Bool>();
1441  }
1442 
1443 
1444 
1445  const char *Anything::description_init = "[Anything";
1446 
1447 
1448 
1449  bool
1450  Anything::match(const std::string &) const
1451  {
1452  return true;
1453  }
1454 
1455 
1456 
1457  std::string
1459  {
1460  switch (style)
1461  {
1462  case Machine:
1463  {
1464  std::ostringstream description;
1465 
1466  description << description_init << "]";
1467 
1468  return description.str();
1469  }
1470  case Text:
1471  case LaTeX:
1472  {
1473  return "Any string";
1474  }
1475  default:
1476  AssertThrow(false, ExcNotImplemented());
1477  }
1478  // Should never occur without an exception, but prevent compiler from
1479  // complaining
1480  return "";
1481  }
1482 
1483 
1484 
1485  std::unique_ptr<PatternBase>
1487  {
1488  return std::unique_ptr<PatternBase>(new Anything());
1489  }
1490 
1491 
1492 
1493  std::unique_ptr<Anything>
1494  Anything::create(const std::string &description)
1495  {
1496  if (description.compare(0,
1497  std::strlen(description_init),
1498  description_init) == 0)
1499  return std::make_unique<Anything>();
1500  else
1501  return std::unique_ptr<Anything>();
1502  }
1503 
1504 
1505 
1506  const char *FileName::description_init = "[FileName";
1507 
1508 
1510  : file_type(type)
1511  {}
1512 
1513 
1514 
1515  bool
1516  FileName::match(const std::string &) const
1517  {
1518  return true;
1519  }
1520 
1521 
1522 
1523  std::string
1525  {
1526  switch (style)
1527  {
1528  case Machine:
1529  {
1530  std::ostringstream description;
1531 
1533 
1534  if (file_type == input)
1535  description << " (Type: input)]";
1536  else
1537  description << " (Type: output)]";
1538 
1539  return description.str();
1540  }
1541  case Text:
1542  case LaTeX:
1543  {
1544  if (file_type == input)
1545  return "an input filename";
1546  else
1547  return "an output filename";
1548  }
1549  default:
1550  AssertThrow(false, ExcNotImplemented());
1551  }
1552  // Should never occur without an exception, but prevent compiler from
1553  // complaining
1554  return "";
1555  }
1556 
1557 
1558 
1559  std::unique_ptr<PatternBase>
1561  {
1562  return std::unique_ptr<PatternBase>(new FileName(file_type));
1563  }
1564 
1565 
1566 
1567  std::unique_ptr<FileName>
1568  FileName::create(const std::string &description)
1569  {
1570  if (description.compare(0,
1571  std::strlen(description_init),
1572  description_init) == 0)
1573  {
1574  std::istringstream is(description);
1575  std::string file_type;
1576  FileType type;
1577 
1578  is.ignore(strlen(description_init) + strlen(" (Type:"));
1579 
1580  is >> file_type;
1581 
1582  if (file_type == "input)]")
1583  type = input;
1584  else
1585  type = output;
1586 
1587  return std::make_unique<FileName>(type);
1588  }
1589  else
1590  return std::unique_ptr<FileName>();
1591  }
1592 
1593 
1594 
1595  const char *DirectoryName::description_init = "[DirectoryName";
1596 
1597 
1598 
1599  bool
1600  DirectoryName::match(const std::string &) const
1601  {
1602  return true;
1603  }
1604 
1605 
1606 
1607  std::string
1609  {
1610  switch (style)
1611  {
1612  case Machine:
1613  {
1614  std::ostringstream description;
1615 
1616  description << description_init << "]";
1617 
1618  return description.str();
1619  }
1620  case Text:
1621  case LaTeX:
1622  {
1623  return "A directory name";
1624  }
1625  default:
1626  AssertThrow(false, ExcNotImplemented());
1627  }
1628  // Should never occur without an exception, but prevent compiler from
1629  // complaining
1630  return "";
1631  }
1632 
1633 
1634 
1635  std::unique_ptr<PatternBase>
1637  {
1638  return std::unique_ptr<PatternBase>(new DirectoryName());
1639  }
1640 
1641 
1642 
1643  std::unique_ptr<DirectoryName>
1644  DirectoryName::create(const std::string &description)
1645  {
1646  if (description.compare(0,
1647  std::strlen(description_init),
1648  description_init) == 0)
1649  return std::make_unique<DirectoryName>();
1650  else
1651  return std::unique_ptr<DirectoryName>();
1652  }
1653 
1654 } // end namespace Patterns
1655 
static std::unique_ptr< Anything > create(const std::string &description)
Definition: patterns.cc:1494
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1450
static const char * description_init
Definition: patterns.h:1064
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1458
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1486
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1397
static const char * description_init
Definition: patterns.h:1015
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1425
static std::unique_ptr< Bool > create(const std::string &description)
Definition: patterns.cc:1433
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1636
static const char * description_init
Definition: patterns.h:1204
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1608
static std::unique_ptr< DirectoryName > create(const std::string &description)
Definition: patterns.cc:1644
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1600
static std::unique_ptr< Double > create(const std::string &description)
Definition: patterns.cc:489
static const char * description_init
Definition: patterns.h:369
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:481
Double(const double lower_bound=min_double_value, const double upper_bound=max_double_value)
Definition: patterns.cc:350
const double lower_bound
Definition: patterns.h:356
const double upper_bound
Definition: patterns.h:364
static const double max_double_value
Definition: patterns.h:304
static const double min_double_value
Definition: patterns.h:298
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:381
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:358
FileType file_type
Definition: patterns.h:1132
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1516
FileName(const FileType type=input)
Definition: patterns.cc:1509
static const char * description_init
Definition: patterns.h:1146
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1560
static std::unique_ptr< FileName > create(const std::string &description)
Definition: patterns.cc:1568
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1524
static std::unique_ptr< Integer > create(const std::string &description)
Definition: patterns.cc:310
static const char * description_init
Definition: patterns.h:271
const int upper_bound
Definition: patterns.h:266
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:302
Integer(const int lower_bound=min_int_value, const int upper_bound=max_int_value)
Definition: patterns.cc:211
const int lower_bound
Definition: patterns.h:258
static const int min_int_value
Definition: patterns.h:196
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:241
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:219
static const int max_int_value
Definition: patterns.h:203
const unsigned int max_elements
Definition: patterns.h:555
static const char * description_init
Definition: patterns.h:565
const unsigned int min_elements
Definition: patterns.h:550
std::unique_ptr< PatternBase > pattern
Definition: patterns.h:545
const std::string separator
Definition: patterns.h:560
std::size_t memory_consumption() const override
Definition: patterns.cc:766
static std::unique_ptr< List > create(const std::string &description)
Definition: patterns.cc:775
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:714
const PatternBase & get_base_pattern() const
Definition: patterns.cc:686
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:694
const std::string & get_separator() const
Definition: patterns.cc:678
List(const PatternBase &base_pattern, const unsigned int min_elements=0, const unsigned int max_elements=max_int_value, const std::string &separator=",")
Definition: patterns.cc:652
static const unsigned int max_int_value
Definition: patterns.h:457
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:758
static std::unique_ptr< Map > create(const std::string &description)
Definition: patterns.cc:967
std::unique_ptr< PatternBase > value_pattern
Definition: patterns.h:694
const unsigned int min_elements
Definition: patterns.h:699
const PatternBase & get_key_pattern() const
Definition: patterns.cc:1022
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:863
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=",", const std::string &key_value_separator=":")
Definition: patterns.cc:823
const unsigned int max_elements
Definition: patterns.h:704
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:943
const PatternBase & get_value_pattern() const
Definition: patterns.cc:1030
const std::string & get_separator() const
Definition: patterns.cc:1038
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:893
static const unsigned int max_int_value
Definition: patterns.h:591
std::unique_ptr< PatternBase > key_pattern
Definition: patterns.h:693
const std::string separator
Definition: patterns.h:709
std::size_t memory_consumption() const override
Definition: patterns.cc:955
static const char * description_init
Definition: patterns.h:720
const std::string & get_key_value_separator() const
Definition: patterns.cc:1045
const std::string key_value_separator
Definition: patterns.h:715
MultipleSelection(const std::string &seq)
Definition: patterns.cc:1239
static std::unique_ptr< MultipleSelection > create(const std::string &description)
Definition: patterns.cc:1368
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1254
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1352
static const char * description_init
Definition: patterns.h:973
std::size_t memory_consumption() const override
Definition: patterns.cc:1359
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1317
virtual std::size_t memory_consumption() const
Definition: patterns.cc:190
static const char * description_init
Definition: patterns.h:438
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:576
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:611
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:544
static std::unique_ptr< Selection > create(const std::string &description)
Definition: patterns.cc:627
std::size_t memory_consumption() const override
Definition: patterns.cc:618
Selection(const std::string &seq)
Definition: patterns.cc:532
std::string sequence
Definition: patterns.h:433
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1088
Tuple(const std::vector< std::unique_ptr< PatternBase >> &patterns, const std::string &separator=":")
Definition: patterns.cc:1055
std::size_t memory_consumption() const override
Definition: patterns.cc:1164
static std::unique_ptr< Tuple > create(const std::string &description)
Definition: patterns.cc:1173
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:879
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1157
const std::string separator
Definition: patterns.h:884
static const char * description_init
Definition: patterns.h:889
const std::string & get_separator() const
Definition: patterns.cc:1229
const PatternBase & get_pattern(const unsigned int i) const
Definition: patterns.cc:1221
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1107
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:474
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:475
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
#define Assert(cond, exc)
Definition: exceptions.h:1586
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcCommasNotAllowed(int arg1)
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1675
std::enable_if_t< std::is_fundamental< T >::value, std::size_t > memory_consumption(const T &t)
std::string escape(const std::string &input, const PatternBase::OutputStyle style)
Definition: patterns.cc:53
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
Definition: patterns.cc:138
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:702
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition: utilities.cc:510
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:999
int string_to_int(const std::string &s)
Definition: utilities.cc:606