* 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
* 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.
*/
const std::string separator;
+
+ /**
+ * Separator between keys and values.
+ */
+ const std::string key_value_separator;
+
/**
* Initial part of description
*/
if (p != nullptr )
return p;
+ p = Map::create(description);
+ if (p != nullptr )
+ return p;
+
p = MultipleSelection::create(description);
if (p != nullptr )
return p;
std::ostringstream description;
description << description_init
- << " list of <" << pattern->description(style) << ">"
+ << " of <" << pattern->description(style) << ">"
<< " of length " << min_elements << "..." << max_elements
<< " (inclusive)";
if (separator != ",")
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, '>');
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 = ",";
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"));
}
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)
{}
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;
}
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)";
{
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 != ",")
{
return std::unique_ptr<PatternBase>(new Map(*key_pattern, *value_pattern,
min_elements, max_elements,
- separator));
+ separator, key_value_separator));
}
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));
}
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));
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>();
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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;
+}
--- /dev/null
+
+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