Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/PathName.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: PathName.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.3 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
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   // parse path name
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) { // if second path is absolute, wipe out this
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 }

Generated on Thu Jul 29 15:56:09 2004 for OpenSim by doxygen 1.3.6