+/* $Id$ */
+
package "msppath"
{
version "0.1";
-/*
+/* $Id$
+
This file is part of libmsppath
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+
#include <msp/strings/utils.h>
#include "path.h"
#include "utils.h"
using namespace std;
namespace Msp {
-namespace Path {
/**
Returns the number of components in the path.
*/
unsigned Path::size() const
{
- if(!path.size()) return 0;
- if(path.size()==1 && path[0]==DIRCHAR) return 1;
+ if(path.empty())
+ return 0;
+ if(path.size()==1 && path[0]==DIRCHAR)
+ return 1;
+
unsigned count=1;
for(string::const_iterator i=path.begin(); i!=path.end(); ++i)
if(*i==DIRCHAR) ++count;
bool Path::is_absolute() const
{
#ifdef WIN32
- if(is_windows_drive((*this)[0])) return true;
+ if(is_windows_drive((*this)[0]))
+ return true;
#endif
- if(path[0]==DIRCHAR) return true;
+ if(path[0]==DIRCHAR)
+ return true;
return false;
}
Path Path::subpath(unsigned start, unsigned count) const
{
Path result;
- iterator i=begin();
+ Iterator i=begin();
for(unsigned j=0; (j<start && i!=end()); ++j)
++i;
for(unsigned j=0; (j<count && i!=end()); ++j)
path=p.path;
else
{
- for(iterator i=p.begin(); i!=p.end(); ++i)
+ for(Iterator i=p.begin(); i!=p.end(); ++i)
add_component(*i);
}
return *this;
{
if(n>=0)
{
- for(iterator i=begin(); i!=end(); ++i,--n)
+ for(Iterator i=begin(); i!=end(); ++i, --n)
if(!n) return *i;
}
else
{
- for(iterator i=--end();; --i)
+ for(Iterator i=--end();; --i)
{
if(!++n) return *i;
if(i==begin()) break;
add_component(string(1, DIRCHAR));
while(1)
{
- unsigned slash=p.find_first_of("/\\",start);
+ unsigned slash=p.find_first_of("/\\", start);
if(slash>start)
- {
add_component(p.substr(start, slash-start));
- }
if(slash==string::npos)
break;
start=slash+1;
#ifdef WIN32
unsigned slash=path.find(DIRCHAR);
if(is_windows_drive(path.substr(0, slash)))
- path=path.substr(0,2);
+ path=path.substr(0, 2);
else
#endif
path=comp;
}
}
-Path::iterator::iterator(const Path &p):
+Path::Iterator::Iterator(const Path &p):
path(p),
start(0)
{
else if(path.path[0]==DIRCHAR)
end=1;
#ifdef WIN32
- else if(path.path.size()>2 && path.path[2]==DIRCHAR && is_windows_drive(path.path.substr(0,2)))
+ else if(path.path.size()>2 && path.path[2]==DIRCHAR && is_windows_drive(path.path.substr(0, 2)))
end=2;
#endif
else
end=path.path.find(DIRCHAR);
}
-Path::iterator &Path::iterator::operator++()
+Path::Iterator &Path::Iterator::operator++()
{
start=end;
if(start>=path.path.size()) return *this;
if(path.path[start]==DIRCHAR) ++start;
- end=path.path.find(DIRCHAR,start);
+ end=path.path.find(DIRCHAR, start);
return *this;
}
-Path::iterator &Path::iterator::operator--()
+Path::Iterator &Path::Iterator::operator--()
{
end=start;
if(end==0) return *this;
if(end>1 && end<path.path.size() && path.path[end]!=DIRCHAR) --end;
- start=path.path.rfind(DIRCHAR,end-1);
+ start=path.path.rfind(DIRCHAR, end-1);
if(start==string::npos)
start=0;
else if(start<end-1)
return *this;
}
-string Path::iterator::operator*() const
+string Path::Iterator::operator*() const
{
if(start>=path.path.size()) return "";
if(start==end) return "";
- return path.path.substr(start,end-start);
+ return path.path.substr(start, end-start);
}
-} // namespace Path
} // namespace Msp
-/*
+/* $Id$
+
This file is part of libmsppath
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+
#ifndef MSP_PATH_PATH_H_
#define MSP_PATH_PATH_H_
#include <string>
namespace Msp {
-namespace Path {
enum
{
class Path
{
public:
- class iterator
+ class Iterator
{
public:
- iterator &operator++();
- iterator &operator--();
+ Iterator &operator++();
+ Iterator &operator--();
std::string operator*() const;
- bool operator==(const iterator &i) const { return (start==i.start && end==i.end); }
- bool operator!=(const iterator &i) const { return !(*this==i); }
+ bool operator==(const Iterator &i) const { return (start==i.start && end==i.end); }
+ bool operator!=(const Iterator &i) const { return !(*this==i); }
private:
const Path &path;
unsigned start,end;
- iterator(const Path &);
+ Iterator(const Path &);
friend class Path;
};
Path &operator/=(const Path &);
std::string operator[](int) const;
bool operator==(const Path &) const;
- iterator begin() const { return iterator(*this); }
- iterator end() const { iterator i(*this); i.start=i.end=std::string::npos; return i; }
+ Iterator begin() const { return Iterator(*this); }
+ Iterator end() const { Iterator i(*this); i.start=i.end=std::string::npos; return i; }
private:
std::string path;
inline std::ostream &operator<<(std::ostream &o, const Path &p) { o<<p.str(); return o; }
-} // namespace Path
} // namespace Msp
#endif
-/*
+/* $Id$
+
This file is part of libmsppath
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+
#include <dirent.h>
-#include <sys/stat.h>
#include <errno.h>
+#include <msp/core/error.h>
#ifndef WIN32
#include <fnmatch.h>
#else
using namespace std;
namespace Msp {
-namespace Path {
/**
Fixes the case of the given path to match files / directories on the
{
bool found=true;
Path result;
- for(Path::iterator i=path.begin(); i!=path.end(); ++i)
+ for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
{
if(!found || *i=="/")
result/=*i;
return result;
}
+void mkdir(const Path &path, int mode)
+{
+ int err;
+#ifdef WIN32
+ // The win32 version of this function doesn't take the mode argument. Go figure.
+ (void)mode;
+ err=::mkdir(path.str().c_str());
+#else
+ err=::mkdir(path.str().c_str(), mode);
+#endif
+
+ if(err==-1)
+ throw SystemError("mkdir failed", errno);
+}
+
/**
-Creates the given directory and any parent directories if needed.
+Creates a directory and any parent directories if needed.
@param path The path to create
@param mode Access mode for new directories
@return 0 on success, -1 on error
*/
-int mkpath(const Path &path, int mode)
+void mkpath(const Path &path, int mode)
{
Path p;
- for(Path::iterator i=path.begin(); i!=path.end(); ++i)
+ for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
{
p/=*i;
#ifdef WIN32
- if(p.size()==1 && is_windows_drive(*i)) continue;
+ if(p.size()==1 && is_windows_drive(*i))
+ continue;
#endif
struct stat st;
- int err=stat(p.str().c_str(),&st);
+ int err=stat(p, st);
if(err==0)
{
if(!S_ISDIR(st.st_mode))
- {
- errno=EEXIST;
- return -1;
- }
+ throw Exception("A component exists and is not a directory");
continue;
}
else if(errno!=ENOENT)
- return -1;
+ throw SystemError("stat failed", errno);
else
- {
-#ifdef WIN32
- // The win32 version of this function doesn't take the mode argument. Go figure.
- (void)mode;
- err=mkdir(p.str().c_str());
-#else
- err=mkdir(p.str().c_str(),mode);
-#endif
- if(err==-1) return -1;
- }
+ mkdir(p, mode);
}
+}
- return 0;
+void rmdir(const Path &path)
+{
+ if(::rmdir(path.str().c_str())==-1)
+ throw SystemError("rmdir failed", errno);
}
-int rmdir(const Path &path, bool recursive)
+void rmdirs(const Path &path)
{
- if(recursive)
+ list<string> files=list_files(path);
+ for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
{
- list<string> files=list_files(path);
- for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
- {
- Path p=path/ *i;
- struct stat st;
- stat(p.str().c_str(),&st);
- int err=0;
- if(S_ISDIR(st.st_mode))
- err=rmdir(p,true);
- else
- err=unlink(p.str().c_str());
- if(err) return err;
- }
+ Path p=path / *i;
+ struct stat st=stat(p.str().c_str());
+ if(S_ISDIR(st.st_mode))
+ rmdirs(p);
+ else
+ unlink(p);
}
- return rmdir(path.str().c_str());
+
+ rmdir(path);
+}
+
+void unlink(const Path &path)
+{
+ if(::unlink(path.str().c_str())==-1)
+ throw SystemError("unlink failed", errno);
}
-/**
-Lists all files in a directory except the implied . and .. entries.
-*/
list<string> list_files(const Path &path)
{
list<string> result;
}
closedir(dir);
}
+
return result;
}
bool exists(const Path &path)
{
- struct stat st;
- return !stat(path.str().c_str(), &st);
+ return access(path.str().c_str(), F_OK)==0;
}
Filename splitext(const string &fn)
Path relative(const Path &path, const Path &base)
{
- Path::iterator i=path.begin();
- Path::iterator j=base.begin();
+ Path::Iterator i=path.begin();
+ Path::Iterator j=base.begin();
for(; (i!=path.end() && j!=base.end() && *i==*j); ++i,++j);
Path result;
return p.substr(slash+1);
}
-} // namespace Path
+int stat(const Path &fn, struct stat &st)
+{
+ return ::stat(fn.str().c_str(), &st);
+}
+
+struct stat stat(const Path &fn)
+{
+ struct stat st;
+ if(stat(fn, st)==-1)
+ throw SystemError("stat failed", errno);
+ return st;
+}
+
+Path getcwd()
+{
+ char buf[1024];
+ return ::getcwd(buf, sizeof(buf));
+}
+
} // namespace Msp
-/*
+/* $Id$
+
This file is part of libmsppath
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+
#ifndef MSP_PATH_UTILS_H_
#define MSP_PATH_UTILS_H_
#include <sys/stat.h>
-#include <unistd.h>
#include <list>
#include <string>
-#include "path.h"
namespace Msp {
-namespace Path {
+
+class Path;
struct Filename
{
std::string ext;
};
-extern Path fix_case(const Path &);
-extern int mkpath(const Path &, int);
-extern int rmdir(const Path &, bool =false);
-extern std::list<std::string> list_files(const Path &);
-extern bool exists(const Path &);
-extern Filename splitext(const std::string &);
-extern int fnmatch(const std::string &, const Path &);
-extern Path relative(const Path &, const Path &);
-extern std::string basename(const std::string &);
+Path fix_case(const Path &path);
+
+/// Creates a directory
+void mkdir(const Path &path, int mode);
+
+/// Creates a directory and any required parent directories
+void mkpath(const Path &path, int mode);
+
+/// Removes a directory
+void rmdir(const Path &path);
+
+/// Removes a directory and anything it contains
+void rmdirs(const Path &path);
+
+/// Removes a file
+void unlink(const Path &path);
-inline int stat(const Path &fn, struct stat &st)
-{ return ::stat(fn.str().c_str(), &st); }
+/// Lists the contents of a directory
+std::list<std::string> list_files(const Path &path);
+
+Filename splitext(const std::string &);
+int fnmatch(const std::string &, const Path &);
+
+/// Makes a path relative to some base path. That is, base/result==path.
+Path relative(const Path &path, const Path &base);
+
+std::string basename(const std::string &);
+
+/// Tests for existence of a file
+bool exists(const Path &path);
+
+/**
+Gets information about a file. Returns 0 on success or -1 on error. This
+version can be used to check for file existence and get information in one
+call.
+*/
+int stat(const Path &fn, struct stat &st);
+
+/**
+Returns information about a file. This version throws an exception if an error
+occurs.
+*/
+struct stat stat(const Path &fn);
-inline Path getcwd()
-{ char buf[1024]; return ::getcwd(buf, sizeof(buf)); }
+Path getcwd();
inline bool is_windows_drive(const std::string &p)
{ return (p.size()==2 && ((p[0]>='A' && p[0]<='Z') || (p[0]>='a' && p[0]<='z')) && p[1]==':'); }
-} // namespace Path
} // namespace Msp
#endif