diff --git a/mrw/configfile.cpp b/mrw/configfile.cpp
index 5548ac0..0be203f 100644
--- a/mrw/configfile.cpp
+++ b/mrw/configfile.cpp
@@ -1,7 +1,7 @@
/** @file
$Id$
-
+
$Date$
$Author$
@@ -9,6 +9,9 @@
@license LGPL, see file COPYING
$Log$
+ Revision 1.2 2005/01/28 07:49:32 marc
+ Save configuration using file.hpp
+
Revision 1.1 2005/01/07 00:31:38 marc
initial version
@@ -20,12 +23,13 @@
#include
#include
#include
+#include
#include
mrw::ConfigFileReader::Value&
-mrw::ConfigFileReader::operator()(const std::string& section,
- const std::string& name,
- const std::string& default_)
+ mrw::ConfigFileReader::operator()(const std::string& section,
+ const std::string& name,
+ const std::string& default_)
throw(std::bad_exception) {
_values[section].insert(std::make_pair(name, Value(default_)));
return _values[section].find(name)->second;
@@ -38,26 +42,9 @@ mrw::ConfigFileReader& mrw::ConfigFileReader::load(const std::string& filename)
}
mrw::ConfigFileReader& mrw::ConfigFileReader::reload() throw(std::exception) {
- return parse(readFile());
-}
-
-std::string mrw::ConfigFileReader::readFile() const throw(std::exception) {
- std::string fileContents; // declaration as first allows optimization
- std::ifstream file(_filename.c_str());
- if (!file)
- throw mrw::invalid_argument("Error file not found: '"+_filename+"'");
- file.seekg(0, std::ios::end);
- int size(file.tellg());
- fileContents.resize(size); // make buffer long enough to store all
- file.seekg(0, std::ios::beg);
- file.read(fileContents.begin().operator->(), size); // hack to get the buffer
- if (!file.good() && file.eof())
- throw mrw::invalid_argument("Error reading file: '"+_filename+"'");
- return fileContents;
+ return parse(mrw::File::read(_filename));
}
-#include
-using namespace std;
mrw::ConfigFileReader& mrw::ConfigFileReader::parse(const std::string& file)
throw(std::exception) {
_values.erase(_values.begin(), _values.end());
@@ -142,7 +129,7 @@ mrw::ConfigFileReader&
mrw::ConfigFileWriter&
#endif
mrw::ConfigFileWriter::reload() throw(std::exception) {
- return parse(_file=readFile());
+ return parse(_file=mrw::File::read(_filename));
}
mrw::ConfigFileWriter& mrw::ConfigFileWriter::save() throw(std::exception) {
@@ -193,10 +180,6 @@ mrw::ConfigFileWriter& mrw::ConfigFileWriter::save() throw(std::exception) {
_sections[sec->first] = _file.size();
}
}
- if (!changed) return *this;
- // save to file
- std::ofstream file(_filename.c_str());
- if (!(file<<_file))
- throw mrw::invalid_argument("Cannot write file '"+_filename+"'");
+ if (changed) mrw::File::save(_filename, _file);
return *this;
}
diff --git a/mrw/configfile.hpp b/mrw/configfile.hpp
index 8ba0e5e..9d75740 100644
--- a/mrw/configfile.hpp
+++ b/mrw/configfile.hpp
@@ -9,11 +9,14 @@
@license LGPL, see file COPYING
$Log$
+ Revision 1.2 2005/01/28 07:49:32 marc
+ Save configuration using file.hpp
+
Revision 1.1 2005/01/07 00:31:38 marc
initial version
-*/
+ */
#ifndef __MRW_CONFIGFILE_HPP__
#define __MRW_CONFIGFILE_HPP__
@@ -24,6 +27,8 @@ namespace mrw {
/** @defgroup config Configuration File Handler
+ @pre #include
+
Read configuration parameters from a file.
@section configSyntax Configuration File Syntax
@@ -141,12 +146,12 @@ namespace mrw {
[Global] # start of section "Global"
- multi line text = this is a text
- that is longer than one
- line!
+ multi line text = this is a text
+ that is longer than one
+ line!
1234 = "var=17" # if you need an equal inside a text, enclose it
- # either in " or in '
+ # either in " or in '
@endverbatim
@section configFileCode Code Sample
@@ -159,202 +164,302 @@ namespace mrw {
} catch (...) { // file read or evaluation error
}
@endcode
- */
+ */
//@{
- /// Parse configuration file and access the contents.
- /** Parse a configuration file that consists of sections containing
+ //============================================================================
+ /** @brief Parse configuration file and access the contents.
+
+ Parse a configuration file that consists of sections containing
variables with values. This class does not store anything in the
file, even if variables have changed.
- @see If you want %to save changes %to the file, use
- @ref ConfigFileWriter.
- @see For details, see @ref configSyntax. */
+
+ @see If you want %to save changes %to the file, use @ref ConfigFileWriter.
+ @see For details, see @ref configSyntax.
+ */
class ConfigFileReader {
- public:
- /// A configuration file value.
- class Value {
+
+ //............................................................... typedefs
public:
- /// Get the value string.
- /** Get the value string. Trailing and leading white spaces have
- been truncated. If the variable was quoted, quotes have been
- removed.
- @return the variable's value as string */
- operator const std::string&() const throw() {
- return value;
+
+ //------------------------------------------------------------------ Value
+ /// A configuration file value.
+ class Value {
+
+ //............................................................ methods
+ public:
+
+ /** @brief Get the value string.
+
+ Get the value string. Trailing and leading white spaces have
+ been truncated. If the variable was quoted, quotes have been
+ removed.
+
+ @return the variable's value as string
+ */
+ operator const std::string&() const throw() {
+ return value;
+ }
+
+ /** @brief Get the value string.
+
+ Alternative access to the variable's contents. Trailing and
+ leading white spaces have been truncated. If the variable
+ was quoted, quotes have been removed.
+
+ @return the variable's value as string
+ */
+ const std::string& operator()() const throw() {
+ return value;
+ }
+
+ /** @brief Assign a new value.
+
+ Assign a new value. The new value is lost if you use the
+ ConfigFileReader, but it is stored in the destructor, if you
+ use the ConfigFileWriter instead.
+ */
+ Value& operator=(const std::string& newValue) throw() {
+ changed = true;
+ value = newValue;
+ return *this;
+ }
+
+ /// Compare the value to a string.
+ bool operator==(const std::string& o) const throw() {
+ return o==value;
+ }
+
+ /// Compare a string to the value.
+ friend bool operator==(const std::string& o, const Value& v) throw() {
+ return v==o;
+ }
+
+ //............................................................ methods
+ protected:
+
+ friend class ConfigFileReader;
+ friend class ConfigFileWriter;
+
+ Value(const std::string& v, std::string::size_type s,
+ std::string::size_type e) throw():
+ value(v), changed(false), start(s), end(e) {}
+
+ Value(const std::string& v) throw():
+ value(v), changed(true), start(0), end(0) {
+ }
+
+ //.......................................................... variables
+ protected:
+
+ std::string value;
+ bool changed;
+ std::string::size_type start;
+ std::string::size_type end;
+
+ //............................................................ methods
+ private:
+
+ Value(); // not implemented, must be initialized
+ Value& operator=(const Value&); // not implemented, no assignment
+
+ };
+ //------------------------------------------------------------------------
+
+ //................................................................ methods
+ public:
+
+ /** @brief Uninitialized construction.
+
+ Uninitialized construction. Use this constructor, if you
+ want to call @ref load() later.
+ */
+ ConfigFileReader() throw() {}
+
+ /** @brief Parse a file at construction.
+
+ This should be the normal case: load and parse the file at
+ construction.
+
+ @param filename the name of the file to read
+ @throw mrw::invalid_argument
+ - if the file does not exist
+ - if reading the file fails
+ - if there is an unterminated section name in the file
+ - if there is an empty variable name in the file
+ */
+ ConfigFileReader(const std::string& filename) throw(std::exception):
+ _filename(filename) {
+ reload();
}
- /// Get the value string.
- /** Alternative access to the variable's contents. Trailing and
- leading white spaces have been truncated. If the variable
- was quoted, quotes have been removed.
- @return the variable's value as string */
- const std::string& operator()() const throw() {
- return value;
+
+ /// Copy construct from other ConfigFileReader.
+ ConfigFileReader(const ConfigFileReader& o) throw():
+ _filename(o._filename), _values(o._values) {
}
- /// Assign a new value.
- /** Assign a new value. The new value is lost if you use the
- ConfigFileReader, but it is stored in the destructor, if you
- use the ConfigFileWriter instead. */
- Value& operator=(const std::string& newValue) throw() {
- changed = true;
- value = newValue;
+
+ virtual ~ConfigFileReader() throw() {}
+
+ /// Copy from other ConfigFileReader.
+ ConfigFileReader& operator=(const ConfigFileReader& o) {
+ _filename = o._filename;
+ _values = o._values;
return *this;
}
- /// Compare the value to a string.
- bool operator==(const std::string& o) const throw() {
- return o==value;
- }
- /// Compare a string to the value.
- friend bool operator==(const std::string& o, const Value& v) throw() {
- return v==o;
- }
+
+ /** @brief Access a value read from the file.
+
+ Access a value read from the file.
+
+ @param section the section in the configuration file
+ @param name the variable name
+ @param default_ the default value that is set, if the variable is
+ not configured
+ @return the Value you are looking for
+ */
+ Value& operator()(const std::string& section, const std::string& name,
+ const std::string& default_)
+ throw(std::bad_exception);
+
+ /** @brief Load and parse a new file.
+
+ Load and parse a new file.
+
+ @param filename the name of the file to load
+ @throw mrw::invalid_argument
+ - if the file does not exist
+ - if reading the file fails
+ - if there is an unterminated section name in the file
+ - if there is an empty variable name in the file
+ */
+ ConfigFileReader& load(const std::string& filename) throw(std::exception);
+
+ /** @brief Reload the last file again.
+
+ Reload the last file again.
+
+ @throw mrw::invalid_argument
+ - if the file does not exist
+ - if reading the file fails
+ - if there is an unterminated section name in the file
+ - if there is an empty variable name in the file
+ */
+ virtual ConfigFileReader& reload() throw(std::exception);
+
+ //............................................................... typedefs
protected:
- friend class ConfigFileReader;
- friend class ConfigFileWriter;
- Value(const std::string& v,
- std::string::size_type s, std::string::size_type e) throw():
- value(v), changed(false), start(s), end(e) {
- }
- Value(const std::string& v) throw():
- value(v), changed(true), start(0), end(0) {
- }
- std::string value;
- bool changed;
- std::string::size_type start;
- std::string::size_type end;
- private:
- Value(); // not implemented, must be initialized
- Value& operator=(const Value&); // not implemented, no assignment
- };
- /// Uninitialized construction.
- /** Uninitialized construction. Use this constructor, if you want
- to call @ref load() later. */
- ConfigFileReader() throw() {}
- /// Parse a file at construction.
- /** This should be the normal case: load and parse the file at
- construction.
- @param filename the name of the file to read
- @throw mrw::invalid_argument
- - if the file does not exist
- - if reading the file fails
- - if there is an unterminated section name in the file
- - if there is an empty variable name in the file */
- ConfigFileReader(const std::string& filename) throw(std::exception):
- _filename(filename) {
- reload();
- }
- /// Copy construct from other ConfigFileReader.
- ConfigFileReader(const ConfigFileReader& o) throw():
- _filename(o._filename), _values(o._values) {
- }
- virtual ~ConfigFileReader() throw() {}
- /// Copy from other ConfigFileReader.
- ConfigFileReader& operator=(const ConfigFileReader& o) {
- _filename = o._filename;
- _values = o._values;
- return *this;
- }
- /// Access a value read from the file.
- /** Access a value read from the file.
- @param section the section in the configuration file
- @param name the variable name
- @param default_ the default value that is set, if the variable is
- not configured
- @return the Value you are looking for */
- Value& operator()(const std::string& section, const std::string& name,
- const std::string& default_)
- throw(std::bad_exception);
- /// Load and parse a new file.
- /** Load and parse a new file.
- @throw mrw::invalid_argument
- - if the file does not exist
- - if reading the file fails
- - if there is an unterminated section name in the file
- - if there is an empty variable name in the file */
- ConfigFileReader& load(const std::string& filename) throw(std::exception);
- /// Reload the last file again.
- /** Reload the last file again.
- @throw mrw::invalid_argument
- - if the file does not exist
- - if reading the file fails
- - if there is an unterminated section name in the file
- - if there is an empty variable name in the file */
- virtual ConfigFileReader& reload() throw(std::exception);
- protected:
- typedef std::map< std::string, std::map > Values;
- typedef std::map Sections;
- std::string readFile() const throw(std::exception);
- ConfigFileReader& parse(const std::string& file) throw(std::exception);
- std::string parseSection(const std::string& file,
- std::string::size_type& pos)
- const throw(std::exception);
- Values::mapped_type::value_type parseValue(const std::string& file,
- std::string::size_type& pos)
- const throw(std::exception);
- std::string parseComment(const std::string& file,
- std::string::size_type& pos)
- const throw(std::bad_exception);
- std::string _filename;
- Values _values;
- Sections _sections;
+
+ typedef std::map< std::string, std::map > Values;
+ typedef std::map Sections;
+
+ //.............................................................. variables
+ protected:
+
+ std::string _filename;
+ Values _values;
+ Sections _sections;
+
+ //................................................................ methods
+ protected:
+
+ ConfigFileReader& parse(const std::string& file) throw(std::exception);
+
+ std::string parseSection(const std::string& file,
+ std::string::size_type& pos)
+ const throw(std::exception);
+
+ Values::mapped_type::value_type parseValue(const std::string& file,
+ std::string::size_type& pos)
+ const throw(std::exception);
+
+ std::string parseComment(const std::string& file,
+ std::string::size_type& pos)
+ const throw(std::bad_exception);
};
+ //============================================================================
/** @brief Parse configuration file and offer read / write
access to the contents.
Parse a configuration file that consists of sections containing
variables with values. This class stores the file in the destructor
if variables have changed.
- @see If you want %to leave the file untouched, use
- @ref ConfigFileReader.
- @see For details, see @ref configSyntax. */
+
+ @see If you want %to leave the file untouched, use @ref ConfigFileReader.
+ @see For details, see @ref configSyntax.
+ */
class ConfigFileWriter: virtual public ConfigFileReader {
- public:
- /// Uninitialized construction.
- /** @copydoc ConfigFileReader() */
- ConfigFileWriter() throw() {}
- /// Parse a file at construction.
- /** @copydoc ConfigFileReader(const std::string& filename) */
- ConfigFileWriter(const std::string& filename) throw(std::exception){
- load(filename);
- }
- /// Copy construct from other ConfigFileWriter.
- ConfigFileWriter(const ConfigFileWriter& o) throw():
- ConfigFileReader(o) {
- }
- /// The file is stored at destruction.
- virtual ~ConfigFileWriter() throw() {
- save();
- }
- /// Copy from other ConfigFileWriter.
- ConfigFileWriter& operator=(const ConfigFileWriter& o) {
- ConfigFileReader::operator=(o);
- return *this;
- }
-// GNU g++ prior to 3.4 does not implement covariant returns
-# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
- /// Reload the last file again.
- /** @copydoc mrw::ConfigFileReader::reload()
- @bug Bug in GNU g++ compiler:
- return type should be ConfigFileWriter&
,
- but the compiler sais:
- ../mrw/configfile.hpp:295:
- sorry, unimplemented: adjusting pointers for
- covariant returns
- The problem is fixed since GNU g++ 3.4, so the signature
- will be changed as soon as you upgrade to the new compiler
- version. */
- virtual ConfigFileReader& reload() throw(std::exception);
-# else
- /// Reload the last file again.
- /** @copydoc mrw::ConfigFileReader::reload() */
- virtual ConfigFileWriter& reload() throw(std::exception);
-# endif
- /// Saves changes back to the file.
- /** All changed parameters are stored in the configuration
- file. The rest of the file is left untouched. */
- ConfigFileWriter& save() throw(std::exception);
- protected:
- std::string _file;
+
+ //................................................................ methods
+ public:
+
+ /** @brief Uninitialized construction.
+
+ @copydoc ConfigFileReader()
+ */
+ ConfigFileWriter() throw() {}
+
+ /** @brief Parse a file at construction.
+
+ @copydoc ConfigFileReader(const std::string&)
+ */
+ ConfigFileWriter(const std::string& filename) throw(std::exception) {
+ load(filename);
+ }
+
+ /// Copy construct from other ConfigFileWriter.
+ ConfigFileWriter(const ConfigFileWriter& o) throw():
+ ConfigFileReader(o) {
+ }
+
+ /// The file is stored at destruction.
+ virtual ~ConfigFileWriter() throw() {
+ save();
+ }
+
+ /// Copy from other ConfigFileWriter.
+ ConfigFileWriter& operator=(const ConfigFileWriter& o) {
+ ConfigFileReader::operator=(o);
+ return *this;
+ }
+
+ // GNU g++ prior to 3.4 does not implement covariant returns
+# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
+ /** @brief Reload the last file again.
+
+ @copydoc mrw::ConfigFileReader::reload()
+
+ @bug Bug in GNU g++ compiler:
+ return type should be ConfigFileWriter&
,
+ but the compiler sais:
+ ../mrw/configfile.hpp:295:
+ sorry, unimplemented: adjusting pointers for
+ covariant returns
+ The problem is fixed since GNU g++ 3.4, so the signature
+ will be changed as soon as you upgrade to the new compiler
+ version.
+ */
+ virtual ConfigFileReader& reload() throw(std::exception);
+# else
+ /** @brief Reload the last file again.
+
+ @copydoc mrw::ConfigFileReader::reload()
+ */
+ virtual ConfigFileWriter& reload() throw(std::exception);
+# endif
+
+ /** @brief Saves changes back to the file.
+
+ All changed parameters are stored in the configuration
+ file. The rest of the file is left untouched.
+ */
+ ConfigFileWriter& save() throw(std::exception);
+
+ //.............................................................. variables
+ protected:
+
+ std::string _file;
+
};
//@}
diff --git a/mrw/file.hpp b/mrw/file.hpp
index 9e7248e..e5633aa 100644
--- a/mrw/file.hpp
+++ b/mrw/file.hpp
@@ -1,3 +1,4 @@
+
/** @file
$Id$
@@ -9,39 +10,305 @@
@license LGPL, see file COPYING
$Log$
+ Revision 1.2 2005/01/28 07:49:32 marc
+ Save configuration using file.hpp
+
Revision 1.1 2005/01/07 00:31:38 marc
initial version
- 1 2 3 4 5 6 7 8
+ 1 2 3 4 5 6 7 8
5678901234567890123456789012345678901234567890123456789012345678901234567890
-*/
+ */
#ifndef __MRW_FILE_HPP__
#define __MRW_FILE_HPP__
#include
#include
#include
+#include
+#include
namespace mrw {
+
+ /** @defgroup sysFile File and System Utilities
+
+ @brief By now, some utilies for file handling, i.e. a copy command.
+
+ Some file and system specific utilities are missing in C++ and
+ often there is even no good alternative in C libraries.
+ */
+ //@{
+
+ //============================================================================
+ /** @brief File handling utilities.
+
+ Utilities for file access in C++.
+ */
class File {
- public:
- static void copy(std::string from, std::string to) throw (std::exception) {
- std::ifstream is(from.c_str());
- if (!is)
- throw mrw::invalid_argument("Cannot read file: '"+from+"'");
- is.seekg(0, std::ios::end);
- int size(is.tellg());
- std::string contents(size, 0); // make buffer long enough to store all
- is.seekg(0, std::ios::beg);
- is.read(contents.begin().operator->(), size); // hack to get the buffer
- if (!is.good() && is.eof())
- throw mrw::invalid_argument("Cannot read file: '"+from+"'");
- std::ofstream os(to.c_str());
- os<(), sz); // hack to get the buffer
+ if (!is.good() && is.eof())
+ throw mrw::invalid_argument("Cannot read file: '"+filename+"'");
+ return contents;
+ };
+
+ /** @brief Save a string to a file.
+
+ A string is stored in a file, the whole file is overwritten by
+ the contents of the string. This is the counterpart of
+ read(const std::string&).
+
+ @throw mrw::invalid_argument if write fails
+ @param filename the name of the output file
+ @param contents the text to be written to the file
+ */
+ static void save(const std::string& filename, const std::string& contents)
+ throw(std::exception) {
+ std::ofstream file(filename.c_str());
+ if (!(file<. and
+ ..
(self anf top)
+ */
+ Dir(const std::string& dir, bool ignoreDots=true) throw(std::exception):
+ _ignoreDots(ignoreDots), _dir(opendir(dir.c_str())) {
+ if (!_dir)
+ throw mrw::invalid_argument("Cannot read directory: '"+dir+'\'');
+ }
+
+ /// Directory is closed automatically in the destructor.
+ ~Dir() throw() {
+ closedir(_dir);
+ }
+
+ /** @brief Advance to the next directory entry.
+
+ Advance to the next directory entry.
+
+ @code
+ mrw::Dir dir("/home");
+ while (dir) ...
+ @endcode
+
+ @return
+ - @c true if an entry has been found
+ - @c false if there are no more entries left
+
+ @warning If you call this method again after @c false was
+ returned, behaviour is unspecified, but a crash
+ is probable.
+ */
+ operator bool() throw() {
+ static const std::string D("."), DD("..");
+ static dirent* fake;
+ if (readdir_r(_dir, &_entry.entry(), &fake)) return false;
+ if (_ignoreDots && _entry==Entry::DIR && (D==_entry() || D==_entry()))
+ return operator bool();
+ return true;
+ }
+
+ /** @brief Get the actual directory entry.
+
+ Returns the actual directory entry.
+
+ @code
+ mrw::Dir dir("/home");
+ while (dir) {
+ dirent entry(dir());
+ ...
+ }
+ @endcode
+
+ @return the actual directory entry
+
+ @warning You must first call operator bool(), otherwise the
+ behaviour is undefined, but a crash is probable.
+ */
+ const Entry& operator()() {
+ return _entry;
+ }
+
+ //.............................................................. variables
+ private:
+
+ bool _ignoreDots;
+ DIR* _dir;
+ Entry _entry;
+
};
+
+ //@}
}
#endif