2005-01-28 07:49:32 +00:00
|
|
|
|
2005-01-07 00:35:17 +00:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
$Date$
|
|
|
|
$Author$
|
|
|
|
|
|
|
|
@copy © Marc Wäckerlin
|
|
|
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
|
|
|
|
|
|
|
$Log$
|
2005-01-28 07:49:32 +00:00
|
|
|
Revision 1.2 2005/01/28 07:49:32 marc
|
|
|
|
Save configuration using file.hpp
|
|
|
|
|
2005-01-07 00:35:17 +00:00
|
|
|
Revision 1.1 2005/01/07 00:31:38 marc
|
|
|
|
initial version
|
|
|
|
|
|
|
|
|
2005-01-28 07:49:32 +00:00
|
|
|
1 2 3 4 5 6 7 8
|
2005-01-07 00:35:17 +00:00
|
|
|
5678901234567890123456789012345678901234567890123456789012345678901234567890
|
2005-01-28 07:49:32 +00:00
|
|
|
*/
|
2005-01-07 00:35:17 +00:00
|
|
|
#ifndef __MRW_FILE_HPP__
|
|
|
|
#define __MRW_FILE_HPP__
|
|
|
|
|
|
|
|
#include <mrw/exception.hpp>
|
|
|
|
#include <string>
|
|
|
|
#include <fstream>
|
2005-01-28 07:49:32 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <dirent.h>
|
2005-01-07 00:35:17 +00:00
|
|
|
|
|
|
|
namespace mrw {
|
2005-01-28 07:49:32 +00:00
|
|
|
|
|
|
|
/** @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++.
|
|
|
|
*/
|
2005-01-07 00:35:17 +00:00
|
|
|
class File {
|
2005-01-28 07:49:32 +00:00
|
|
|
|
|
|
|
//................................................................ methods
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** @brief Copy a file.
|
|
|
|
|
|
|
|
Copy a file to a new location.
|
|
|
|
|
|
|
|
First the source file is fully read into memory, then written
|
|
|
|
to the destination. If the source file cannot be fully read,
|
|
|
|
the destination is left untouched.
|
|
|
|
|
|
|
|
@throw mrw::invalid_argument if read or write fails
|
|
|
|
@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());
|
|
|
|
os<<read(from);
|
|
|
|
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;
|
|
|
|
|
2005-01-07 00:35:17 +00:00
|
|
|
};
|
2005-01-28 07:49:32 +00:00
|
|
|
|
|
|
|
//@}
|
2005-01-07 00:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|