--- /dev/null
+New:Created a new Patterns::Tuple class, that allows parsing arbitrary tuples
+of objects in parameter files.
+<br>
+(Luca Heltai, 2017/10/26)
};
+
+ /**
+ * This pattern matches comma-separated values of arbitrary types. Each type
+ * has to match a pattern given to the constructor.
+ *
+ * The constructor expects a vector of Patterns, and optionally an
+ * std::string, specifying the separator to use when parsing the Tuple from a
+ * string.
+ */
+ class Tuple : public PatternBase
+ {
+ public:
+ /**
+ * Constructor. Specify each pattern that the Tuple should contain.
+ *
+ * Optionally specify a separator string.
+ */
+
+ /**
+ * Constructor.
+ * @param patterns The pattern each object of the Tuple should match
+ * @param separator An optional string used to delimit each element
+ */
+ Tuple (const std::vector<std::unique_ptr<PatternBase> > &patterns,
+ const std::string &separator = ",");
+
+ /**
+ * Copy constructor.
+ */
+ Tuple (const Tuple &other);
+
+ /**
+ * Return <tt>true</tt> if the string is a list of strings
+ * each of which matches the patterns given to the constructor.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match.
+ */
+ virtual std::string description (const OutputStyle style=Machine) const;
+
+ /**
+ * Return a copy of the present object, which is newly allocated on the
+ * heap. Ownership of that object is transferred to the caller of this
+ * function.
+ */
+ virtual std::unique_ptr<PatternBase> clone () const;
+
+ /**
+ * Creates new object if the start of description matches
+ * description_init. Ownership of that object is transferred to the
+ * caller of this function.
+ */
+ static std::unique_ptr<Tuple> create (const std::string &description);
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
+ */
+ std::size_t memory_consumption () const;
+
+ /**
+ * Return a reference to the i-th pattern in the tuple.
+ */
+ const PatternBase &get_pattern(const unsigned int &i) const;
+
+ /**
+ * Return the separator of the tuple entries.
+ */
+ const std::string &get_separator() const;
+
+ private:
+ /**
+ * Copy of the patterns stored in the Tuple.
+ */
+ std::vector<std::unique_ptr<PatternBase> > patterns;
+
+ /**
+ * Separator between elements of the list.
+ */
+ const std::string separator;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+
+
/**
* This class is much like the Selection class, but it allows the input to
* be a comma-separated list of values which each have to be given in the
}
+
+ const char *Tuple::description_init = "[Tuple";
+
+
+ Tuple::Tuple (const std::vector<std::unique_ptr<PatternBase> > &ps,
+ const std::string &separator)
+ :
+ separator (separator)
+ {
+ Assert (ps.size() > 0,
+ ExcMessage ("The Patterns list must have a non-zero length."));
+ Assert (separator.size() > 0,
+ ExcMessage ("The separator must have a non-zero length."));
+ patterns.resize(ps.size());
+ for (unsigned int i=0; i<ps.size(); ++i)
+ patterns[i] = ps[i]->clone();
+ }
+
+
+
+ Tuple::Tuple (const Tuple &other)
+ :
+ separator (other.separator)
+ {
+ patterns.resize(other.patterns.size());
+ for (unsigned int i=0; i<other.patterns.size(); ++i)
+ patterns[i] = other.patterns[i]->clone();
+ }
+
+
+
+ bool Tuple::match (const std::string &test_string_list) const
+ {
+ std::vector<std::string> split_list =
+ Utilities::split_string_list(test_string_list, separator);
+ if (split_list.size() != patterns.size())
+ return false;
+
+ for (unsigned int i=0; i<patterns.size(); ++i)
+ {
+ if (patterns[i]->match (split_list[i]) == false)
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ std::string Tuple::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << " of <"
+ << patterns.size() << "> elements <"
+ << patterns[0]->description(style)
+ << ">";
+ for (unsigned int i=1; i<patterns.size(); ++i)
+ description << ", <"
+ << patterns[i]->description(style)
+ << ">";
+
+ if (separator != ",")
+ description << " separated by <" << separator << ">";
+ description << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ std::ostringstream description;
+
+ description << "A Tuple of "
+ << patterns.size()
+ << " elements ";
+ if (separator != ",")
+ description << " separated by <" << separator << "> ";
+ description << " where each element is ["
+ << patterns[0]->description(style)
+ << "]";
+ for (unsigned int i=1; i<patterns.size(); ++i)
+ {
+ description << separator
+ << "[" << patterns[i]->description(style) << "]";
+
+ return description.str();
+ }
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> Tuple::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Tuple(patterns, separator));
+ }
+
+
+ std::size_t
+ Tuple::memory_consumption () const
+ {
+ return (sizeof(*this) +
+ MemoryConsumption::memory_consumption (patterns) +
+ MemoryConsumption::memory_consumption (separator));
+ }
+
+
+
+ std::unique_ptr<Tuple> Tuple::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ std::vector<std::unique_ptr<PatternBase> > patterns;
+
+ std::istringstream is(description);
+ is.ignore(strlen(description_init) + strlen(" of <"));
+
+ std::string len;
+ std::getline(is, len, '>');
+ const unsigned int n_elements = Utilities::string_to_int(len);
+ Assert(n_elements>0,
+ ExcMessage("Provide at least 1 element in the tuple."));
+ patterns.resize(n_elements);
+
+ is.ignore(strlen(" elements <"));
+
+ std::string element;
+ std::getline(is, element, '>');
+ patterns[0] = pattern_factory(element);
+
+ for (unsigned int i=1; i<n_elements; ++i)
+ {
+ is.ignore(strlen(", <"));
+ std::getline(is, element, '>');
+ patterns[i] = pattern_factory(element);
+ }
+
+ is.ignore(strlen(" separated by <"));
+
+ std::string separator;
+ if (is)
+ std::getline(is, separator, '>');
+ else
+ separator = ",";
+
+ return std::unique_ptr<Tuple>(new Tuple(patterns,separator));
+ }
+ else
+ return std::unique_ptr<Tuple>();
+ }
+
+
+
+ const PatternBase &Tuple::get_pattern(const unsigned int &i) const
+ {
+ return *patterns[i];
+ }
+
+
+
+ const std::string &Tuple::get_separator() const
+ {
+ return separator;
+ }
+
+
+
const char *MultipleSelection::description_init = "[MultipleSelection";
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2015 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/std_cxx14/memory.h>
+#include <memory>
+
+int main()
+{
+ initlog();
+
+ // create a pattern and let it
+ // output its description
+ std::vector<std::unique_ptr<Patterns::PatternBase> > ps;
+ ps.push_back(std_cxx14::make_unique<Patterns::Integer>());
+ ps.push_back(std_cxx14::make_unique<Patterns::Double>());
+ ps.push_back(std_cxx14::make_unique<Patterns::Anything>());
+
+ Patterns::Tuple pattern(ps, ";");
+ const std::string desc = pattern.description();
+
+ // now let the same class re-create
+ // a pattern object from the
+ // description and verify that the
+ // result is the same as what we
+ // started out with
+ std::unique_ptr<Patterns::Tuple> pattern2 = Patterns::Tuple::create (desc);
+
+ AssertThrow (pattern2 != nullptr, ExcInternalError());
+ AssertThrow (desc == pattern2->description(), ExcInternalError());
+
+ deallog << desc << std::endl;
+}
--- /dev/null
+
+DEAL::[Tuple of <3> elements <[Integer range -2147483648...2147483647 (inclusive)]>, <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]>, <[Anything]> separated by <;>]
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2015 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/std_cxx14/memory.h>
+#include <memory>
+
+int main()
+{
+ initlog();
+
+ // create a pattern and match a string
+ std::vector<std::unique_ptr<Patterns::PatternBase> > ps;
+ ps.push_back(std_cxx14::make_unique<Patterns::Integer>());
+ ps.push_back(std_cxx14::make_unique<Patterns::Double>());
+ ps.push_back(std_cxx14::make_unique<Patterns::Anything>());
+
+ Patterns::Tuple pattern(ps, ";");
+ const std::string desc = pattern.description();
+
+ deallog << desc << std::endl;
+
+ std::string test = "5; 3.14; Ciao";
+
+ if (pattern.match(test))
+ deallog << "OK" << std::endl;
+ else
+ deallog << "Not OK" << std::endl;
+}
--- /dev/null
+
+DEAL::[Tuple of <3> elements <[Integer range -2147483648...2147483647 (inclusive)]>, <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]>, <[Anything]> separated by <;>]
+DEAL::OK