3 This file is part of libmspfs
4 Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #include <msp/strings/utils.h>
17 Returns the number of components in the path.
19 unsigned Path::size() const
23 if(path.size()==1 && path[0]==DIRCHAR)
27 for(string::const_iterator i=path.begin(); i!=path.end(); ++i)
28 if(*i==DIRCHAR) ++count;
32 bool Path::is_absolute() const
35 if(is_windows_drive((*this)[0]))
44 Extracts the given component range from the path.
46 Path Path::subpath(unsigned start, unsigned count) const
50 for(unsigned j=0; (j<start && i!=end()); ++j)
52 for(unsigned j=0; (j<count && i!=end()); ++j)
61 Attaches another path to the end of this one. An absolute path replaces the
62 existing data. ".." elements annihilate the last component and "." elements
65 Path &Path::operator/=(const Path &p)
71 for(Iterator i=p.begin(); i!=p.end(); ++i)
78 Returns the path component at the specified index. Negative indices count from
81 string Path::operator[](int n) const
85 for(Iterator i=begin(); i!=end(); ++i, --n)
90 for(Iterator i=--end();; --i)
100 bool Path::operator==(const Path &p) const
103 return !strcasecmp(path, p.path);
109 void Path::init(const string &p)
112 if(p[0]=='/' || p[0]=='\\')
113 add_component(string(1, DIRCHAR));
116 unsigned slash=p.find_first_of("/\\", start);
118 add_component(p.substr(start, slash-start));
119 if(slash==string::npos)
126 Adds a single component to the path, emulating the cd command.
128 void Path::add_component(const string &comp)
132 else if(comp.size()==1 && comp[0]==DIRCHAR)
134 // Replace the path with the root directory
136 unsigned slash=path.find(DIRCHAR);
137 if(is_windows_drive(path.substr(0, slash)))
138 path=path.substr(0, 2);
144 else if(is_windows_drive(comp))
151 // .. in root directory is a no-op
152 else if(path.size()==1 && path[0]==DIRCHAR)
155 else if(is_windows_drive(path))
160 unsigned slash=path.rfind(DIRCHAR);
161 unsigned start=(slash==string::npos)?0:slash+1;
162 if(!path.compare(start, string::npos, ".."))
164 // If the last component already is a .., add another
169 // Otherwise, erase the last component
170 path.erase(slash, string::npos);
173 else if(comp!="." || path.empty())
177 if(path.size()>1 || (path.size()==1 && path[0]!=DIRCHAR))
183 Path::Iterator::Iterator(const Path &p):
187 if(path.path.empty())
188 start=end=string::npos;
189 else if(path.path[0]==DIRCHAR)
192 else if(path.path.size()>2 && path.path[2]==DIRCHAR && is_windows_drive(path.path.substr(0, 2)))
196 end=path.path.find(DIRCHAR);
199 Path::Iterator &Path::Iterator::operator++()
202 if(start>=path.path.size()) return *this;
203 if(path.path[start]==DIRCHAR) ++start;
204 end=path.path.find(DIRCHAR, start);
208 Path::Iterator &Path::Iterator::operator--()
211 if(end==0) return *this;
212 if(end>1 && end<path.path.size() && path.path[end]!=DIRCHAR) --end;
213 start=path.path.rfind(DIRCHAR, end-1);
214 if(start==string::npos)
221 string Path::Iterator::operator*() const
223 if(start>=path.path.size()) return "";
224 if(start==end) return "";
225 return path.path.substr(start, end-start);