]> https://gitweb.dealii.org/ - dealii.git/commitdiff
New tuple pattern.
authorLuca Heltai <luca.heltai@sissa.it>
Thu, 26 Oct 2017 10:10:35 +0000 (12:10 +0200)
committerLuca Heltai <luca.heltai@sissa.it>
Thu, 26 Oct 2017 10:18:10 +0000 (12:18 +0200)
doc/news/changes/minor/20171026LucaHeltai [new file with mode: 0644]
include/deal.II/base/patterns.h
source/base/patterns.cc
tests/base/patterns_08.cc [new file with mode: 0644]
tests/base/patterns_08.output [new file with mode: 0644]
tests/base/patterns_09.cc [new file with mode: 0644]
tests/base/patterns_09.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20171026LucaHeltai b/doc/news/changes/minor/20171026LucaHeltai
new file mode 100644 (file)
index 0000000..b74c649
--- /dev/null
@@ -0,0 +1,4 @@
+New:Created a new Patterns::Tuple class, that allows parsing arbitrary tuples 
+of objects in parameter files. 
+<br> 
+(Luca Heltai, 2017/10/26)
index b6d168d2e71a64db66076d5fd38c013c21962212..60e1fd1da9802037053caa270281e77598d945d4 100644 (file)
@@ -661,6 +661,98 @@ namespace Patterns
   };
 
 
