]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Added new parameter to Patterns::Map
authorLuca Heltai <luca.heltai@sissa.it>
Wed, 14 Jun 2017 15:54:36 +0000 (17:54 +0200)
committerLuca Heltai <luca.heltai@sissa.it>
Wed, 14 Jun 2017 16:10:12 +0000 (18:10 +0200)
doc/news/changes/minor/20170614LucaHeltai-b [new file with mode: 0644]
include/deal.II/base/parameter_handler.h
source/base/parameter_handler.cc
tests/base/patterns_04.cc [new file with mode: 0644]
tests/base/patterns_04.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20170614LucaHeltai-b b/doc/news/changes/minor/20170614LucaHeltai-b
new file mode 100644 (file)
index 0000000..6518c6a
--- /dev/null
@@ -0,0 +1,5 @@
+New: Patterns::Map now accepts a new optional parameter,
+that allows to specify also the separator between 
+key-value pairs.
+<br>
+(Luca Heltai, 2017/06/14)
index 9e35f26f485ee935221c9a4136755a12ac3f4744..f80fa5bbf64dd6a5dadaaa8a4d97ff4b9d056e51 100644 (file)
@@ -498,8 +498,9 @@ namespace Patterns
    * pattern given to the constructor. For each entry of the map, parameters
    * have to be entered in the form <code>key: value</code>. In other words, a
    * map is described in the form <code>key1: value1, key2: value2, key3:
-   * value3, ...</code>. A constructor argument allows to choose a delimiter
-   * between pairs other than the comma.
+   * value3, ...</code>. Two constructor arguments allow to choose a delimiter
+   * between pairs other than the comma, and a delimeter between key and value
+   * other than column.
    *
    * With two additional parameters, the number of elements this list has to
    * have can be specified. If none is specified, the map may have zero or
@@ -519,15 +520,16 @@ namespace Patterns
      * Constructor. Take the given parameter as the specification of valid
      * elements of the list.
      *
-     * The three other arguments can be used to denote minimal and maximal
-     * allowable lengths of the list as well as the separator used to delimit
-     * pairs of the map.
+     * The four other arguments can be used to denote minimal and maximal
+     * allowable lengths of the list as well as the separators used to delimit
+     * pairs of the map and the symbol used to separate keys and values.
      */
     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  &separator = ",",
+         const std::string  &key_value_separator = ":");
 
     /**
      * Copy constructor.
@@ -602,6 +604,12 @@ namespace Patterns
      */
     const std::string separator;
 
+
+    /**
+     * Separator between keys and values.
+     */
+    const std::string key_value_separator;
+
     /**
      * Initial part of description
      */
index e50971f748e81e1d3475d122bad0763ed906a4c0..5e9b463f47fd5f01d570ef9dcdfd582a21acd579 100644 (file)
@@ -96,6 +96,10 @@ namespace Patterns
     if (p != nullptr )
       return p;
 
+    p = Map::create(description);
+    if (p != nullptr )
+      return p;
+
     p = MultipleSelection::create(description);
     if (p != nullptr )
       return p;
@@ -650,7 +654,7 @@ namespace Patterns
         std::ostringstream description;
 
         description << description_init
-                    << " list of <" << pattern->description(style) << ">"
+                    << " of <" << pattern->description(style) << ">"
                     << " of length " << min_elements << "..." << max_elements
                     << " (inclusive)";
         if (separator != ",")
@@ -708,7 +712,7 @@ namespace Patterns
         int min_elements, max_elements;
 
         std::istringstream is(description);
-        is.ignore(strlen(description_init) + strlen(" list of <"));
+        is.ignore(strlen(description_init) + strlen(" of <"));
 
         std::string str;
         std::getline(is, str, '>');
@@ -723,9 +727,9 @@ namespace Patterns
         if (!(is >> max_elements))
           return std::unique_ptr<List>(new List(*base_pattern, min_elements));
 
-        is.ignore(strlen(" separated by <"));
+        is.ignore(strlen(" (inclusive) separated by <"));
         std::string separator;
-        if (!is)
+        if (is)
           std::getline(is, separator, '>');
         else
           separator = ",";
@@ -748,21 +752,26 @@ namespace Patterns
             const PatternBase  &p_value,
             const unsigned int  min_elements,
             const unsigned int  max_elements,
-            const std::string  &separator)
+            const std::string  &separator,
+            const std::string  &key_value_separator)
     :
     key_pattern (p_key.clone()),
     value_pattern (p_value.clone()),
     min_elements (min_elements),
     max_elements (max_elements),
-    separator (separator)
+    separator (separator),
+    key_value_separator(key_value_separator)
   {
     Assert (min_elements <= max_elements,
             ExcInvalidRange (min_elements, max_elements));
     Assert (separator.size() > 0,
             ExcMessage ("The separator must have a non-zero length."));
-    Assert (separator != ":",
-            ExcMessage ("The separator can not be a colon ':' since that "
-                        "is the separator between the two elements of <key:value> pairs"));
+    Assert (key_value_separator.size() > 0,
+            ExcMessage ("The key_value_separator must have a non-zero length."));
+    Assert (separator != key_value_separator,
+            ExcMessage ("The separator can not be the same of the key_value_separator "
+                        "since that is used as the separator between the two elements "
+                        "of <key:value> pairs"));
   }
 
 
