]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Implement the ability to read XML files of parameters.
authorbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 20 Dec 2010 13:57:15 +0000 (13:57 +0000)
committerbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 20 Dec 2010 13:57:15 +0000 (13:57 +0000)
git-svn-id: https://svn.dealii.org/trunk@23019 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/include/deal.II/base/parameter_handler.h
deal.II/source/base/parameter_handler.cc
tests/bits/parameter_handler_read_xml.cc [new file with mode: 0644]
tests/bits/parameter_handler_read_xml/cmp/generic [new file with mode: 0644]
tests/bits/parameter_handler_read_xml/prm [new file with mode: 0644]

index 72b14ce920aa9085c04bf380a070f421b0752203..c2c90671a0dff8537c2640dc54558e368384ad95 100644 (file)
@@ -1746,6 +1746,23 @@ class ParameterHandler : public Subscriptor
                                      */
     virtual bool read_input_from_string (const char *s);
 
+                                    /**
+                                     * Read a parameter file in XML
+                                     * format. This could be from a file
+                                     * originally written by the
+                                     * print_parameters() function using the
+                                     * XML output style and then modified by
+                                     * hand as necessary; or from a file
+                                     * written using this method and then
+                                     * modified by the graphical parameter
+                                     * GUI (see the general documentation of
+                                     * this class).
+                                     *
+                                     * Return whether the read was
+                                     * successful.
+                                     */
+    virtual bool read_input_from_xml (std::istream &input);
+    
                                     /**
                                      * Clear all contents.
                                      */
index 04d12d406250bb9d7d18a7edf89bea0198fc4938..18a4b621c120dbc8a89341930953f94586705140 100644 (file)
@@ -1141,13 +1141,152 @@ bool ParameterHandler::read_input_from_string (const char *s)
 
       if (!scan_line (line, lineno))
        status = false;
-    };
+    }
 
   return status;
 }
 
 
 
