* Declare some regexps which
* may be used to define patterns.
*/
-struct Patterns
+namespace Patterns
{
- public:
/**
* Base class to declare common
* interface.
virtual string description () const = 0;
/**
- * Return a pointer to an exact
- * copy of the object. This is
- * necessary since we want to store
+ * Return a pointer to an
+ * exact copy of the
+ * object. This is necessary
+ * since we want to store
* objects of this type in
- * containers.
+ * 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 PatternBase * clone () const = 0;
};
/**
* Test for the string being an
- * integer.
+ * integer. If bounds are given
+ * to the constructor, then the
+ * integer given also needs to be
+ * withing 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 the
+ * infinite interval is implied,
+ * i.e. 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:
+ /**
+ * 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 infinite
+ * interval is meant. The
+ * default values are chosen
+ * such that no bounds are
+ * enforced on parameters.
+ */
+ Integer (const int lower_bound = 1,
+ const int upper_bound = 0);
+
+ /**
+ * Return @p{true} if the
+ * string is an integer and
+ * its value is within the
+ * specified range.
+ */
virtual bool match (const string &test_string) const;
+
+ /**
+ * Return a description of
+ * the pattern that valid
+ * string are expected to
+ * match. If bounds were
+ * specified to the
+ * constructor, then include
+ * them into this
+ * description.
+ */
virtual string description () 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 PatternBase * clone () const;
+
+ private:
+ /**
+ * Value of the lower
+ * bound. A number that
+ * satisfies the @p{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 @p{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;
};
/**
- * Test for the string being a double.
+ * Test for the string being a
+ * @p{double}. If bounds are
+ * given to the constructor, then
+ * the integer given also needs
+ * to be withing 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 the
+ * infinite interval is implied,
+ * i.e. 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 damping parameters are
+ * frequently only reasonable if
+ * between zero and one), or in
+ * many other cases.
*/
class Double : public PatternBase
{
public:
+ /**
+ * 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 infinite
+ * interval is meant. The
+ * default values are chosen
+ * such that no bounds are
+ * enforced on parameters.
+ */
+ Double (const int lower_bound = 1,
+ const int upper_bound = 0);
+
+ /**
+ * Return @p{true} if the
+ * string is a number and its
+ * value is within the
+ * specified range.
+ */
virtual bool match (const string &test_string) const;
+
+ /**
+ * Return a description of
+ * the pattern that valid
+ * string are expected to
+ * match. If bounds were
+ * specified to the
+ * constructor, then include
+ * them into this
+ * description.
+ */
virtual string description () 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 PatternBase * clone () const;
+
+ private:
+ /**
+ * Value of the lower
+ * bound. A number that
+ * satisfies the @p{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 @p{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;
};
/**
- * 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 "red|blue|black", then the @p{match}
- * function returns @p{true} exactly if
- * the string is either "red" or "blue"
- * or "black". Spaces around the pipe
- * signs do not matter and are
- * eliminated.
+ * 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
+ * @p{"red|blue|black"}, then the
+ * @p{match} function returns
+ * @p{true} 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 string &seq);
+
+ /**
+ * Return @p{true} if the
+ * string is an element of
+ * the description list
+ * passed to the constructor.
+ */
virtual bool match (const string &test_string) const;
+
+ /**
+ * Return a description of
+ * the pattern that valid
+ * string are expected to
+ * match. Here, this is the
+ * list of valid strings
+ * passed to the constructor.
+ */
virtual string description () 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 PatternBase * clone () const;
+
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.
+ */
string sequence;
};
/**
- * This class is much like the @p{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. For example, if the string to
- * the constructor was @p{"ucd|gmv|eps"}, then
- * the following would be legal input:
- * @p{eps, gmv}. You may give an arbitrarily
- * long list of values, where there may be
- * as many spaces around commas as you like.
- * However, commas are not allowed inside
- * the values given to the constructor.
+ * This class is much like the
+ * @p{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. For
+ * example, if the string to the
+ * constructor was
+ * @p{"ucd|gmv|eps"}, then the
+ * following would be legal
+ * input: @p{eps, gmv}. You may
+ * give an arbitrarily long list
+ * of values, where there may be
+ * as many spaces around commas
+ * as you like. However, commas
+ * are not allowed inside the
+ * values given to the
+ * constructor.
*/
class MultipleSelection : public PatternBase
{
public:
+ /**
+ * Constructor. Take the
+ * given parameter as the
+ * specification of valid
+ * strings.
+ */
MultipleSelection (const string &seq);
+
+ /**
+ * Return @p{true} if the
+ * string is an element of
+ * the description list
+ * passed to the constructor.
+ */
virtual bool match (const string &test_string) const;
+
+ /**
+ * Return a description of
+ * the pattern that valid
+ * string are expected to
+ * match. Here, this is the
+ * list of valid strings
+ * passed to the constructor.
+ */
virtual string description () 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 PatternBase * clone () const;
+ /**
+ * 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.
+ */
string sequence;
};
/**
- * Test for the string being either
- * "true" or "false". This is mapped
- * to the @p{Selection} class.
+ * Test for the string being
+ * either "true" or "false". This
+ * is mapped to the @p{Selection}
+ * class.
*/
class Bool : public Selection
{
public:
+ /**
+ * Constrcuctor.
+ */
Bool ();
+
+ /**
+ * 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 PatternBase * clone () const;
};
{
public:
/**
- * Allow for at least one non-virtual
+ * Constructor. (Allow for at
+ * least one non-virtual
* function in this class, as
- * otherwise sometimes no virtual
- * table is emitted.
+ * otherwise sometimes no
+ * virtual table is emitted.)
*/
Anything ();
+
+ /**
+ * Return @p{true} if the
+ * string matches its
+ * constraints, i.e. always.
+ */
virtual bool match (const string &test_string) const;
+
+ /**
+ * Return a description of
+ * the pattern that valid
+ * string are expected to
+ * match. Here, this is the
+ * string @p{"[Anything]"}.
+ */
virtual string description () 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 PatternBase * clone () const;
};
};
-Patterns::PatternBase::~PatternBase ()
-{};
+namespace Patterns
+{
+ PatternBase::~PatternBase ()
+ {};
-bool Patterns::Integer::match (const string &test_string) const
-{
- istrstream str(test_string.c_str());
- int i;
- if (str >> i) return true;
- return false;
-};
+ Integer::Integer (const int lower_bound,
+ const int upper_bound) :
+ lower_bound (lower_bound),
+ upper_bound (upper_bound)
+ {};
-string Patterns::Integer::description () const
-{
- return "[Integer]";
-};
+ bool Integer::match (const string &test_string) const
+ {
+ istrstream str(test_string.c_str());
+ int i;
+ if (str >> i)
+ {
+ // 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;
+ };
+
+ return false;
+ };
-Patterns::PatternBase *
-Patterns::Integer::clone () const
-{
- return new Patterns::Integer();
-};
+ string Integer::description () const
+ {
+ // check whether valid bounds
+ // were specified, and if so
+ // output their values
+ if (lower_bound <= upper_bound)
+ {
+ ostrstream description;
+ description << "[Integer range "
+ << lower_bound << "..." << upper_bound
+ << " (inclusive)]"
+ << ends;
+ return description.str();
+ }
+ else
+ // if no bounds were given, then
+ // return generic string
+ return "[Integer]";
+ };
-bool Patterns::Double::match (const string &test_string) const
-{
- istrstream str(test_string.c_str());
- double d;
- if (str >> d) return true;
- return false;
-};
+ PatternBase *
+ Integer::clone () const
+ {
+ return new Integer(lower_bound, upper_bound);
+ };
-string Patterns::Double::description () const
-{
- return "[Integer]";
-};
+ Double::Double (const int lower_bound,
+ const int upper_bound) :
+ lower_bound (lower_bound),
+ upper_bound (upper_bound)
+ {};
-Patterns::PatternBase *
-Patterns::Double::clone () const {
- return new Patterns::Double();
-};
+ bool Double::match (const string &test_string) const
+ {
+ istrstream str(test_string.c_str());
+ double d;
+ if (str >> d)
+ {
+ // 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;
+ };
+ return false;
+ };
-Patterns::Selection::Selection (const string &seq)
-{
- sequence = seq;
- while (sequence.find(" |") != string::npos)
- sequence.replace (sequence.find(" |"), 2, '|');
- while (sequence.find("| ") != string::npos)
- sequence.replace (sequence.find("| "), 2, '|');
-};
+ string Double::description () const
+ {
+ // check whether valid bounds
+ // were specified, and if so
+ // output their values
+ if (lower_bound <= upper_bound)
+ {
+ ostrstream description;
+ description << "[Floating point range "
+ << lower_bound << "..." << upper_bound
+ << " (inclusive)]"
+ << ends;
+ return description.str();
+ }
+ else
+ // if no bounds were given, then
+ // return generic string
+ return "[Double]";
+ };
-bool Patterns::Selection::match (const string &test_string) const
-{
- vector<string> choices;
- string tmp(sequence);
- // check the different possibilities
- while (tmp.find('|') != string::npos)
- {
- if (test_string == string(tmp, 0, tmp.find('|')))
- return true;
+ PatternBase *
+ Double::clone () const
+ {
+ return new Double(lower_bound, upper_bound);
+ };
+
+
+
+ Selection::Selection (const string &seq)
+ {
+ sequence = seq;
+
+ while (sequence.find(" |") != string::npos)
+ sequence.replace (sequence.find(" |"), 2, '|');
+ while (sequence.find("| ") != string::npos)
+ sequence.replace (sequence.find("| "), 2, '|');
+ };
+
+
+
+ bool Selection::match (const string &test_string) const
+ {
+ vector<string> choices;
+ string tmp(sequence);
+ // check the different possibilities
+ while (tmp.find('|') != string::npos)
+ {
+ if (test_string == string(tmp, 0, tmp.find('|')))
+ return true;
- tmp.erase (0, tmp.find('|')+1);
- };
- // check last choice, not finished by |
- if (test_string == tmp)
- return true;
+ tmp.erase (0, tmp.find('|')+1);
+ };
+ // check last choice, not finished by |
+ if (test_string == tmp)
+ return true;
- // not found
- return false;
-};
+ // not found
+ return false;
+ };
-string Patterns::Selection::description () const
-{
- return sequence;
-};
+ string Selection::description () const
+ {
+ return sequence;
+ };
-Patterns::PatternBase *
-Patterns::Selection::clone () const
-{
- return new Patterns::Selection(sequence);
-};
+ PatternBase *
+ Selection::clone () const
+ {
+ return new Selection(sequence);
+ };
-Patterns::MultipleSelection::MultipleSelection (const string &seq)
-{
- Assert (seq.find (",") == string::npos, ExcCommasNotAllowed(seq.find(",")));
+ MultipleSelection::MultipleSelection (const string &seq)
+ {
+ Assert (seq.find (",") == string::npos, ExcCommasNotAllowed(seq.find(",")));
- sequence = seq;
- while (sequence.find(" |") != string::npos)
- sequence.replace (sequence.find(" |"), 2, '|');
- while (sequence.find("| ") != string::npos)
- sequence.replace (sequence.find("| "), 2, '|');
-};
+ sequence = seq;
+ while (sequence.find(" |") != string::npos)
+ sequence.replace (sequence.find(" |"), 2, '|');
+ while (sequence.find("| ") != string::npos)
+ sequence.replace (sequence.find("| "), 2, '|');
+ };
-bool Patterns::MultipleSelection::match (const string &test_string_list) const
-{
- string tmp = test_string_list;
- list<string> split_list;
+ bool MultipleSelection::match (const string &test_string_list) const
+ {
+ string tmp = test_string_list;
+ list<string> split_list;
- // first split the input list
- while (tmp.length() != 0)
- {
- string name;
- name = tmp;
+ // first split the input list
+ while (tmp.length() != 0)
+ {
+ string name;
+ name = tmp;
- if (name.find(",") != string::npos)
- {
- name.erase (name.find(","), string::npos);
- tmp.erase (0, test_string_list.find(",")+1);
- }
- else
- tmp = "";
+ if (name.find(",") != string::npos)
+ {
+ name.erase (name.find(","), string::npos);
+ tmp.erase (0, test_string_list.find(",")+1);
+ }
+ else
+ tmp = "";
- while ((name.length() != 0) &&
- (name[0] == ' '))
- name.erase (0,1);
- while (name[name.length()-1] == ' ')
- name.erase (name.length()-1, 1);
+ while ((name.length() != 0) &&
+ (name[0] == ' '))
+ name.erase (0,1);
+ while (name[name.length()-1] == ' ')
+ name.erase (name.length()-1, 1);
- split_list.push_back (name);
- };
+ split_list.push_back (name);
+ };
- // check the different possibilities
- for (list<string>::const_iterator test_string = split_list.begin();
- test_string != split_list.end(); ++test_string)
- {
- bool string_found = false;
+ // check the different possibilities
+ for (list<string>::const_iterator test_string = split_list.begin();
+ test_string != split_list.end(); ++test_string)
+ {
+ bool string_found = false;
- tmp = sequence;
- while (tmp.find('|') != string::npos)
- {
- if (*test_string == 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 = sequence;
+ while (tmp.find('|') != string::npos)
+ {
+ if (*test_string == 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;
+ 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;
- };
+ if (!string_found)
+ return false;
+ };
- return true;
-};
+ return true;
+ };
-string Patterns::MultipleSelection::description () const
-{
- return sequence;
-};
+ string MultipleSelection::description () const
+ {
+ return sequence;
+ };
-Patterns::PatternBase *
-Patterns::MultipleSelection::clone () const
-{
- return new Patterns::MultipleSelection(sequence);
-};
+ PatternBase *
+ MultipleSelection::clone () const
+ {
+ return new MultipleSelection(sequence);
+ };
-Patterns::Bool::Bool () :
- Selection ("true|false")
-{};
+ Bool::Bool () :
+ Selection ("true|false")
+ {};
-Patterns::PatternBase *
-Patterns::Bool::clone () const
-{
- return new Patterns::Bool();
-};
+ PatternBase *
+ Bool::clone () const
+ {
+ return new Bool();
+ };
-Patterns::Anything::Anything ()
-{};
+ Anything::Anything ()
+ {};
-bool Patterns::Anything::match (const string &) const
-{
- return true;
-};
+ bool Anything::match (const string &) const
+ {
+ return true;
+ };
-string Patterns::Anything::description () const
-{
- return "[Anything]";
-};
+ string Anything::description () const
+ {
+ return "[Anything]";
+ };
-Patterns::PatternBase *
-Patterns::Anything::clone () const
-{
- return new Patterns::Anything();
-};
+ PatternBase *
+ Anything::clone () const
+ {
+ return new Anything();
+ };
+
+} // end namespace Patterns
ExcEntryAlreadyExists (entry));
// Default must match Pattern
Assert (pattern.match (default_value),
- ExcDefaultDoesNotMatchPattern(default_value, pattern.description()));
+ ExcDefaultDoesNotMatchPattern(default_value,
+ pattern.description()));
// does entry already exist?
if (p->entries.find (entry) != p->entries.end())