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