#include <deal.II/base/config.h>
#include <deal.II/base/exceptions.h>
#include <deal.II/base/subscriptor.h>
+#include <deal.II/base/patterns.h>
#include <boost/property_tree/ptree_fwd.hpp>
#include <boost/serialization/split_member.hpp>
class LogStream;
class MultipleParameterLoop;
-/**
- * Namespace for a few classes that act as patterns for the ParameterHandler
- * class. These classes implement an interface that checks whether a parameter
- * in an input file matches a certain pattern, such as "being boolean", "an
- * integer value", etc.
- *
- * @ingroup input
- */
-namespace Patterns
-{
-
- /**
- * Base class to declare common interface. The purpose of this class is
- * mostly to define the interface of patterns, and to force derived classes
- * to have a <tt>clone</tt> function. It is thus, in the languages of the
- * "Design Patterns" book (Gamma et al.), a "prototype".
- */
- class PatternBase
- {
- public:
- /**
- * Make destructor of this and all derived classes virtual.
- */
- virtual ~PatternBase ();
-
- /**
- * Return <tt>true</tt> if the given string matches the pattern.
- */
- virtual bool match (const std::string &test_string) const = 0;
-
- /**
- * List of possible description output formats.
- *
- * Capitalization chosen for similarity to ParameterHandler::OutputStyle.
- */
- enum OutputStyle
- {
- /**
- * Simple text suitable for machine parsing in the static public member
- * functions for all of the built in inheriting classes.
- *
- * Preferably human readable, but machine parsing is more critical.
- */
- Machine,
- /**
- * Easily human readable plain text format suitable for plain text
- * documentation.
- */
- Text,
- /**
- * Easily human readable LaTeX format suitable for printing in manuals.
- */
- LaTeX
- };
-
- /**
- * Return a string describing the pattern.
- */
- virtual std::string description (const OutputStyle style=Machine) const = 0;
-
- /**
- * Return a pointer to an exact copy of the object. This is necessary
- * since we want to store objects of this type in containers, were we need
- * to copy objects without knowledge of their actual data type (we only
- * have pointers to the base class).
- *
- * Ownership of the objects returned by this function is passed to the
- * caller of this function.
- */
- virtual std::unique_ptr<PatternBase> clone () const = 0;
-
- /**
- * Determine an estimate for the memory consumption (in bytes) of this
- * object. To avoid unnecessary overhead, we do not force derived classes
- * to provide this function as a virtual overloaded one, but rather try to
- * cast the present object to one of the known derived classes and if that
- * fails then take the size of this base class instead and add 32 byte
- * (this value is arbitrary, it should account for virtual function
- * tables, and some possible data elements). Since there are usually not
- * many thousands of objects of this type around, and since the
- * memory_consumption mechanism is used to find out where memory in the
- * range of many megabytes is, this seems like a reasonable approximation.
- *
- * On the other hand, if you know that your class deviates from this
- * assumption significantly, you can still overload this function.
- */
- virtual std::size_t memory_consumption () const;
- };
-
- /**
- * Return pointer to the correct derived class based on description.
- */
- std::unique_ptr<PatternBase> pattern_factory (const std::string &description);
-
- /**
- * Test for the string being an integer. If bounds are given to the
- * constructor, then the integer given also needs to be within the interval
- * specified by these bounds. Note that unlike common convention in the C++
- * standard library, both bounds of this interval are inclusive; the reason
- * is that in practice in most cases, one needs closed intervals, but these
- * can only be realized with inclusive bounds for non-integer values. We
- * thus stay consistent by always using closed intervals.
- *
- * If the upper bound given to the constructor is smaller than the
- * lower bound, then every integer is allowed.
- *
- * Giving bounds may be useful if for example a value can only be positive
- * and less than a reasonable upper bound (for example the number of
- * refinement steps to be performed), or in many other cases.
- */
- class Integer : public PatternBase
- {
- public:
- /**
- * Minimal integer value. If the numeric_limits class is available use
- * this information to obtain the extremal values, otherwise set it so
- * that this class understands that all values are allowed.
- */
- static const int min_int_value;
-
- /**
- * Maximal integer value. If the numeric_limits class is available use
- * this information to obtain the extremal values, otherwise set it so
- * that this class understands that all values are allowed.
- */
- static const int max_int_value;
-
- /**
- * Constructor. Bounds can be specified within which a valid
- * parameter has to be. If the upper bound is smaller than the
- * lower bound, then the entire set of integers is implied. The
- * default values are chosen such that no bounds are enforced on
- * parameters.
- */
- Integer (const int lower_bound = min_int_value,
- const int upper_bound = max_int_value);
-
- /**
- * Return <tt>true</tt> if the string is an integer and its value is
- * within the specified range.
- */
- virtual bool match (const std::string &test_string) const;
-
- /**
- * Return a description of the pattern that valid strings are expected to
- * match. If bounds were specified to the constructor, then include them
- * into this description.
- */
- 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<Integer> create (const std::string &description);
-
- private:
- /**
- * Value of the lower bound. A number that satisfies the
- * @ref match
- * operation of this class must be equal to this value or larger, if the
- * bounds of the interval for a valid range.
- */
- const int lower_bound;
-
- /**
- * Value of the upper bound. A number that satisfies the
- * @ref match
- * operation of this class must be equal to this value or less, if the
- * bounds of the interval for a valid range.
- */
- const int upper_bound;
-
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
- /**
- * Test for the string being a <tt>double</tt>. If bounds are given to the
- * constructor, then the integer given also needs to be within the interval
- * specified by these bounds. Note that unlike common convention in the C++
- * standard library, both bounds of this interval are inclusive; the reason
- * is that in practice in most cases, one needs closed intervals, but these
- * can only be realized with inclusive bounds for non-integer values. We
- * thus stay consistent by always using closed intervals.
- *
- * If the upper bound given to the constructor is smaller than the
- * lower bound, then every double precision number is allowed.
- *
- * Giving bounds may be useful if for example a value can only be positive
- * and less than a reasonable upper bound (for example damping parameters
- * are frequently only reasonable if between zero and one), or in many other
- * cases.
- */
- class Double : public PatternBase
- {
- public:
- /**
- * Minimal double value used as default value, taken from
- * <tt>std::numeric_limits</tt>.
- */
- static const double min_double_value;
-
- /**
- * Maximal double value used as default value, taken from
- * <tt>std::numeric_limits</tt>.
- */
- static const double max_double_value;
-
- /**
- * Constructor. Bounds can be specified within which a valid
- * parameter has to be. If the upper bound is smaller than the
- * lower bound, then the entire set of double precision numbers is
- * implied. The default values are chosen such that no bounds are
- * enforced on parameters.
- */
- Double (const double lower_bound = min_double_value,
- const double upper_bound = max_double_value);
-
- /**
- * Return <tt>true</tt> if the string is a number and its value is within
- * the specified range.
- */
- virtual bool match (const std::string &test_string) const;
-
- /**
- * Return a description of the pattern that valid strings are expected to
- * match. If bounds were specified to the constructor, then include them
- * into this description.
- */
- 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 a new object on the heap using @p new if the given
- * @p description is a valid format (for example created by calling
- * description() on an existing object), or @p nullptr otherwise. Ownership
- * of the returned object is transferred to the caller of this function,
- * which should be freed using @p delete.
- */
- static std::unique_ptr<Double> create(const std::string &description);
-
- private:
- /**
- * Value of the lower bound. A number that satisfies the
- * @ref match
- * operation of this class must be equal to this value or larger, if the
- * bounds of the interval form a valid range.
- */
- const double lower_bound;
-
- /**
- * Value of the upper bound. A number that satisfies the
- * @ref match
- * operation of this class must be equal to this value or less, if the
- * bounds of the interval form a valid range.
- */
- const double upper_bound;
-
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
- /**
- * Test for the string being one of a sequence of values given like a
- * regular expression. For example, if the string given to the constructor
- * is <tt>"red|blue|black"</tt>, then the
- * @ref match
- * function returns <tt>true</tt> exactly if the string is either "red" or
- * "blue" or "black". Spaces around the pipe signs do not matter and are
- * eliminated.
- */
- class Selection : public PatternBase
- {
- public:
- /**
- * Constructor. Take the given parameter as the specification of valid
- * strings.
- */
- Selection (const std::string &seq);
-
- /**
- * Return <tt>true</tt> if the string is an element of the description
- * list passed 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. Here, this is the list of valid strings passed to the
- * constructor.
- */
- 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;
-
- /**
- * Determine an estimate for the memory consumption (in bytes) of this
- * object.
- */
- std::size_t memory_consumption () 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<Selection> create (const std::string &description);
-
- private:
- /**
- * List of valid strings as passed to the constructor. We don't make this
- * string constant, as we process it somewhat in the constructor.
- */
- std::string sequence;
-
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
-
- /**
- * This pattern matches a list of values separated by commas (or another
- * string), each of which have to match a pattern given to the constructor.
- * With two additional parameters, the number of elements this list has to
- * have can be specified. If none is specified, the list may have zero or
- * more entries.
- */
- class List : public PatternBase
- {
- public:
- /**
- * Maximal integer value. If the numeric_limits class is available use
- * this information to obtain the extremal values, otherwise set it so
- * that this class understands that all values are allowed.
- */
- static const unsigned int max_int_value;
-
- /**
- * 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, and the string that is used as a
- * separator between elements of the list.
- */
- List (const PatternBase &base_pattern,
- const unsigned int min_elements = 0,
- const unsigned int max_elements = max_int_value,
- const std::string &separator = ",");
-
-
- /**
- * Return the internally stored separator.
- */
- const std::string &get_separator() const;
-
- /**
- * Return the internally stored base pattern.
- */
- const PatternBase &get_base_pattern() const;
-
- /**
- * Copy constructor.
- */
- List (const List &other);
-
- /**
- * Return <tt>true</tt> if the string is a comma-separated list of strings
- * each of which match the pattern 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<List> create (const std::string &description);
-
- /**
- * Determine an estimate for the memory consumption (in bytes) of this
- * object.
- */
- std::size_t memory_consumption () const;
-
- /**
- * @addtogroup Exceptions
- * @{
- */
-
- /**
- * Exception.
- */
- DeclException2 (ExcInvalidRange,
- int, int,
- << "The values " << arg1 << " and " << arg2
- << " do not form a valid range.");
- //@}
- private:
- /**
- * Copy of the pattern that each element of the list has to satisfy.
- */
- std::unique_ptr<PatternBase> pattern;
-
- /**
- * Minimum number of elements the list must have.
- */
- const unsigned int min_elements;
-
- /**
- * Maximum number of elements the list must have.
- */
- const unsigned int max_elements;
-
- /**
- * Separator between elements of the list.
- */
- const std::string separator;
-
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
-
- /**
- * This pattern matches a list of comma-separated values each of which
- * denotes a pair of key and value. Both key and value have to match a
- * 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>. 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
- * more entries.
- */
- class Map : public PatternBase
- {
- public:
- /**
- * Maximal integer value. If the numeric_limits class is available use
- * this information to obtain the extremal values, otherwise set it so
- * that this class understands that all values are allowed.
- */
- static const unsigned int max_int_value;
-
- /**
- * Constructor. Take the given parameter as the specification of valid
- * elements of the list.
- *
- * 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 &key_value_separator = ":");
-
- /**
- * Copy constructor.
- */
- Map (const Map &other);
-
- /**
- * Return <tt>true</tt> if the string is a comma-separated list of strings
- * each of which match the pattern 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<Map> 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 key pattern.
- */
- const PatternBase &get_key_pattern() const;
-
- /**
- * Return a reference to the value pattern.
- */
- const PatternBase &get_value_pattern() const;
-
- /**
- * Return the separator of the map entries.
- */
- const std::string &get_separator() const;
-
- /**
- * Return the key-value separator.
- */
- const std::string &get_key_value_separator() const;
-
- /**
- * @addtogroup Exceptions
- * @{
- */
-
- /**
- * Exception.
- */
- DeclException2 (ExcInvalidRange,
- int, int,
- << "The values " << arg1 << " and " << arg2
- << " do not form a valid range.");
- //@}
- private:
- /**
- * Copy of the patterns that each key and each value of the map has to
- * satisfy.
- */
- std::unique_ptr<PatternBase> key_pattern;
- std::unique_ptr<PatternBase> value_pattern;
-
- /**
- * Minimum number of elements the list must have.
- */
- const unsigned int min_elements;
-
- /**
- * Maximum number of elements the list must have.
- */
- const unsigned int max_elements;
-
- /**
- * Separator between elements of the list.
- */
- const std::string separator;
-
-
- /**
- * Separator between keys and values.
- */
- const std::string key_value_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
- * constructor argument. The input is allowed to be empty or contain values
- * more than once and have an arbitrary number of spaces around commas. Of
- * course commas are not allowed inside the values given to the constructor.
- *
- * For example, if the string to the constructor was <tt>"ucd|gmv|eps"</tt>,
- * then the following would be legal inputs: "eps", "gmv, eps", or "".
- */
- class MultipleSelection : public PatternBase
- {
- public:
- /**
- * Constructor. @p seq is a list of valid options separated by "|".
- */
- MultipleSelection (const std::string &seq);
-
- /**
- * Return <tt>true</tt> if the string is an element of the description
- * list passed 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. Here, this is the list of valid strings passed to the
- * constructor.
- */
- 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<MultipleSelection> create (const std::string &description);
-
- /**
- * Determine an estimate for the memory consumption (in bytes) of this
- * object.
- */
- std::size_t memory_consumption () const;
-
- /**
- * @addtogroup Exceptions
- * @{
- */
-
- /**
- * Exception.
- */
- DeclException1 (ExcCommasNotAllowed,
- int,
- << "A comma was found at position " << arg1
- << " of your input string, but commas are not allowed here.");
- //@}
- private:
- /**
- * List of valid strings as passed to the constructor. We don't make this
- * string constant, as we process it somewhat in the constructor.
- */
- std::string sequence;
-
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
- /**
- * Test for the string being either "true" or "false". This is mapped to the
- * Selection class.
- */
- class Bool : public Selection
- {
- public:
- /**
- * Constructor.
- */
- Bool ();
-
- /**
- * 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<Bool> create(const std::string &description);
-
- private:
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
- /**
- * Always returns <tt>true</tt> when testing a string.
- */
- class Anything : public PatternBase
- {
- public:
- /**
- * Constructor. (Allow for at least one non-virtual function in this
- * class, as otherwise sometimes no virtual table is emitted.)
- */
- Anything ();
-
- /**
- * Return <tt>true</tt> if the string matches its constraints, i.e.
- * always.
- */
- virtual bool match (const std::string &test_string) const;
-
- /**
- * Return a description of the pattern that valid strings are expected to
- * match. Here, this is the string <tt>"[Anything]"</tt>.
- */
- 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<Anything> create(const std::string &description);
-
- private:
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
-
- /**
- * A pattern that can be used to indicate when a parameter is intended to be
- * the name of a file. By itself, this class does not check whether the
- * string that is given in a parameter file actually corresponds to an
- * existing file (it could, for example, be the name of a file to which you
- * want to write output). Functionally, the class is therefore equivalent to
- * the Anything class. However, it allows to specify the <i>intent</i> of a
- * parameter. The flag given to the constructor also allows to specify
- * whether the file is supposed to be an input or output file.
- *
- * The reason for the existence of this class is to support graphical user
- * interfaces for editing parameter files. These may open a file selection
- * dialog if the filename is supposed to represent an input file.
- */
- class FileName : public PatternBase
- {
- public:
- /**
- * Files can be used for input or output. This can be specified in the
- * constructor by choosing the flag <tt>type</tt>.
- */
- enum FileType
- {
- /**
- * Open for input.
- */
- input = 0,
- /**
- * Open for output.
- */
- output = 1
- };
-
- /**
- * Constructor. The type of the file can be specified by choosing the
- * flag.
- */
- FileName (const FileType type = input);
-
- /**
- * Return <tt>true</tt> if the string matches its constraints, i.e.
- * always.
- */
- virtual bool match (const std::string &test_string) const;
-
- /**
- * Return a description of the pattern that valid strings are expected to
- * match. Here, this is the string <tt>"[Filename]"</tt>.
- */
- 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;
-
- /**
- * file type flag
- */
- FileType file_type;
-
- /**
- * 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<FileName> create (const std::string &description);
-
- private:
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-
-
- /**
- * A pattern that can be used to indicate when a parameter is intended to be
- * the name of a directory. By itself, this class does not check whether the
- * string that is given in a parameter file actually corresponds to an
- * existing directory. Functionally, the class is therefore equivalent to
- * the Anything class. However, it allows to specify the <i>intent</i> of a
- * parameter.
- *
- * The reason for the existence of this class is to support graphical user
- * interfaces for editing parameter files. These may open a file selection
- * dialog to select or create a directory.
- */
- class DirectoryName : public PatternBase
- {
- public:
- /**
- * Constructor.
- */
- DirectoryName ();
-
- /**
- * Return <tt>true</tt> if the string matches its constraints, i.e.
- * always.
- */
- virtual bool match (const std::string &test_string) const;
-
- /**
- * Return a description of the pattern that valid strings are expected to
- * match. Here, this is the string <tt>"[Filename]"</tt>.
- */
- 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<DirectoryName> create(const std::string &description);
-
- private:
- /**
- * Initial part of description
- */
- static const char *description_init;
- };
-}
-
-
/**
* The ParameterHandler class provides a standard interface to an input file
* which provides at run-time for program parameters such as time step sizes,
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii__patterns_h
+#define dealii__patterns_h
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+
+#include <boost/property_tree/ptree_fwd.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/archive/basic_archive.hpp>
+#include <boost/property_tree/ptree_serialization.hpp>
+
+#include <map>
+#include <vector>
+#include <string>
+#include <memory>
+
+DEAL_II_NAMESPACE_OPEN
+
+// forward declarations for interfaces and friendship
+class LogStream;
+class MultipleParameterLoop;
+
+/**
+ * Namespace for a few classes that act as patterns for the ParameterHandler
+ * class. These classes implement an interface that checks whether a parameter
+ * in an input file matches a certain pattern, such as "being boolean", "an
+ * integer value", etc.
+ *
+ * @ingroup input
+ */
+namespace Patterns
+{
+
+ /**
+ * Base class to declare common interface. The purpose of this class is
+ * mostly to define the interface of patterns, and to force derived classes
+ * to have a <tt>clone</tt> function. It is thus, in the languages of the
+ * "Design Patterns" book (Gamma et al.), a "prototype".
+ */
+ class PatternBase
+ {
+ public:
+ /**
+ * Make destructor of this and all derived classes virtual.
+ */
+ virtual ~PatternBase ();
+
+ /**
+ * Return <tt>true</tt> if the given string matches the pattern.
+ */
+ virtual bool match (const std::string &test_string) const = 0;
+
+ /**
+ * List of possible description output formats.
+ *
+ * Capitalization chosen for similarity to ParameterHandler::OutputStyle.
+ */
+ enum OutputStyle
+ {
+ /**
+ * Simple text suitable for machine parsing in the static public member
+ * functions for all of the built in inheriting classes.
+ *
+ * Preferably human readable, but machine parsing is more critical.
+ */
+ Machine,
+ /**
+ * Easily human readable plain text format suitable for plain text
+ * documentation.
+ */
+ Text,
+ /**
+ * Easily human readable LaTeX format suitable for printing in manuals.
+ */
+ LaTeX
+ };
+
+ /**
+ * Return a string describing the pattern.
+ */
+ virtual std::string description (const OutputStyle style=Machine) const = 0;
+
+ /**
+ * Return a pointer to an exact copy of the object. This is necessary
+ * since we want to store objects of this type in containers, were we need
+ * to copy objects without knowledge of their actual data type (we only
+ * have pointers to the base class).
+ *
+ * Ownership of the objects returned by this function is passed to the
+ * caller of this function.
+ */
+ virtual std::unique_ptr<PatternBase> clone () const = 0;
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object. To avoid unnecessary overhead, we do not force derived classes
+ * to provide this function as a virtual overloaded one, but rather try to
+ * cast the present object to one of the known derived classes and if that
+ * fails then take the size of this base class instead and add 32 byte
+ * (this value is arbitrary, it should account for virtual function
+ * tables, and some possible data elements). Since there are usually not
+ * many thousands of objects of this type around, and since the
+ * memory_consumption mechanism is used to find out where memory in the
+ * range of many megabytes is, this seems like a reasonable approximation.
+ *
+ * On the other hand, if you know that your class deviates from this
+ * assumption significantly, you can still overload this function.
+ */
+ virtual std::size_t memory_consumption () const;
+ };
+
+ /**
+ * Return pointer to the correct derived class based on description.
+ */
+ std::unique_ptr<PatternBase> pattern_factory (const std::string &description);
+
+ /**
+ * Test for the string being an integer. If bounds are given to the
+ * constructor, then the integer given also needs to be within the interval
+ * specified by these bounds. Note that unlike common convention in the C++
+ * standard library, both bounds of this interval are inclusive; the reason
+ * is that in practice in most cases, one needs closed intervals, but these
+ * can only be realized with inclusive bounds for non-integer values. We
+ * thus stay consistent by always using closed intervals.
+ *
+ * If the upper bound given to the constructor is smaller than the
+ * lower bound, then every integer is allowed.
+ *
+ * Giving bounds may be useful if for example a value can only be positive
+ * and less than a reasonable upper bound (for example the number of
+ * refinement steps to be performed), or in many other cases.
+ */
+ class Integer : public PatternBase
+ {
+ public:
+ /**
+ * Minimal integer value. If the numeric_limits class is available use
+ * this information to obtain the extremal values, otherwise set it so
+ * that this class understands that all values are allowed.
+ */
+ static const int min_int_value;
+
+ /**
+ * Maximal integer value. If the numeric_limits class is available use
+ * this information to obtain the extremal values, otherwise set it so
+ * that this class understands that all values are allowed.
+ */
+ static const int max_int_value;
+
+ /**
+ * Constructor. Bounds can be specified within which a valid
+ * parameter has to be. If the upper bound is smaller than the
+ * lower bound, then the entire set of integers is implied. The
+ * default values are chosen such that no bounds are enforced on
+ * parameters.
+ */
+ Integer (const int lower_bound = min_int_value,
+ const int upper_bound = max_int_value);
+
+ /**
+ * Return <tt>true</tt> if the string is an integer and its value is
+ * within the specified range.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match. If bounds were specified to the constructor, then include them
+ * into this description.
+ */
+ 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<Integer> create (const std::string &description);
+
+ private:
+ /**
+ * Value of the lower bound. A number that satisfies the
+ * @ref match
+ * operation of this class must be equal to this value or larger, if the
+ * bounds of the interval for a valid range.
+ */
+ const int lower_bound;
+
+ /**
+ * Value of the upper bound. A number that satisfies the
+ * @ref match
+ * operation of this class must be equal to this value or less, if the
+ * bounds of the interval for a valid range.
+ */
+ const int upper_bound;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+ /**
+ * Test for the string being a <tt>double</tt>. If bounds are given to the
+ * constructor, then the integer given also needs to be within the interval
+ * specified by these bounds. Note that unlike common convention in the C++
+ * standard library, both bounds of this interval are inclusive; the reason
+ * is that in practice in most cases, one needs closed intervals, but these
+ * can only be realized with inclusive bounds for non-integer values. We
+ * thus stay consistent by always using closed intervals.
+ *
+ * If the upper bound given to the constructor is smaller than the
+ * lower bound, then every double precision number is allowed.
+ *
+ * Giving bounds may be useful if for example a value can only be positive
+ * and less than a reasonable upper bound (for example damping parameters
+ * are frequently only reasonable if between zero and one), or in many other
+ * cases.
+ */
+ class Double : public PatternBase
+ {
+ public:
+ /**
+ * Minimal double value used as default value, taken from
+ * <tt>std::numeric_limits</tt>.
+ */
+ static const double min_double_value;
+
+ /**
+ * Maximal double value used as default value, taken from
+ * <tt>std::numeric_limits</tt>.
+ */
+ static const double max_double_value;
+
+ /**
+ * Constructor. Bounds can be specified within which a valid
+ * parameter has to be. If the upper bound is smaller than the
+ * lower bound, then the entire set of double precision numbers is
+ * implied. The default values are chosen such that no bounds are
+ * enforced on parameters.
+ */
+ Double (const double lower_bound = min_double_value,
+ const double upper_bound = max_double_value);
+
+ /**
+ * Return <tt>true</tt> if the string is a number and its value is within
+ * the specified range.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match. If bounds were specified to the constructor, then include them
+ * into this description.
+ */
+ 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 a new object on the heap using @p new if the given
+ * @p description is a valid format (for example created by calling
+ * description() on an existing object), or @p nullptr otherwise. Ownership
+ * of the returned object is transferred to the caller of this function,
+ * which should be freed using @p delete.
+ */
+ static std::unique_ptr<Double> create(const std::string &description);
+
+ private:
+ /**
+ * Value of the lower bound. A number that satisfies the
+ * @ref match
+ * operation of this class must be equal to this value or larger, if the
+ * bounds of the interval form a valid range.
+ */
+ const double lower_bound;
+
+ /**
+ * Value of the upper bound. A number that satisfies the
+ * @ref match
+ * operation of this class must be equal to this value or less, if the
+ * bounds of the interval form a valid range.
+ */
+ const double upper_bound;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+ /**
+ * Test for the string being one of a sequence of values given like a
+ * regular expression. For example, if the string given to the constructor
+ * is <tt>"red|blue|black"</tt>, then the
+ * @ref match
+ * function returns <tt>true</tt> exactly if the string is either "red" or
+ * "blue" or "black". Spaces around the pipe signs do not matter and are
+ * eliminated.
+ */
+ class Selection : public PatternBase
+ {
+ public:
+ /**
+ * Constructor. Take the given parameter as the specification of valid
+ * strings.
+ */
+ Selection (const std::string &seq);
+
+ /**
+ * Return <tt>true</tt> if the string is an element of the description
+ * list passed 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. Here, this is the list of valid strings passed to the
+ * constructor.
+ */
+ 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;
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
+ */
+ std::size_t memory_consumption () 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<Selection> create (const std::string &description);
+
+ private:
+ /**
+ * List of valid strings as passed to the constructor. We don't make this
+ * string constant, as we process it somewhat in the constructor.
+ */
+ std::string sequence;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+
+ /**
+ * This pattern matches a list of values separated by commas (or another
+ * string), each of which have to match a pattern given to the constructor.
+ * With two additional parameters, the number of elements this list has to
+ * have can be specified. If none is specified, the list may have zero or
+ * more entries.
+ */
+ class List : public PatternBase
+ {
+ public:
+ /**
+ * Maximal integer value. If the numeric_limits class is available use
+ * this information to obtain the extremal values, otherwise set it so
+ * that this class understands that all values are allowed.
+ */
+ static const unsigned int max_int_value;
+
+ /**
+ * 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, and the string that is used as a
+ * separator between elements of the list.
+ */
+ List (const PatternBase &base_pattern,
+ const unsigned int min_elements = 0,
+ const unsigned int max_elements = max_int_value,
+ const std::string &separator = ",");
+
+
+ /**
+ * Return the internally stored separator.
+ */
+ const std::string &get_separator() const;
+
+ /**
+ * Return the internally stored base pattern.
+ */
+ const PatternBase &get_base_pattern() const;
+
+ /**
+ * Copy constructor.
+ */
+ List (const List &other);
+
+ /**
+ * Return <tt>true</tt> if the string is a comma-separated list of strings
+ * each of which match the pattern 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<List> create (const std::string &description);
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
+ */
+ std::size_t memory_consumption () const;
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+
+ /**
+ * Exception.
+ */
+ DeclException2 (ExcInvalidRange,
+ int, int,
+ << "The values " << arg1 << " and " << arg2
+ << " do not form a valid range.");
+ //@}
+ private:
+ /**
+ * Copy of the pattern that each element of the list has to satisfy.
+ */
+ std::unique_ptr<PatternBase> pattern;
+
+ /**
+ * Minimum number of elements the list must have.
+ */
+ const unsigned int min_elements;
+
+ /**
+ * Maximum number of elements the list must have.
+ */
+ const unsigned int max_elements;
+
+ /**
+ * Separator between elements of the list.
+ */
+ const std::string separator;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+
+ /**
+ * This pattern matches a list of comma-separated values each of which
+ * denotes a pair of key and value. Both key and value have to match a
+ * 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>. 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
+ * more entries.
+ */
+ class Map : public PatternBase
+ {
+ public:
+ /**
+ * Maximal integer value. If the numeric_limits class is available use
+ * this information to obtain the extremal values, otherwise set it so
+ * that this class understands that all values are allowed.
+ */
+ static const unsigned int max_int_value;
+
+ /**
+ * Constructor. Take the given parameter as the specification of valid
+ * elements of the list.
+ *
+ * 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 &key_value_separator = ":");
+
+ /**
+ * Copy constructor.
+ */
+ Map (const Map &other);
+
+ /**
+ * Return <tt>true</tt> if the string is a comma-separated list of strings
+ * each of which match the pattern 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<Map> 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 key pattern.
+ */
+ const PatternBase &get_key_pattern() const;
+
+ /**
+ * Return a reference to the value pattern.
+ */
+ const PatternBase &get_value_pattern() const;
+
+ /**
+ * Return the separator of the map entries.
+ */
+ const std::string &get_separator() const;
+
+ /**
+ * Return the key-value separator.
+ */
+ const std::string &get_key_value_separator() const;
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+
+ /**
+ * Exception.
+ */
+ DeclException2 (ExcInvalidRange,
+ int, int,
+ << "The values " << arg1 << " and " << arg2
+ << " do not form a valid range.");
+ //@}
+ private:
+ /**
+ * Copy of the patterns that each key and each value of the map has to
+ * satisfy.
+ */
+ std::unique_ptr<PatternBase> key_pattern;
+ std::unique_ptr<PatternBase> value_pattern;
+
+ /**
+ * Minimum number of elements the list must have.
+ */
+ const unsigned int min_elements;
+
+ /**
+ * Maximum number of elements the list must have.
+ */
+ const unsigned int max_elements;
+
+ /**
+ * Separator between elements of the list.
+ */
+ const std::string separator;
+
+
+ /**
+ * Separator between keys and values.
+ */
+ const std::string key_value_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
+ * constructor argument. The input is allowed to be empty or contain values
+ * more than once and have an arbitrary number of spaces around commas. Of
+ * course commas are not allowed inside the values given to the constructor.
+ *
+ * For example, if the string to the constructor was <tt>"ucd|gmv|eps"</tt>,
+ * then the following would be legal inputs: "eps", "gmv, eps", or "".
+ */
+ class MultipleSelection : public PatternBase
+ {
+ public:
+ /**
+ * Constructor. @p seq is a list of valid options separated by "|".
+ */
+ MultipleSelection (const std::string &seq);
+
+ /**
+ * Return <tt>true</tt> if the string is an element of the description
+ * list passed 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. Here, this is the list of valid strings passed to the
+ * constructor.
+ */
+ 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<MultipleSelection> create (const std::string &description);
+
+ /**
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
+ */
+ std::size_t memory_consumption () const;
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+
+ /**
+ * Exception.
+ */
+ DeclException1 (ExcCommasNotAllowed,
+ int,
+ << "A comma was found at position " << arg1
+ << " of your input string, but commas are not allowed here.");
+ //@}
+ private:
+ /**
+ * List of valid strings as passed to the constructor. We don't make this
+ * string constant, as we process it somewhat in the constructor.
+ */
+ std::string sequence;
+
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+ /**
+ * Test for the string being either "true" or "false". This is mapped to the
+ * Selection class.
+ */
+ class Bool : public Selection
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ Bool ();
+
+ /**
+ * 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<Bool> create(const std::string &description);
+
+ private:
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+ /**
+ * Always returns <tt>true</tt> when testing a string.
+ */
+ class Anything : public PatternBase
+ {
+ public:
+ /**
+ * Constructor. (Allow for at least one non-virtual function in this
+ * class, as otherwise sometimes no virtual table is emitted.)
+ */
+ Anything ();
+
+ /**
+ * Return <tt>true</tt> if the string matches its constraints, i.e.
+ * always.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match. Here, this is the string <tt>"[Anything]"</tt>.
+ */
+ 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<Anything> create(const std::string &description);
+
+ private:
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+
+ /**
+ * A pattern that can be used to indicate when a parameter is intended to be
+ * the name of a file. By itself, this class does not check whether the
+ * string that is given in a parameter file actually corresponds to an
+ * existing file (it could, for example, be the name of a file to which you
+ * want to write output). Functionally, the class is therefore equivalent to
+ * the Anything class. However, it allows to specify the <i>intent</i> of a
+ * parameter. The flag given to the constructor also allows to specify
+ * whether the file is supposed to be an input or output file.
+ *
+ * The reason for the existence of this class is to support graphical user
+ * interfaces for editing parameter files. These may open a file selection
+ * dialog if the filename is supposed to represent an input file.
+ */
+ class FileName : public PatternBase
+ {
+ public:
+ /**
+ * Files can be used for input or output. This can be specified in the
+ * constructor by choosing the flag <tt>type</tt>.
+ */
+ enum FileType
+ {
+ /**
+ * Open for input.
+ */
+ input = 0,
+ /**
+ * Open for output.
+ */
+ output = 1
+ };
+
+ /**
+ * Constructor. The type of the file can be specified by choosing the
+ * flag.
+ */
+ FileName (const FileType type = input);
+
+ /**
+ * Return <tt>true</tt> if the string matches its constraints, i.e.
+ * always.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match. Here, this is the string <tt>"[Filename]"</tt>.
+ */
+ 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;
+
+ /**
+ * file type flag
+ */
+ FileType file_type;
+
+ /**
+ * 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<FileName> create (const std::string &description);
+
+ private:
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+
+
+ /**
+ * A pattern that can be used to indicate when a parameter is intended to be
+ * the name of a directory. By itself, this class does not check whether the
+ * string that is given in a parameter file actually corresponds to an
+ * existing directory. Functionally, the class is therefore equivalent to
+ * the Anything class. However, it allows to specify the <i>intent</i> of a
+ * parameter.
+ *
+ * The reason for the existence of this class is to support graphical user
+ * interfaces for editing parameter files. These may open a file selection
+ * dialog to select or create a directory.
+ */
+ class DirectoryName : public PatternBase
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ DirectoryName ();
+
+ /**
+ * Return <tt>true</tt> if the string matches its constraints, i.e.
+ * always.
+ */
+ virtual bool match (const std::string &test_string) const;
+
+ /**
+ * Return a description of the pattern that valid strings are expected to
+ * match. Here, this is the string <tt>"[Filename]"</tt>.
+ */
+ 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<DirectoryName> create(const std::string &description);
+
+ private:
+ /**
+ * Initial part of description
+ */
+ static const char *description_init;
+ };
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
parameter_handler.cc
parsed_function.cc
partitioner.cc
+ patterns.cc
path_search.cc
polynomial.cc
polynomials_abf.cc
DEAL_II_NAMESPACE_OPEN
-
-//TODO[WB]: various functions here could be simplified by using namespace Utilities
-
-namespace Patterns
-{
-
- namespace
- {
- /**
- * Read to the end of the stream and
- * return whether all there is is
- * whitespace or whether there are other
- * characters as well.
- */
- bool has_only_whitespace (std::istream &in)
- {
- while (in)
- {
- char c;
-
- // skip if we've reached the end of
- // the line
- if (!(in >> c))
- break;
-
- if ((c != ' ') && (c != '\t'))
- return false;
- }
- return true;
- }
- }
-
-
-
- std::unique_ptr<PatternBase> pattern_factory(const std::string &description)
- {
- std::unique_ptr<PatternBase> p;
-
- p = Integer::create(description);
- if (p != nullptr)
- return p;
-
- p = Double::create(description);
- if (p != nullptr )
- return p;
-
- p = Selection::create(description);
- if (p != nullptr )
- return p;
-
- p = List::create(description);
- if (p != nullptr )
- return p;
-
- p = Map::create(description);
- if (p != nullptr )
- return p;
-
- p = MultipleSelection::create(description);
- if (p != nullptr )
- return p;
-
- p = Bool::create(description);
- if (p!=nullptr )
- return p;
-
- p = Anything::create(description);
- if (p != nullptr )
- return p;
-
- p = FileName::create(description);
- if (p != nullptr )
- return p;
-
- p = DirectoryName::create(description);
- if (p!=nullptr )
- return p;
-
- Assert(false, ExcNotImplemented());
-
- return p;
- }
-
-
-
- PatternBase::~PatternBase ()
- {}
-
-
- std::size_t
- PatternBase::memory_consumption () const
- {
- if (dynamic_cast<const Integer *>(this) != nullptr)
- return sizeof(Integer);
- else if (dynamic_cast<const Double *>(this) != nullptr)
- return sizeof(Double);
- else if (dynamic_cast<const Bool *>(this) != nullptr)
- return sizeof(Bool);
- else if (dynamic_cast<const Anything *>(this) != nullptr)
- return sizeof(Anything);
- else
- return sizeof(*this) + 32;
- }
-
-
-
- const int Integer::min_int_value = std::numeric_limits<int>::min();
- const int Integer::max_int_value = std::numeric_limits<int>::max();
-
- const char *Integer::description_init = "[Integer";
-
- Integer::Integer (const int lower_bound,
- const int upper_bound)
- :
- lower_bound (lower_bound),
- upper_bound (upper_bound)
- {}
-
-
-
- bool Integer::match (const std::string &test_string) const
- {
- std::istringstream str(test_string);
-
- int i;
- if (!(str >> i))
- return false;
-
- if (!has_only_whitespace (str))
- return false;
- // check whether valid bounds
- // were specified, and if so
- // enforce their values
- if (lower_bound <= upper_bound)
- return ((lower_bound <= i) &&
- (upper_bound >= i));
- else
- return true;
- }
-
-
-
- std::string Integer::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- // check whether valid bounds
- // were specified, and if so
- // output their values
- if (lower_bound <= upper_bound)
- {
- std::ostringstream description;
-
- description << description_init
- <<" range "
- << lower_bound << "..." << upper_bound
- << " (inclusive)]";
- return description.str();
- }
- else
- // if no bounds were given, then
- // return generic string
- return "[Integer]";
- }
- case Text:
- {
- if (lower_bound <= upper_bound)
- {
- std::ostringstream description;
-
- description << "An integer n such that "
- << lower_bound << " <= n <= " << upper_bound;
-
- return description.str();
- }
- else
- return "An integer";
- }
- case LaTeX:
- {
- if (lower_bound <= upper_bound)
- {
- std::ostringstream description;
-
- description << "An integer $n$ such that $"
- << lower_bound << "\\leq n \\leq " << upper_bound
- << "$";
-
- return description.str();
- }
- else
- return "An integer";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> Integer::clone() const
- {
- return std::unique_ptr<PatternBase>(new Integer(lower_bound, upper_bound));
- }
-
-
-
- std::unique_ptr<Integer> Integer::create(const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- std::istringstream is(description);
-
- if (is.str().size() > strlen(description_init) + 1)
- {
-//TODO: verify that description matches the pattern "^\[Integer range \d+\.\.\.\d+\]$"
- int lower_bound, upper_bound;
-
- is.ignore(strlen(description_init) + strlen(" range "));
-
- if (!(is >> lower_bound))
- return std::unique_ptr<Integer>(new Integer());
-
- is.ignore(strlen("..."));
-
- if (!(is >> upper_bound))
- return std::unique_ptr<Integer>(new Integer());
-
- return std::unique_ptr<Integer>(new Integer(lower_bound, upper_bound));
- }
- else
- return std::unique_ptr<Integer>(new Integer());
- }
- else
- return std::unique_ptr<Integer>();
- }
-
-
-
- const double Double::min_double_value = -std::numeric_limits<double>::max();
- const double Double::max_double_value = std::numeric_limits<double>::max();
-
- const char *Double::description_init = "[Double";
-
- Double::Double (const double lower_bound,
- const double upper_bound)
- :
- lower_bound (lower_bound),
- upper_bound (upper_bound)
- {}
-
-
-
- bool Double::match (const std::string &test_string) const
- {
- std::istringstream str(test_string);
-
- double d;
- str >> d;
- if (str.fail())
- return false;
-
- if (!has_only_whitespace (str))
- return false;
- // check whether valid bounds
- // were specified, and if so
- // enforce their values
- if (lower_bound <= upper_bound)
- return ((lower_bound <= d) &&
- (upper_bound >= d));
- else
- return true;
- }
-
-
-
- std::string Double::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- if (lower_bound <= upper_bound)
- {
- // bounds are valid
- description << description_init << " ";
- // We really want to compare with ==, but -Wfloat-equal would create
- // a warning here, so work around it.
- if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
- description << "-MAX_DOUBLE";
- else
- description << lower_bound;
- description << "...";
- if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
- description << "MAX_DOUBLE";
- else
- description << upper_bound;
- description << " (inclusive)]";
- return description.str();
- }
- else
- {
- // invalid bounds, assume unbounded double:
- description << description_init << "]";
- return description.str();
- }
- }
- case Text:
- {
- if (lower_bound <= upper_bound)
- {
- std::ostringstream description;
-
- description << "A floating point number v such that ";
- if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
- description << "-MAX_DOUBLE";
- else
- description << lower_bound;
- description << " <= v <= ";
- if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
- description << "MAX_DOUBLE";
- else
- description << upper_bound;
-
- return description.str();
- }
- else
- return "A floating point number";
- }
- case LaTeX:
- {
- if (lower_bound <= upper_bound)
- {
- std::ostringstream description;
-
- description << "A floating point number $v$ such that $";
- if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
- description << "-\\text{MAX\\_DOUBLE}";
- else
- description << lower_bound;
- description << " \\leq v \\leq ";
- if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
- description << "\\text{MAX\\_DOUBLE}";
- else
- description << upper_bound;
- description << "$";
-
- return description.str();
- }
- else
- return "A floating point number";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
- std::unique_ptr<PatternBase> Double::clone() const
- {
- return std::unique_ptr<PatternBase>(new Double(lower_bound, upper_bound));
- }
-
-
-
- std::unique_ptr<Double> Double::create (const std::string &description)
- {
- const std::string description_init_str = description_init;
- if (description.compare(0, description_init_str.size(), description_init_str) != 0)
- return std::unique_ptr<Double>();
- if (*description.rbegin() != ']')
- return std::unique_ptr<Double>();
-
- std::string temp = description.substr(description_init_str.size());
- if (temp == "]")
- return std::unique_ptr<Double>(new Double(1.0, -1.0)); // return an invalid range
-
- if (temp.find("...") != std::string::npos)
- temp.replace(temp.find("..."), 3, " ");
-
- double lower_bound = min_double_value,
- upper_bound = max_double_value;
-
- std::istringstream is(temp);
- if (0 == temp.compare(0, std::strlen(" -MAX_DOUBLE"), " -MAX_DOUBLE"))
- is.ignore(std::strlen(" -MAX_DOUBLE"));
- else
- {
- // parse lower bound and give up if not a double
- if (!(is >> lower_bound))
- return std::unique_ptr<Double>();
- }
-
- // ignore failure here and assume we got MAX_DOUBLE as upper bound:
- is >> upper_bound;
- if (is.fail())
- upper_bound = max_double_value;
-
- return std::unique_ptr<Double>(new Double(lower_bound, upper_bound));
- }
-
-
-
- const char *Selection::description_init = "[Selection";
-
-
- Selection::Selection (const std::string &seq)
- : sequence(seq)
- {
- while (sequence.find(" |") != std::string::npos)
- sequence.replace (sequence.find(" |"), 2, "|");
- while (sequence.find("| ") != std::string::npos)
- sequence.replace (sequence.find("| "), 2, "|");
- }
-
-
-
- bool Selection::match (const std::string &test_string) const
- {
- std::string tmp(sequence);
-
- // remove whitespace at beginning
- while ((tmp.length() != 0) && (std::isspace (tmp[0])))
- tmp.erase (0,1);
-
- // check the different possibilities
- while (tmp.find('|') != std::string::npos)
- {
- if (test_string == std::string(tmp, 0, tmp.find('|')))
- return true;
-
- tmp.erase (0, tmp.find('|')+1);
- };
-
- //remove whitespace at the end
- while ((tmp.length() != 0) && (std::isspace (*(tmp.end()-1))))
- tmp.erase (tmp.end()-1);
-
- // check last choice, not finished by |
- if (test_string == tmp)
- return true;
-
- // not found
- return false;
- }
-
-
-
- std::string Selection::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << " "
- << sequence
- << " ]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- std::ostringstream description;
-
- description << "Any one of "
- << Utilities::replace_in_string(sequence,"|",", ");
-
- return description.str();
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> Selection::clone() const
- {
- return std::unique_ptr<PatternBase>(new Selection(sequence));
- }
-
-
- std::size_t
- Selection::memory_consumption () const
- {
- return (sizeof(PatternBase) +
- MemoryConsumption::memory_consumption(sequence));
- }
-
-
-
- std::unique_ptr<Selection> Selection::create(const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- std::string sequence(description);
-
- sequence.erase(0, std::strlen(description_init) + 1);
- sequence.erase(sequence.length()-2, 2);
-
- return std::unique_ptr<Selection>(new Selection(sequence));
- }
- else
- return std::unique_ptr<Selection>();
- }
-
-
-
- const unsigned int List::max_int_value
- = std::numeric_limits<unsigned int>::max();
-
- const char *List::description_init = "[List";
-
-
- List::List (const PatternBase &p,
- const unsigned int min_elements,
- const unsigned int max_elements,
- const std::string &separator)
- :
- pattern (p.clone()),
- min_elements (min_elements),
- max_elements (max_elements),
- separator (separator)
- {
- Assert (min_elements <= max_elements,
- ExcInvalidRange (min_elements, max_elements));
- Assert (separator.size() > 0,
- ExcMessage ("The separator must have a non-zero length."));
- }
-
-
-
- List::List (const List &other)
- :
- pattern (other.pattern->clone()),
- min_elements (other.min_elements),
- max_elements (other.max_elements),
- separator (other.separator)
- {}
-
-
- const std::string &List::get_separator() const
- {
- return separator;
- }
-
-
-
- const PatternBase &List::get_base_pattern() const
- {
- return *pattern;
- }
-
-
-
- bool List::match (const std::string &test_string_list) const
- {
- const 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 (const std::string &string : split_list)
- if (pattern->match (string) == false)
- return false;
-
- return true;
- }
-
-
-
- std::string List::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << " of <" << pattern->description(style) << ">"
- << " of length " << min_elements << "..." << max_elements
- << " (inclusive)";
- if (separator != ",")
- description << " separated by <" << separator << ">";
- description << "]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- std::ostringstream description;
-
- description << "A list of "
- << min_elements << " to " << max_elements
- << " elements ";
- if (separator != ",")
- description << "separated by <" << separator << "> ";
- description << "where each element is ["
- << pattern->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> List::clone() const
- {
- return std::unique_ptr<PatternBase>(new List(*pattern, min_elements, max_elements, separator));
- }
-
-
- std::size_t
- List::memory_consumption () const
- {
- return (sizeof(*this) +
- MemoryConsumption::memory_consumption(*pattern) +
- MemoryConsumption::memory_consumption(separator));
- }
-
-
-
- std::unique_ptr<List> List::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- int min_elements, max_elements;
-
- std::istringstream is(description);
- is.ignore(strlen(description_init) + strlen(" of <"));
-
- std::string str;
- std::getline(is, str, '>');
-
- std::shared_ptr<PatternBase> base_pattern (pattern_factory(str));
-
- is.ignore(strlen(" of length "));
- if (!(is >> min_elements))
- return std::unique_ptr<List>(new List(*base_pattern));
-
- is.ignore(strlen("..."));
- if (!(is >> max_elements))
- return std::unique_ptr<List>(new List(*base_pattern, min_elements));
-
- is.ignore(strlen(" (inclusive) separated by <"));
- std::string separator;
- if (is)
- std::getline(is, separator, '>');
- else
- separator = ",";
-
- return std::unique_ptr<List>(new List(*base_pattern, min_elements, max_elements, separator));
- }
- else
- return std::unique_ptr<List>();
- }
-
-
-
- const unsigned int Map::max_int_value
- = std::numeric_limits<unsigned int>::max();
-
- const char *Map::description_init = "[Map";
-
-
- Map::Map (const PatternBase &p_key,
- const PatternBase &p_value,
- const unsigned int min_elements,
- const unsigned int max_elements,
- 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),
- 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 (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"));
- }
-
-
-
- Map::Map (const Map &other)
- :
- key_pattern (other.key_pattern->clone()),
- value_pattern (other.value_pattern->clone()),
- min_elements (other.min_elements),
- max_elements (other.max_elements),
- 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 =
- Utilities::split_string_list(test_string_list, separator);
- if ((split_list.size() < min_elements) ||
- (split_list.size() > max_elements))
- return false;
-
- for (auto &key_value_pair : split_list)
- {
- std::vector<std::string> pair =
- Utilities::split_string_list(key_value_pair, key_value_separator);
-
- // 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 (pair[0]) == false)
- return false;
- if (value_pattern->match (pair[1]) == false)
- return false;
- }
-
- return true;
- }
-
-
-
- std::string Map::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << " of <"
- << key_pattern->description(style) << ">"
- << key_value_separator << "<"
- << value_pattern->description(style) << ">"
- << " of length " << min_elements << "..." << max_elements
- << " (inclusive)";
- if (separator != ",")
- description << " separated by <" << separator << ">";
- description << "]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- std::ostringstream description;
-
- description << "A key"
- << key_value_separator
- << "value map of "
- << min_elements << " to " << max_elements
- << " elements ";
- if (separator != ",")
- description << " separated by <" << separator << "> ";
- description << " where each key is ["
- << key_pattern->description(style)
- << "]"
- << " and each value is ["
- << value_pattern->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> Map::clone() const
- {
- return std::unique_ptr<PatternBase>(new Map(*key_pattern, *value_pattern,
- min_elements, max_elements,
- separator, key_value_separator));
- }
-
-
- std::size_t
- Map::memory_consumption () const
- {
- return (sizeof(*this) +
- MemoryConsumption::memory_consumption (*key_pattern) +
- MemoryConsumption::memory_consumption (*value_pattern) +
- MemoryConsumption::memory_consumption (separator)+
- MemoryConsumption::memory_consumption (key_value_separator));
- }
-
-
-
- std::unique_ptr<Map> Map::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- int min_elements, max_elements;
-
- std::istringstream is(description);
- is.ignore(strlen(description_init) + strlen(" of <"));
-
- std::string key;
- std::getline(is, key, '>');
-
- std::string key_value_separator;
- std::getline(is, key_value_separator, '<');
-
- // 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));
-
- is.ignore(strlen(" of length "));
- if (!(is >> min_elements))
- return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern));
-
- is.ignore(strlen("..."));
- if (!(is >> max_elements))
- return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern, min_elements));
-
- is.ignore(strlen(" (inclusive) separated by <"));
- std::string separator;
- if (is)
- std::getline(is, separator, '>');
- else
- separator = ",";
-
- return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern,
- min_elements, max_elements,
- separator, key_value_separator));
- }
- else
- return std::unique_ptr<Map>();
- }
-
-
-
- const PatternBase &Map::get_key_pattern() const
- {
- return *key_pattern;
- }
-
-
-
- const PatternBase &Map::get_value_pattern() const
- {
- return *value_pattern;
- }
-
-
-
- const std::string &Map::get_separator() const
- {
- return separator;
- }
-
-
- const std::string &Map::get_key_value_separator() const
- {
- return key_value_separator;
- }
-
-
- const char *MultipleSelection::description_init = "[MultipleSelection";
-
-
- MultipleSelection::MultipleSelection (const std::string &seq)
- {
- Assert (seq.find (",") == std::string::npos, ExcCommasNotAllowed(seq.find(",")));
-
- sequence = seq;
- while (sequence.find(" |") != std::string::npos)
- sequence.replace (sequence.find(" |"), 2, "|");
- while (sequence.find("| ") != std::string::npos)
- sequence.replace (sequence.find("| "), 2, "|");
- }
-
-
-
- bool MultipleSelection::match (const std::string &test_string_list) const
- {
- std::string tmp = test_string_list;
- std::vector<std::string> split_names;
-
- // first split the input list
- while (tmp.length() != 0)
- {
- std::string name;
- name = tmp;
-
- if (name.find(",") != std::string::npos)
- {
- name.erase (name.find(","), std::string::npos);
- tmp.erase (0, tmp.find(",")+1);
- }
- else
- tmp = "";
-
- while ((name.length() != 0) &&
- (std::isspace (name[0])))
- name.erase (0,1);
- while (std::isspace (name[name.length()-1]))
- name.erase (name.length()-1, 1);
-
- split_names.push_back (name);
- };
-
-
- // check the different possibilities
- for (std::vector<std::string>::const_iterator test_string = split_names.begin();
- test_string != split_names.end(); ++test_string)
- {
- bool string_found = false;
-
- tmp = sequence;
- while (tmp.find('|') != std::string::npos)
- {
- if (*test_string == std::string(tmp, 0, tmp.find('|')))
- {
- // string found, quit
- // loop. don't change
- // tmp, since we don't
- // need it anymore.
- string_found = true;
- break;
- };
-
- tmp.erase (0, tmp.find('|')+1);
- };
- // check last choice, not finished by |
- if (!string_found)
- if (*test_string == tmp)
- string_found = true;
-
- if (!string_found)
- return false;
- };
-
- return true;
- }
-
-
-
- std::string MultipleSelection::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << " "
- << sequence
- << " ]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- std::ostringstream description;
-
- description << "A comma-separated list of any of "
- << Utilities::replace_in_string(sequence,"|",", ");
-
- return description.str();
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> MultipleSelection::clone() const
- {
- return std::unique_ptr<PatternBase>(new MultipleSelection(sequence));
- }
-
-
- std::size_t
- MultipleSelection::memory_consumption () const
- {
- return (sizeof(PatternBase) +
- MemoryConsumption::memory_consumption(sequence));
- }
-
-
-
- std::unique_ptr<MultipleSelection> MultipleSelection::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- std::string sequence(description);
-
- sequence.erase(0, std::strlen(description_init) + 1);
- sequence.erase(sequence.length()-2, 2);
-
- return std::unique_ptr<MultipleSelection>(new MultipleSelection(sequence));
- }
- else
- return std::unique_ptr<MultipleSelection>();
- }
-
-
-
- const char *Bool::description_init = "[Bool";
-
-
- Bool::Bool ()
- :
- Selection ("true|false")
- {}
-
-
-
- std::string Bool::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << "]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- return "A boolean value (true or false)";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> Bool::clone() const
- {
- return std::unique_ptr<PatternBase>(new Bool());
- }
-
-
-
- std::unique_ptr<Bool> Bool::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- return std::unique_ptr<Bool>(new Bool());
- else
- return std::unique_ptr<Bool>();
- }
-
-
-
- const char *Anything::description_init = "[Anything";
-
-
- Anything::Anything ()
- {}
-
-
-
- bool Anything::match (const std::string &) const
- {
- return true;
- }
-
-
-
- std::string Anything::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init
- << "]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- return "Any string";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> Anything::clone() const
- {
- return std::unique_ptr<PatternBase>(new Anything());
- }
-
-
-
- std::unique_ptr<Anything> Anything::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- return std::unique_ptr<Anything>(new Anything());
- else
- return std::unique_ptr<Anything>();
- }
-
-
-
- const char *FileName::description_init = "[FileName";
-
-
- FileName::FileName (const FileType type)
- : file_type (type)
- {}
-
-
-
- bool FileName::match (const std::string &) const
- {
- return true;
- }
-
-
-
- std::string FileName::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init;
-
- if (file_type == input)
- description << " (Type: input)]";
- else
- description << " (Type: output)]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- if (file_type == input)
- return "an input filename";
- else
- return "an output filename";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> FileName::clone() const
- {
- return std::unique_ptr<PatternBase>(new FileName(file_type));
- }
-
-
-
- std::unique_ptr<FileName> FileName::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- {
- std::istringstream is(description);
- std::string file_type;
- FileType type;
-
- is.ignore(strlen(description_init) + strlen(" (Type:"));
-
- is >> file_type;
-
- if (file_type == "input)]")
- type = input;
- else
- type = output;
-
- return std::unique_ptr<FileName>(new FileName(type));
- }
- else
- return std::unique_ptr<FileName>();
- }
-
-
-
- const char *DirectoryName::description_init = "[DirectoryName";
-
-
- DirectoryName::DirectoryName ()
- {}
-
-
-
- bool DirectoryName::match (const std::string &) const
- {
- return true;
- }
-
-
-
- std::string DirectoryName::description (const OutputStyle style) const
- {
- switch (style)
- {
- case Machine:
- {
- std::ostringstream description;
-
- description << description_init << "]";
-
- return description.str();
- }
- case Text:
- case LaTeX:
- {
- return "A directory name";
- }
- default:
- AssertThrow(false, ExcNotImplemented());
- }
- // Should never occur without an exception, but prevent compiler from
- // complaining
- return "";
- }
-
-
-
- std::unique_ptr<PatternBase> DirectoryName::clone() const
- {
- return std::unique_ptr<PatternBase>(new DirectoryName());
- }
-
-
-
- std::unique_ptr<DirectoryName> DirectoryName::create (const std::string &description)
- {
- if (description.compare(0, std::strlen(description_init), description_init) == 0)
- return std::unique_ptr<DirectoryName>(new DirectoryName());
- else
- return std::unique_ptr<DirectoryName>();
- }
-
-} // end namespace Patterns
-
-
-
ParameterHandler::ParameterHandler ()
:
entries (new boost::property_tree::ptree())
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 1998 - 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/base/patterns.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/path_search.h>
+#include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/utilities.h>
+
+DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <boost/io/ios_state.hpp>
+DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <cstdlib>
+#include <algorithm>
+#include <sstream>
+#include <cctype>
+#include <limits>
+#include <cstring>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+//TODO[WB]: various functions here could be simplified by using namespace Utilities
+
+namespace Patterns
+{
+
+ namespace
+ {
+ /**
+ * Read to the end of the stream and
+ * return whether all there is is
+ * whitespace or whether there are other
+ * characters as well.
+ */
+ bool has_only_whitespace (std::istream &in)
+ {
+ while (in)
+ {
+ char c;
+
+ // skip if we've reached the end of
+ // the line
+ if (!(in >> c))
+ break;
+
+ if ((c != ' ') && (c != '\t'))
+ return false;
+ }
+ return true;
+ }
+ }
+
+
+
+ std::unique_ptr<PatternBase> pattern_factory(const std::string &description)
+ {
+ std::unique_ptr<PatternBase> p;
+
+ p = Integer::create(description);
+ if (p != nullptr)
+ return p;
+
+ p = Double::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = Selection::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = List::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = Map::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = MultipleSelection::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = Bool::create(description);
+ if (p!=nullptr )
+ return p;
+
+ p = Anything::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = FileName::create(description);
+ if (p != nullptr )
+ return p;
+
+ p = DirectoryName::create(description);
+ if (p!=nullptr )
+ return p;
+
+ Assert(false, ExcNotImplemented());
+
+ return p;
+ }
+
+
+
+ PatternBase::~PatternBase ()
+ {}
+
+
+ std::size_t
+ PatternBase::memory_consumption () const
+ {
+ if (dynamic_cast<const Integer *>(this) != nullptr)
+ return sizeof(Integer);
+ else if (dynamic_cast<const Double *>(this) != nullptr)
+ return sizeof(Double);
+ else if (dynamic_cast<const Bool *>(this) != nullptr)
+ return sizeof(Bool);
+ else if (dynamic_cast<const Anything *>(this) != nullptr)
+ return sizeof(Anything);
+ else
+ return sizeof(*this) + 32;
+ }
+
+
+
+ const int Integer::min_int_value = std::numeric_limits<int>::min();
+ const int Integer::max_int_value = std::numeric_limits<int>::max();
+
+ const char *Integer::description_init = "[Integer";
+
+ Integer::Integer (const int lower_bound,
+ const int upper_bound)
+ :
+ lower_bound (lower_bound),
+ upper_bound (upper_bound)
+ {}
+
+
+
+ bool Integer::match (const std::string &test_string) const
+ {
+ std::istringstream str(test_string);
+
+ int i;
+ if (!(str >> i))
+ return false;
+
+ if (!has_only_whitespace (str))
+ return false;
+ // check whether valid bounds
+ // were specified, and if so
+ // enforce their values
+ if (lower_bound <= upper_bound)
+ return ((lower_bound <= i) &&
+ (upper_bound >= i));
+ else
+ return true;
+ }
+
+
+
+ std::string Integer::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ // check whether valid bounds
+ // were specified, and if so
+ // output their values
+ if (lower_bound <= upper_bound)
+ {
+ std::ostringstream description;
+
+ description << description_init
+ <<" range "
+ << lower_bound << "..." << upper_bound
+ << " (inclusive)]";
+ return description.str();
+ }
+ else
+ // if no bounds were given, then
+ // return generic string
+ return "[Integer]";
+ }
+ case Text:
+ {
+ if (lower_bound <= upper_bound)
+ {
+ std::ostringstream description;
+
+ description << "An integer n such that "
+ << lower_bound << " <= n <= " << upper_bound;
+
+ return description.str();
+ }
+ else
+ return "An integer";
+ }
+ case LaTeX:
+ {
+ if (lower_bound <= upper_bound)
+ {
+ std::ostringstream description;
+
+ description << "An integer $n$ such that $"
+ << lower_bound << "\\leq n \\leq " << upper_bound
+ << "$";
+
+ return description.str();
+ }
+ else
+ return "An integer";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> Integer::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Integer(lower_bound, upper_bound));
+ }
+
+
+
+ std::unique_ptr<Integer> Integer::create(const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ std::istringstream is(description);
+
+ if (is.str().size() > strlen(description_init) + 1)
+ {
+//TODO: verify that description matches the pattern "^\[Integer range \d+\.\.\.\d+\]$"
+ int lower_bound, upper_bound;
+
+ is.ignore(strlen(description_init) + strlen(" range "));
+
+ if (!(is >> lower_bound))
+ return std::unique_ptr<Integer>(new Integer());
+
+ is.ignore(strlen("..."));
+
+ if (!(is >> upper_bound))
+ return std::unique_ptr<Integer>(new Integer());
+
+ return std::unique_ptr<Integer>(new Integer(lower_bound, upper_bound));
+ }
+ else
+ return std::unique_ptr<Integer>(new Integer());
+ }
+ else
+ return std::unique_ptr<Integer>();
+ }
+
+
+
+ const double Double::min_double_value = -std::numeric_limits<double>::max();
+ const double Double::max_double_value = std::numeric_limits<double>::max();
+
+ const char *Double::description_init = "[Double";
+
+ Double::Double (const double lower_bound,
+ const double upper_bound)
+ :
+ lower_bound (lower_bound),
+ upper_bound (upper_bound)
+ {}
+
+
+
+ bool Double::match (const std::string &test_string) const
+ {
+ std::istringstream str(test_string);
+
+ double d;
+ str >> d;
+ if (str.fail())
+ return false;
+
+ if (!has_only_whitespace (str))
+ return false;
+ // check whether valid bounds
+ // were specified, and if so
+ // enforce their values
+ if (lower_bound <= upper_bound)
+ return ((lower_bound <= d) &&
+ (upper_bound >= d));
+ else
+ return true;
+ }
+
+
+
+ std::string Double::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ if (lower_bound <= upper_bound)
+ {
+ // bounds are valid
+ description << description_init << " ";
+ // We really want to compare with ==, but -Wfloat-equal would create
+ // a warning here, so work around it.
+ if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
+ description << "-MAX_DOUBLE";
+ else
+ description << lower_bound;
+ description << "...";
+ if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
+ description << "MAX_DOUBLE";
+ else
+ description << upper_bound;
+ description << " (inclusive)]";
+ return description.str();
+ }
+ else
+ {
+ // invalid bounds, assume unbounded double:
+ description << description_init << "]";
+ return description.str();
+ }
+ }
+ case Text:
+ {
+ if (lower_bound <= upper_bound)
+ {
+ std::ostringstream description;
+
+ description << "A floating point number v such that ";
+ if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
+ description << "-MAX_DOUBLE";
+ else
+ description << lower_bound;
+ description << " <= v <= ";
+ if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
+ description << "MAX_DOUBLE";
+ else
+ description << upper_bound;
+
+ return description.str();
+ }
+ else
+ return "A floating point number";
+ }
+ case LaTeX:
+ {
+ if (lower_bound <= upper_bound)
+ {
+ std::ostringstream description;
+
+ description << "A floating point number $v$ such that $";
+ if (0==std::memcmp(&lower_bound, &min_double_value, sizeof(lower_bound)))
+ description << "-\\text{MAX\\_DOUBLE}";
+ else
+ description << lower_bound;
+ description << " \\leq v \\leq ";
+ if (0==std::memcmp(&upper_bound, &max_double_value, sizeof(upper_bound)))
+ description << "\\text{MAX\\_DOUBLE}";
+ else
+ description << upper_bound;
+ description << "$";
+
+ return description.str();
+ }
+ else
+ return "A floating point number";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+ std::unique_ptr<PatternBase> Double::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Double(lower_bound, upper_bound));
+ }
+
+
+
+ std::unique_ptr<Double> Double::create (const std::string &description)
+ {
+ const std::string description_init_str = description_init;
+ if (description.compare(0, description_init_str.size(), description_init_str) != 0)
+ return std::unique_ptr<Double>();
+ if (*description.rbegin() != ']')
+ return std::unique_ptr<Double>();
+
+ std::string temp = description.substr(description_init_str.size());
+ if (temp == "]")
+ return std::unique_ptr<Double>(new Double(1.0, -1.0)); // return an invalid range
+
+ if (temp.find("...") != std::string::npos)
+ temp.replace(temp.find("..."), 3, " ");
+
+ double lower_bound = min_double_value,
+ upper_bound = max_double_value;
+
+ std::istringstream is(temp);
+ if (0 == temp.compare(0, std::strlen(" -MAX_DOUBLE"), " -MAX_DOUBLE"))
+ is.ignore(std::strlen(" -MAX_DOUBLE"));
+ else
+ {
+ // parse lower bound and give up if not a double
+ if (!(is >> lower_bound))
+ return std::unique_ptr<Double>();
+ }
+
+ // ignore failure here and assume we got MAX_DOUBLE as upper bound:
+ is >> upper_bound;
+ if (is.fail())
+ upper_bound = max_double_value;
+
+ return std::unique_ptr<Double>(new Double(lower_bound, upper_bound));
+ }
+
+
+
+ const char *Selection::description_init = "[Selection";
+
+
+ Selection::Selection (const std::string &seq)
+ : sequence(seq)
+ {
+ while (sequence.find(" |") != std::string::npos)
+ sequence.replace (sequence.find(" |"), 2, "|");
+ while (sequence.find("| ") != std::string::npos)
+ sequence.replace (sequence.find("| "), 2, "|");
+ }
+
+
+
+ bool Selection::match (const std::string &test_string) const
+ {
+ std::string tmp(sequence);
+
+ // remove whitespace at beginning
+ while ((tmp.length() != 0) && (std::isspace (tmp[0])))
+ tmp.erase (0,1);
+
+ // check the different possibilities
+ while (tmp.find('|') != std::string::npos)
+ {
+ if (test_string == std::string(tmp, 0, tmp.find('|')))
+ return true;
+
+ tmp.erase (0, tmp.find('|')+1);
+ };
+
+ //remove whitespace at the end
+ while ((tmp.length() != 0) && (std::isspace (*(tmp.end()-1))))
+ tmp.erase (tmp.end()-1);
+
+ // check last choice, not finished by |
+ if (test_string == tmp)
+ return true;
+
+ // not found
+ return false;
+ }
+
+
+
+ std::string Selection::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << " "
+ << sequence
+ << " ]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ std::ostringstream description;
+
+ description << "Any one of "
+ << Utilities::replace_in_string(sequence,"|",", ");
+
+ return description.str();
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> Selection::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Selection(sequence));
+ }
+
+
+ std::size_t
+ Selection::memory_consumption () const
+ {
+ return (sizeof(PatternBase) +
+ MemoryConsumption::memory_consumption(sequence));
+ }
+
+
+
+ std::unique_ptr<Selection> Selection::create(const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ std::string sequence(description);
+
+ sequence.erase(0, std::strlen(description_init) + 1);
+ sequence.erase(sequence.length()-2, 2);
+
+ return std::unique_ptr<Selection>(new Selection(sequence));
+ }
+ else
+ return std::unique_ptr<Selection>();
+ }
+
+
+
+ const unsigned int List::max_int_value
+ = std::numeric_limits<unsigned int>::max();
+
+ const char *List::description_init = "[List";
+
+
+ List::List (const PatternBase &p,
+ const unsigned int min_elements,
+ const unsigned int max_elements,
+ const std::string &separator)
+ :
+ pattern (p.clone()),
+ min_elements (min_elements),
+ max_elements (max_elements),
+ separator (separator)
+ {
+ Assert (min_elements <= max_elements,
+ ExcInvalidRange (min_elements, max_elements));
+ Assert (separator.size() > 0,
+ ExcMessage ("The separator must have a non-zero length."));
+ }
+
+
+
+ List::List (const List &other)
+ :
+ pattern (other.pattern->clone()),
+ min_elements (other.min_elements),
+ max_elements (other.max_elements),
+ separator (other.separator)
+ {}
+
+
+ const std::string &List::get_separator() const
+ {
+ return separator;
+ }
+
+
+
+ const PatternBase &List::get_base_pattern() const
+ {
+ return *pattern;
+ }
+
+
+
+ bool List::match (const std::string &test_string_list) const
+ {
+ const 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 (const std::string &string : split_list)
+ if (pattern->match (string) == false)
+ return false;
+
+ return true;
+ }
+
+
+
+ std::string List::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << " of <" << pattern->description(style) << ">"
+ << " of length " << min_elements << "..." << max_elements
+ << " (inclusive)";
+ if (separator != ",")
+ description << " separated by <" << separator << ">";
+ description << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ std::ostringstream description;
+
+ description << "A list of "
+ << min_elements << " to " << max_elements
+ << " elements ";
+ if (separator != ",")
+ description << "separated by <" << separator << "> ";
+ description << "where each element is ["
+ << pattern->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> List::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new List(*pattern, min_elements, max_elements, separator));
+ }
+
+
+ std::size_t
+ List::memory_consumption () const
+ {
+ return (sizeof(*this) +
+ MemoryConsumption::memory_consumption(*pattern) +
+ MemoryConsumption::memory_consumption(separator));
+ }
+
+
+
+ std::unique_ptr<List> List::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ int min_elements, max_elements;
+
+ std::istringstream is(description);
+ is.ignore(strlen(description_init) + strlen(" of <"));
+
+ std::string str;
+ std::getline(is, str, '>');
+
+ std::shared_ptr<PatternBase> base_pattern (pattern_factory(str));
+
+ is.ignore(strlen(" of length "));
+ if (!(is >> min_elements))
+ return std::unique_ptr<List>(new List(*base_pattern));
+
+ is.ignore(strlen("..."));
+ if (!(is >> max_elements))
+ return std::unique_ptr<List>(new List(*base_pattern, min_elements));
+
+ is.ignore(strlen(" (inclusive) separated by <"));
+ std::string separator;
+ if (is)
+ std::getline(is, separator, '>');
+ else
+ separator = ",";
+
+ return std::unique_ptr<List>(new List(*base_pattern, min_elements, max_elements, separator));
+ }
+ else
+ return std::unique_ptr<List>();
+ }
+
+
+
+ const unsigned int Map::max_int_value
+ = std::numeric_limits<unsigned int>::max();
+
+ const char *Map::description_init = "[Map";
+
+
+ Map::Map (const PatternBase &p_key,
+ const PatternBase &p_value,
+ const unsigned int min_elements,
+ const unsigned int max_elements,
+ 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),
+ 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 (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"));
+ }
+
+
+
+ Map::Map (const Map &other)
+ :
+ key_pattern (other.key_pattern->clone()),
+ value_pattern (other.value_pattern->clone()),
+ min_elements (other.min_elements),
+ max_elements (other.max_elements),
+ 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 =
+ Utilities::split_string_list(test_string_list, separator);
+ if ((split_list.size() < min_elements) ||
+ (split_list.size() > max_elements))
+ return false;
+
+ for (auto &key_value_pair : split_list)
+ {
+ std::vector<std::string> pair =
+ Utilities::split_string_list(key_value_pair, key_value_separator);
+
+ // 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 (pair[0]) == false)
+ return false;
+ if (value_pattern->match (pair[1]) == false)
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ std::string Map::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << " of <"
+ << key_pattern->description(style) << ">"
+ << key_value_separator << "<"
+ << value_pattern->description(style) << ">"
+ << " of length " << min_elements << "..." << max_elements
+ << " (inclusive)";
+ if (separator != ",")
+ description << " separated by <" << separator << ">";
+ description << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ std::ostringstream description;
+
+ description << "A key"
+ << key_value_separator
+ << "value map of "
+ << min_elements << " to " << max_elements
+ << " elements ";
+ if (separator != ",")
+ description << " separated by <" << separator << "> ";
+ description << " where each key is ["
+ << key_pattern->description(style)
+ << "]"
+ << " and each value is ["
+ << value_pattern->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> Map::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Map(*key_pattern, *value_pattern,
+ min_elements, max_elements,
+ separator, key_value_separator));
+ }
+
+
+ std::size_t
+ Map::memory_consumption () const
+ {
+ return (sizeof(*this) +
+ MemoryConsumption::memory_consumption (*key_pattern) +
+ MemoryConsumption::memory_consumption (*value_pattern) +
+ MemoryConsumption::memory_consumption (separator)+
+ MemoryConsumption::memory_consumption (key_value_separator));
+ }
+
+
+
+ std::unique_ptr<Map> Map::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ int min_elements, max_elements;
+
+ std::istringstream is(description);
+ is.ignore(strlen(description_init) + strlen(" of <"));
+
+ std::string key;
+ std::getline(is, key, '>');
+
+ std::string key_value_separator;
+ std::getline(is, key_value_separator, '<');
+
+ // 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));
+
+ is.ignore(strlen(" of length "));
+ if (!(is >> min_elements))
+ return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern));
+
+ is.ignore(strlen("..."));
+ if (!(is >> max_elements))
+ return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern, min_elements));
+
+ is.ignore(strlen(" (inclusive) separated by <"));
+ std::string separator;
+ if (is)
+ std::getline(is, separator, '>');
+ else
+ separator = ",";
+
+ return std::unique_ptr<Map>(new Map(*key_pattern, *value_pattern,
+ min_elements, max_elements,
+ separator, key_value_separator));
+ }
+ else
+ return std::unique_ptr<Map>();
+ }
+
+
+
+ const PatternBase &Map::get_key_pattern() const
+ {
+ return *key_pattern;
+ }
+
+
+
+ const PatternBase &Map::get_value_pattern() const
+ {
+ return *value_pattern;
+ }
+
+
+
+ const std::string &Map::get_separator() const
+ {
+ return separator;
+ }
+
+
+ const std::string &Map::get_key_value_separator() const
+ {
+ return key_value_separator;
+ }
+
+
+ const char *MultipleSelection::description_init = "[MultipleSelection";
+
+
+ MultipleSelection::MultipleSelection (const std::string &seq)
+ {
+ Assert (seq.find (",") == std::string::npos, ExcCommasNotAllowed(seq.find(",")));
+
+ sequence = seq;
+ while (sequence.find(" |") != std::string::npos)
+ sequence.replace (sequence.find(" |"), 2, "|");
+ while (sequence.find("| ") != std::string::npos)
+ sequence.replace (sequence.find("| "), 2, "|");
+ }
+
+
+
+ bool MultipleSelection::match (const std::string &test_string_list) const
+ {
+ std::string tmp = test_string_list;
+ std::vector<std::string> split_names;
+
+ // first split the input list
+ while (tmp.length() != 0)
+ {
+ std::string name;
+ name = tmp;
+
+ if (name.find(",") != std::string::npos)
+ {
+ name.erase (name.find(","), std::string::npos);
+ tmp.erase (0, tmp.find(",")+1);
+ }
+ else
+ tmp = "";
+
+ while ((name.length() != 0) &&
+ (std::isspace (name[0])))
+ name.erase (0,1);
+ while (std::isspace (name[name.length()-1]))
+ name.erase (name.length()-1, 1);
+
+ split_names.push_back (name);
+ };
+
+
+ // check the different possibilities
+ for (std::vector<std::string>::const_iterator test_string = split_names.begin();
+ test_string != split_names.end(); ++test_string)
+ {
+ bool string_found = false;
+
+ tmp = sequence;
+ while (tmp.find('|') != std::string::npos)
+ {
+ if (*test_string == std::string(tmp, 0, tmp.find('|')))
+ {
+ // string found, quit
+ // loop. don't change
+ // tmp, since we don't
+ // need it anymore.
+ string_found = true;
+ break;
+ };
+
+ tmp.erase (0, tmp.find('|')+1);
+ };
+ // check last choice, not finished by |
+ if (!string_found)
+ if (*test_string == tmp)
+ string_found = true;
+
+ if (!string_found)
+ return false;
+ };
+
+ return true;
+ }
+
+
+
+ std::string MultipleSelection::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << " "
+ << sequence
+ << " ]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ std::ostringstream description;
+
+ description << "A comma-separated list of any of "
+ << Utilities::replace_in_string(sequence,"|",", ");
+
+ return description.str();
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> MultipleSelection::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new MultipleSelection(sequence));
+ }
+
+
+ std::size_t
+ MultipleSelection::memory_consumption () const
+ {
+ return (sizeof(PatternBase) +
+ MemoryConsumption::memory_consumption(sequence));
+ }
+
+
+
+ std::unique_ptr<MultipleSelection> MultipleSelection::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ std::string sequence(description);
+
+ sequence.erase(0, std::strlen(description_init) + 1);
+ sequence.erase(sequence.length()-2, 2);
+
+ return std::unique_ptr<MultipleSelection>(new MultipleSelection(sequence));
+ }
+ else
+ return std::unique_ptr<MultipleSelection>();
+ }
+
+
+
+ const char *Bool::description_init = "[Bool";
+
+
+ Bool::Bool ()
+ :
+ Selection ("true|false")
+ {}
+
+
+
+ std::string Bool::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ return "A boolean value (true or false)";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> Bool::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Bool());
+ }
+
+
+
+ std::unique_ptr<Bool> Bool::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ return std::unique_ptr<Bool>(new Bool());
+ else
+ return std::unique_ptr<Bool>();
+ }
+
+
+
+ const char *Anything::description_init = "[Anything";
+
+
+ Anything::Anything ()
+ {}
+
+
+
+ bool Anything::match (const std::string &) const
+ {
+ return true;
+ }
+
+
+
+ std::string Anything::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init
+ << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ return "Any string";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> Anything::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new Anything());
+ }
+
+
+
+ std::unique_ptr<Anything> Anything::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ return std::unique_ptr<Anything>(new Anything());
+ else
+ return std::unique_ptr<Anything>();
+ }
+
+
+
+ const char *FileName::description_init = "[FileName";
+
+
+ FileName::FileName (const FileType type)
+ : file_type (type)
+ {}
+
+
+
+ bool FileName::match (const std::string &) const
+ {
+ return true;
+ }
+
+
+
+ std::string FileName::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init;
+
+ if (file_type == input)
+ description << " (Type: input)]";
+ else
+ description << " (Type: output)]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ if (file_type == input)
+ return "an input filename";
+ else
+ return "an output filename";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> FileName::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new FileName(file_type));
+ }
+
+
+
+ std::unique_ptr<FileName> FileName::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ {
+ std::istringstream is(description);
+ std::string file_type;
+ FileType type;
+
+ is.ignore(strlen(description_init) + strlen(" (Type:"));
+
+ is >> file_type;
+
+ if (file_type == "input)]")
+ type = input;
+ else
+ type = output;
+
+ return std::unique_ptr<FileName>(new FileName(type));
+ }
+ else
+ return std::unique_ptr<FileName>();
+ }
+
+
+
+ const char *DirectoryName::description_init = "[DirectoryName";
+
+
+ DirectoryName::DirectoryName ()
+ {}
+
+
+
+ bool DirectoryName::match (const std::string &) const
+ {
+ return true;
+ }
+
+
+
+ std::string DirectoryName::description (const OutputStyle style) const
+ {
+ switch (style)
+ {
+ case Machine:
+ {
+ std::ostringstream description;
+
+ description << description_init << "]";
+
+ return description.str();
+ }
+ case Text:
+ case LaTeX:
+ {
+ return "A directory name";
+ }
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ // Should never occur without an exception, but prevent compiler from
+ // complaining
+ return "";
+ }
+
+
+
+ std::unique_ptr<PatternBase> DirectoryName::clone() const
+ {
+ return std::unique_ptr<PatternBase>(new DirectoryName());
+ }
+
+
+
+ std::unique_ptr<DirectoryName> DirectoryName::create (const std::string &description)
+ {
+ if (description.compare(0, std::strlen(description_init), description_init) == 0)
+ return std::unique_ptr<DirectoryName>(new DirectoryName());
+ else
+ return std::unique_ptr<DirectoryName>();
+ }
+
+} // end namespace Patterns
+
+DEAL_II_NAMESPACE_CLOSE