Save configuration using file.hpp
This commit is contained in:
@@ -9,6 +9,9 @@
|
|||||||
@license LGPL, see file <a href="license.html">COPYING</a>
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||||||
|
|
||||||
$Log$
|
$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
|
Revision 1.1 2005/01/07 00:31:38 marc
|
||||||
initial version
|
initial version
|
||||||
|
|
||||||
@@ -20,10 +23,11 @@
|
|||||||
#include <mrw/configfile.hpp>
|
#include <mrw/configfile.hpp>
|
||||||
#include <mrw/exception.hpp>
|
#include <mrw/exception.hpp>
|
||||||
#include <mrw/string.hpp>
|
#include <mrw/string.hpp>
|
||||||
|
#include <mrw/file.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
mrw::ConfigFileReader::Value&
|
mrw::ConfigFileReader::Value&
|
||||||
mrw::ConfigFileReader::operator()(const std::string& section,
|
mrw::ConfigFileReader::operator()(const std::string& section,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& default_)
|
const std::string& default_)
|
||||||
throw(std::bad_exception) {
|
throw(std::bad_exception) {
|
||||||
@@ -38,26 +42,9 @@ mrw::ConfigFileReader& mrw::ConfigFileReader::load(const std::string& filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mrw::ConfigFileReader& mrw::ConfigFileReader::reload() throw(std::exception) {
|
mrw::ConfigFileReader& mrw::ConfigFileReader::reload() throw(std::exception) {
|
||||||
return parse(readFile());
|
return parse(mrw::File::read(_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
using namespace std;
|
|
||||||
mrw::ConfigFileReader& mrw::ConfigFileReader::parse(const std::string& file)
|
mrw::ConfigFileReader& mrw::ConfigFileReader::parse(const std::string& file)
|
||||||
throw(std::exception) {
|
throw(std::exception) {
|
||||||
_values.erase(_values.begin(), _values.end());
|
_values.erase(_values.begin(), _values.end());
|
||||||
@@ -142,7 +129,7 @@ mrw::ConfigFileReader&
|
|||||||
mrw::ConfigFileWriter&
|
mrw::ConfigFileWriter&
|
||||||
#endif
|
#endif
|
||||||
mrw::ConfigFileWriter::reload() throw(std::exception) {
|
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) {
|
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();
|
_sections[sec->first] = _file.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!changed) return *this;
|
if (changed) mrw::File::save(_filename, _file);
|
||||||
// save to file
|
|
||||||
std::ofstream file(_filename.c_str());
|
|
||||||
if (!(file<<_file))
|
|
||||||
throw mrw::invalid_argument("Cannot write file '"+_filename+"'");
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@@ -9,11 +9,14 @@
|
|||||||
@license LGPL, see file <a href="license.html">COPYING</a>
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||||||
|
|
||||||
$Log$
|
$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
|
Revision 1.1 2005/01/07 00:31:38 marc
|
||||||
initial version
|
initial version
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#ifndef __MRW_CONFIGFILE_HPP__
|
#ifndef __MRW_CONFIGFILE_HPP__
|
||||||
#define __MRW_CONFIGFILE_HPP__
|
#define __MRW_CONFIGFILE_HPP__
|
||||||
|
|
||||||
@@ -24,6 +27,8 @@ namespace mrw {
|
|||||||
|
|
||||||
/** @defgroup config Configuration File Handler
|
/** @defgroup config Configuration File Handler
|
||||||
|
|
||||||
|
@pre #include <mrw/configfile.hpp>
|
||||||
|
|
||||||
Read configuration parameters from a file.
|
Read configuration parameters from a file.
|
||||||
|
|
||||||
@section configSyntax Configuration File Syntax
|
@section configSyntax Configuration File Syntax
|
||||||
@@ -162,178 +167,268 @@ namespace mrw {
|
|||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/// 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
|
variables with values. This class does not store anything in the
|
||||||
file, even if variables have changed.
|
file, even if variables have changed.
|
||||||
@see If you want %to save changes %to the file, use
|
|
||||||
@ref ConfigFileWriter.
|
@see If you want %to save changes %to the file, use @ref ConfigFileWriter.
|
||||||
@see For details, see @ref configSyntax. */
|
@see For details, see @ref configSyntax.
|
||||||
|
*/
|
||||||
class ConfigFileReader {
|
class ConfigFileReader {
|
||||||
|
|
||||||
|
//............................................................... typedefs
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//------------------------------------------------------------------ Value
|
||||||
/// A configuration file value.
|
/// A configuration file value.
|
||||||
class Value {
|
class Value {
|
||||||
|
|
||||||
|
//............................................................ methods
|
||||||
public:
|
public:
|
||||||
/// Get the value string.
|
|
||||||
/** Get the value string. Trailing and leading white spaces have
|
/** @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
|
been truncated. If the variable was quoted, quotes have been
|
||||||
removed.
|
removed.
|
||||||
@return the variable's value as string */
|
|
||||||
|
@return the variable's value as string
|
||||||
|
*/
|
||||||
operator const std::string&() const throw() {
|
operator const std::string&() const throw() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
/// Get the value string.
|
|
||||||
/** Alternative access to the variable's contents. Trailing and
|
/** @brief Get the value string.
|
||||||
|
|
||||||
|
Alternative access to the variable's contents. Trailing and
|
||||||
leading white spaces have been truncated. If the variable
|
leading white spaces have been truncated. If the variable
|
||||||
was quoted, quotes have been removed.
|
was quoted, quotes have been removed.
|
||||||
@return the variable's value as string */
|
|
||||||
|
@return the variable's value as string
|
||||||
|
*/
|
||||||
const std::string& operator()() const throw() {
|
const std::string& operator()() const throw() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
/// Assign a new value.
|
|
||||||
/** Assign a new value. The new value is lost if you use the
|
/** @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
|
ConfigFileReader, but it is stored in the destructor, if you
|
||||||
use the ConfigFileWriter instead. */
|
use the ConfigFileWriter instead.
|
||||||
|
*/
|
||||||
Value& operator=(const std::string& newValue) throw() {
|
Value& operator=(const std::string& newValue) throw() {
|
||||||
changed = true;
|
changed = true;
|
||||||
value = newValue;
|
value = newValue;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare the value to a string.
|
/// Compare the value to a string.
|
||||||
bool operator==(const std::string& o) const throw() {
|
bool operator==(const std::string& o) const throw() {
|
||||||
return o==value;
|
return o==value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare a string to the value.
|
/// Compare a string to the value.
|
||||||
friend bool operator==(const std::string& o, const Value& v) throw() {
|
friend bool operator==(const std::string& o, const Value& v) throw() {
|
||||||
return v==o;
|
return v==o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//............................................................ methods
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
friend class ConfigFileReader;
|
friend class ConfigFileReader;
|
||||||
friend class ConfigFileWriter;
|
friend class ConfigFileWriter;
|
||||||
Value(const std::string& v,
|
|
||||||
std::string::size_type s, std::string::size_type e) throw():
|
Value(const std::string& v, std::string::size_type s,
|
||||||
value(v), changed(false), start(s), end(e) {
|
std::string::size_type e) throw():
|
||||||
}
|
value(v), changed(false), start(s), end(e) {}
|
||||||
|
|
||||||
Value(const std::string& v) throw():
|
Value(const std::string& v) throw():
|
||||||
value(v), changed(true), start(0), end(0) {
|
value(v), changed(true), start(0), end(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//.......................................................... variables
|
||||||
|
protected:
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
bool changed;
|
bool changed;
|
||||||
std::string::size_type start;
|
std::string::size_type start;
|
||||||
std::string::size_type end;
|
std::string::size_type end;
|
||||||
|
|
||||||
|
//............................................................ methods
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Value(); // not implemented, must be initialized
|
Value(); // not implemented, must be initialized
|
||||||
Value& operator=(const Value&); // not implemented, no assignment
|
Value& operator=(const Value&); // not implemented, no assignment
|
||||||
|
|
||||||
};
|
};
|
||||||
/// Uninitialized construction.
|
//------------------------------------------------------------------------
|
||||||
/** Uninitialized construction. Use this constructor, if you want
|
|
||||||
to call @ref load() later. */
|
//................................................................ methods
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** @brief Uninitialized construction.
|
||||||
|
|
||||||
|
Uninitialized construction. Use this constructor, if you
|
||||||
|
want to call @ref load() later.
|
||||||
|
*/
|
||||||
ConfigFileReader() throw() {}
|
ConfigFileReader() throw() {}
|
||||||
/// Parse a file at construction.
|
|
||||||
/** This should be the normal case: load and parse the file at
|
/** @brief Parse a file at construction.
|
||||||
|
|
||||||
|
This should be the normal case: load and parse the file at
|
||||||
construction.
|
construction.
|
||||||
|
|
||||||
@param filename the name of the file to read
|
@param filename the name of the file to read
|
||||||
@throw mrw::invalid_argument
|
@throw mrw::invalid_argument
|
||||||
- if the file does not exist
|
- if the file does not exist
|
||||||
- if reading the file fails
|
- if reading the file fails
|
||||||
- if there is an unterminated section name in the file
|
- if there is an unterminated section name in the file
|
||||||
- if there is an empty variable name in the file */
|
- if there is an empty variable name in the file
|
||||||
|
*/
|
||||||
ConfigFileReader(const std::string& filename) throw(std::exception):
|
ConfigFileReader(const std::string& filename) throw(std::exception):
|
||||||
_filename(filename) {
|
_filename(filename) {
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy construct from other ConfigFileReader.
|
/// Copy construct from other ConfigFileReader.
|
||||||
ConfigFileReader(const ConfigFileReader& o) throw():
|
ConfigFileReader(const ConfigFileReader& o) throw():
|
||||||
_filename(o._filename), _values(o._values) {
|
_filename(o._filename), _values(o._values) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ConfigFileReader() throw() {}
|
virtual ~ConfigFileReader() throw() {}
|
||||||
|
|
||||||
/// Copy from other ConfigFileReader.
|
/// Copy from other ConfigFileReader.
|
||||||
ConfigFileReader& operator=(const ConfigFileReader& o) {
|
ConfigFileReader& operator=(const ConfigFileReader& o) {
|
||||||
_filename = o._filename;
|
_filename = o._filename;
|
||||||
_values = o._values;
|
_values = o._values;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
/// Access a value read from the file.
|
|
||||||
/** Access a value read from the file.
|
/** @brief Access a value read from the file.
|
||||||
|
|
||||||
|
Access a value read from the file.
|
||||||
|
|
||||||
@param section the section in the configuration file
|
@param section the section in the configuration file
|
||||||
@param name the variable name
|
@param name the variable name
|
||||||
@param default_ the default value that is set, if the variable is
|
@param default_ the default value that is set, if the variable is
|
||||||
not configured
|
not configured
|
||||||
@return the Value you are looking for */
|
@return the Value you are looking for
|
||||||
|
*/
|
||||||
Value& operator()(const std::string& section, const std::string& name,
|
Value& operator()(const std::string& section, const std::string& name,
|
||||||
const std::string& default_)
|
const std::string& default_)
|
||||||
throw(std::bad_exception);
|
throw(std::bad_exception);
|
||||||
/// Load and parse a new file.
|
|
||||||
/** Load and parse a new file.
|
/** @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
|
@throw mrw::invalid_argument
|
||||||
- if the file does not exist
|
- if the file does not exist
|
||||||
- if reading the file fails
|
- if reading the file fails
|
||||||
- if there is an unterminated section name in the file
|
- if there is an unterminated section name in the file
|
||||||
- if there is an empty variable name in the file */
|
- if there is an empty variable name in the file
|
||||||
|
*/
|
||||||
ConfigFileReader& load(const std::string& filename) throw(std::exception);
|
ConfigFileReader& load(const std::string& filename) throw(std::exception);
|
||||||
/// Reload the last file again.
|
|
||||||
/** Reload the last file again.
|
/** @brief Reload the last file again.
|
||||||
|
|
||||||
|
Reload the last file again.
|
||||||
|
|
||||||
@throw mrw::invalid_argument
|
@throw mrw::invalid_argument
|
||||||
- if the file does not exist
|
- if the file does not exist
|
||||||
- if reading the file fails
|
- if reading the file fails
|
||||||
- if there is an unterminated section name in the file
|
- if there is an unterminated section name in the file
|
||||||
- if there is an empty variable name in the file */
|
- if there is an empty variable name in the file
|
||||||
|
*/
|
||||||
virtual ConfigFileReader& reload() throw(std::exception);
|
virtual ConfigFileReader& reload() throw(std::exception);
|
||||||
|
|
||||||
|
//............................................................... typedefs
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::map< std::string, std::map<std::string, Value> > Values;
|
typedef std::map< std::string, std::map<std::string, Value> > Values;
|
||||||
typedef std::map<std::string, std::string::size_type> Sections;
|
typedef std::map<std::string, std::string::size_type> Sections;
|
||||||
std::string readFile() const throw(std::exception);
|
|
||||||
ConfigFileReader& parse(const std::string& file) throw(std::exception);
|
//.............................................................. variables
|
||||||
std::string parseSection(const std::string& file,
|
protected:
|
||||||
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;
|
std::string _filename;
|
||||||
Values _values;
|
Values _values;
|
||||||
Sections _sections;
|
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
|
/** @brief Parse configuration file and offer read / write
|
||||||
access to the contents.
|
access to the contents.
|
||||||
|
|
||||||
Parse a configuration file that consists of sections containing
|
Parse a configuration file that consists of sections containing
|
||||||
variables with values. This class stores the file in the destructor
|
variables with values. This class stores the file in the destructor
|
||||||
if variables have changed.
|
if variables have changed.
|
||||||
@see If you want %to leave the file untouched, use
|
|
||||||
@ref ConfigFileReader.
|
@see If you want %to leave the file untouched, use @ref ConfigFileReader.
|
||||||
@see For details, see @ref configSyntax. */
|
@see For details, see @ref configSyntax.
|
||||||
|
*/
|
||||||
class ConfigFileWriter: virtual public ConfigFileReader {
|
class ConfigFileWriter: virtual public ConfigFileReader {
|
||||||
|
|
||||||
|
//................................................................ methods
|
||||||
public:
|
public:
|
||||||
/// Uninitialized construction.
|
|
||||||
/** @copydoc ConfigFileReader() */
|
/** @brief Uninitialized construction.
|
||||||
|
|
||||||
|
@copydoc ConfigFileReader()
|
||||||
|
*/
|
||||||
ConfigFileWriter() throw() {}
|
ConfigFileWriter() throw() {}
|
||||||
/// Parse a file at construction.
|
|
||||||
/** @copydoc ConfigFileReader(const std::string& filename) */
|
/** @brief Parse a file at construction.
|
||||||
ConfigFileWriter(const std::string& filename) throw(std::exception){
|
|
||||||
|
@copydoc ConfigFileReader(const std::string&)
|
||||||
|
*/
|
||||||
|
ConfigFileWriter(const std::string& filename) throw(std::exception) {
|
||||||
load(filename);
|
load(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy construct from other ConfigFileWriter.
|
/// Copy construct from other ConfigFileWriter.
|
||||||
ConfigFileWriter(const ConfigFileWriter& o) throw():
|
ConfigFileWriter(const ConfigFileWriter& o) throw():
|
||||||
ConfigFileReader(o) {
|
ConfigFileReader(o) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The file is stored at destruction.
|
/// The file is stored at destruction.
|
||||||
virtual ~ConfigFileWriter() throw() {
|
virtual ~ConfigFileWriter() throw() {
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy from other ConfigFileWriter.
|
/// Copy from other ConfigFileWriter.
|
||||||
ConfigFileWriter& operator=(const ConfigFileWriter& o) {
|
ConfigFileWriter& operator=(const ConfigFileWriter& o) {
|
||||||
ConfigFileReader::operator=(o);
|
ConfigFileReader::operator=(o);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
// GNU g++ prior to 3.4 does not implement covariant returns
|
|
||||||
|
// GNU g++ prior to 3.4 does not implement covariant returns
|
||||||
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
|
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
|
||||||
/// Reload the last file again.
|
/** @brief Reload the last file again.
|
||||||
/** @copydoc mrw::ConfigFileReader::reload()
|
|
||||||
|
@copydoc mrw::ConfigFileReader::reload()
|
||||||
|
|
||||||
@bug Bug in GNU g++ compiler:
|
@bug Bug in GNU g++ compiler:
|
||||||
return type should be <code>ConfigFileWriter&</code>,
|
return type should be <code>ConfigFileWriter&</code>,
|
||||||
but the compiler sais:<br>
|
but the compiler sais:<br>
|
||||||
@@ -342,19 +437,29 @@ namespace mrw {
|
|||||||
covariant returns</code><br>
|
covariant returns</code><br>
|
||||||
The problem is fixed since GNU g++ 3.4, so the signature
|
The problem is fixed since GNU g++ 3.4, so the signature
|
||||||
will be changed as soon as you upgrade to the new compiler
|
will be changed as soon as you upgrade to the new compiler
|
||||||
version. */
|
version.
|
||||||
|
*/
|
||||||
virtual ConfigFileReader& reload() throw(std::exception);
|
virtual ConfigFileReader& reload() throw(std::exception);
|
||||||
# else
|
# else
|
||||||
/// Reload the last file again.
|
/** @brief Reload the last file again.
|
||||||
/** @copydoc mrw::ConfigFileReader::reload() */
|
|
||||||
|
@copydoc mrw::ConfigFileReader::reload()
|
||||||
|
*/
|
||||||
virtual ConfigFileWriter& reload() throw(std::exception);
|
virtual ConfigFileWriter& reload() throw(std::exception);
|
||||||
# endif
|
# endif
|
||||||
/// Saves changes back to the file.
|
|
||||||
/** All changed parameters are stored in the configuration
|
/** @brief Saves changes back to the file.
|
||||||
file. The rest of the file is left untouched. */
|
|
||||||
|
All changed parameters are stored in the configuration
|
||||||
|
file. The rest of the file is left untouched.
|
||||||
|
*/
|
||||||
ConfigFileWriter& save() throw(std::exception);
|
ConfigFileWriter& save() throw(std::exception);
|
||||||
|
|
||||||
|
//.............................................................. variables
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::string _file;
|
std::string _file;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
293
mrw/file.hpp
293
mrw/file.hpp
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
@@ -9,39 +10,305 @@
|
|||||||
@license LGPL, see file <a href="license.html">COPYING</a>
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
||||||
|
|
||||||
$Log$
|
$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
|
Revision 1.1 2005/01/07 00:31:38 marc
|
||||||
initial version
|
initial version
|
||||||
|
|
||||||
|
|
||||||
1 2 3 4 5 6 7 8
|
1 2 3 4 5 6 7 8
|
||||||
5678901234567890123456789012345678901234567890123456789012345678901234567890
|
5678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
*/
|
*/
|
||||||
#ifndef __MRW_FILE_HPP__
|
#ifndef __MRW_FILE_HPP__
|
||||||
#define __MRW_FILE_HPP__
|
#define __MRW_FILE_HPP__
|
||||||
|
|
||||||
#include <mrw/exception.hpp>
|
#include <mrw/exception.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
namespace mrw {
|
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 {
|
class File {
|
||||||
|
|
||||||
|
//................................................................ methods
|
||||||
public:
|
public:
|
||||||
static void copy(std::string from, std::string to) throw (std::exception) {
|
|
||||||
std::ifstream is(from.c_str());
|
/** @brief Copy a file.
|
||||||
if (!is)
|
|
||||||
throw mrw::invalid_argument("Cannot read file: '"+from+"'");
|
Copy a file to a new location.
|
||||||
is.seekg(0, std::ios::end);
|
|
||||||
int size(is.tellg());
|
First the source file is fully read into memory, then written
|
||||||
std::string contents(size, 0); // make buffer long enough to store all
|
to the destination. If the source file cannot be fully read,
|
||||||
is.seekg(0, std::ios::beg);
|
the destination is left untouched.
|
||||||
is.read(contents.begin().operator->(), size); // hack to get the buffer
|
|
||||||
if (!is.good() && is.eof())
|
@throw mrw::invalid_argument if read or write fails
|
||||||
throw mrw::invalid_argument("Cannot read file: '"+from+"'");
|
@param from the source file name
|
||||||
|
@param to the destination file name
|
||||||
|
@note If the destination file already exists, it will be overwritten.
|
||||||
|
*/
|
||||||
|
static void copy(const std::string& from,
|
||||||
|
const std::string& to) throw(std::exception) {
|
||||||
std::ofstream os(to.c_str());
|
std::ofstream os(to.c_str());
|
||||||
os<<contents;
|
os<<read(from);
|
||||||
if (!os) throw mrw::invalid_argument("Cannot write file: '"+to+"'");
|
if (!os) throw mrw::invalid_argument("Cannot write file: '"+to+"'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Read a file fully into memory.
|
||||||
|
|
||||||
|
Read a file fully into memory.
|
||||||
|
|
||||||
|
@throw mrw::invalid_argument if read fails
|
||||||
|
@param filename the file to read
|
||||||
|
@return the file's contents
|
||||||
|
*/
|
||||||
|
static std::string read(const std::string& filename)
|
||||||
|
throw(std::exception) {
|
||||||
|
std::string contents; // declare on top to allow compiler optimization
|
||||||
|
std::ifstream is(filename.c_str());
|
||||||
|
std::string::size_type sz(size(is, filename));
|
||||||
|
contents.resize(sz); // make buffer long enough to store all
|
||||||
|
is.read(contents.begin().operator->(), 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<<contents))
|
||||||
|
throw mrw::invalid_argument("Cannot write file '"+filename+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get the size of a file
|
||||||
|
|
||||||
|
Get the size of a file.
|
||||||
|
|
||||||
|
@throw mrw::invalid_argument if read fails
|
||||||
|
@param filename the file name
|
||||||
|
@return the file's size
|
||||||
|
*/
|
||||||
|
static std::string::size_type size(const std::string& filename)
|
||||||
|
throw(std::exception) {
|
||||||
|
std::ifstream is(filename.c_str());
|
||||||
|
if (!is)
|
||||||
|
throw mrw::invalid_argument("Cannot get size of file: '"
|
||||||
|
+filename+"'");
|
||||||
|
is.seekg(0, std::ios::end);
|
||||||
|
if (!is)
|
||||||
|
throw mrw::invalid_argument("Cannot get size of file: '"
|
||||||
|
+filename+"'");
|
||||||
|
return is.tellg();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get the size of a file
|
||||||
|
|
||||||
|
Get the size of a file.
|
||||||
|
|
||||||
|
@throw mrw::invalid_argument if read fails
|
||||||
|
@param file the filestream
|
||||||
|
@param filename the name of the file (required for the exception)
|
||||||
|
@return the file's size
|
||||||
|
*/
|
||||||
|
static std::string::size_type size(std::ifstream& file,
|
||||||
|
const std::string& filename = "")
|
||||||
|
throw(std::exception) {
|
||||||
|
if (!file)
|
||||||
|
throw mrw::invalid_argument("Cannot get size of file: '"
|
||||||
|
+filename+"'");
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
std::string::size_type sz(file.tellg());
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
if (!file)
|
||||||
|
throw mrw::invalid_argument("Cannot get size of file: '"
|
||||||
|
+filename+"'");
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
class Dir {
|
||||||
|
|
||||||
|
//............................................................... typedefs
|
||||||
|
public:
|
||||||
|
|
||||||
|
//------------------------------------------------------------------ Entry
|
||||||
|
class Entry {
|
||||||
|
|
||||||
|
//........................................................... typedefs
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** @brief The type of the actual file.
|
||||||
|
|
||||||
|
The type of the actual file.
|
||||||
|
|
||||||
|
@note On some systems UNKNOWN is the only
|
||||||
|
value returned.
|
||||||
|
*/
|
||||||
|
enum FileType {
|
||||||
|
UNKNOWN = DT_UNKNOWN, ///< The type is unknown.
|
||||||
|
REGULAR = DT_REG, ///< A regular file.
|
||||||
|
DIR = DT_DIR, ///< A directory.
|
||||||
|
FIFO = DT_FIFO, ///< A named pipe, or FIFO.
|
||||||
|
SOCKET = DT_SOCK, ///< A local-domain socket.
|
||||||
|
CHAR = DT_CHR, ///< A character device.
|
||||||
|
BLOCK = DT_BLK ///< A block device.
|
||||||
|
};
|
||||||
|
|
||||||
|
//............................................................ methods
|
||||||
|
public:
|
||||||
|
|
||||||
|
Entry(): _new(true) {}
|
||||||
|
|
||||||
|
/// Get the name of the actual file.
|
||||||
|
operator const std::string&() throw(std::bad_exception) {
|
||||||
|
if (_new) { // only convert to string once
|
||||||
|
_new = false;
|
||||||
|
_name = _dirent.d.d_name;
|
||||||
|
}
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the name of the actual file.
|
||||||
|
const std::string& operator()() throw(std::bad_exception) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the type of the actual file.
|
||||||
|
operator FileType() const throw() {
|
||||||
|
return FileType(_dirent.d.d_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
//.......................................................... variables
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Dir;
|
||||||
|
|
||||||
|
union { // for portability reasons, see "info readdir_r"
|
||||||
|
dirent d;
|
||||||
|
char b[offsetof (struct dirent, d_name) + NAME_MAX + 1];
|
||||||
|
} _dirent;
|
||||||
|
|
||||||
|
bool _new;
|
||||||
|
std::string _name;
|
||||||
|
|
||||||
|
//............................................................ methods
|
||||||
|
private:
|
||||||
|
|
||||||
|
dirent& entry() throw() {
|
||||||
|
_new = true;
|
||||||
|
return _dirent.d;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//................................................................ methods
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** @brief Open a directory for reading the file list.
|
||||||
|
|
||||||
|
Open a directory for reading the file list.
|
||||||
|
|
||||||
|
@throw mrw::invalid_argument if directory cannot be opened
|
||||||
|
@param dir name of the directory to open
|
||||||
|
@param ignoreDots ignore directories <code>.<code> and
|
||||||
|
<code>..</code> (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
|
#endif
|
||||||
|
Reference in New Issue
Block a user