]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Use exceptions in ParameterHandler::read_input.
authorDavid Wells <wellsd2@rpi.edu>
Thu, 15 Sep 2016 23:12:03 +0000 (19:12 -0400)
committerDavid Wells <wellsd2@rpi.edu>
Wed, 28 Sep 2016 13:48:07 +0000 (09:48 -0400)
include/deal.II/base/parameter_handler.h
include/deal.II/base/parsed_function.h
source/base/parameter_handler.cc
tests/parameter_handler/parameter_handler_19.cc
tests/parameter_handler/parameter_handler_19.debug.output
tests/parameter_handler/parameter_handler_22_last_line.cc
tests/parameter_handler/parameter_handler_dos_endings.cc

index 659ed2c77f259886ea67f007c0dece10b0f1d299..3134e84db7075c06c739051f9f6a8b42c42e9042 100644 (file)
@@ -1061,7 +1061,7 @@ namespace Patterns
  *   @endcode
  * The file so referenced is searched for relative to the current directory
  * (not relative to the directory in which the including parameter file is
- * located, since this is not known to all three versions of the read_input()
+ * located, since this is not known to all three versions of the parse_input()
  * function).
  *
  *
@@ -1076,12 +1076,12 @@ namespace Patterns
  *     ...
  *     // declaration of entries
  *     ...
- *     prm.read_input (cin);         // read input from standard in,
+ *     prm.parse_input (std::cin); // read input from standard in,
  *     // or
- *     prm.read_input ("simulation.in");
+ *     prm.parse_input ("simulation.prm");
  *     // or
  *     char *in = "set Time step size = 0.3 \n ...";
- *     prm.read_input_from_string (in);
+ *     prm.parse_input_from_string (in);
  *     ...
  *   @endcode
  * You can use several sources of input successively. Entries which are
@@ -1089,7 +1089,7 @@ namespace Patterns
  *
  * You should not try to declare entries using declare_entry() and
  * enter_subsection() with as yet unknown subsection names after using
- * read_input(). The results in this case are unspecified.
+ * parse_input(). The results in this case are unspecified.
  *
  * If an error occurs upon reading the input, error messages are written to
  * <tt>std::cerr</tt> and the reader function returns with a return value of
@@ -1328,7 +1328,7 @@ namespace Patterns
  *     p.declare_parameters (prm);
  *     // read input from "prmtest.prm"; giving argv[1] would also be a
  *     // good idea
- *     prm.read_input ("prmtest.prm");
+ *     prm.parse_input ("prmtest.prm");
  *     // print parameters to std::cout as ASCII text
  *     std::cout << "\n\n";
  *     prm.print_parameters (std::cout, ParameterHandler::Text);
@@ -1628,11 +1628,28 @@ public:
    * will stop parsing lines after encountering @p last_line .
    * This is handy when adding extra data that shall be parsed manually.
    *
-   * Return whether the read was successful.
+   * @deprecated This function has been deprecated in favor of the replacement
+   * ParameterHandler::parse_input, which raises exceptions to indicate errors
+   * instead of returning an error code.
    */
   virtual bool read_input (std::istream &input,
                            const std::string &filename = "input file",
-                           const std::string &last_line = "");
+                           const std::string &last_line = "") DEAL_II_DEPRECATED;
+
+  /**
+   * Parse each line from a stream until the stream returns the <tt>eof</tt>
+   * condition or error to provide values for known parameter fields. The second
+   * argument can be used to denote the name of the file (if that's what the
+   * input stream represents) we are reading from; this is only used when
+   * creating output for exceptions.
+   *
+   * If non-empty @p last_line is provided, the ParameterHandler object
+   * will stop parsing lines after encountering @p last_line .
+   * This is handy when adding extra data that shall be parsed manually.
+   */
+  virtual void parse_input (std::istream &input,
+                            const std::string &filename = "input file",
+                            const std::string &last_line = "");
 
   /**
    * Read input from a file the name of which is given. The PathSearch class
@@ -1662,11 +1679,24 @@ public:
    * will stop parsing lines after encountering @p last_line .
    * This is handy when adding extra data that shall be parsed manually.
    *
-   * Return whether the read was successful.
+   * @deprecated This function has been deprecated in favor of the replacement
+   * ParameterHandler::parse_input_from_string, which raises exceptions to
+   * indicate errors instead of returning an error code.
    */
   virtual bool read_input_from_string (const char *s,
                                        const std::string &last_line = "");
 
