SGPath/Dir extensions to ease file handling in TerraGear. Also a unit-test, shocking.
This commit is contained in:
@@ -41,3 +41,8 @@ target_link_libraries(test_tabbed_values sgmisc)
|
||||
add_executable(test_strings strutils_test.cxx )
|
||||
add_test(test_strings ${EXECUTABLE_OUTPUT_PATH}/test_strings)
|
||||
target_link_libraries(test_strings sgmisc)
|
||||
|
||||
add_executable(test_path path_test.cxx )
|
||||
add_test(test_path ${EXECUTABLE_OUTPUT_PATH}/test_path)
|
||||
target_link_libraries(test_path sgmisc sgdebug)
|
||||
|
||||
|
||||
142
simgear/misc/path_test.cxx
Normal file
142
simgear/misc/path_test.cxx
Normal file
@@ -0,0 +1,142 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
#define COMPARE(a, b) \
|
||||
if ((a) != (b)) { \
|
||||
cerr << "failed:" << #a << " != " << #b << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define VERIFY(a) \
|
||||
if (!(a)) { \
|
||||
cerr << "failed:" << #a << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
||||
void test_dir()
|
||||
{
|
||||
simgear::Dir temp = simgear::Dir::tempDir("foo");
|
||||
cout << "created:" << temp.path().str() << endl;
|
||||
|
||||
VERIFY(temp.exists());
|
||||
VERIFY(temp.path().isDir());
|
||||
VERIFY(!temp.path().isFile());
|
||||
|
||||
SGPath fileInDir = temp.file("foobaz");
|
||||
VERIFY(!fileInDir.exists());
|
||||
|
||||
if (!temp.remove(true)) {
|
||||
cout << "remove failed!" << endl;
|
||||
}
|
||||
|
||||
cout << temp.path().modTime() << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SGPath pa;
|
||||
VERIFY(pa.isNull());
|
||||
COMPARE(pa.exists(), false);
|
||||
|
||||
// test basic parsing
|
||||
SGPath pb("/Foo/bar/something.png");
|
||||
COMPARE(pb.str(), std::string("/Foo/bar/something.png"));
|
||||
COMPARE(strcmp(pb.c_str(), "/Foo/bar/something.png"), 0);
|
||||
COMPARE(pb.dir(), std::string("/Foo/bar"));
|
||||
COMPARE(pb.file(), std::string("something.png"));
|
||||
COMPARE(pb.base(), std::string("/Foo/bar/something"));
|
||||
COMPARE(pb.file_base(), std::string("something"));
|
||||
COMPARE(pb.extension(), std::string("png"));
|
||||
VERIFY(pb.isAbsolute());
|
||||
VERIFY(!pb.isRelative());
|
||||
|
||||
// relative paths
|
||||
SGPath ra("where/to/begin.txt");
|
||||
COMPARE(ra.str(), std::string("where/to/begin.txt"));
|
||||
COMPARE(ra.dir(), std::string("where/to"));
|
||||
COMPARE(ra.file(), std::string("begin.txt"));
|
||||
COMPARE(ra.file_base(), std::string("begin"));
|
||||
VERIFY(!ra.isAbsolute());
|
||||
VERIFY(ra.isRelative());
|
||||
|
||||
// dots in paths / missing extensions
|
||||
SGPath pk("/Foo/bar.dot/thing");
|
||||
COMPARE(pk.dir(), std::string("/Foo/bar.dot"));
|
||||
COMPARE(pk.file(), std::string("thing"));
|
||||
COMPARE(pk.base(), std::string("/Foo/bar.dot/thing"));
|
||||
COMPARE(pk.file_base(), std::string("thing"));
|
||||
COMPARE(pk.extension(), std::string());
|
||||
|
||||
// multiple file extensions
|
||||
SGPath pj("/Foo/zot.dot/thing.tar.gz");
|
||||
COMPARE(pj.dir(), std::string("/Foo/zot.dot"));
|
||||
COMPARE(pj.file(), std::string("thing.tar.gz"));
|
||||
COMPARE(pj.base(), std::string("/Foo/zot.dot/thing"));
|
||||
COMPARE(pj.file_base(), std::string("thing"));
|
||||
COMPARE(pj.extension(), std::string("gz"));
|
||||
COMPARE(pj.complete_lower_extension(), std::string("tar.gz"));
|
||||
|
||||
// path fixing
|
||||
SGPath rd("where\\to\\begin.txt");
|
||||
COMPARE(rd.str(), std::string("where/to/begin.txt"));
|
||||
|
||||
// test modification
|
||||
// append
|
||||
SGPath d1("/usr/local");
|
||||
SGPath pc = d1;
|
||||
COMPARE(pc.str(), std::string("/usr/local"));
|
||||
pc.append("include");
|
||||
|
||||
COMPARE(pc.str(), std::string("/usr/local/include"));
|
||||
COMPARE(pc.file(), std::string("include"));
|
||||
|
||||
// add
|
||||
pc.add("/opt/local");
|
||||
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
||||
|
||||
// concat
|
||||
SGPath pd = pb;
|
||||
pd.concat("-1");
|
||||
COMPARE(pd.str(), std::string("/Foo/bar/something.png-1"));
|
||||
|
||||
// create with relative path
|
||||
SGPath rb(d1, "include/foo");
|
||||
COMPARE(rb.str(), std::string("/usr/local/include/foo"));
|
||||
VERIFY(rb.isAbsolute());
|
||||
|
||||
// lower-casing of file extensions
|
||||
SGPath extA("FOO.ZIP");
|
||||
COMPARE(extA.base(), "FOO");
|
||||
COMPARE(extA.extension(), "ZIP");
|
||||
COMPARE(extA.lower_extension(), "zip");
|
||||
COMPARE(extA.complete_lower_extension(), "zip");
|
||||
|
||||
SGPath extB("BAH/FOO.HTML.GZ");
|
||||
COMPARE(extB.extension(), "GZ");
|
||||
COMPARE(extB.base(), "BAH/FOO");
|
||||
COMPARE(extB.lower_extension(), "gz");
|
||||
COMPARE(extB.complete_lower_extension(), "html.gz");
|
||||
#ifdef _WIN32
|
||||
COMPARE(d1.str_native(), std::string("\\usr\\local"));
|
||||
|
||||
SGPath winAbs("C:\\Windows\\System32");
|
||||
COMPARE(winAbs.str(), std::string("C:/Windows/System32"));
|
||||
#else
|
||||
COMPARE(d1.str_native(), std::string("/usr/local"));
|
||||
#endif
|
||||
|
||||
test_dir();
|
||||
|
||||
cout << "all tests passed OK" << endl;
|
||||
return 0; // passed
|
||||
}
|
||||
|
||||
@@ -24,27 +24,59 @@
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
Dir::Dir(const SGPath& path) :
|
||||
_path(path)
|
||||
{
|
||||
_path.set_cached(false); // disable caching, so create/remove work
|
||||
}
|
||||
|
||||
Dir::Dir(const Dir& rel, const SGPath& relPath) :
|
||||
_path(rel.file(relPath.str()))
|
||||
{
|
||||
_path.set_cached(false); // disable caching, so create/remove work
|
||||
}
|
||||
|
||||
Dir Dir::current()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char* buf = _getcwd(NULL, 0);
|
||||
#else
|
||||
char* buf = ::getcwd(NULL, 0);
|
||||
#endif
|
||||
SGPath p(buf);
|
||||
free(buf);
|
||||
return Dir(p);
|
||||
}
|
||||
|
||||
Dir Dir::tempDir(const std::string& templ)
|
||||
{
|
||||
SGPath p(tempnam(0, templ.c_str()));
|
||||
Dir t(p);
|
||||
if (!t.create(0700)) {
|
||||
SG_LOG(SG_IO, SG_WARN, "failed to create temporary directory at " << p.str());
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
@@ -175,8 +207,79 @@ bool Dir::exists() const
|
||||
SGPath Dir::file(const std::string& name) const
|
||||
{
|
||||
SGPath childPath = _path;
|
||||
childPath.set_cached(true);
|
||||
childPath.append(name);
|
||||
return childPath;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
# define sgMkDir(d,m) _mkdir(d)
|
||||
#else
|
||||
# define sgMkDir(d,m) mkdir(d,m)
|
||||
#endif
|
||||
|
||||
bool Dir::create(mode_t mode)
|
||||
{
|
||||
if (exists()) {
|
||||
return false; // already exists
|
||||
}
|
||||
|
||||
// recursively create parent directories
|
||||
Dir pr(parent());
|
||||
if (!pr.exists()) {
|
||||
bool ok = pr.create(mode);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, create ourselves
|
||||
int err = sgMkDir(_path.c_str(), mode);
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "directory creation failed: (" << _path.str() << ") " << strerror(errno) );
|
||||
}
|
||||
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
bool Dir::remove(bool recursive)
|
||||
{
|
||||
if (!exists()) {
|
||||
SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
bool ok;
|
||||
PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR);
|
||||
BOOST_FOREACH(SGPath path, cs) {
|
||||
if (path.isDir()) {
|
||||
Dir childDir(path);
|
||||
ok = childDir.remove(true);
|
||||
} else {
|
||||
ok = path.remove();
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
} // of child iteration
|
||||
} // of recursive deletion
|
||||
|
||||
#ifdef _WIN32
|
||||
int err = _rmdir(_path.c_str());
|
||||
#else
|
||||
int err = rmdir(_path.c_str());
|
||||
#endif
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "rmdir failed:" << _path.str() << ":" << strerror(errno));
|
||||
}
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
Dir Dir::parent() const
|
||||
{
|
||||
return Dir(_path.dir());
|
||||
}
|
||||
|
||||
} // of namespace simgear
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef int mode_t;
|
||||
#endif
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::vector<SGPath> PathList;
|
||||
@@ -38,6 +42,13 @@ namespace simgear
|
||||
class Dir
|
||||
{
|
||||
public:
|
||||
static Dir current();
|
||||
|
||||
/**
|
||||
* create a temporary directory, using the supplied name
|
||||
*/
|
||||
static Dir tempDir(const std::string& templ);
|
||||
|
||||
Dir(const SGPath& path);
|
||||
Dir(const Dir& rel, const SGPath& relPath);
|
||||
|
||||
@@ -53,10 +64,31 @@ namespace simgear
|
||||
|
||||
SGPath file(const std::string& name) const;
|
||||
|
||||
SGPath path() const
|
||||
{ return _path; }
|
||||
|
||||
/**
|
||||
* create the directory (and any parents as required) with the
|
||||
* request mode, or return failure
|
||||
*/
|
||||
bool create(mode_t mode);
|
||||
|
||||
/**
|
||||
* remove the directory.
|
||||
* If recursive is true, contained files and directories are
|
||||
* recursively removed
|
||||
*/
|
||||
bool remove(bool recursive = false);
|
||||
|
||||
/**
|
||||
* Check that the directory at the path exists (and is a directory!)
|
||||
*/
|
||||
bool exists() const;
|
||||
|
||||
/**
|
||||
* parent directory, if one exists
|
||||
*/
|
||||
Dir parent() const;
|
||||
private:
|
||||
mutable SGPath _path;
|
||||
};
|
||||
|
||||
@@ -28,13 +28,16 @@
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <direct.h>
|
||||
#endif
|
||||
#include "sg_path.hxx"
|
||||
|
||||
using std::string;
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
using std::string;
|
||||
|
||||
/**
|
||||
* define directory path separators
|
||||
@@ -58,14 +61,14 @@ SGPath::fix()
|
||||
{
|
||||
for ( string::size_type i = 0; i < path.size(); ++i ) {
|
||||
#if defined( WIN32 )
|
||||
// for windoze, don't replace the ":" for the second character
|
||||
if ( i == 1 ) {
|
||||
continue;
|
||||
}
|
||||
// for windoze, don't replace the ":" for the second character
|
||||
if ( i == 1 ) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ( path[i] == sgDirPathSepBad ) {
|
||||
path[i] = sgDirPathSep;
|
||||
}
|
||||
if ( path[i] == sgDirPathSepBad ) {
|
||||
path[i] = sgDirPathSep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +76,8 @@ SGPath::fix()
|
||||
// default constructor
|
||||
SGPath::SGPath()
|
||||
: path(""),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +85,8 @@ SGPath::SGPath()
|
||||
// create a path based on "path"
|
||||
SGPath::SGPath( const std::string& p )
|
||||
: path(p),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(true)
|
||||
{
|
||||
fix();
|
||||
}
|
||||
@@ -89,7 +94,8 @@ SGPath::SGPath( const std::string& p )
|
||||
// create a path based on "path" and a "subpath"
|
||||
SGPath::SGPath( const SGPath& p, const std::string& r )
|
||||
: path(p.path),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(p._cacheEnabled)
|
||||
{
|
||||
append(r);
|
||||
fix();
|
||||
@@ -98,9 +104,11 @@ SGPath::SGPath( const SGPath& p, const std::string& r )
|
||||
SGPath::SGPath(const SGPath& p) :
|
||||
path(p.path),
|
||||
_cached(p._cached),
|
||||
_cacheEnabled(p._cacheEnabled),
|
||||
_exists(p._exists),
|
||||
_isDir(p._isDir),
|
||||
_isFile(p._isFile)
|
||||
_isFile(p._isFile),
|
||||
_modTime(p._modTime)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -108,9 +116,11 @@ SGPath& SGPath::operator=(const SGPath& p)
|
||||
{
|
||||
path = p.path;
|
||||
_cached = p._cached;
|
||||
_cacheEnabled = p._cacheEnabled;
|
||||
_exists = p._exists;
|
||||
_isDir = p._isDir;
|
||||
_isFile = p._isFile;
|
||||
_modTime = p._modTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -126,16 +136,20 @@ void SGPath::set( const string& p ) {
|
||||
_cached = false;
|
||||
}
|
||||
|
||||
void SGPath::set_cached(bool cached)
|
||||
{
|
||||
_cacheEnabled = cached;
|
||||
}
|
||||
|
||||
// append another piece to the existing path
|
||||
void SGPath::append( const string& p ) {
|
||||
if ( path.size() == 0 ) {
|
||||
path = p;
|
||||
path = p;
|
||||
} else {
|
||||
if ( p[0] != sgDirPathSep ) {
|
||||
path += sgDirPathSep;
|
||||
}
|
||||
path += p;
|
||||
if ( p[0] != sgDirPathSep ) {
|
||||
path += sgDirPathSep;
|
||||
}
|
||||
path += p;
|
||||
}
|
||||
fix();
|
||||
_cached = false;
|
||||
@@ -151,9 +165,9 @@ void SGPath::add( const string& p ) {
|
||||
// path separator
|
||||
void SGPath::concat( const string& p ) {
|
||||
if ( path.size() == 0 ) {
|
||||
path = p;
|
||||
path = p;
|
||||
} else {
|
||||
path += p;
|
||||
path += p;
|
||||
}
|
||||
fix();
|
||||
_cached = false;
|
||||
@@ -164,9 +178,9 @@ void SGPath::concat( const string& p ) {
|
||||
string SGPath::file() const {
|
||||
int index = path.rfind(sgDirPathSep);
|
||||
if (index >= 0) {
|
||||
return path.substr(index + 1);
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,20 +189,45 @@ string SGPath::file() const {
|
||||
string SGPath::dir() const {
|
||||
int index = path.rfind(sgDirPathSep);
|
||||
if (index >= 0) {
|
||||
return path.substr(0, index);
|
||||
return path.substr(0, index);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// get the base part of the path (everything but the extension.)
|
||||
string SGPath::base() const {
|
||||
int index = path.rfind(".");
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(0, index);
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
return "";
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
// find the first dot after the final separator
|
||||
unsigned int firstDot = path.find(".", index);
|
||||
if (firstDot == string::npos) {
|
||||
return path; // no extension, return whole path
|
||||
}
|
||||
|
||||
return path.substr(0, firstDot);
|
||||
}
|
||||
|
||||
string SGPath::file_base() const
|
||||
{
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
unsigned int firstDot = path.find(".", index);
|
||||
if (firstDot == string::npos) {
|
||||
return path.substr(index); // no extensions
|
||||
}
|
||||
|
||||
return path.substr(index, firstDot - index);
|
||||
}
|
||||
|
||||
// get the extension (everything after the final ".")
|
||||
@@ -197,15 +236,36 @@ string SGPath::base() const {
|
||||
string SGPath::extension() const {
|
||||
int index = path.rfind(".");
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(index + 1);
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
string SGPath::lower_extension() const {
|
||||
return boost::to_lower_copy(extension());
|
||||
}
|
||||
|
||||
string SGPath::complete_lower_extension() const
|
||||
{
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
int firstDot = path.find(".", index);
|
||||
if ((firstDot >= 0) && (path.find(sgDirPathSep, firstDot) == string::npos)) {
|
||||
return boost::to_lower_copy(path.substr(firstDot + 1));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void SGPath::validate() const
|
||||
{
|
||||
if (_cached) {
|
||||
if (_cached && _cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,6 +281,7 @@ void SGPath::validate() const
|
||||
_exists = true;
|
||||
_isFile = ((S_IFREG & buf.st_mode ) !=0);
|
||||
_isDir = ((S_IFDIR & buf.st_mode ) !=0);
|
||||
_modTime = buf.st_mtime;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -232,6 +293,7 @@ void SGPath::validate() const
|
||||
_exists = true;
|
||||
_isFile = ((S_ISREG(buf.st_mode )) != 0);
|
||||
_isDir = ((S_ISDIR(buf.st_mode )) != 0);
|
||||
_modTime = buf.st_mtime;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -383,3 +445,29 @@ std::string SGPath::str_native() const
|
||||
return str();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SGPath::remove()
|
||||
{
|
||||
int err = ::unlink(c_str());
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "file remove failed: (" << str() << ") " << strerror(errno));
|
||||
}
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
time_t SGPath::modTime() const
|
||||
{
|
||||
validate();
|
||||
return _modTime;
|
||||
}
|
||||
|
||||
bool SGPath::operator==(const SGPath& other) const
|
||||
{
|
||||
return (path == other.path);
|
||||
}
|
||||
|
||||
bool SGPath::operator!=(const SGPath& other) const
|
||||
{
|
||||
return (path != other.path);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
@@ -49,10 +50,6 @@
|
||||
|
||||
class SGPath {
|
||||
|
||||
private:
|
||||
|
||||
std::string path;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor */
|
||||
@@ -86,6 +83,15 @@ public:
|
||||
void set( const std::string& p );
|
||||
SGPath& operator= ( const char* p ) { this->set(p); return *this; }
|
||||
|
||||
bool operator==(const SGPath& other) const;
|
||||
bool operator!=(const SGPath& other) const;
|
||||
|
||||
/**
|
||||
* Set if file information (exists, type, mod-time) is cached or
|
||||
* retrieved each time it is queried. Caching is enabled by default
|
||||
*/
|
||||
void set_cached(bool cached);
|
||||
|
||||
/**
|
||||
* Append another piece to the existing path. Inserts a path
|
||||
* separator between the existing component and the new component.
|
||||
@@ -123,12 +129,33 @@ public:
|
||||
*/
|
||||
std::string base() const;
|
||||
|
||||
/**
|
||||
* Get the base part of the filename (everything before the first '.')
|
||||
* @return the base filename
|
||||
*/
|
||||
std::string file_base() const;
|
||||
|
||||
/**
|
||||
* Get the extension part of the path (everything after the final ".")
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string extension() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get the extension part of the path (everything after the final ".")
|
||||
* converted to lowercase
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string lower_extension() const;
|
||||
|
||||
/**
|
||||
* Get the complete extension part of the path (everything after the first ".")
|
||||
* this might look like 'tar.gz' or 'txt.Z', or might be identical to 'extension' above
|
||||
* the extension is converted to lowercase.
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string complete_lower_extension() const;
|
||||
|
||||
/**
|
||||
* Get the path string
|
||||
* @return path string
|
||||
@@ -176,16 +203,30 @@ public:
|
||||
* check for default constructed path
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/**
|
||||
* delete the file, if possible
|
||||
*/
|
||||
bool remove();
|
||||
|
||||
/**
|
||||
* modification time of the file
|
||||
*/
|
||||
time_t modTime() const;
|
||||
private:
|
||||
|
||||
void fix();
|
||||
|
||||
void validate() const;
|
||||
|
||||
mutable bool _cached;
|
||||
mutable bool _exists;
|
||||
mutable bool _isDir;
|
||||
mutable bool _isFile;
|
||||
std::string path;
|
||||
|
||||
mutable bool _cached : 1;
|
||||
bool _cacheEnabled : 1; ///< cacheing can be disbled if required
|
||||
mutable bool _exists : 1;
|
||||
mutable bool _isDir : 1;
|
||||
mutable bool _isFile : 1;
|
||||
mutable time_t _modTime;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user