+
+  /**
+   * This pattern matches comma-separated values of arbitrary types. Each type
+   * has to match a pattern given to the constructor.
+   *
+   * The constructor expects a vector of Patterns, and optionally an
+   * std::string, specifying the separator to use when parsing the Tuple from a
+   * string.
+   */
+  class Tuple : public PatternBase
+  {
+  public:
+    /**
+     * Constructor. Specify each pattern that the Tuple should contain.
+     *
+     * Optionally specify a separator string.
+     */
+
+    /**
+     * Constructor.
+     * @param patterns The pattern each object of the Tuple should match
+     * @param separator An optional string used to delimit each element
+     */
+    Tuple (const std::vector<std::unique_ptr<PatternBase> > &patterns,
+           const std::string  &separator = ",");
+
+    /**
+     * Copy constructor.
+     */
+    Tuple (const Tuple &other);
+
+    /**
+     * Return <tt>true</tt> if the string is a list of strings
+     * each of which matches the patterns given to the constructor.
+     */
+    virtual bool match (const std::string &test_string) const;
+
+    /**
+     * Return a description of the pattern that valid strings are expected to
+     * match.
+     */
+    virtual std::string description (const OutputStyle style=Machine) const;
+
+    /**
+     * Return a copy of the present object, which is newly allocated on the
+     * heap. Ownership of that object is transferred to the caller of this
+     * function.
+     */
+    virtual std::unique_ptr<PatternBase> clone () const;
+
+    /**
+     * Creates new object if the start of description matches
+     * description_init.  Ownership of that object is transferred to the
+     * caller of this function.
+     */
+    static std::unique_ptr<Tuple> create (const std::string &description);
+
+    /**
+     * Determine an estimate for the memory consumption (in bytes) of this
+     * object.
+     */
+    std::size_t memory_consumption () const;
+
+    /**
+     * Return a reference to the i-th pattern in the tuple.
+     */
+    const PatternBase &get_pattern(const unsigned int &i) const;
+
+    /**
+     * Return the separator of the tuple entries.
+     */
+    const std::string &get_separator() const;
+
+  private:
+    /**
+     * Copy of the patterns stored in the Tuple.
+     */
+    std::vector<std::unique_ptr<PatternBase> > patterns;
+
+    /**
+     * Separator between elements of the list.
+     */
+    const std::string separator;
+
+    /**
+     * Initial part of description
+     */
+    static const char *description_init;
+  };
+
+
+
   /**
    * This class is much like the Selection class, but it allows the input to
    * be a comma-separated list of values which each have to be given in the
index 7057a733bc9db66bbde61edc6b00534ff676ad3a..4d56e88b62eff19c04d8cb319e35a811aea17bbe 100644 (file)
@@ -946,6 +946,185 @@ namespace Patterns
   }
 
 
+
+  const char *Tuple::description_init = "[Tuple";
+
+
+  Tuple::Tuple (const std::vector<std::unique_ptr<PatternBase> >  &ps,
+                const std::string  &separator)
+    :
+    separator (separator)
+  {
+    Assert (ps.size() > 0,
+            ExcMessage ("The Patterns list must have a non-zero length."));
+    Assert (separator.size() > 0,
+            ExcMessage ("The separator must have a non-zero length."));
+    patterns.resize(ps.size());
+    for (unsigned int i=0; i<ps.size(); ++i)
+      patterns[i] = ps[i]->clone();
+  }
+
+
+
+  Tuple::Tuple (const Tuple &other)
+    :
+    separator (other.separator)
+  {
+    patterns.resize(other.patterns.size());
+    for (unsigned int i=0; i<other.patterns.size(); ++i)
+      patterns[i] = other.patterns[i]->clone();
+  }
+
+
+
+  bool Tuple::match (const std::string &test_string_list) const
+  {
+    std::vector<std::string> split_list =
+      Utilities::split_string_list(test_string_list, separator);
+    if (split_list.size() != patterns.size())
+      return false;
+
+    for (unsigned int i=0; i<patterns.size(); ++i)
+      {
+        if (patterns[i]->match (split_list[i]) == false)
+          return false;
+      }
+
+    return true;
+  }
+
+
+
+  std::string Tuple::description (const OutputStyle style) const
+  {
+    switch (style)
+      {
+      case Machine:
+      {
+        std::ostringstream description;
+
+        description << description_init
+                    << " of <"
+                    << patterns.size() << "> elements <"
+                    << patterns[0]->description(style)
+                    << ">";
+        for (unsigned int i=1; i<patterns.size(); ++i)
+          description << ", <"
+                      << patterns[i]->description(style)
+                      << ">";
+
+        if (separator != ",")
+          description << " separated by <" << separator << ">";
+        description << "]";
+
+        return description.str();
+      }
+      case Text:
+      case LaTeX:
+      {
+        std::ostringstream description;
+
+        description << "A Tuple of "
+                    << patterns.size()
+                    << " elements ";
+        if (separator != ",")
+          description << " separated by <" << separator << "> ";
+        description << " where each element is ["
+                    <<  patterns[0]->description(style)
+                    << "]";
+        for (unsigned int i=1; i<patterns.size(); ++i)
+          {
+            description << separator
+                        << "[" << patterns[i]->description(style) << "]";
+
+            return description.str();
+          }
+      }
+      default:
+        AssertThrow(false, ExcNotImplemented());
+      }
+    // Should never occur without an exception, but prevent compiler from
+    // complaining
+    return "";
+  }
+
+
+
+  std::unique_ptr<PatternBase> Tuple::clone() const
+  {
+    return std::unique_ptr<PatternBase>(new Tuple(patterns, separator));
+  }
+
+
+  std::size_t
+  Tuple::memory_consumption () const
+  {
+    return (sizeof(*this) +
+            MemoryConsumption::memory_consumption (patterns) +
+            MemoryConsumption::memory_consumption (separator));
+  }
+
+
+
+  std::unique_ptr<Tuple> Tuple::create (const std::string &description)
+  {
+    if (description.compare(0, std::strlen(description_init), description_init) == 0)
+      {
+        std::vector<std::unique_ptr<PatternBase> > patterns;
+
+        std::istringstream is(description);
+        is.ignore(strlen(description_init) + strlen(" of <"));
+
+        std::string len;
+        std::getline(is, len, '>');
+        const unsigned int n_elements = Utilities::string_to_int(len);
+        Assert(n_elements>0,
+               ExcMessage("Provide at least 1 element in the tuple."));
+        patterns.resize(n_elements);
+
+        is.ignore(strlen(" elements <"));
+
+        std::string element;
+        std::getline(is, element, '>');
+        patterns[0] = pattern_factory(element);
+
+        for (unsigned int i=1; i<n_elements; ++i)
+          {
+            is.ignore(strlen(", <"));
+            std::getline(is, element, '>');
+            patterns[i] = pattern_factory(element);
+          }
+
+        is.ignore(strlen(" separated by <"));
+
+        std::string separator;
+        if (is)
+          std::getline(is, separator, '>');
+        else
+          separator = ",";
+
+        return std::unique_ptr<Tuple>(new Tuple(patterns,separator));
+      }
+    else
+      return std::unique_ptr<Tuple>();
+  }
+
+
+
+  const PatternBase &Tuple::get_pattern(const unsigned int &i) const
+  {
+    return *patterns[i];
+  }
+
+
+
+  const std::string &Tuple::get_separator() const
+  {
+    return separator;
+  }
+
+
+
   const char *MultipleSelection::description_init = "[MultipleSelection";
 
 
diff --git a/tests/base/patterns_08.cc b/tests/base/patterns_08.cc
new file mode 100644 (file)
index 0000000..b736dd3
--- /dev/null
@@ -0,0 +1,47 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2015 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/std_cxx14/memory.h>
+#include <memory>
+
+int main()
+{
+  initlog();
+
+  // create a pattern and let it
+  // output its description
+  std::vector<std::unique_ptr<Patterns::PatternBase> > ps;
+  ps.push_back(std_cxx14::make_unique<Patterns::Integer>());
+  ps.push_back(std_cxx14::make_unique<Patterns::Double>());
+  ps.push_back(std_cxx14::make_unique<Patterns::Anything>());
+
+  Patterns::Tuple pattern(ps, ";");
+  const std::string desc = pattern.description();
+
+  // now let the same class re-create
+  // a pattern object from the
+  // description and verify that the
+  // result is the same as what we
+  // started out with
+  std::unique_ptr<Patterns::Tuple> pattern2 = Patterns::Tuple::create (desc);
+
+  AssertThrow (pattern2 != nullptr, ExcInternalError());
+  AssertThrow (desc == pattern2->description(), ExcInternalError());
+
+  deallog << desc << std::endl;
+}
diff --git a/tests/base/patterns_08.output b/tests/base/patterns_08.output
new file mode 100644 (file)
index 0000000..774b01d
--- /dev/null
@@ -0,0 +1,2 @@
+
+DEAL::[Tuple of <3> elements <[Integer range -2147483648...2147483647 (inclusive)]>, <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]>, <[Anything]> separated by <;>]
diff --git a/tests/base/patterns_09.cc b/tests/base/patterns_09.cc
new file mode 100644 (file)
index 0000000..6b469a6
--- /dev/null
@@ -0,0 +1,43 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2015 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/std_cxx14/memory.h>
+#include <memory>
+
+int main()
+{
+  initlog();
+
+  // create a pattern and match a string
+  std::vector<std::unique_ptr<Patterns::PatternBase> > ps;
+  ps.push_back(std_cxx14::make_unique<Patterns::Integer>());
+  ps.push_back(std_cxx14::make_unique<Patterns::Double>());
+  ps.push_back(std_cxx14::make_unique<Patterns::Anything>());
+
+  Patterns::Tuple pattern(ps, ";");
+  const std::string desc = pattern.description();
+
+  deallog << desc << std::endl;
+
+  std::string test = "5; 3.14; Ciao";
+
+  if (pattern.match(test))
+    deallog << "OK" << std::endl;
+  else
+    deallog << "Not OK" << std::endl;
+}
diff --git a/tests/base/patterns_09.output b/tests/base/patterns_09.output
new file mode 100644 (file)
index 0000000..d24657a
--- /dev/null
@@ -0,0 +1,3 @@
+
+DEAL::[Tuple of <3> elements <[Integer range -2147483648...2147483647 (inclusive)]>, <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]>, <[Anything]> separated by <;>]
+DEAL::OK

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.