Reference documentation for deal.II version GIT 9042b9283b 2023-12-02 14:50: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 - 2023 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() > std::strlen(description_init) + 1)
319  {
320  // TODO: verify that description matches the pattern "^\[Integer
321  // range \d+\.\.\.\d+\]@f$"
323 
324  is.ignore(std::strlen(description_init) + std::strlen(" range "));
325 
326  if (!(is >> lower_bound))
327  return std::make_unique<Integer>();
328 
329  is.ignore(std::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::string::const_iterator it = description.begin() +
784  std::strlen(description_init) +
785  std::strlen(" of <");
786 
787  int n_open_angular = 1;
788  auto tmp_it = it - 1;
789  while (n_open_angular > 0)
790  {
791  tmp_it = std::find_if(tmp_it + 1, description.end(), [](char c) {
792  return (c == '>' || c == '<');
793  });
794  AssertThrow(tmp_it != description.end(),
795  ExcMessage(
796  "Couldn't find a closing '>' in description!"));
797  if (*tmp_it == '<')
798  ++n_open_angular;
799  else
800  --n_open_angular;
801  }
802 
803  std::string base_pattern_string(it, tmp_it);
804  std::unique_ptr<PatternBase> base_pattern(
805  pattern_factory(base_pattern_string));
806 
807  std::istringstream is(
808  std::string(tmp_it + std::strlen(" of length "), description.end()));
809  if (!(is >> min_elements))
810  return std::make_unique<List>(*base_pattern);
811 
812  is.ignore(std::strlen("..."));
813  if (!(is >> max_elements))
814  return std::make_unique<List>(*base_pattern, min_elements);
815 
816  is.ignore(std::strlen(" (inclusive) separated by <"));
817  std::string separator;
818  if (!is.eof())
819  std::getline(is, separator, '>');
820  else
821  separator = ",";
822 
823  return std::make_unique<List>(*base_pattern,
824  min_elements,
825  max_elements,
826  separator);
827  }
828  else
829  return std::unique_ptr<List>();
830  }
831 
832 
833 
834  const unsigned int Map::max_int_value =
836 
837  const char *Map::description_init = "[Map";
838 
839 
840  Map::Map(const PatternBase &p_key,
841  const PatternBase &p_value,
842  const unsigned int min_elements,
843  const unsigned int max_elements,
844  const std::string &separator,
845  const std::string &key_value_separator)
846  : key_pattern(p_key.clone())
847  , value_pattern(p_value.clone())
848  , min_elements(min_elements)
849  , max_elements(max_elements)
850  , separator(separator)
851  , key_value_separator(key_value_separator)
852  {
855  Assert(separator.size() > 0,
856  ExcMessage("The separator must have a non-zero length."));
857  Assert(key_value_separator.size() > 0,
858  ExcMessage("The key_value_separator must have a non-zero length."));
860  ExcMessage(
861  "The separator can not be the same of the key_value_separator "
862  "since that is used as the separator between the two elements "
863  "of <key:value> pairs"));
864  }
865 
866 
867 
868  Map::Map(const Map &other)
869  : key_pattern(other.key_pattern->clone())
870  , value_pattern(other.value_pattern->clone())
871  , min_elements(other.min_elements)
872  , max_elements(other.max_elements)
873  , separator(other.separator)
874  , key_value_separator(other.key_value_separator)
875  {}
876 
877 
878 
879  bool
880  Map::match(const std::string &test_string_list) const
881  {
882  std::vector<std::string> split_list =
883  Utilities::split_string_list(test_string_list, separator);
884  if ((split_list.size() < min_elements) ||
885  (split_list.size() > max_elements))
886  return false;
887 
888  for (const auto &key_value_pair : split_list)
889  {
890  std::vector<std::string> pair =
892 
893  // Check that we have in fact two matches
894  if (pair.size() != 2)
895  return false;
896 
897  // then verify that the patterns are satisfied
898  if (key_pattern->match(pair[0]) == false)
899  return false;
900  if (value_pattern->match(pair[1]) == false)
901  return false;
902  }
903 
904  return true;
905  }
906 
907 
908 
909  std::string
910  Map::description(const OutputStyle style) const
911  {
912  switch (style)
913  {
914  case Machine:
915  {
916  std::ostringstream description;
917 
918  description << description_init << " of <"
919  << key_pattern->description(style) << ">"
920  << key_value_separator << "<"
921  << value_pattern->description(style) << ">"
922  << " of length " << min_elements << "..."
923  << max_elements << " (inclusive)";
924  if (separator != ",")
925  description << " separated by <" << separator << ">";
926  description << "]";
927 
928  return description.str();
929  }
930  case Text:
931  case LaTeX:
932  {
933  std::ostringstream description;
934 
935  description << "A key"
937  << "value map of " << min_elements << " to "
938  << max_elements << " elements ";
939  if (separator != ",")
940  description << " separated by <"
941  << internal::escape(separator, style) << "> ";
942  description << " where each key is ["
943  << key_pattern->description(style) << "]"
944  << " and each value is ["
945  << value_pattern->description(style) << "]";
946 
947  return description.str();
948  }
949  default:
950  AssertThrow(false, ExcNotImplemented());
951  }
952  // Should never occur without an exception, but prevent compiler from
953  // complaining
954  return "";
955  }
956 
957 
958 
959  std::unique_ptr<PatternBase>
960  Map::clone() const
961  {
962  return std::unique_ptr<PatternBase>(new Map(*key_pattern,
963  *value_pattern,
964  min_elements,
965  max_elements,
966  separator,
968  }
969 
970 
971  std::size_t
973  {
974  return (sizeof(*this) +
979  }
980 
981 
982 
983  std::unique_ptr<Map>
984  Map::create(const std::string &description)
985  {
986  if (description.compare(0,
987  std::strlen(description_init),
988  description_init) == 0)
989  {
990  unsigned int min_elements = 0, max_elements = 0;
991 
992  std::istringstream is(description);
993  is.ignore(std::strlen(description_init) + std::strlen(" of <"));
994 
995  std::string key;
996  std::getline(is, key, '>');
997 
998  std::string key_value_separator;
999  std::getline(is, key_value_separator, '<');
1000 
1001  // split 'str' into key and value
1002  std::string value;
1003  std::getline(is, value, '>');
1004 
1005  std::unique_ptr<PatternBase> key_pattern(pattern_factory(key));
1006  std::unique_ptr<PatternBase> value_pattern(pattern_factory(value));
1007 
1008  is.ignore(std::strlen(" of length "));
1009  if (!(is >> min_elements))
1010  return std::make_unique<Map>(*key_pattern, *value_pattern);
1011 
1012  is.ignore(std::strlen("..."));
1013  if (!(is >> max_elements))
1014  return std::make_unique<Map>(*key_pattern,
1015  *value_pattern,
1016  min_elements);
1017 
1018  is.ignore(std::strlen(" (inclusive) separated by <"));
1019  std::string separator;
1020  if (!is.eof())
1021  std::getline(is, separator, '>');
1022  else
1023  separator = ",";
1024 
1025  return std::make_unique<Map>(*key_pattern,
1026  *value_pattern,
1027  min_elements,
1028  max_elements,
1029  separator,
1031  }
1032  else
1033  return std::unique_ptr<Map>();
1034  }
1035 
1036 
1037 
1038  const PatternBase &
1040  {
1041  return *key_pattern;
1042  }
1043 
1044 
1045 
1046  const PatternBase &
1048  {
1049  return *value_pattern;
1050  }
1051 
1052 
1053 
1054  const std::string &
1056  {
1057  return separator;
1058  }
1059 
1060 
1061  const std::string &
1063  {
1064  return key_value_separator;
1065  }
1066 
1067 
1068 
1069  const char *Tuple::description_init = "[Tuple";
1070 
1071 
1072  Tuple::Tuple(const std::vector<std::unique_ptr<PatternBase>> &ps,
1073  const std::string &separator)
1074  : separator(separator)
1075  {
1076  Assert(ps.size() > 0,
1077  ExcMessage("The Patterns list must have a non-zero length."));
1078  Assert(separator.size() > 0,
1079  ExcMessage("The separator must have a non-zero length."));
1080  patterns.resize(ps.size());
1081  for (unsigned int i = 0; i < ps.size(); ++i)
1082  patterns[i] = ps[i]->clone();
1083  }
1084 
1085 
1086 
1087  Tuple::Tuple(const std::vector<std::unique_ptr<PatternBase>> &ps,
1088  const char *separator)
1089  : Tuple(ps, std::string(separator))
1090  {}
1091 
1092 
1093 
1094  Tuple::Tuple(const Tuple &other)
1095  : separator(other.separator)
1096  {
1097  patterns.resize(other.patterns.size());
1098  for (unsigned int i = 0; i < other.patterns.size(); ++i)
1099  patterns[i] = other.patterns[i]->clone();
1100  }
1101 
1102 
1103 
1104  bool
1105  Tuple::match(const std::string &test_string_list) const
1106  {
1107  std::vector<std::string> split_list =
1108  Utilities::split_string_list(test_string_list, separator);
1109  if (split_list.size() != patterns.size())
1110  return false;
1111 
1112  for (unsigned int i = 0; i < patterns.size(); ++i)
1113  {
1114  if (patterns[i]->match(split_list[i]) == false)
1115  return false;
1116  }
1117 
1118  return true;
1119  }
1120 
1121 
1122 
1123  std::string
1124  Tuple::description(const OutputStyle style) const
1125  {
1126  switch (style)
1127  {
1128  case Machine:
1129  {
1130  std::ostringstream description;
1131 
1132  description << description_init << " of <" << patterns.size()
1133  << "> elements <" << patterns[0]->description(style)
1134  << ">";
1135  for (unsigned int i = 1; i < patterns.size(); ++i)
1136  description << ", <" << patterns[i]->description(style) << ">";
1137 
1138  if (separator != ":")
1139  description << " separated by <" << separator << ">";
1140  description << "]";
1141 
1142  return description.str();
1143  }
1144  case Text:
1145  case LaTeX:
1146  {
1147  std::ostringstream description;
1148 
1149  description << "A Tuple of " << patterns.size() << " elements ";
1150  if (separator != ":")
1151  description << " separated by <"
1152  << internal::escape(separator, style) << "> ";
1153  description << " where each element is ["
1154  << patterns[0]->description(style) << "]";
1155  for (unsigned int i = 1; i < patterns.size(); ++i)
1156  {
1157  description << internal::escape(separator, style) << "["
1158  << patterns[i]->description(style) << "]";
1159  }
1160  return description.str();
1161  }
1162 
1163  default:
1164  AssertThrow(false, ExcNotImplemented());
1165  }
1166  // Should never occur without an exception, but prevent compiler from
1167  // complaining
1168  return "";
1169  }
1170 
1171 
1172 
1173  std::unique_ptr<PatternBase>
1175  {
1176  return std::unique_ptr<PatternBase>(new Tuple(patterns, separator));
1177  }
1178 
1179 
1180  std::size_t
1182  {
1183  return (sizeof(*this) + MemoryConsumption::memory_consumption(patterns) +
1185  }
1186 
1187 
1188 
1189  std::unique_ptr<Tuple>
1190  Tuple::create(const std::string &description)
1191  {
1192  if (description.compare(0,
1193  std::strlen(description_init),
1194  description_init) == 0)
1195  {
1196  std::vector<std::unique_ptr<PatternBase>> patterns;
1197 
1198  std::istringstream is(description);
1199  is.ignore(std::strlen(description_init) + std::strlen(" of <"));
1200 
1201  std::string len;
1202  std::getline(is, len, '>');
1203  const unsigned int n_elements = Utilities::string_to_int(len);
1204  Assert(n_elements > 0,
1205  ExcMessage("Provide at least 1 element in the tuple."));
1206  patterns.resize(n_elements);
1207 
1208  is.ignore(std::strlen(" elements <"));
1209 
1210  std::string element;
1211  std::getline(is, element, '>');
1212  patterns[0] = pattern_factory(element);
1213 
1214  for (unsigned int i = 1; i < n_elements; ++i)
1215  {
1216  is.ignore(std::strlen(", <"));
1217  std::getline(is, element, '>');
1218  patterns[i] = pattern_factory(element);
1219  }
1220 
1221  is.ignore(std::strlen(" separated by <"));
1222 
1223  std::string separator;
1224  if (!is.eof())
1225  std::getline(is, separator, '>');
1226  else
1227  separator = ":";
1228 
1229  return std::make_unique<Tuple>(patterns, separator);
1230  }
1231  else
1232  return std::unique_ptr<Tuple>();
1233  }
1234 
1235 
1236 
1237  const PatternBase &
1238  Tuple::get_pattern(const unsigned int i) const
1239  {
1240  return *patterns[i];
1241  }
1242 
1243 
1244 
1245  const std::string &
1247  {
1248  return separator;
1249  }
1250 
1251 
1252 
1253  const char *MultipleSelection::description_init = "[MultipleSelection";
1254 
1255 
1257  {
1258  Assert(seq.find(',') == std::string::npos,
1259  ExcCommasNotAllowed(seq.find(',')));
1260 
1261  sequence = seq;
1262  while (sequence.find(" |") != std::string::npos)
1263  sequence.replace(sequence.find(" |"), 2, "|");
1264  while (sequence.find("| ") != std::string::npos)
1265  sequence.replace(sequence.find("| "), 2, "|");
1266  }
1267 
1268 
1269 
1270  bool
1271  MultipleSelection::match(const std::string &test_string_list) const
1272  {
1273  std::string tmp = test_string_list;
1274  std::vector<std::string> split_names;
1275 
1276  // first split the input list
1277  while (tmp.size() != 0)
1278  {
1279  std::string name;
1280  name = tmp;
1281 
1282  if (name.find(',') != std::string::npos)
1283  {
1284  name.erase(name.find(','), std::string::npos);
1285  tmp.erase(0, tmp.find(',') + 1);
1286  }
1287  else
1288  tmp = "";
1289 
1290  while ((name.size() != 0) && (std::isspace(name.front()) != 0))
1291  name.erase(0, 1);
1292  while ((name.size() != 0) && (std::isspace(name.back()) != 0))
1293  name.erase(name.size() - 1, 1);
1294 
1295  split_names.push_back(name);
1296  }
1297 
1298 
1299  // check the different possibilities
1300  for (const auto &test_string : split_names)
1301  {
1302  bool string_found = false;
1303 
1304  tmp = sequence;
1305  while (tmp.find('|') != std::string::npos)
1306  {
1307  if (test_string == std::string(tmp, 0, tmp.find('|')))
1308  {
1309  // string found, quit
1310  // loop. don't change
1311  // tmp, since we don't
1312  // need it anymore.
1313  string_found = true;
1314  break;
1315  }
1316 
1317  tmp.erase(0, tmp.find('|') + 1);
1318  }
1319  // check last choice, not finished by |
1320  if (!string_found)
1321  if (test_string == tmp)
1322  string_found = true;
1323 
1324  if (!string_found)
1325  return false;
1326  }
1327 
1328  return true;
1329  }
1330 
1331 
1332 
1333  std::string
1335  {
1336  switch (style)
1337  {
1338  case Machine:
1339  {
1340  std::ostringstream description;
1341 
1342  description << description_init << " " << sequence << " ]";
1343 
1344  return description.str();
1345  }
1346  case Text:
1347  case LaTeX:
1348  {
1349  std::ostringstream description;
1350 
1351  description << "A comma-separated list of any of "
1352  << internal::escape(
1354  style);
1355 
1356  return description.str();
1357  }
1358  default:
1359  AssertThrow(false, ExcNotImplemented());
1360  }
1361  // Should never occur without an exception, but prevent compiler from
1362  // complaining
1363  return "";
1364  }
1365 
1366 
1367 
1368  std::unique_ptr<PatternBase>
1370  {
1371  return std::unique_ptr<PatternBase>(new MultipleSelection(sequence));
1372  }
1373 
1374 
1375  std::size_t
1377  {
1378  return (sizeof(PatternBase) +
1380  }
1381 
1382 
1383 
1384  std::unique_ptr<MultipleSelection>
1385  MultipleSelection::create(const std::string &description)
1386  {
1387  if (description.compare(0,
1388  std::strlen(description_init),
1389  description_init) == 0)
1390  {
1391  std::string sequence(description);
1392 
1393  sequence.erase(0, std::strlen(description_init) + 1);
1394  sequence.erase(sequence.size() - 2, 2);
1395 
1396  return std::make_unique<MultipleSelection>(sequence);
1397  }
1398  else
1399  return std::unique_ptr<MultipleSelection>();
1400  }
1401 
1402 
1403 
1404  const char *Bool::description_init = "[Bool";
1405 
1406 
1408  : Selection("true|false")
1409  {}
1410 
1411 
1412 
1413  std::string
1414  Bool::description(const OutputStyle style) const
1415  {
1416  switch (style)
1417  {
1418  case Machine:
1419  {
1420  std::ostringstream description;
1421 
1422  description << description_init << "]";
1423 
1424  return description.str();
1425  }
1426  case Text:
1427  case LaTeX:
1428  {
1429  return "A boolean value (true or false)";
1430  }
1431  default:
1432  AssertThrow(false, ExcNotImplemented());
1433  }
1434  // Should never occur without an exception, but prevent compiler from
1435  // complaining
1436  return "";
1437  }
1438 
1439 
1440 
1441  std::unique_ptr<PatternBase>
1442  Bool::clone() const
1443  {
1444  return std::unique_ptr<PatternBase>(new Bool());
1445  }
1446 
1447 
1448 
1449  std::unique_ptr<Bool>
1450  Bool::create(const std::string &description)
1451  {
1452  if (description.compare(0,
1453  std::strlen(description_init),
1454  description_init) == 0)
1455  return std::make_unique<Bool>();
1456  else
1457  return std::unique_ptr<Bool>();
1458  }
1459 
1460 
1461 
1462  const char *Anything::description_init = "[Anything";
1463 
1464 
1465 
1466  bool
1467  Anything::match(const std::string &) const
1468  {
1469  return true;
1470  }
1471 
1472 
1473 
1474  std::string
1476  {
1477  switch (style)
1478  {
1479  case Machine:
1480  {
1481  std::ostringstream description;
1482 
1483  description << description_init << "]";
1484 
1485  return description.str();
1486  }
1487  case Text:
1488  case LaTeX:
1489  {
1490  return "Any string";
1491  }
1492  default:
1493  AssertThrow(false, ExcNotImplemented());
1494  }
1495  // Should never occur without an exception, but prevent compiler from
1496  // complaining
1497  return "";
1498  }
1499 
1500 
1501 
1502  std::unique_ptr<PatternBase>
1504  {
1505  return std::unique_ptr<PatternBase>(new Anything());
1506  }
1507 
1508 
1509 
1510  std::unique_ptr<Anything>
1511  Anything::create(const std::string &description)
1512  {
1513  if (description.compare(0,
1514  std::strlen(description_init),
1515  description_init) == 0)
1516  return std::make_unique<Anything>();
1517  else
1518  return std::unique_ptr<Anything>();
1519  }
1520 
1521 
1522 
1523  const char *FileName::description_init = "[FileName";
1524 
1525 
1527  : file_type(type)
1528  {}
1529 
1530 
1531 
1532  bool
1533  FileName::match(const std::string &) const
1534  {
1535  return true;
1536  }
1537 
1538 
1539 
1540  std::string
1542  {
1543  switch (style)
1544  {
1545  case Machine:
1546  {
1547  std::ostringstream description;
1548 
1550 
1551  if (file_type == input)
1552  description << " (Type: input)]";
1553  else
1554  description << " (Type: output)]";
1555 
1556  return description.str();
1557  }
1558  case Text:
1559  case LaTeX:
1560  {
1561  if (file_type == input)
1562  return "an input filename";
1563  else
1564  return "an output filename";
1565  }
1566  default:
1567  AssertThrow(false, ExcNotImplemented());
1568  }
1569  // Should never occur without an exception, but prevent compiler from
1570  // complaining
1571  return "";
1572  }
1573 
1574 
1575 
1576  std::unique_ptr<PatternBase>
1578  {
1579  return std::unique_ptr<PatternBase>(new FileName(file_type));
1580  }
1581 
1582 
1583 
1584  std::unique_ptr<FileName>
1585  FileName::create(const std::string &description)
1586  {
1587  if (description.compare(0,
1588  std::strlen(description_init),
1589  description_init) == 0)
1590  {
1591  std::istringstream is(description);
1592  std::string file_type;
1593  FileType type;
1594 
1595  is.ignore(std::strlen(description_init) + std::strlen(" (Type:"));
1596 
1597  is >> file_type;
1598 
1599  if (file_type == "input)]")
1600  type = input;
1601  else
1602  type = output;
1603 
1604  return std::make_unique<FileName>(type);
1605  }
1606  else
1607  return std::unique_ptr<FileName>();
1608  }
1609 
1610 
1611 
1612  const char *DirectoryName::description_init = "[DirectoryName";
1613 
1614 
1615 
1616  bool
1617  DirectoryName::match(const std::string &) const
1618  {
1619  return true;
1620  }
1621 
1622 
1623 
1624  std::string
1626  {
1627  switch (style)
1628  {
1629  case Machine:
1630  {
1631  std::ostringstream description;
1632 
1633  description << description_init << "]";
1634 
1635  return description.str();
1636  }
1637  case Text:
1638  case LaTeX:
1639  {
1640  return "A directory name";
1641  }
1642  default:
1643  AssertThrow(false, ExcNotImplemented());
1644  }
1645  // Should never occur without an exception, but prevent compiler from
1646  // complaining
1647  return "";
1648  }
1649 
1650 
1651 
1652  std::unique_ptr<PatternBase>
1654  {
1655  return std::unique_ptr<PatternBase>(new DirectoryName());
1656  }
1657 
1658 
1659 
1660  std::unique_ptr<DirectoryName>
1661  DirectoryName::create(const std::string &description)
1662  {
1663  if (description.compare(0,
1664  std::strlen(description_init),
1665  description_init) == 0)
1666  return std::make_unique<DirectoryName>();
1667  else
1668  return std::unique_ptr<DirectoryName>();
1669  }
1670 
1671 } // end namespace Patterns
1672 
static std::unique_ptr< Anything > create(const std::string &description)
Definition: patterns.cc:1511
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1467
static const char * description_init
Definition: patterns.h:1064
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1475
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1503
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1414
static const char * description_init
Definition: patterns.h:1015
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1442
static std::unique_ptr< Bool > create(const std::string &description)
Definition: patterns.cc:1450
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1653
static const char * description_init
Definition: patterns.h:1204
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1625
static std::unique_ptr< DirectoryName > create(const std::string &description)
Definition: patterns.cc:1661
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1617
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:1533
FileName(const FileType type=input)
Definition: patterns.cc:1526
static const char * description_init
Definition: patterns.h:1146
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1577
static std::unique_ptr< FileName > create(const std::string &description)
Definition: patterns.cc:1585
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1541
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:984
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:1039
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:880
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:840
const unsigned int max_elements
Definition: patterns.h:704
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:960
const PatternBase & get_value_pattern() const
Definition: patterns.cc:1047
const std::string & get_separator() const
Definition: patterns.cc:1055
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:910
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:972
static const char * description_init
Definition: patterns.h:720
const std::string & get_key_value_separator() const
Definition: patterns.cc:1062
const std::string key_value_separator
Definition: patterns.h:715
MultipleSelection(const std::string &seq)
Definition: patterns.cc:1256
static std::unique_ptr< MultipleSelection > create(const std::string &description)
Definition: patterns.cc:1385
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1271
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1369
static const char * description_init
Definition: patterns.h:973
std::size_t memory_consumption() const override
Definition: patterns.cc:1376
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1334
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:1105
Tuple(const std::vector< std::unique_ptr< PatternBase >> &patterns, const std::string &separator=":")
Definition: patterns.cc:1072
std::size_t memory_consumption() const override
Definition: patterns.cc:1181
static std::unique_ptr< Tuple > create(const std::string &description)
Definition: patterns.cc:1190
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:879
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1174
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:1246
const PatternBase & get_pattern(const unsigned int i) const
Definition: patterns.cc:1238
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1124
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:477
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:478
static ::ExceptionBase & ExcInvalidRange(int arg1, int arg2)
#define Assert(cond, exc)
Definition: exceptions.h:1631
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:1732
std::enable_if_t< std::is_fundamental_v< T >, 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:1008
int string_to_int(const std::string &s)
Definition: utilities.cc:606