+/**
+Adds a single component to the path, emulating the cd command. Fails horribly
+if comp contains a separator character.
+*/
+void Path::add_component(const string &comp)
+{
+ if(comp.empty())
+ ;
+ else if(comp.size()==1 && comp[0]==DIRSEP)
+ {
+ // Replace the path with the root directory
+#ifdef WIN32
+ unsigned slash=path.find(DIRSEP);
+ if(is_windows_drive(path.substr(0, slash)))
+ path=path.substr(0, 2);
+ else
+#endif
+ path=comp;
+ }
+#ifdef WIN32
+ else if(is_windows_drive(comp))
+ path=comp;
+#endif
+ else if(comp=="..")
+ {
+ if(path.empty() || path==".")
+ path=comp;
+ // .. in root directory is a no-op
+ else if(path.size()==1 && path[0]==DIRSEP)
+ ;
+#ifdef WIN32
+ else if(is_windows_drive(path))
+ ;
+#endif
+ else
+ {
+ string::size_type slash=path.rfind(DIRSEP);
+ string::size_type start=(slash==string::npos ? 0 : slash+1);
+ if(!path.compare(start, string::npos, ".."))
+ {
+ // If the last component already is a .., add another
+ path+=DIRSEP;
+ path+=comp;
+ }
+ else if(slash==string::npos)
+ path=".";
+ else
+ {
+ if(slash==0)
+ slash=1;
+ // Otherwise, erase the last component
+ path.erase(slash, string::npos);
+ }
+ }
+ }
+ else if(comp!="." || path.empty())
+ {
+ if(comp!="." && path.empty())
+ path=".";
+ if(path.size()>1 || (path.size()==1 && path[0]!=DIRSEP))
+ path+=DIRSEP;
+ path+=comp;
+ }
+}
+
+
+Path::Iterator::Iterator(const Path &p):