+namespace
+{
+                                  // Recursively go through the 'source' tree
+                                  // and see if we can find corresponding
+                                  // entries in the 'destination' tree. If
+                                  // not, error out (i.e. we have just read
+                                  // an XML file that has entries that
+                                  // weren't declared in the ParameterHandler
+                                  // object); if so, copy the value of these
+                                  // nodes into the destination object
+  bool
+  read_xml_recursively (const boost::property_tree::ptree &source,
+                       const std::string                 &current_path,
+                       const char                         path_separator,
+                       boost::property_tree::ptree       &destination)
+  {
+    for (boost::property_tree::ptree::const_iterator p = source.begin();
+        p != source.end(); ++p)
+      {
+                                        // a sub-tree must either be a
+                                        // parameter node or a subsection
+       if (p->second.get_optional<std::string>("value"))
+         {
+                                            // make sure we have a
+                                            // corresponding entry in the
+                                            // destination object as well
+           const std::string full_path
+             = (current_path == ""
+                ?
+                p->first
+                :
+                current_path + path_separator + p->first);
+           if (destination.get_optional<std::string> (full_path)
+               &&
+               destination.get_optional<std::string> (full_path +
+                                                      path_separator +
+                                                      "value"))
+             {
+                                                // set the found parameter in
+                                                // the destination argument
+               destination.put (full_path + path_separator + "value",
+                                p->second.get_optional<std::string>("value"));
+               
+                                                // this node might have
+                                                // sub-nodes in addition to
+                                                // "value", such as
+                                                // "default_value",
+                                                // "documentation", etc. we
+                                                // might at some point in the
+                                                // future want to make sure
+                                                // that if they exist that
+                                                // they match the ones in the
+                                                // 'destination' tree
+             }
+           else
+             {
+               std::cerr << "The entry <" << full_path
+                         << "> with value <"
+                         << p->second.get<std::string>("value")
+                         << "> has not been declared.";
+               return false;
+             }
+         }
+       else
+         {
+                                            // it must be a subsection
+           const bool result
+             = read_xml_recursively (p->second,
+                                     (current_path == "" ?
+                                      p->first :
+                                      current_path + path_separator + p->first),
+                                     path_separator,
+                                     destination);
+
+                                            // see if the recursive read
+                                            // succeeded. if yes, continue,
+                                            // otherwise exit now
+           if (result == false)
+             return false;
+         }
+      }
+
+    return true;
+  }
+}
+
+
+
+bool ParameterHandler::read_input_from_xml (std::istream &in)
+{
+                                  // read the XML tree assuming that (as we
+                                  // do in print_parameters(XML) it has only
+                                  // a single top-level node called
+                                  // "ParameterHandler"
+  boost::property_tree::ptree single_node_tree;
+  try
+    {
+      read_xml (in, single_node_tree);
+    }
+  catch (...)
+    {
+      std::cerr << "This input stream appears not to be valid XML"
+               << std::endl;
+      return false;
+    }
+
+                                  // make sure there is a top-level element
+                                  // called "ParameterHandler"
+  if (!single_node_tree.get_optional<std::string>("ParameterHandler"))
+    {
+      std::cerr << "There is no top-level XML element called \"ParameterHandler\"."
+               << std::endl;
+      return false;
+    }
+
+                                  // ensure that there is only a single
+                                  // top-level element
+  if (std::distance (single_node_tree.begin(), single_node_tree.end()) != 1)
+    {
+      std::cerr << "The top-level XML element \"ParameterHandler\" is "
+               << "not the only one."
+               << std::endl;
+      std::cerr << "(There are "
+               << std::distance (single_node_tree.begin(),
+                                 single_node_tree.end())
+               << " top-level elements.)"
+               << std::endl;
+      return false;
+    }
+
+                                  // read the child elements recursively
+  const boost::property_tree::ptree
+    &my_entries = single_node_tree.get_child("ParameterHandler");
+
+  return read_xml_recursively (my_entries, "", path_separator, *entries);
+}
+
+
+
 void ParameterHandler::clear ()
 {
   entries.reset (new boost::property_tree::ptree());
diff --git a/tests/bits/parameter_handler_read_xml.cc b/tests/bits/parameter_handler_read_xml.cc
new file mode 100644 (file)
index 0000000..e32bfac
--- /dev/null
@@ -0,0 +1,85 @@
+//----------------------------  parameter_handler_read_xml.cc  ---------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 2002, 2003, 2004, 2005, 2010 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//----------------------------  parameter_handler_read_xml.cc  ---------------------------
+
+
+// check ParameterHandler::print_parameters (..., XML). have a few
+// names that contain all sorts of weird (for XML) characters
+
+#include "../tests.h"
+#include <base/logstream.h>
+#include <base/parameter_handler.h>
+#include <fstream>
+
+
+int main ()
+{
+  std::ofstream logfile("parameter_handler_read_xml/output");
+  deallog.attach(logfile);
+  deallog.depth_console(0);
+  deallog.threshold_double(1.e-10);
+
+  ParameterHandler prm;
+  prm.declare_entry ("int1",
+                    "1",
+                    Patterns::Integer(),
+                    "doc 1");
+  prm.declare_entry ("int2",
+                    "2",
+                    Patterns::Integer(),
+                    "doc 2");
+  prm.enter_subsection ("ss1");
+  {
+    prm.declare_entry ("double 1",
+                      "1.234",
+                      Patterns::Double(),
+                      "doc 3");
+
+    prm.enter_subsection ("ss2");
+    {
+      prm.declare_entry ("double 2",
+                        "4.321",
+                        Patterns::Double(),
+                        "doc 4");
+    }
+    prm.leave_subsection ();
+  }
+  prm.leave_subsection ();
+
+                                  // things with strange characters
+  prm.enter_subsection ("Testing%testing");
+  {
+    prm.declare_entry ("string&list",
+                      "< & > ; /",
+                      Patterns::Anything(),
+                      "docs 1");
+    prm.declare_entry ("int*int",
+                      "2",
+                      Patterns::Integer());
+    prm.declare_entry ("double+double",
+                      "6.1415926",
+                      Patterns::Double(),
+                      "docs 3");
+  }
+  prm.leave_subsection ();
+
+                                  // read from XML
+  std::ifstream in ("parameter_handler_read_xml/prm");
+  bool result = prm.read_input_from_xml (in);
+  Assert (result == true, ExcInternalError());
+
+                                  // write it out again
+  prm.print_parameters (deallog.get_file_stream(), ParameterHandler::XML);
+  logfile << std::endl;
+
+  return 0;
+}
diff --git a/tests/bits/parameter_handler_read_xml/cmp/generic b/tests/bits/parameter_handler_read_xml/cmp/generic
new file mode 100644 (file)
index 0000000..c9f5c7e
--- /dev/null
@@ -0,0 +1,3 @@
+
+<?xml version="1.0" encoding="utf-8"?>
+<ParameterHandler><int1><value> 2</value><default_value>1</default_value><documentation>doc 1</documentation><pattern>0</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int1><int2><value> 3</value><default_value>2</default_value><documentation>doc 2</documentation><pattern>1</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int2><ss1><double_201><value> 2.234</value><default_value>1.234</default_value><documentation>doc 3</documentation><pattern>2</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_201><ss2><double_202><value> 5.321</value><default_value>4.321</default_value><documentation>doc 4</documentation><pattern>3</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_202></ss2></ss1><Testing_25testing><string_26list><value> __&lt; &amp; &gt; ; /</value><default_value>&lt; &amp; &gt; ; /</default_value><documentation>docs 1</documentation><pattern>4</pattern><pattern_description>[Anything]</pattern_description></string_26list><int_2aint><value> __2</value><default_value>2</default_value><documentation/><pattern>5</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int_2aint><double_2bdouble><value> 7.1415926</value><default_value>6.1415926</default_value><documentation>docs 3</documentation><pattern>6</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_2bdouble></Testing_25testing></ParameterHandler>
diff --git a/tests/bits/parameter_handler_read_xml/prm b/tests/bits/parameter_handler_read_xml/prm
new file mode 100644 (file)
index 0000000..cad7566
--- /dev/null
@@ -0,0 +1,4 @@
+
+<?xml version="1.0" encoding="utf-8"?>
+<ParameterHandler><int1><value>2</value><default_value>1</default_value><documentation>doc 1</documentation><pattern>0</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int1><int2><value>3</value><default_value>2</default_value><documentation>doc 2</documentation><pattern>1</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int2><ss1><double_201><value>2.234</value><default_value>1.234</default_value><documentation>doc 3</documentation><pattern>2</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_201><ss2><double_202><value>5.321</value><default_value>4.321</default_value><documentation>doc 4</documentation><pattern>3</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_202></ss2></ss1><Testing_25testing><string_26list><value>__&lt; &amp; &gt; ; /</value><default_value>&lt; &amp; &gt; ; /</default_value><documentation>docs 1</documentation><pattern>4</pattern><pattern_description>[Anything]</pattern_description></string_26list><int_2aint><value>__2</value><default_value>2</default_value><documentation/>
+<pattern>5</pattern><pattern_description>[Integer range -2147483648...2147483647 (inclusive)]</pattern_description></int_2aint><double_2bdouble><value>7.1415926</value><default_value>6.1415926</default_value><documentation>docs 3</documentation><pattern>6</pattern><pattern_description>[Double -1.79769e+308...1.79769e+308 (inclusive)]</pattern_description></double_2bdouble></Testing_25testing></ParameterHandler>

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.