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