Reference documentation for deal.II version Git d4ec8156ca 2019-11-18 14:03:00 -0700
\(\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
398  description << lower_bound;
399  description << "...";
400  if (0 == std::memcmp(&upper_bound,
402  sizeof(upper_bound)))
403  description << "MAX_DOUBLE";
404  else
405  description << upper_bound;
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
428  description << lower_bound;
429  description << " <= v <= ";
430  if (0 == std::memcmp(&upper_bound,
432  sizeof(upper_bound)))
433  description << "MAX_DOUBLE";
434  else
435  description << upper_bound;
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
454  description << lower_bound;
455  description << " \\leq v \\leq ";
456  if (0 == std::memcmp(&upper_bound,
458  sizeof(upper_bound)))
459  description << "\\text{MAX\\_DOUBLE}";
460  else
461  description << upper_bound;
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())
520  upper_bound = max_double_value;
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  {
659  Assert(min_elements <= max_elements,
660  ExcInvalidRange(min_elements, max_elements));
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  {
834  Assert(min_elements <= max_elements,
835  ExcInvalidRange(min_elements, max_elements));
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."));
840  Assert(separator != key_value_separator,
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)
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 (const auto &test_string : split_names)
1282  {
1283  bool string_found = false;
1284 
1285  tmp = sequence;
1286  while (tmp.find('|') != std::string::npos)
1287  {
1288  if (test_string == std::string(tmp, 0, tmp.find('|')))
1289  {
1290  // string found, quit
1291  // loop. don't change
1292  // tmp, since we don't
1293  // need it anymore.
1294  string_found = true;
1295  break;
1296  }
1297 
1298  tmp.erase(0, tmp.find('|') + 1);
1299  }
1300  // check last choice, not finished by |
1301  if (!string_found)
1302  if (test_string == tmp)
1303  string_found = true;
1304 
1305  if (!string_found)
1306  return false;
1307  }
1308 
1309  return true;
1310  }
1311 
1312 
1313 
1314  std::string
1316  {
1317  switch (style)
1318  {
1319  case Machine:
1320  {
1321  std::ostringstream description;
1322 
1323  description << description_init << " " << sequence << " ]";
1324 
1325  return description.str();
1326  }
1327  case Text:
1328  case LaTeX:
1329  {
1330  std::ostringstream description;
1331 
1332  description << "A comma-separated list of any of "
1333  << internal::escape(
1334  Utilities::replace_in_string(sequence, "|", ", "),
1335  style);
1336 
1337  return description.str();
1338  }
1339  default:
1340  AssertThrow(false, ExcNotImplemented());
1341  }
1342  // Should never occur without an exception, but prevent compiler from
1343  // complaining
1344  return "";
1345  }
1346 
1347 
1348 
1349  std::unique_ptr<PatternBase>
1351  {
1352  return std::unique_ptr<PatternBase>(new MultipleSelection(sequence));
1353  }
1354 
1355 
1356  std::size_t
1358  {
1359  return (sizeof(PatternBase) +
1361  }
1362 
1363 
1364 
1365  std::unique_ptr<MultipleSelection>
1367  {
1368  if (description.compare(0,
1369  std::strlen(description_init),
1370  description_init) == 0)
1371  {
1372  std::string sequence(description);
1373 
1374  sequence.erase(0, std::strlen(description_init) + 1);
1375  sequence.erase(sequence.length() - 2, 2);
1376 
1377  return std_cxx14::make_unique<MultipleSelection>(sequence);
1378  }
1379  else
1380  return std::unique_ptr<MultipleSelection>();
1381  }
1382 
1383 
1384 
1385  const char *Bool::description_init = "[Bool";
1386 
1387 
1389  : Selection("true|false")
1390  {}
1391 
1392 
1393 
1394  std::string
1395  Bool::description(const OutputStyle style) const
1396  {
1397  switch (style)
1398  {
1399  case Machine:
1400  {
1401  std::ostringstream description;
1402 
1403  description << description_init << "]";
1404 
1405  return description.str();
1406  }
1407  case Text:
1408  case LaTeX:
1409  {
1410  return "A boolean value (true or false)";
1411  }
1412  default:
1413  AssertThrow(false, ExcNotImplemented());
1414  }
1415  // Should never occur without an exception, but prevent compiler from
1416  // complaining
1417  return "";
1418  }
1419 
1420 
1421 
1422  std::unique_ptr<PatternBase>
1423  Bool::clone() const
1424  {
1425  return std::unique_ptr<PatternBase>(new Bool());
1426  }
1427 
1428 
1429 
1430  std::unique_ptr<Bool>
1431  Bool::create(const std::string &description)
1432  {
1433  if (description.compare(0,
1434  std::strlen(description_init),
1435  description_init) == 0)
1436  return std_cxx14::make_unique<Bool>();
1437  else
1438  return std::unique_ptr<Bool>();
1439  }
1440 
1441 
1442 
1443  const char *Anything::description_init = "[Anything";
1444 
1445 
1446 
1447  bool
1448  Anything::match(const std::string &) const
1449  {
1450  return true;
1451  }
1452 
1453 
1454 
1455  std::string
1457  {
1458  switch (style)
1459  {
1460  case Machine:
1461  {
1462  std::ostringstream description;
1463 
1464  description << description_init << "]";
1465 
1466  return description.str();
1467  }
1468  case Text:
1469  case LaTeX:
1470  {
1471  return "Any string";
1472  }
1473  default:
1474  AssertThrow(false, ExcNotImplemented());
1475  }
1476  // Should never occur without an exception, but prevent compiler from
1477  // complaining
1478  return "";
1479  }
1480 
1481 
1482 
1483  std::unique_ptr<PatternBase>
1485  {
1486  return std::unique_ptr<PatternBase>(new Anything());
1487  }
1488 
1489 
1490 
1491  std::unique_ptr<Anything>
1492  Anything::create(const std::string &description)
1493  {
1494  if (description.compare(0,
1495  std::strlen(description_init),
1496  description_init) == 0)
1497  return std_cxx14::make_unique<Anything>();
1498  else
1499  return std::unique_ptr<Anything>();
1500  }
1501 
1502 
1503 
1504  const char *FileName::description_init = "[FileName";
1505 
1506 
1508  : file_type(type)
1509  {}
1510 
1511 
1512 
1513  bool
1514  FileName::match(const std::string &) const
1515  {
1516  return true;
1517  }
1518 
1519 
1520 
1521  std::string
1523  {
1524  switch (style)
1525  {
1526  case Machine:
1527  {
1528  std::ostringstream description;
1529 
1530  description << description_init;
1531 
1532  if (file_type == input)
1533  description << " (Type: input)]";
1534  else
1535  description << " (Type: output)]";
1536 
1537  return description.str();
1538  }
1539  case Text:
1540  case LaTeX:
1541  {
1542  if (file_type == input)
1543  return "an input filename";
1544  else
1545  return "an output filename";
1546  }
1547  default:
1548  AssertThrow(false, ExcNotImplemented());
1549  }
1550  // Should never occur without an exception, but prevent compiler from
1551  // complaining
1552  return "";
1553  }
1554 
1555 
1556 
1557  std::unique_ptr<PatternBase>
1559  {
1560  return std::unique_ptr<PatternBase>(new FileName(file_type));
1561  }
1562 
1563 
1564 
1565  std::unique_ptr<FileName>
1566  FileName::create(const std::string &description)
1567  {
1568  if (description.compare(0,
1569  std::strlen(description_init),
1570  description_init) == 0)
1571  {
1572  std::istringstream is(description);
1573  std::string file_type;
1574  FileType type;
1575 
1576  is.ignore(strlen(description_init) + strlen(" (Type:"));
1577 
1578  is >> file_type;
1579 
1580  if (file_type == "input)]")
1581  type = input;
1582  else
1583  type = output;
1584 
1585  return std_cxx14::make_unique<FileName>(type);
1586  }
1587  else
1588  return std::unique_ptr<FileName>();
1589  }
1590 
1591 
1592 
1593  const char *DirectoryName::description_init = "[DirectoryName";
1594 
1595 
1596 
1597  bool
1598  DirectoryName::match(const std::string &) const
1599  {
1600  return true;
1601  }
1602 
1603 
1604 
1605  std::string
1607  {
1608  switch (style)
1609  {
1610  case Machine:
1611  {
1612  std::ostringstream description;
1613 
1614  description << description_init << "]";
1615 
1616  return description.str();
1617  }
1618  case Text:
1619  case LaTeX:
1620  {
1621  return "A directory name";
1622  }
1623  default:
1624  AssertThrow(false, ExcNotImplemented());
1625  }
1626  // Should never occur without an exception, but prevent compiler from
1627  // complaining
1628  return "";
1629  }
1630 
1631 
1632 
1633  std::unique_ptr<PatternBase>
1635  {
1636  return std::unique_ptr<PatternBase>(new DirectoryName());
1637  }
1638 
1639 
1640 
1641  std::unique_ptr<DirectoryName>
1643  {
1644  if (description.compare(0,
1645  std::strlen(description_init),
1646  description_init) == 0)
1647  return std_cxx14::make_unique<DirectoryName>();
1648  else
1649  return std::unique_ptr<DirectoryName>();
1650  }
1651 
1652 } // end namespace Patterns
1653 
1654 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:603
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:1566
std::string sequence
Definition: patterns.h:435
const double upper_bound
Definition: patterns.h:366
static const char * description_init
Definition: patterns.h:371
static const char * description_init
Definition: patterns.h:1150
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:1598
const PatternBase & get_pattern(const unsigned int i) const
Definition: patterns.cc:1219
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1423
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:888
const std::string separator
Definition: patterns.h:711
static std::unique_ptr< List > create(const std::string &description)
Definition: patterns.cc:773
std::unique_ptr< PatternBase > pattern
Definition: patterns.h:547
static const unsigned int max_int_value
Definition: patterns.h:593
static const char * description_init
Definition: patterns.h:722
std::size_t memory_consumption() const override
Definition: patterns.cc:1357
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1350
STL namespace.
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1448
static const int max_int_value
Definition: patterns.h:205
#define AssertThrow(cond, exc)
Definition: exceptions.h:1523
const std::string & get_separator() const
Definition: patterns.cc:1036
const unsigned int max_elements
Definition: patterns.h:706
static const char * description_init
Definition: patterns.h:977
FileType file_type
Definition: patterns.h:1136
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:1492
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:198
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:358
FileName(const FileType type=input)
Definition: patterns.cc:1507
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:217
static const char * description_init
Definition: patterns.h:567
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:1019
static std::unique_ptr< DirectoryName > create(const std::string &description)
Definition: patterns.cc:1642
std::size_t memory_consumption() const override
Definition: patterns.cc:953
static const char * description_init
Definition: patterns.h:440
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:883
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: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: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:273
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:893
virtual bool match(const std::string &test_string) const override
Definition: patterns.cc:1252
std::unique_ptr< PatternBase > key_pattern
Definition: patterns.h:695
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1395
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:1315
static const double min_double_value
Definition: patterns.h:300
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:1208
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:1514
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:1558
std::size_t memory_consumption() const override
Definition: patterns.cc:764
static const char * description_init
Definition: patterns.h:1068
static const double max_double_value
Definition: patterns.h:306
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:1634
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:1366
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:1431
static std::unique_ptr< Selection > create(const std::string &description)
Definition: patterns.cc:625
const int upper_bound
Definition: patterns.h:268
int string_to_int(const std::string &s)
Definition: utilities.cc:507
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:1606
const unsigned int min_elements
Definition: patterns.h:701
static const unsigned int max_int_value
Definition: patterns.h:459
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:1522
const int lower_bound
Definition: patterns.h:260
virtual std::string description(const OutputStyle style=Machine) const override
Definition: patterns.cc:712
const std::string separator
Definition: patterns.h:562
const std::string key_value_separator
Definition: patterns.h:717
const unsigned int max_elements
Definition: patterns.h:557
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:1456
const unsigned int min_elements
Definition: patterns.h:552
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:1484
virtual std::unique_ptr< PatternBase > clone() const override
Definition: patterns.cc:756