+  /**
+   * Parse input from a string to populate known parameter fields. The lines
+   * in the string must be separated by <tt>@\n</tt> characters.
+   *
+   * If non-empty @p last_line is provided, the ParameterHandler object
+   * will stop parsing lines after encountering @p last_line .
+   * This is handy when adding extra data that shall be parsed manually.
+   */
+  virtual void parse_input_from_string (const char *s,
+                                        const std::string &last_line = "");
+
   /**
    * 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
@@ -2011,12 +2041,15 @@ public:
 
   /**
    * Exception for when there are an unequal number of 'subsection' and 'end'
-   * statements.
+   * statements. The first argument is the name of the file and the second
+   * argument is a formatted list of the subsection path before and after
+   * entering the parser.
    */
-  DeclException1 (ExcUnbalancedSubsections,
-                  std::string,
+  DeclException2 (ExcUnbalancedSubsections,
+                  std::string, std::string,
                   << "There are unequal numbers of 'subsection' and 'end' "
-                  "statements in the parameter file <" << arg1 << ">.");
+                  "statements in the parameter file <" << arg1 << ">."
+                  << (arg2.size() > 0 ? "\n" + arg2 : ""));
 
   /**
    * Exception for when, during parsing of a parameter file, the parser
@@ -2254,7 +2287,7 @@ private:
  *       class MultipleParameterLoop prm;
  *       HelperClass h;
  *       HelperClass::declare_parameters (prm);
- *       prm.read_input ("prmtest.prm");
+ *       prm.parse_input ("prmtest.prm");
  *       prm.loop (h);
  *       return 0;
  *     }
@@ -2424,20 +2457,51 @@ public:
    * This is handy when adding extra data that shall be parsed manually.
    *
    * @note Of the three <tt>read_input</tt> functions implemented by
-   * ParameterHandler, this is the only one overridden with new behavior by
-   * this class. This is because the other two <tt>read_input</tt> functions
-   * just reformat their inputs and then call this version.
+   * ParameterHandler, this method and its replacement
+   * (MultipleParameterLoop::parse_input) are the only ones overridden with
+   * new behavior by this class. This is because the other two
+   * <tt>read_input</tt> functions just reformat their inputs and then call
+   * this version.
+   *
+   * @deprecated This function has been deprecated in favor of the replacement
+   * MultipleParameterLoop::parse_input, which raises exceptions to indicate
+   * errors instead of returning an error code.
    */
   virtual bool read_input (std::istream &input,
                            const std::string &filename = "input file",
-                           const std::string &last_line = "");
+                           const std::string &last_line = "") DEAL_II_DEPRECATED;
+
+  /**
+   * Read input from a stream until the stream returns the <tt>eof</tt>
+   * condition or error. The second argument can be used to denote the name of
+   * the file (if that's what the input stream represents) we are reading
+   * from; this is only used when creating output for error messages.
+   *
+   * If non-empty @p last_line is provided, the ParameterHandler object
+   * will stop parsing lines after encountering @p last_line .
+   * This is handy when adding extra data that shall be parsed manually.
+   *
+   * @note Of the three <tt>parse_input</tt> functions implemented by
+   * ParameterHandler, this method and the deprecated method
+   * MultipleParameterLoop::read_input are the only ones overridden with new
+   * behavior by this class. This is because the other two <tt>parse_input</tt>
+   * functions just reformat their inputs and then call this version.
+   */
+  virtual void parse_input (std::istream &input,
+                            const std::string &filename = "input file",
+                            const std::string &last_line = "");
 
   /**
    * Overriding virtual functions which are overloaded (like
-   * ParameterHandler::read_input, which has two different sets of input
+   * ParameterHandler::parse_input, which has two different sets of input
    * argument types) causes the non-overridden functions to be hidden. Get
    * around this by explicitly using both variants of
-   * ParameterHandler::read_input and then overriding the one we care about.
+   * ParameterHandler::parse_input and then overriding the one we care about.
+   */
+  using ParameterHandler::parse_input;
+
+  /**
+   * For backwards compatibility also include the deprecated read functions.
    */
   using ParameterHandler::read_input;
 
