Skip to content
Snippets Groups Projects
Commit ac00a77f authored by Oliver Sander's avatar Oliver Sander
Browse files

Inherit from the new class ParameterTree instead of implementing

a parameter hierarchy container directly.  That way, the data
structure is separated from the various ways to fill it.

Having a parser class inherit from a container is certainly not
a good design.  However, it is the simplest way to get rid of
the container implementation and still be 100% backward-compatible.
I will deprecated a few container-related methods in the near
future.

[[Imported from SVN: r6036]]
parent 087608e3
No related branches found
No related tags found
No related merge requests found
......@@ -128,69 +128,6 @@ void ConfigParser::parseCmd(int argc, char* argv [])
return;
}
void ConfigParser::report() const
{
report("");
}
void ConfigParser::report(const string prefix) const
{
reportStream(std::cout, prefix);
}
void ConfigParser::reportStream(ostream& stream, const string& prefix) const
{
typedef map<string, string>::const_iterator ValueIt;
ValueIt vit = values.begin();
ValueIt vend = values.end();
for(; vit!=vend; ++vit)
stream << vit->first << " = \"" << vit->second << "\"" << endl;
typedef map<string, ConfigParser>::const_iterator SubIt;
SubIt sit = subs.begin();
SubIt send = subs.end();
for(; sit!=send; ++sit)
{
stream << "[ " << prefix + sit->first << " ]" << endl;
(sit->second).report(prefix + sit->first + ".");
}
}
bool ConfigParser::hasKey(const string& key) const
{
string::size_type dot = key.find(".");
if (dot != string::npos)
{
string prefix = key.substr(0,dot);
if (subs.count(prefix) == 0)
return false;
const ConfigParser& s = sub(prefix);
return s.hasKey(key.substr(dot+1));
}
else
return (values.count(key) != 0);
}
bool ConfigParser::hasSub(const string& key) const
{
string::size_type dot = key.find(".");
if (dot != string::npos)
{
string prefix = key.substr(0,dot);
if (subs.count(prefix) == 0)
return false;
const ConfigParser& s = sub(prefix);
return s.hasSub(key.substr(dot+1));
}
else
return (subs.count(key) != 0);
}
ConfigParser& ConfigParser::sub(const string& key)
{
string::size_type dot = key.find(".");
......@@ -201,7 +138,9 @@ ConfigParser& ConfigParser::sub(const string& key)
return s.sub(key.substr(dot+1));
}
else
return subs[key];
// Cast is safe, because ConfigParser has the same memory layout as ParameterTree,
// and this method is temporary anyways.
return static_cast<ConfigParser&>(subs[key]);
}
const ConfigParser& ConfigParser::sub(const string& key) const
......@@ -214,141 +153,7 @@ const ConfigParser& ConfigParser::sub(const string& key) const
return s.sub(key.substr(dot+1));
}
else
return subs.find(key)->second;
}
string& ConfigParser::operator[] (const string& key)
{
string::size_type dot = key.find(".");
if (dot != string::npos)
{
if (not (hasSub(key.substr(0,dot))))
subKeys.push_back(key.substr(0,dot));
ConfigParser& s = sub(key.substr(0,dot));
return s[key.substr(dot+1)];
}
else
{
if (not (hasKey(key)))
valueKeys.push_back(key);
return values[key];
}
}
string ConfigParser::get(const string& key, const string& defaultValue)
{
if (hasKey(key))
return (*this)[key];
else
return defaultValue;
}
string ConfigParser::get(const string& key, const char* defaultValue)
{
if (hasKey(key))
return (*this)[key];
else
return defaultValue;
}
int ConfigParser::get(const string& key, int defaultValue)
{
stringstream stream;
stream << defaultValue;
string ret = get(key, stream.str());
return atoi(ret.c_str());
}
double ConfigParser::get(const string& key, double defaultValue)
{
if(hasKey(key))
return atof((*this)[key].c_str());
else
return defaultValue;
}
bool ConfigParser::get(const string& key, bool defaultValue)
{
stringstream stream;
if (defaultValue)
stream << 1;
else
stream << 0;
string ret = get(key, stream.str());
return (atoi(ret.c_str()) !=0 );
}
// This namespace here is needed to make the code compile...
namespace Dune {
template<>
string ConfigParser::get<string>(const string& key)
{
if (hasKey(key))
return (*this)[key];
DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter file!");
}
template<>
int ConfigParser::get<int>(const string& key)
{
if (hasKey(key))
return std::atoi((*this)[key].c_str());
DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter file!");
}
template<>
double ConfigParser::get<double>(const string& key)
{
if (hasKey(key))
return std::atof((*this)[key].c_str());
DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter file!");
}
template<>
bool ConfigParser::get<bool>(const string& key)
{
if (hasKey(key))
return (std::atoi((*this)[key].c_str()) !=0 );
DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter file!");
}
} // end namespace Dune
string ConfigParser::ltrim(const string& s)
{
std::size_t firstNonWS = s.find_first_not_of(" \t\n\r");
if (firstNonWS!=string::npos)
return s.substr(firstNonWS);
return string();
}
string ConfigParser::rtrim(const string& s)
{
std::size_t lastNonWS = s.find_last_not_of(" \t\n\r");
if (lastNonWS!=string::npos)
return s.substr(0, lastNonWS+1);
return string();
}
const ConfigParser::KeyVector& ConfigParser::getValueKeys() const
{
return valueKeys;
}
const ConfigParser::KeyVector& ConfigParser::getSubKeys() const
{
return subKeys;
// Cast is safe, because ConfigParser has the same memory layout as ParameterTree,
// and this method is temporary anyways.
return static_cast<const ConfigParser&>(subs.find(key)->second);
}
......@@ -12,6 +12,8 @@
#include <vector>
#include <dune/common/fvector.hh>
#include <dune/common/deprecated.hh>
#include <dune/common/parametertree.hh>
namespace Dune {
......@@ -62,16 +64,10 @@ namespace Dune {
*
*/
class ConfigParser
: public ParameterTree
{
// class providing a single static parse() function, used by the
// generic get() method
template<typename T>
struct Parser;
public:
typedef std::vector<std::string> KeyVector;
/** \brief Create new ConfigParser
*/
ConfigParser();
......@@ -132,279 +128,23 @@ namespace Dune {
void parseCmd(int argc, char* argv []);
/** \brief test for key
*
* Tests wether given key exists.
*
* \param key key name
* \return true if key exists in structure, otherwise false
*/
bool hasKey(const std::string& key) const;
/** \brief test for substructure
*
* Tests wether given substructure exists.
*
* \param sub substructure name
* \return true if substructure exists in structure, otherwise false
*/
bool hasSub(const std::string& sub) const;
/** \brief get value reference for key
*
* Returns refference to value for given key name.
* This creates the key, if not existent.
*
* \param key key name
* \return reference to coresponding value
*/
std::string& operator[] (const std::string& key);
/** \brief print structure to std::cout
*/
void report() const;
/** \brief print distinct substructure to std::cout
*
* Prints all entries with given prefix.
*
* \param prefix for key and substructure names
*/
void report(const std::string prefix) const;
/** \brief print distinct substructure to stream
*
* Prints all entries with given prefix.
*
* \param stream Stream to print to
* \param prefix for key and substructure names
*/
void reportStream(std::ostream& stream,
const std::string& prefix = "") const;
/** \brief get substructure by name
*
* \param sub substructure name
* \return reference to substructure
* \deprecated Use the corresponding method in ParameterTree, which returns a ParameterTree
*/
ConfigParser& sub(const std::string& sub);
ConfigParser& sub(const std::string& sub) DUNE_DEPRECATED;
/** \brief get const substructure by name
*
* \param sub substructure name
* \return reference to substructure
* \deprecated Use the corresponding method in ParameterTree, which returns a ParameterTree
*/
const ConfigParser& sub(const std::string& sub) const;
/** \brief get value as string
*
* Returns pure string value for given key.
*
* \param key key name
* \param defaultValue default if key does not exist
* \return value as string
*/
std::string get(const std::string& key, const std::string& defaultValue);
/** \brief get value as string
*
* Returns pure string value for given key.
*
* \todo This is a hack so get("my_key", "xyz") compiles
* (without this method "xyz" resolves to bool instead of std::string)
* \param key key name
* \param defaultValue default if key does not exist
* \return value as string
*/
std::string get(const std::string& key, const char* defaultValue);
/** \brief get value as int
*
* Returns value for given key interpreted as int.
*
* \param key key name
* \param defaultValue default if key does not exist
* \return value as int
*/
int get(const std::string& key, int defaultValue);
/** \brief get value as double
*
* Returns value for given key interpreted as double.
*
* \param key key name
* \param defaultValue default if key does not exist
* \return value as double
*/
double get(const std::string& key, double defaultValue);
/** \brief get value as bool
*
* Returns value for given key interpreted as bool.
*
* \param key key name
* \param defaultValue default if key does not exist
* \return value as bool, false if values = '0', true if value = '1'
*/
bool get(const std::string& key, bool defaultValue);
/** \brief get value converted to a certain type
*
* Returns value as type T for given key.
*
* \tparam T type of returned value.
* \param key key name
* \param defaultValue default if key does not exist
* \return value converted to T
*/
template<typename T>
T get(const std::string& key, const T& defaultValue) {
if(hasKey(key))
return get<T>(key);
else
return defaultValue;
}
/** \brief Get value
*
* \tparam T Type of the value
* \param key Key name
* \throws RangeError if key does not exist
* \throws NotImplemented Type is not supported
* \return value as T
*/
template <class T>
T get(const std::string& key) {
if(not hasKey(key))
DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
"file!");
try {
return Parser<T>::parse((*this)[key]);
}
catch(const RangeError&) {
DUNE_THROW(RangeError, "Cannot parse value \"" <<
(*this)[key] << "\" for key \"" << key << "\" as a " <<
typeid(T).name());
}
}
/** \brief get value keys
*
* Returns a vector of all keys associated to (key,values) entries in
* order of appearance
*
* \return reference to entry vector
*/
const KeyVector& getValueKeys() const;
/** \brief get substructure keys
*
* Returns a vector of all keys associated to (key,substructure) entries
* in order of appearance
*
* \return reference to entry vector
*/
const KeyVector& getSubKeys() const;
private:
KeyVector valueKeys;
KeyVector subKeys;
std::map<std::string, std::string> values;
std::map<std::string, ConfigParser> subs;
static std::string ltrim(const std::string& s);
static std::string rtrim(const std::string& s);
};
template<typename T>
struct ConfigParser::Parser {
static T parse(const std::string& str) {
T val;
std::istringstream s(str);
s >> val;
if(!s)
DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
typeid(T).name());
T dummy;
s >> dummy;
// now extraction should have failed, and eof should be set
if(not s.fail() or not s.eof())
DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
typeid(T).name());
return val;
}
};
// "How do I convert a string into a wstring in C++?" "Why, that very simple
// son. You just need a these hundred lines of code."
// Instead im gonna restrict myself to string with charT=char here
template<typename traits, typename Allocator>
struct ConfigParser::Parser<std::basic_string<char, traits, Allocator> > {
static std::basic_string<char, traits, Allocator>
parse(const std::string& str) {
std::string trimmed = ltrim(rtrim(str));
return std::basic_string<char, traits, Allocator>(trimmed.begin(),
trimmed.end());
}
};
template<typename T, int n>
struct ConfigParser::Parser<FieldVector<T, n> > {
static FieldVector<T, n>
parse(const std::string& str) {
FieldVector<T, n> val;
std::istringstream s(str);
for(int i = 0; i < n; ++i) {
s >> val[i];
if(!s)
DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
"FieldVector<" << typeid(T).name() << ", " << n << ">");
}
T dummy;
s >> dummy;
// now extraction should have failed, and eof should be set
if(not s.fail() or not s.eof())
DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
"FieldVector<double, " << n << ">");
return val;
}
};
const ConfigParser& sub(const std::string& sub) const DUNE_DEPRECATED;
template<typename T, typename A>
struct ConfigParser::Parser<std::vector<T, A> > {
static std::vector<T, A>
parse(const std::string& str) {
std::vector<T, A> vec;
std::istringstream s(str);
while(true) {
T val;
s >> val;
if(s.fail()) {
if(s.eof())
// extraction failed because of EOF, that OK
break;
// otherwise, it failed because of something else
DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
"std::vector<" << typeid(T).name() << ", " <<
typeid(A).name() << ">");
}
vec.push_back(val);
}
return vec;
}
};
} // end namespace Dune
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment