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