@@ -773,7 +782,8 @@ namespace Patterns
     value_pattern (other.value_pattern->clone()),
     min_elements (other.min_elements),
     max_elements (other.max_elements),
-    separator (other.separator)
+    separator (other.separator),
+    key_value_separator(other.key_value_separator)
   {}
 
 
@@ -781,61 +791,25 @@ namespace Patterns
   bool Map::match (const std::string &test_string_list) const
   {
     std::string tmp = test_string_list;
-    std::vector<std::string> split_list;
-
-    // first split the input list at comma sites
-    while (tmp.length() != 0)
-      {
-        std::string map_entry;
-        map_entry = tmp;
-
-        if (map_entry.find(separator) != std::string::npos)
-          {
-            map_entry.erase (map_entry.find(separator), std::string::npos);
-            tmp.erase (0, tmp.find(separator)+separator.size());
-          }
-        else
-          tmp = "";
-
-        while ((map_entry.length() != 0) &&
-               (std::isspace (map_entry[0])))
-          map_entry.erase (0,1);
-
-        while (std::isspace (map_entry[map_entry.length()-1]))
-          map_entry.erase (map_entry.length()-1, 1);
-
-        split_list.push_back (map_entry);
-      }
-
+    std::vector<std::string> split_list =
+      Utilities::split_string_list(test_string_list, separator);
     if ((split_list.size() < min_elements) ||
         (split_list.size() > max_elements))
       return false;
 
-    // check the different possibilities
-    for (std::vector<std::string>::const_iterator
-         test_string = split_list.begin();
-         test_string != split_list.end(); ++test_string)
+    for (auto &key_value_pair : split_list)
       {
-        // separate key and value from the test_string
-        if (test_string->find(":") == std::string::npos)
-          return false;
-
-        // we know now that there is a ':', so split the string there
-        // and trim spaces
-        std::string key = *test_string;
-        key.erase (key.find(":"), std::string::npos);
-        while ((key.length() > 0) && (std::isspace (key[key.length()-1])))
-          key.erase (key.length()-1, 1);
+        std::vector<std::string> pair =
+          Utilities::split_string_list(key_value_pair, key_value_separator);
 
-        std::string value = *test_string;
-        value.erase (0, value.find(":")+1);
-        while ((value.length() > 0) && (std::isspace (value[0])))
-          value.erase (0, 1);
+        // Check that we have in fact two mathces
+        if (pair.size() != 2)
+          return false;
 
         // then verify that the patterns are satisfied
-        if (key_pattern->match (key) == false)
+        if (key_pattern->match (pair[0]) == false)
           return false;
-        if (value_pattern->match (value) == false)
+        if (value_pattern->match (pair[1]) == false)
           return false;
       }
 
@@ -853,8 +827,9 @@ namespace Patterns
         std::ostringstream description;
 
         description << description_init
-                    << " map of <"
-                    << key_pattern->description(style) << ":"
+                    << " of <"
+                    << key_pattern->description(style) << ">"
+                    << key_value_separator << "<"
                     << value_pattern->description(style) << ">"
                     << " of length " << min_elements << "..." << max_elements
                     << " (inclusive)";
@@ -869,7 +844,9 @@ namespace Patterns
       {
         std::ostringstream description;
 
-        description << "A key-value map of "
+        description << "A key"
+                    << key_value_separator
+                    << "value map of "
                     << min_elements << " to " << max_elements
                     << " elements ";
         if (separator != ",")
@@ -897,7 +874,7 @@ namespace Patterns
   {
     return std::unique_ptr<PatternBase>(new Map(*key_pattern, *value_pattern,
                                                 min_elements, max_elements,
-                                                separator));
+                                                separator, key_value_separator));
   }
 
 
@@ -907,7 +884,8 @@ namespace Patterns
     return (sizeof(*this) +
             MemoryConsumption::memory_consumption (*key_pattern) +
             MemoryConsumption::memory_consumption (*value_pattern) +
-            MemoryConsumption::memory_consumption (separator));
+            MemoryConsumption::memory_consumption (separator)+
+            MemoryConsumption::memory_consumption (key_value_separator));
   }
 
 
@@ -919,17 +897,17 @@ namespace Patterns
         int min_elements, max_elements;
 
         std::istringstream is(description);
-        is.ignore(strlen(description_init) + strlen(" map of <"));
+        is.ignore(strlen(description_init) + strlen(" of <"));
 
-        std::string str;
-        std::getline(is, str, '>');
+        std::string key;
+        std::getline(is, key, '>');
 
-        // split 'str' into key and value
-        std::string key = str;
-        key.erase (key.find(":"), std::string::npos);
+        std::string key_value_separator;
+        std::getline(is, key_value_separator, '<');
 
