]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Patterns: Fix parsing lists of lists
authorDaniel Arndt <arndtd@ornl.gov>
Tue, 16 May 2023 17:57:16 +0000 (13:57 -0400)
committerDaniel Arndt <arndtd@ornl.gov>
Tue, 16 May 2023 18:19:53 +0000 (14:19 -0400)
doc/news/changes/minor/20230516DanielArndt [new file with mode: 0644]
source/base/patterns.cc
tests/parameter_handler/patterns_18.cc [new file with mode: 0644]
tests/parameter_handler/patterns_18.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20230516DanielArndt b/doc/news/changes/minor/20230516DanielArndt
new file mode 100644 (file)
index 0000000..6ab8ac7
--- /dev/null
@@ -0,0 +1,3 @@
+Fixed: Patterns::pattern_factory now parses lists of lists correctly.
+<br>
+(Daniel Arndt, 2023/05/16)
index 69322932e4c232d20c07fef0f60b758dc3fc1433..e76155a937c8157b308633cf0ec847b0140a5b28 100644 (file)
@@ -780,15 +780,30 @@ namespace Patterns
       {
         unsigned int min_elements = 0, max_elements = 0;
 
-        std::istringstream is(description);
-        is.ignore(strlen(description_init) + strlen(" of <"));
+        std::string::const_iterator it =
+          description.begin() + strlen(description_init) + strlen(" of <");
 
-        std::string str;
-        std::getline(is, str, '>');
+        int  n_open_angular = 1;
+        auto tmp_it         = it - 1;
+        while (n_open_angular > 0)
+          {
+            tmp_it = std::find_if(tmp_it + 1, description.end(), [](char c) {
+              return (c == '>' || c == '<');
+            });
+            Assert(tmp_it != description.end(),
+                   ExcMessage("Couldn't find a closing '>' in description!"));
+            if (*tmp_it == '<')
+              ++n_open_angular;
+            else
+              --n_open_angular;
+          }
 
-        std::unique_ptr<PatternBase> base_pattern(pattern_factory(str));
+        std::string                  base_pattern_string(it, tmp_it);
+        std::unique_ptr<PatternBase> base_pattern(
+          pattern_factory(base_pattern_string));
 
-        is.ignore(strlen(" of length "));
+        std::istringstream is(
+          std::string(tmp_it + strlen(" of length "), description.end()));
         if (!(is >> min_elements))
           return std::make_unique<List>(*base_pattern);
 
diff --git a/tests/parameter_handler/patterns_18.cc b/tests/parameter_handler/patterns_18.cc
new file mode 100644 (file)
index 0000000..7432747
--- /dev/null
@@ -0,0 +1,61 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+// test that lists of lists are parsed correctly
+#include <deal.II/base/patterns.h>
+
+#include "../tests.h"
+
+int
+main()
+{
+  initlog();
+
+  // Example parameter pattern for a list of lists
+  const std::string description =
+    "[List of <[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 3...3 (inclusive) separated by < >]> of length 0...4294967295 (inclusive)]";
+  // The above pattern describes a list of lists of 3 doubles, e.g.:
+  // "1 2 3,1.2 3.2 1.2" is valid
+  // "1.2,1.3,1.4,1.6 1.2,1.3,1.0,1.5,6.5,5.1 7.6,13.5,1.5" is not valid
+
+  // Parse the description in deal.ii
+  std::unique_ptr<dealii::Patterns::PatternBase> pattern =
+    dealii::Patterns::pattern_factory(description);
+
+  // Write the original and parsed description
+  deallog << "Original description: " << std::endl
+          << description << std::endl
+          << std::endl
+          << "Parsed description: " << std::endl
+          << pattern->description(dealii::Patterns::PatternBase::Machine)
+          << std::endl;
+
+  // First check, should be a match
+  deallog << "First check: \"\" is "
+          << (pattern->match("") ? "a match" : "not a match") << std::endl;
+
+  // Second check, should be a match
+  deallog << "Second check: \"1 2 3,1.2 3.2 1.2\" is "
+          << (pattern->match("1 2 3,1.2 3.2 1.2") ? "a match" : "not a match")
+          << std::endl;
+
+  // Third check, should not be a match
+  deallog
+    << "Third check: \"1.2,1.3,1.4,1.6 1.2,1.3,1.0,1.5,6.5,5.1 7.6,13.5,1.5\" is "
+    << (pattern->match("1.2,1.3,1.4,1.6 1.2,1.3,1.0,1.5,6.5,5.1 7.6,13.5,1.5") ?
+          "a match" :
+          "not a match")
+    << std::endl;
+}
diff --git a/tests/parameter_handler/patterns_18.output b/tests/parameter_handler/patterns_18.output
new file mode 100644 (file)
index 0000000..55c7ba1
--- /dev/null
@@ -0,0 +1,9 @@
+
+DEAL::Original description: 
+DEAL::[List of <[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 3...3 (inclusive) separated by < >]> of length 0...4294967295 (inclusive)]
+DEAL::
+DEAL::Parsed description: 
+DEAL::[List of <[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 3...3 (inclusive) separated by < >]> of length 0...4294967295 (inclusive)]
+DEAL::First check: "" is a match
+DEAL::Second check: "1 2 3,1.2 3.2 1.2" is a match
+DEAL::Third check: "1.2,1.3,1.4,1.6 1.2,1.3,1.0,1.5,6.5,5.1 7.6,13.5,1.5" is not a match

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.