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