-        std::string value = str;
-        value.erase (0, value.find(":")+1);
+        // split 'str' into key and value
+        std::string value;
+        std::getline(is, value, '>');
 
         std::shared_ptr<PatternBase> key_pattern (pattern_factory(key));
         std::shared_ptr<PatternBase> value_pattern (pattern_factory(value));
@@ -942,16 +920,16 @@ namespace Patterns
         if (!(is >> max_elements))
           return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern, min_elements));
 
-        is.ignore(strlen(" separated by <"));
+        is.ignore(strlen(" (inclusive) separated by <"));
         std::string separator;
-        if (!is)
+        if (is)
           std::getline(is, separator, '>');
         else
           separator = ",";
 
         return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern,
                                             min_elements, max_elements,
-                                            separator));
+                                            separator, key_value_separator));
       }
     else
       return std::unique_ptr<Map>();
diff --git a/tests/base/patterns_04.cc b/tests/base/patterns_04.cc
new file mode 100644 (file)
index 0000000..8201cb2
--- /dev/null
@@ -0,0 +1,74 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 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 at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// pattern_factory tests
+
+#include "../tests.h"
+#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/logstream.h>
+#include <memory>
+
+
+void
+test(const Patterns::PatternBase &p)
+{
+  // Print description
+  auto desc = p.description();
+  deallog << p.description() << std::endl;
+
+  // Check that we can clone
+  auto p2 = p.clone();
+  deallog << p2->description() << std::endl;
+
+  auto p3 = Patterns::pattern_factory(desc);
+  deallog << p3->description() << std::endl;
+
+  AssertThrow(desc == p2->description(),
+              ExcInternalError("Cloned pattern does not have the same "
+                               "description of the original pattern!"));
+
+  AssertThrow(desc == p3->description(),
+              ExcInternalError("Pattern created using factory "
+                               "does not have the same "
+                               "description of the original pattern!"));
+}
+
+
+using namespace Patterns;
+
+int main()
+{
+  initlog();
+  test(Integer());
+  test(Integer(-1));
+  test(Integer(-1,50));
+
+  test(Double());
+  test(Double(0.0, 50.0));
+
+  test(Bool());
+
+  test(List(Integer()));
+  test(List(Double()));
+  test(List(Bool()));
+
+  test(Selection("alpha|beta"));
+  test(List(Double(),0,3,";"));
+
+  test(Map(Integer(), Double()));
+  test(Map(Integer(0,10), Double(), 0, 10, ";", "="));
+
+  deallog << "OK" << std::endl;
+}
diff --git a/tests/base/patterns_04.output b/tests/base/patterns_04.output
new file mode 100644 (file)
index 0000000..9cf54f1
--- /dev/null
@@ -0,0 +1,41 @@
+
+DEAL::[Integer range -2147483648...2147483647 (inclusive)]
+DEAL::[Integer range -2147483648...2147483647 (inclusive)]
+DEAL::[Integer range -2147483648...2147483647 (inclusive)]
+DEAL::[Integer range -1...2147483647 (inclusive)]
+DEAL::[Integer range -1...2147483647 (inclusive)]
+DEAL::[Integer range -1...2147483647 (inclusive)]
+DEAL::[Integer range -1...50 (inclusive)]
+DEAL::[Integer range -1...50 (inclusive)]
+DEAL::[Integer range -1...50 (inclusive)]
+DEAL::[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]
+DEAL::[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]
+DEAL::[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]
+DEAL::[Double 0...50 (inclusive)]
+DEAL::[Double 0...50 (inclusive)]
+DEAL::[Double 0...50 (inclusive)]
+DEAL::[Bool]
+DEAL::[Bool]
+DEAL::[Bool]
+DEAL::[List of <[Integer range -2147483648...2147483647 (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Integer range -2147483648...2147483647 (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Integer range -2147483648...2147483647 (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Bool]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Bool]> of length 0...4294967295 (inclusive)]
+DEAL::[List of <[Bool]> of length 0...4294967295 (inclusive)]
+DEAL::[Selection alpha|beta ]
+DEAL::[Selection alpha|beta ]
+DEAL::[Selection alpha|beta ]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...3 (inclusive) separated by <;>]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...3 (inclusive) separated by <;>]
+DEAL::[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...3 (inclusive) separated by <;>]
+DEAL::[Map of <[Integer range -2147483648...2147483647 (inclusive)]>:<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[Map of <[Integer range -2147483648...2147483647 (inclusive)]>:<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[Map of <[Integer range -2147483648...2147483647 (inclusive)]>:<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...4294967295 (inclusive)]
+DEAL::[Map of <[Integer range 0...10 (inclusive)]>=<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...10 (inclusive) separated by <;>]
+DEAL::[Map of <[Integer range 0...10 (inclusive)]>=<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...10 (inclusive) separated by <;>]
+DEAL::[Map of <[Integer range 0...10 (inclusive)]>=<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 0...10 (inclusive) separated by <;>]
+DEAL::OK

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.