00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef RAUL_PATH_HPP
00019 #define RAUL_PATH_HPP
00020
00021 #include <iostream>
00022 #include <cctype>
00023 #include <string>
00024 #include <cstring>
00025 #include <cassert>
00026
00027 #include "raul/Symbol.hpp"
00028 #include "raul/URI.hpp"
00029
00030 namespace Raul {
00031
00032
00046 class Path : public URI {
00047 public:
00048 class BadPath : public std::exception {
00049 public:
00050 BadPath(const std::string& path) : _path(path) {}
00051 ~BadPath() throw() {}
00052 const char* what() const throw() { return _path.c_str(); }
00053 private:
00054 std::string _path;
00055 };
00056
00063 static const Path root();
00064
00078 static void set_root(const Raul::URI& uri);
00079
00080 static bool is_path(const Raul::URI& uri);
00081
00083 Path() : URI(root()) {}
00084
00090 Path(const std::basic_string<char>& path);
00091
00097 Path(const char* cpath);
00098
00099
00105 Path(const Path& copy) : URI(copy) {}
00106
00107 static bool is_valid(const std::basic_string<char>& path);
00108
00109 static bool is_valid_name(const std::basic_string<char>& name) {
00110 return name.length() > 0 && name.find("/") == std::string::npos
00111 && is_valid(std::string("/").append(name));
00112 }
00113
00114 static std::string pathify(const std::basic_string<char>& str);
00115 static std::string nameify(const std::basic_string<char>& str);
00116
00117 static void replace_invalid_chars(std::string& str, size_t start, bool replace_slash = false);
00118
00119 bool is_root() const { return (*this) == root(); }
00120
00121 bool is_child_of(const Path& parent) const;
00122 bool is_parent_of(const Path& child) const;
00123
00124 Path child(const std::string& s) const {
00125 if (is_valid(s))
00126 return base() + Path(s).chop_scheme().substr(1);
00127 else
00128 return base() + s;
00129 }
00130
00131 Path child(const Path& p) const {
00132 return base() + p.chop_scheme().substr(1);
00133 }
00134
00135 Path operator+(const Path& p) const { return child(p); }
00136
00142 inline const char* symbol() const {
00143 if ((*this) != root()) {
00144 const char* last_slash = strrchr(c_str(), '/');
00145 if (last_slash) {
00146 return last_slash + 1;
00147 }
00148 }
00149 return "";
00150 }
00151
00157 inline Path parent() const {
00158 if ((*this) == root()) {
00159 return *this;
00160 } else {
00161 const std::string str(this->str());
00162 const size_t first_slash = str.find('/');
00163 const size_t last_slash = str.find_last_of('/');
00164 return (first_slash == last_slash) ? root() : str.substr(0, last_slash);
00165 }
00166 }
00167
00168
00171 inline Path child(const Raul::Symbol& symbol) const {
00172 return base() + symbol.c_str();
00173 }
00174
00175
00178 inline Path relative_to_base(const Path& base) const {
00179 if ((*this) == base) {
00180 return "/";
00181 } else {
00182 assert(length() > base.length());
00183 return substr(base.length() - 1);
00184 }
00185 }
00186
00187
00193 inline const std::string base() const {
00194 std::string ret = str();
00195 if ((*this) == root() && ret[ret.length() - 1] == '/')
00196 return ret;
00197 else
00198 return ret + '/';
00199 }
00200
00206 inline const std::string base_no_scheme() const {
00207 return base().substr(find(":") + 1);
00208 }
00209
00210
00212 static bool descendant_comparator(const Path& parent, const Path& child) {
00213 return ( child == parent || (child.length() > parent.length() &&
00214 (!std::strncmp(parent.c_str(), child.c_str(), parent.length())
00215 && (parent == root() || child.str()[parent.length()] == '/'))) );
00216 }
00217
00218 private:
00219 inline Path(bool unchecked, const URI& uri) : URI(uri) {}
00220 };
00221
00222
00223 }
00224
00225 #endif // RAUL_PATH_HPP