From feed75ef949e6b315517b2b0d87abeb43e375640 Mon Sep 17 00:00:00 2001 From: David Wells Date: Thu, 15 Sep 2016 19:12:03 -0400 Subject: [PATCH] Use exceptions in ParameterHandler::read_input. --- include/deal.II/base/parameter_handler.h | 104 ++++++++++++++---- include/deal.II/base/parsed_function.h | 2 +- source/base/parameter_handler.cc | 99 ++++++++++++----- .../parameter_handler/parameter_handler_19.cc | 42 ++++--- .../parameter_handler_19.debug.output | 32 +++--- .../parameter_handler_22_last_line.cc | 3 +- .../parameter_handler_dos_endings.cc | 3 +- 7 files changed, 201 insertions(+), 84 deletions(-) diff --git a/include/deal.II/base/parameter_handler.h b/include/deal.II/base/parameter_handler.h index 659ed2c77f..3134e84db7 100644 --- a/include/deal.II/base/parameter_handler.h +++ b/include/deal.II/base/parameter_handler.h @@ -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 * std::cerr 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 eof + * 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 @\n 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 read_input functions implemented by - * ParameterHandler, this is the only one overridden with new behavior by - * this class. This is because the other two read_input 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 + * read_input 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 eof + * 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 parse_input 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 parse_input + * 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; diff --git a/include/deal.II/base/parsed_function.h b/include/deal.II/base/parsed_function.h index bd78213f25..b25730d6ec 100644 --- a/include/deal.II/base/parsed_function.h +++ b/include/deal.II/base/parsed_function.h @@ -48,7 +48,7 @@ namespace Functions * ParsedFunction 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"); diff --git a/source/base/parameter_handler.cc b/source/base/parameter_handler.cc index fe611210cc..2dc356d68c 100644 --- a/source/base/parameter_handler.cc +++ b/source/base/parameter_handler.cc @@ -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 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 . +DEAL:: +DEAL::Exception -------------------------------------------------------- An error occurred in file 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 . +Path before loading input: + subsection test +Current path: + subsection test2 diff --git a/tests/parameter_handler/parameter_handler_22_last_line.cc b/tests/parameter_handler/parameter_handler_22_last_line.cc index 07eb5584ee..8360b10b9f 100644 --- a/tests/parameter_handler/parameter_handler_22_last_line.cc +++ b/tests/parameter_handler/parameter_handler_22_last_line.cc @@ -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; diff --git a/tests/parameter_handler/parameter_handler_dos_endings.cc b/tests/parameter_handler/parameter_handler_dos_endings.cc index 4021a34683..94ac30e361 100644 --- a/tests/parameter_handler/parameter_handler_dos_endings.cc +++ b/tests/parameter_handler/parameter_handler_dos_endings.cc @@ -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; -- 2.39.5