00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <base/PathName>
00026
00027 using base::PathName;
00028 using base::PathComponent;
00029
00030
00031 PathName::PathName()
00032 : relative(true)
00033 {
00034 }
00035
00036 PathName::PathName(const String& name) throw(std::invalid_argument)
00037 {
00038
00039 String remainder = name;
00040
00041 if (remainder==currentDirectory)
00042 remainder="";
00043
00044 if (remainder.size() == 0)
00045 relative = true;
00046 else {
00047 if ((remainder.length() > 1) && remainder[remainder.length()-1] == separator)
00048 remainder = remainder.substr(0,remainder.length()-1);
00049 if (remainder[0] == separator) {
00050 relative = false;
00051 remainder = remainder.substr(1,remainder.length()-1);
00052 }
00053 else
00054 relative = true;
00055
00056 while (remainder.length()>0) {
00057 String::size_type p = remainder.find(separator);
00058 if (p != String::npos) {
00059 String componentString = remainder.substr(0,p);
00060 if (componentString.length()==0) {
00061 String e("path string has an empty component: "); e += name;
00062 throw std::invalid_argument(Exception(e));
00063 }
00064 if (componentString != currentDirectory)
00065 _path.push_back(PathComponent(componentString));
00066 remainder = remainder.substr(p+1,remainder.length()-componentString.length()-1);
00067 }
00068 else {
00069 String componentString = remainder;
00070 if (componentString != currentDirectory)
00071 _path.push_back(PathComponent(componentString));
00072 remainder="";
00073 }
00074 }
00075
00076 }
00077 }
00078
00079
00080 PathName::PathName(const PathName& pn)
00081 : relative(pn.relative), _path(pn._path)
00082 {
00083 }
00084
00085 PathName::~PathName()
00086 {
00087 }
00088
00089
00090 const String PathName::currentDirectory = ".";
00091 const String PathName::parentDirectory = "..";
00092
00093
00094 void PathName::parent()
00095 {
00096 if (!relative && (_path.size()==0))
00097 throw std::runtime_error(Exception("can't find parent directory of an empty relative path [too many '..'s?]"));
00098
00099 if (_path.size()>0)
00100 _path.pop_back();
00101 }
00102
00103 void PathName::canonical()
00104 {
00105 PathName np;
00106 np+=*this;
00107 *this=np;
00108 }
00109
00110
00111 String PathName::str() const
00112 {
00113 String pathName;
00114 if (!relative)
00115 pathName+=separator;
00116
00117 PathComponents::const_iterator pc = _path.begin();
00118 while (pc != _path.end()) {
00119 pathName+=(*pc).name();
00120 ++pc;
00121 if (pc != _path.end())
00122 pathName+=separator;
00123 }
00124 if (pathName.length()==0)
00125 pathName=currentDirectory;
00126
00127 return pathName;
00128 }
00129
00130
00131 PathName PathName::path() const
00132 {
00133 PathName pn(*this);
00134 pn.canonical();
00135 pn._path.pop_back();
00136 return pn;
00137 }
00138
00139 PathName PathName::name() const
00140 {
00141 if (_path.size()!=0)
00142 return PathName(_path.back().name());
00143 else
00144 return relative?PathName(currentDirectory):PathName();
00145 }
00146
00147
00148 String PathName::extension() const
00149 {
00150 String name = PathName::name().str();
00151
00152 String::size_type p = name.find(currentDirectory);
00153 if (p != String::npos)
00154 return name.substr(p+1,name.length()-p-1);
00155 else
00156 return "";
00157 }
00158
00159
00160
00161 bool PathName::operator==(const PathName& pn) const
00162 {
00163 return (relative==pn.relative) && (_path == pn._path);
00164 }
00165
00166 bool PathName::operator!=(const PathName& pn) const
00167 {
00168 return (relative!=pn.relative) || (_path != pn._path);
00169 }
00170
00171 bool PathName::operator==(const String& pn) const
00172 {
00173 return (relative==PathName(pn).isRelative()) && (_path == PathName(pn)._path);
00174 }
00175
00176 bool PathName::operator!=(const String& pn) const
00177 {
00178 return (relative!=PathName(pn).isRelative()) || (_path != PathName(pn)._path);
00179 }
00180
00181
00182 PathName& PathName::operator=(const PathName& pn)
00183 {
00184 relative=pn.relative;
00185 _path=pn._path;
00186 return *this;
00187 }
00188
00189
00190 PathName& PathName::operator+=(const PathName& pn)
00191 {
00192 if (!pn.relative) {
00193 _path.clear();
00194 relative=false;
00195 }
00196
00197 PathComponents::const_iterator pc = pn._path.begin();
00198 while (pc != pn._path.end()) {
00199 if ( (*pc).name() != parentDirectory )
00200 _path.push_back(*pc);
00201 else {
00202 if (_path.size()>0)
00203 _path.pop_back();
00204 else
00205 if (relative)
00206 throw std::runtime_error(Exception("can't find parent directory of an empty relative path [too many '..'s?]"));
00207 }
00208 ++pc;
00209 }
00210
00211 return *this;
00212 }
00213
00214
00215 base::Object& PathName::clone() const
00216 {
00217 return *new PathName(*this);
00218 }