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
00104 Path(const Path& copy) : URI(copy) {}
00105
00106 static bool is_valid(const std::basic_string<char>& path);
00107
00108 static bool is_valid_name(const std::basic_string<char>& name) {
00109 return name.length() > 0 && name.find("/") == std::string::npos
00110 && is_valid(std::string("/").append(name));
00111 }
00112
00113 static std::string pathify(const std::basic_string<char>& str);
00114 static std::string nameify(const std::basic_string<char>& str);
00115
00116 static void replace_invalid_chars(std::string& str, size_t start, bool replace_slash = false);
00117
00118 bool is_root() const { return (*this) == root(); }
00119
00120 bool is_child_of(const Path& parent) const;
00121 bool is_parent_of(const Path& child) const;
00122
00123 Path child(const std::string& s) const {
00124 if (is_valid(s))
00125 return base() + Path(s).chop_scheme().substr(1);
00126 else
00127 return base() + s;
00128 }
00129
00130 Path child(const Path& p) const {
00131 return base() + p.chop_scheme().substr(1);
00132 }
00133
00134 Path operator+(const Path& p) const { return child(p); }
00135
00141 inline const char* symbol() const {
00142 if ((*this) != root()) {
00143 const char* last_slash = strrchr(c_str(), '/');
00144 if (last_slash) {
00145 return last_slash + 1;
00146 }
00147 }
00148 return "";
00149 }
00150
00156 inline Path parent() const {
00157 if ((*this) == root()) {
00158 return *this;
00159 } else {
00160 const std::string str(this->str());
00161 const size_t first_slash = str.find('/');
00162 const size_t last_slash = str.find_last_of('/');
00163 return (first_slash == last_slash) ? root() : str.substr(0, last_slash);
00164 }
00165 }
00166
00167
00170 inline Path child(const Raul::Symbol& symbol) const {
00171 return base() + symbol.c_str();
00172 }
00173
00174
00177 inline Path relative_to_base(const Path& base) const {
00178 if ((*this) == base) {
00179 return "/";
00180 } else {
00181 assert(length() > base.length());
00182 return substr(base.length() - 1);
00183 }
00184 }
00185
00186
00192 inline const std::string base() const {
00193 std::string ret = str();
00194 if ((*this) == root() && ret[ret.length() - 1] == '/')
00195 return ret;
00196 else
00197 return ret + '/';
00198 }
00199
00205 inline const std::string base_no_scheme() const {
00206 return base().substr(find(":") + 1);
00207 }
00208
00209
00211 static bool descendant_comparator(const Path& parent, const Path& child) {
00212 return ( child == parent || (child.length() > parent.length() &&
00213 (!std::strncmp(parent.c_str(), child.c_str(), parent.length())
00214 && (parent == root() || child.str()[parent.length()] == '/'))) );
00215 }
00216
00217 private:
00218 inline Path(bool unchecked, const URI& uri) : URI(uri) {}
00219 };
00220
00221
00222 }
00223
00224 #endif // RAUL_PATH_HPP