index bd78213f2523d166f9720a42f010a3e879d030c5..b25730d6ec1052af7f94408d4dfd9f7d049f7374 100644 (file)
@@ -48,7 +48,7 @@ namespace Functions
    *   ParsedFunction<dim> my_vector_function(dim);
    *
    *   // Parse an input file.
-   *   prm.read_input(some_input_file);
+   *   prm.parse_input(some_input_file);
    *
    *   // Initialize the ParsedFunction object with the given file
    *   prm.enter_subsection("My vector function");
index fe611210ccaf09135d2d04396205526aee031bdb..2dc356d68c9a6f0582d89e5b1f670329d5861d57 100644 (file)
@@ -1607,6 +1607,16 @@ ParameterHandler::get_current_full_path (const std::string &name) const
 bool ParameterHandler::read_input (std::istream &input,
                                    const std::string &filename,
                                    const std::string &last_line)
+{
+  parse_input(input, filename, last_line);
+  return true;
+}
+
+
+
+void ParameterHandler::parse_input (std::istream &input,
+                                    const std::string &filename,
+                                    const std::string &last_line)
 {
   AssertThrow (input, ExcIO());
 
@@ -1621,7 +1631,6 @@ bool ParameterHandler::read_input (std::istream &input,
   // current line continuation started.
   unsigned int current_line_n = 0;
   unsigned int current_logical_line_n = 0;
-  bool status = true;
 
   while (std::getline (input, input_line))
     {
@@ -1676,28 +1685,34 @@ bool ParameterHandler::read_input (std::istream &input,
       scan_line (fully_concatenated_line, filename, current_line_n);
     }
 
-  if (status && (saved_path != subsection_path))
+  if (saved_path != subsection_path)
     {
-      std::cerr << "Unbalanced 'subsection'/'end' in file <" << filename
-                << ">." << std::endl;
-      if (saved_path.size()>0)
+      std::stringstream paths_message;
+      if (saved_path.size() > 0)
         {
-          std::cerr << "Path before loading input:" << std::endl;
-          for (unsigned int i=0; i<saved_path.size(); ++i)
-            std::cerr << std::setw(i*2+4) << " "
-                      << "subsection " << saved_path[i] << std::endl;
+          paths_message << "Path before loading input:\n";
+          for (unsigned int i=0; i < subsection_path.size(); ++i)
+            {
+              paths_message << std::setw(i*2 + 4)
+                            << " "
+                            << "subsection "
+                            << saved_path[i]
+                            << '\n';
+            }
+          paths_message << "Current path:\n";
+          for (unsigned int i=0; i < subsection_path.size(); ++i)
+            {
+              paths_message << std::setw(i*2 + 4)
+                            << " "
+                            << "subsection "
+                            << subsection_path[i]
+                            << (i == subsection_path.size() - 1 ? "" : "\n");
+            }
         }
-      std::cerr << "Current path:" << std::endl;
-      for (unsigned int i=0; i<subsection_path.size(); ++i)
-        std::cerr << std::setw(i*2+4) << " "
-                  << "subsection " << subsection_path[i] << std::endl;
-
-      // restore subsection we started with and return failure:
+      // restore subsection we started with before throwing the exception:
       subsection_path = saved_path;
-      return false;
+      AssertThrow (false, ExcUnbalancedSubsections (filename, paths_message.str()));
     }
-
-  return status;
 }
 
 
@@ -1715,7 +1730,7 @@ bool ParameterHandler::read_input (const std::string &filename,
       std::ifstream file_stream (openname.c_str());
       AssertThrow(file_stream, ExcIO());
 
-      return read_input (file_stream, filename, last_line);
+      parse_input (file_stream, filename, last_line);
     }
   catch (const PathSearch::ExcFileNotFound &)
     {
@@ -1735,11 +1750,22 @@ bool ParameterHandler::read_input (const std::string &filename,
 
 
 
-bool ParameterHandler::read_input_from_string (const char *s,
-                                               const std::string &last_line)
+bool
+ParameterHandler::read_input_from_string (const char *s,
+                                          const std::string &last_line)
+{
+  parse_input_from_string(s, last_line);
+  return true;
+}
+
+
+
+void
+ParameterHandler::parse_input_from_string (const char *s,
+                                           const std::string &last_line)
 {
   std::istringstream input_stream (s);
-  return read_input (input_stream, "input string", last_line);
+  parse_input (input_stream, "input string", last_line);
 }
 
 
@@ -2945,7 +2971,7 @@ ParameterHandler::scan_line (std::string         line,
       AssertThrow (input, ExcCannotOpenIncludeStatementFile (current_line_n,
                                                              input_filename,
                                                              line));
-      read_input (input);
+      parse_input (input);
     }
   else
     {
@@ -3017,16 +3043,29 @@ MultipleParameterLoop::~MultipleParameterLoop ()
 
 
 
-bool MultipleParameterLoop::read_input (std::istream &input,
-                                        const std::string &filename,
-                                        const std::string &last_line)
+bool
+MultipleParameterLoop::read_input (std::istream &input,
+                                   const std::string &filename,
+                                   const std::string &last_line)
+{
+  MultipleParameterLoop::parse_input(input, filename, last_line);
+  return true;
+}
+
+
+
+void
+MultipleParameterLoop::parse_input (std::istream &input,
+                                    const std::string &filename,
+                                    const std::string &last_line)
 {
   AssertThrow (input, ExcIO());
 
-  bool x = ParameterHandler::read_input (input, filename, last_line);
-  if (x)
-    init_branches ();
-  return x;
+  // Note that (to avoid infinite recursion) we have to explicitly call the
+  // base class version of parse_input and *not* a wrapper (which may be
+  // virtual and lead us back here)
+  ParameterHandler::parse_input (input, filename, last_line);
+  init_branches ();
 }
 
 
index cbc443aff640e0b3ba9bc13bde3d4b9af7600dcb..4bd2155000e024b1bbdaf63ae8bad2a62923d12b 100644 (file)
@@ -49,13 +49,21 @@ void check ()
 
 
 
-  deallog << std::endl << "* read_input with missing 'end':" << std::endl;
+  deallog << std::endl << "* parse_input with missing 'end':" << std::endl;
 
-  std::string s = "set dim=2\nsubsection test\n\n"; // note: missing "end"
-  bool success = prm.read_input_from_string (s.c_str());
-  deallog << "success? " << success << " (should fail)" << std::endl;
+  try
+    {
+      std::string s = "set dim=2\nsubsection test\n\n"; // note: missing "end"
+      prm.parse_input_from_string (s.c_str());
+    }
+  catch (const ParameterHandler::ExcUnbalancedSubsections &exc)
+    {
+      deallog << exc.get_exc_name() << std::endl;
+      exc.print_info(deallog.get_file_stream());
+    }
+  deallog << std::endl;
 
-  // make sure read_input resets the current path:
+  // make sure parse_input resets the current path:
   try
     {
       prm.leave_subsection();
@@ -68,29 +76,31 @@ void check ()
 
 
 
-  deallog << std::endl << "* Check non empty path before read_input()" << std::endl;
+  deallog << std::endl << "* Check non empty path before parse_input()" << std::endl;
 
   {
     prm.enter_subsection("test");
     std::string s = "set x=5\n";
-    bool success = prm.read_input_from_string (s.c_str());
-    deallog << "success? "
-            << success
-            << " (should work), x correct? "
-            << (prm.get_integer("x")==5) << std::endl;
+    prm.parse_input_from_string (s.c_str());
     prm.leave_subsection();
   }
 
 
-  deallog << std::endl << "* Check read_input() catches messing with path:" << std::endl;
+  deallog << std::endl << "* Check parse_input() catches messing with path:" << std::endl;
   {
     prm.enter_subsection("test");
-    std::string s = "end\nsubsection test2\nset y=7\n";
-    bool success = prm.read_input_from_string (s.c_str());
-    deallog << "success = " << success << " -- (should fail)" << std::endl;
+    try
+      {
+        std::string s = "end\nsubsection test2\nset y=7\n";
+        prm.parse_input_from_string (s.c_str());
+      }
+    catch (const ParameterHandler::ExcUnbalancedSubsections &exc)
+      {
+        deallog << exc.get_exc_name() << std::endl;
+        exc.print_info(deallog.get_file_stream());
+      }
     prm.leave_subsection();
   }
-
 }
 
 
index c80e0cd0f47bf608a1e17837f3f0bf2e4ecba0b7..6e93f143c70cd24deaeabc1681cb4327e04c66c5 100644 (file)
@@ -1,35 +1,41 @@
 
-DEAL::* no subsection to leave: 
-DEAL::Exception 
+DEAL::* no subsection to leave:
+DEAL::Exception
 --------------------------------------------------------
 An error occurred in file <parameter_handler.cc> in function
     void dealii::ParameterHandler::leave_subsection()
-The violated condition was: 
+The violated condition was:
     subsection_path.size() != 0
 The name and call sequence of the exception was:
     ExcAlreadyAtTopLevel()
-Additional Information: 
+Additional Information:
 (none)
 --------------------------------------------------------
 
 DEAL::
-DEAL::* read_input with missing 'end':
-DEAL::success? 0 (should fail)
-DEAL::Exception 
+DEAL::* parse_input with missing 'end':
+DEAL::ExcUnbalancedSubsections (filename, paths_message.str())
+There are unequal numbers of 'subsection' and 'end' statements in the parameter file <input string>.
+DEAL::
+DEAL::Exception
 --------------------------------------------------------
 An error occurred in file <parameter_handler.cc> in function
     void dealii::ParameterHandler::leave_subsection()
-The violated condition was: 
+The violated condition was:
     subsection_path.size() != 0
 The name and call sequence of the exception was:
     ExcAlreadyAtTopLevel()
-Additional Information: 
+Additional Information:
 (none)
 --------------------------------------------------------
 
 DEAL::
-DEAL::* Check non empty path before read_input()
-DEAL::success? 1 (should work), x correct? 1
+DEAL::* Check non empty path before parse_input()
 DEAL::
-DEAL::* Check read_input() catches messing with path:
-DEAL::success = 0 -- (should fail)
+DEAL::* Check parse_input() catches messing with path:
+DEAL::ExcUnbalancedSubsections (filename, paths_message.str())
+There are unequal numbers of 'subsection' and 'end' statements in the parameter file <input string>.
+Path before loading input:
+    subsection test
+Current path:
+    subsection test2
index 07eb5584ee2bc9811efe0f63d1ea585dd3d2308b..8360b10b9f7ddf5d4588ce79867cb70344d08bd9 100644 (file)
@@ -32,8 +32,7 @@ void check (const char *p, std::string last_line)
                      Patterns::Integer(-1,1));
 
   std::ifstream in(p);
-  bool status = prm.read_input (in, "input file", last_line);
-  Assert (status == true, ExcInternalError());
+  prm.parse_input (in, "input file", last_line);
 
   deallog << "var_1=" << prm.get ("var_1") << std::endl
           << "var_2=" << prm.get ("var_2") << std::endl;
index 4021a346832174c7fe4149e1078319ab37984507..94ac30e361f6641c9ccf34f4d521a7181a61f1c2 100644 (file)
@@ -45,8 +45,7 @@ void test ()
   file_contents << "end\r\n";
 
   std::istringstream input_stream(file_contents.str());
-  bool okay = foo.read_input(input_stream);
-  AssertThrow(okay, ExcMessage("read_input failed"));
+  foo.parse_input(input_stream);
 
   foo.enter_subsection("bar");
   deallog << foo.get ("val") << std::endl;

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.