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
00047 class Path : public URI {
00048 public:
00049 class BadPath : public std::exception {
00050 public:
00051 BadPath(const std::string& path) : _path(path) {}
00052 ~BadPath() throw() {}
00053 const char* what() const throw() { return _path.c_str(); }
00054 private:
00055 std::string _path;
00056 };
00057
00058 static const std::string scheme;
00059 static const std::string prefix;
00060 static const size_t prefix_len;
00061 static const std::string root_uri;
00062
00064 Path() : URI(root_uri) {}
00065
00071 Path(const std::basic_string<char>& path)
00072 : URI((path.find(":") == std::string::npos) ? prefix + path : path)
00073 {
00074 if (!is_valid(str()))
00075 throw BadPath(str());
00076 }
00077
00083 Path(const char* cpath)
00084 : URI((std::string(cpath).find(":") == std::string::npos) ? prefix + cpath : cpath)
00085 {
00086 if (!is_valid(str()))
00087 throw BadPath(str());
00088 }
00089
00090 static bool is_valid(const std::basic_string<char>& path);
00091
00092 static bool is_valid_name(const std::basic_string<char>& name) {
00093 return name.length() > 0 && name.find("/") == std::string::npos
00094 && is_valid(std::string("/").append(name));
00095 }
00096
00097 static std::string pathify(const std::basic_string<char>& str);
00098 static std::string nameify(const std::basic_string<char>& str);
00099
00100 static void replace_invalid_chars(std::string& str, size_t start, bool replace_slash = false);
00101
00102 bool is_root() const { return str() == root_uri; }
00103
00104 bool is_child_of(const Path& parent) const;
00105 bool is_parent_of(const Path& child) const;
00106
00107 Path child(const std::string& s) const {
00108 if (is_valid(s))
00109 return std::string(base()) + Path(s).chop_scheme().substr(1);
00110 else
00111 return std::string(base()) + s;
00112 }
00113
00114 Path operator+(const Path& p) const { return child(p); }
00115
00120 inline std::string name() const {
00121 if (str() == root_uri)
00122 return "";
00123 else
00124 return substr(find_last_of("/")+1);
00125 }
00126
00127
00132 inline Symbol symbol() const {
00133 return substr(find_last_of("/")+1);
00134 }
00135
00136
00142 inline Path parent() const {
00143 if (str() == root_uri) {
00144 return str();
00145 } else {
00146 size_t last_slash = find_last_of("/");
00147 return (last_slash == prefix_len) ? root_uri : substr(0, last_slash);
00148 }
00149 }
00150
00151
00154 inline Path relative_to_base(const Path& base) const {
00155 if (str() == base) {
00156 return "/";
00157 } else {
00158 assert(length() > base.length());
00159 return substr(base.length() - 1);
00160 }
00161 }
00162
00163
00169 inline const std::string base() const {
00170 if (str() == root_uri)
00171 return str();
00172 else
00173 return str() + "/";
00174 }
00175
00176
00178 static bool descendant_comparator(const Path& parent, const Path& child) {
00179 return ( child == parent || (child.length() > parent.length() &&
00180 (!std::strncmp(parent.c_str(), child.c_str(), parent.length())
00181 && (parent.str() == root_uri || child[parent.length()] == '/'))) );
00182 }
00183 };
00184
00185
00186 }
00187
00188 #endif // RAUL_PATH_HPP