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