* @endcode
* get() returns the value of the given entry. If the entry was not specified
* in the input source(s), the default value is returned. You have to enter
- * and leave subsections exactly as you did when declaring subsection. You may
- * chose the order in which to transverse the subsection tree.
+ * and leave subsections exactly as you did when declaring subsections. You may
+ * choose the order in which to traverse the subsection tree.
+ *
+ * It is possible to avoid calls to enter_subsection() and leave_subsection()
+ * by supplying get() with a vector of strings representing the path from
+ * which to get a value. For example, the following two versions of
+ * get_parameters() will produce the same result:
+ * @code
+ * void NonLinEq::get_parameters (ParameterHandler &prm)
+ * {
+ * prm.enter_subsection ("Equation 1 Settings");
+ * prm.enter_subsection ("Linear solver");
+ * solver_ = prm.get ("Solver");
+ * prm.leave_subsection ();
+ * prm.leave_subsection ();
+ * }
+ * @endcode
+ *
+ * @code
+ * void NonLinEq::get_parameters (const ParameterHandler &prm)
+ * {
+ * std::vector<std::string> path =
+ * {"Equation 1 Settings", "Linear solver"};
+ * solver_ = prm.get (path, "Solver");
+ * }
+ * @endcode
+ *
+ * The latter method allows the ParameterHandler reference to be @p const.
*
* It is guaranteed that only entries matching the given regular expression
* are returned, i.e. an input entry value which does not match the regular
leave_subsection();
/**
- * Return value of entry <tt>entry_string</tt>. If the entry was changed,
+ * Return value of entry @p entry_string. If the entry was changed,
* then the changed value is returned, otherwise the default value. If the
- * value of an undeclared entry is required, an exception will be thrown.
+ * value of an undeclared entry is required, an @p Assert will fail.
*/
std::string
get(const std::string &entry_string) const;
/**
- * Return value of entry <tt>entry_string</tt> as <tt>long int</tt>. (A long
+ * Return value of entry @p entry_string. If the entry was changed,
+ * then the changed value is returned, otherwise the default value. If the
+ * value of an undeclared entry is required, an @p Assert will fail.
+ * If @p entry_subsection_path is non-empty, the value will be gotten
+ * from the subsection represented by that path instead of the current
+ * subsection. The first string in @p entry_subsection_path must be the name
+ * of a subsection of the current section, and each next string must be the
+ * name of a subsection of the one before it.
+ */
+ std::string
+ get(const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const;
+
+ /**
+ * Return value of entry @p entry_string as <code>long int</code>. (A long
* int is chosen so that even very large unsigned values can be returned by
* this function).
*/
get_integer(const std::string &entry_string) const;
/**
- * Return value of entry <tt>entry_name</tt> as <tt>double</tt>.
+ * Return value of entry @p entry_string as <code>long int</code>. (A long
+ * int is chosen so that even very large unsigned values can be returned by
+ * this function).
+ * If @p entry_subsection_path is non-empty, the value will be gotten
+ * from the subsection represented by that path instead of the current
+ * subsection.
+ */
+ long int
+ get_integer(const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const;
+
+ /**
+ * Return value of entry @p entry_name as @p double.
*/
double
get_double(const std::string &entry_name) const;
/**
- * Return value of entry <tt>entry_name</tt> as <tt>bool</tt>. The entry may
- * be "true" or "yes" for <tt>true</tt>, "false" or "no" for <tt>false</tt>
+ * Return value of entry @p entry_name as @p double.
+ * If @p entry_subsection_path is non-empty, the value will be gotten
+ * from the subsection represented by that path instead of the current
+ * subsection.
+ */
+ double
+ get_double(const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const;
+ /**
+ * Return value of entry @p entry_name as @p bool. The entry may
+ * be "true" or "yes" for @p true, "false" or "no" for @p false
* respectively.
*/
bool
get_bool(const std::string &entry_name) const;
+ /**
+ * Return value of entry @p entry_name as @p bool. The entry may
+ * be "true" or "yes" for @p true, "false" or "no" for @p false
+ * respectively.
+ * If @p entry_subsection_path is non-empty, the value will be gotten
+ * from the subsection represented by that path instead of the current
+ * subsection.
+ */
+ bool
+ get_bool(const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const;
+
/**
* Change the value presently stored for <tt>entry_name</tt> to the one
* given in the second argument.
std::string
get_current_full_path(const std::string &name) const;
+ /**
+ * This function computes a full path into the parameter tree given a path
+ * from the current subsection and the name of an entry.
+ */
+ std::string
+ get_current_full_path(const std::vector<std::string> &sub_path,
+ const std::string & name) const;
+
/**
* Scan one line of input. <tt>input_filename</tt> and
* <tt>current_line_n</tt> are the name of the input file and the number of
+std::string
+ParameterHandler::get_current_full_path(
+ const std::vector<std::string> &sub_path,
+ const std::string & name) const
+{
+ std::string path = get_current_path();
+ if (path.empty() == false)
+ path += path_separator;
+
+ if (sub_path.empty() == false)
+ path += collate_path_string(sub_path) + path_separator;
+
+ path += mangle(name);
+
+ return path;
+}
+
+
+
void
ParameterHandler::parse_input(std::istream & input,
const std::string &filename,
+std::string
+ParameterHandler::get(const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const
+{
+ // assert that the entry is indeed
+ // declared
+ if (boost::optional<std::string> value = entries->get_optional<std::string>(
+ get_current_full_path(entry_subsection_path, entry_string) +
+ path_separator + "value"))
+ return value.get();
+ else
+ {
+ Assert(false,
+ ExcEntryUndeclared(demangle(
+ get_current_full_path(entry_subsection_path, entry_string))));
+ return "";
+ }
+}
+
+
+
long int
ParameterHandler::get_integer(const std::string &entry_string) const
{
AssertThrow(false,
ExcMessage("Can't convert the parameter value <" +
get(entry_string) + "> for entry <" +
- entry_string + " to an integer."));
+ entry_string + "> to an integer."));
+ return 0;
+ }
+}
+
+
+
+long int
+ParameterHandler::get_integer(
+ const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const
+{
+ try
+ {
+ return Utilities::string_to_int(get(entry_subsection_path, entry_string));
+ }
+ catch (...)
+ {
+ AssertThrow(false,
+ ExcMessage(
+ "Can't convert the parameter value <" +
+ get(entry_subsection_path, entry_string) + "> for entry <" +
+ demangle(get_current_full_path(entry_subsection_path,
+ entry_string)) +
+ "> to an integer."));
return 0;
}
}
ExcMessage("Can't convert the parameter value <" +
get(entry_string) + "> for entry <" +
entry_string +
- " to a double precision variable."));
+ "> to a double precision variable."));
+ return 0;
+ }
+}
+
+
+
+double
+ParameterHandler::get_double(
+ const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const
+{
+ try
+ {
+ return Utilities::string_to_double(
+ get(entry_subsection_path, entry_string));
+ }
+ catch (...)
+ {
+ AssertThrow(false,
+ ExcMessage(
+ "Can't convert the parameter value <" +
+ get(entry_subsection_path, entry_string) + "> for entry <" +
+ demangle(get_current_full_path(entry_subsection_path,
+ entry_string)) +
+ "> to a double precision variable."));
return 0;
}
}
AssertThrow((s == "true") || (s == "false") || (s == "yes") || (s == "no"),
ExcMessage("Can't convert the parameter value <" +
get(entry_string) + "> for entry <" + entry_string +
- " to a boolean."));
+ "> to a boolean."));
+ if (s == "true" || s == "yes")
+ return true;
+ else
+ return false;
+}
+
+
+
+bool
+ParameterHandler::get_bool(
+ const std::vector<std::string> &entry_subsection_path,
+ const std::string & entry_string) const
+{
+ const std::string s = get(entry_subsection_path, entry_string);
+
+ AssertThrow((s == "true") || (s == "false") || (s == "yes") || (s == "no"),
+ ExcMessage("Can't convert the parameter value <" +
+ get(entry_subsection_path, entry_string) +
+ "> for entry <" +
+ demangle(get_current_full_path(entry_subsection_path,
+ entry_string)) +
+ "> to a boolean."));
if (s == "true" || s == "yes")
return true;
else
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 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.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// check use of path in ParameterHandler::Get
+
+#include <deal.II/base/parameter_handler.h>
+
+#include <sstream>
+
+#include "../tests.h"
+
+void
+log_entry(const ParameterHandler & prm,
+ const std::vector<std::string> path,
+ const std::string & entry)
+{
+ for (unsigned int i = 0; i < path.size(); ++i)
+ {
+ deallog << path[i] << ".";
+ }
+
+ deallog << entry << " = ";
+ deallog << prm.get(path, entry) << std::endl;
+}
+
+void
+log_exception(const StandardExceptions::ExcMessage &exc)
+{
+ std::ostringstream string_stream;
+ exc.print_info(string_stream);
+ std::string exc_info = string_stream.str();
+
+ const std::string whitespace_chars = " \t\r\n\v\f";
+ exc_info.erase(0, exc_info.find_first_not_of(whitespace_chars));
+ exc_info.erase(exc_info.find_last_not_of(whitespace_chars) + 1);
+
+ deallog << exc_info << std::endl;
+}
+
+void
+test_basic()
+{
+ ParameterHandler prm;
+ prm.declare_entry("a", "1");
+ prm.enter_subsection("x");
+ prm.declare_entry("a", "2");
+ prm.enter_subsection("y");
+ prm.declare_entry("a", "3");
+ prm.declare_entry("b", "4");
+ prm.leave_subsection();
+ prm.enter_subsection("v");
+ prm.enter_subsection("v");
+ prm.enter_subsection("v");
+ prm.declare_entry("a", "5");
+ prm.declare_entry("b", "6");
+ prm.leave_subsection();
+ prm.declare_entry("a", "7");
+ prm.leave_subsection();
+ prm.leave_subsection();
+ prm.enter_subsection("z");
+ prm.declare_entry("a", "8");
+ prm.leave_subsection();
+ prm.leave_subsection();
+ prm.declare_entry("b", "9");
+
+ /*
+ prm should now look like this
+
+ # Listing of Parameters
+ # ---------------------
+ set a = 1
+ set b = 9
+
+ subsection x
+ set a = 2
+
+
+ subsection v
+ subsection v
+ set a = 7
+
+
+ subsection v
+ set a = 5
+ set b = 6
+ end
+
+ end
+
+ end
+
+ subsection y
+ set a = 3
+ set b = 4
+ end
+
+ subsection z
+ set a = 8
+ end
+
+ end
+
+ */
+
+ // reading from top level
+ std::vector<std::string> path = {};
+ log_entry(prm, path, "a");
+ path.push_back("x");
+ log_entry(prm, path, "a");
+ path.push_back("y");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ path.push_back("v");
+ path.push_back("v");
+ path.push_back("v");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ log_entry(prm, path, "a");
+ path.pop_back();
+ path.pop_back();
+ path.push_back("z");
+ log_entry(prm, path, "a");
+ path.pop_back();
+ path.pop_back();
+ log_entry(prm, path, "b");
+
+ // reading from other subsections
+ prm.enter_subsection("x");
+ deallog << "in x" << std::endl;
+ log_entry(prm, path, "a");
+ path.push_back("y");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ path.push_back("v");
+ path.push_back("v");
+ path.push_back("v");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ log_entry(prm, path, "a");
+ path.pop_back();
+ path.pop_back();
+ path.push_back("z");
+ log_entry(prm, path, "a");
+ path.pop_back();
+
+ prm.enter_subsection("y");
+ deallog << "in y" << std::endl;
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+
+ prm.leave_subsection();
+ prm.enter_subsection("v");
+ deallog << "in v (first)" << std::endl;
+ path.push_back("v");
+ path.push_back("v");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ log_entry(prm, path, "a");
+ path.pop_back();
+
+ prm.enter_subsection("v");
+ deallog << "in v (second)" << std::endl;
+ path.push_back("v");
+ log_entry(prm, path, "a");
+ log_entry(prm, path, "b");
+ path.pop_back();
+ log_entry(prm, path, "a");
+}
+
+void
+test_getting_types()
+{
+ ParameterHandler prm;
+ prm.enter_subsection("foo");
+ prm.enter_subsection("bar");
+ prm.declare_entry("jik", "1");
+ prm.declare_entry("baz", "77.3");
+ prm.declare_entry("yox", "true");
+ prm.declare_entry("spam", "eggs");
+ prm.leave_subsection();
+ prm.leave_subsection();
+
+ deallog << "in test_getting_types top level" << std::endl;
+
+ if (prm.get_integer({"foo", "bar"}, "jik") != 1)
+ deallog << "unexpected failure to read \"1\" as an integer" << std::endl;
+
+ if (prm.get_double({"foo", "bar"}, "jik") != 1)
+ deallog << "unexpected failure to read \"1\" as a double" << std::endl;
+
+ if (prm.get_double({"foo", "bar"}, "baz") != 77.3)
+ deallog << "unexpected failure to read \"77.3\" as a double" << std::endl;
+
+ if (prm.get_bool({"foo", "bar"}, "yox") != true)
+ deallog << "unexpected failure to read \"true\" as a boolean" << std::endl;
+
+ try
+ {
+ prm.get_integer({"foo", "bar"}, "baz");
+ }
+ catch (StandardExceptions::ExcMessage &e)
+ {
+ log_exception(e);
+ }
+
+ try
+ {
+ prm.get_integer({"foo", "bar"}, "yox");
+ }
+ catch (StandardExceptions::ExcMessage &e)
+ {
+ log_exception(e);
+ }
+
+ try
+ {
+ prm.get_double({"foo", "bar"}, "yox");
+ }
+ catch (StandardExceptions::ExcMessage &e)
+ {
+ log_exception(e);
+ }
+
+ try
+ {
+ prm.get_bool({"foo", "bar"}, "jik");
+ }
+ catch (StandardExceptions::ExcMessage &e)
+ {
+ log_exception(e);
+ }
+
+ try
+ {
+ prm.get_bool({"foo", "bar"}, "spam");
+ }
+ catch (StandardExceptions::ExcMessage &e)
+ {
+ log_exception(e);
+ }
+}
+
+void
+test_weird_strings()
+{
+ const std::vector<std::string> weird_strings = {
+ ".,/<[\"';:=-_)*&~\t`/.\\",
+ "$.7.%... = . -",
+ "`/=/a/!",
+ "<<>>>]]]\t\n\n ",
+ "****&//&%.^$!.$@$%@^*&(*)_/*-`~",
+ ".,/<[\"';:=-_)*&~\t`/.\\",
+ "value",
+ " set value = 5 \n\n."};
+
+ ParameterHandler prm;
+
+ for (int i = 0; i < 6; ++i)
+ {
+ prm.enter_subsection(weird_strings[i]);
+ }
+
+ prm.declare_entry(weird_strings[6], weird_strings[7]);
+
+ for (int i = 0; i < 6; ++i)
+ {
+ prm.leave_subsection();
+ }
+
+ std::vector<std::string> path = {};
+ for (int i = 0; i < 3; ++i)
+ {
+ prm.enter_subsection(weird_strings[i]);
+ path.push_back(weird_strings[3 + i]);
+ }
+
+ deallog << "in <weird_strings[3]>" << std::endl;
+ log_entry(prm, path, weird_strings[6]);
+}
+
+int
+main()
+{
+ initlog();
+
+ try
+ {
+ test_basic();
+ test_getting_types();
+ test_weird_strings();
+ }
+ catch (std::exception &exc)
+ {
+ deallog << std::endl
+ << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ deallog << "Exception on processing: " << std::endl
+ << exc.what() << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+
+ return 1;
+ }
+ catch (...)
+ {
+ deallog << std::endl
+ << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ deallog << "Unknown exception!" << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ return 1;
+ };
+
+ return 0;
+}