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