sg_path.cxx

00001 // sg_path.cxx -- routines to abstract out path separator differences
00002 //               between MacOS and the rest of the world
00003 //
00004 // Written by Curtis L. Olson, started April 1999.
00005 //
00006 // Copyright (C) 1999  Curtis L. Olson - http://www.flightgear.org/~curt
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00021 //
00022 // $Id: sg__path_8cxx-source.html,v 1.15 2007-12-17 15:37:10 curt Exp $
00023 
00024 
00025 #include <simgear/compiler.h>
00026 
00027 #include <simgear_config.h>
00028 #include <simgear/debug/logstream.hxx>
00029 #include <stdio.h>
00030 #include <sys/stat.h>
00031 #include <sys/stat.h>
00032 #if defined( _MSC_VER) || defined(__MINGW32__)
00033 #  include <direct.h>
00034 #endif
00035 #include "sg_path.hxx"
00036 
00037 
00042 #if defined( macintosh )
00043 static const char sgDirPathSep = ':';
00044 static const char sgDirPathSepBad = '/';
00045 #else
00046 static const char sgDirPathSep = '/';
00047 static const char sgDirPathSepBad = '\\';
00048 #endif
00049 
00050 #if defined( WIN32 ) && !defined(__CYGWIN__)
00051 static const char sgSearchPathSep = ';';
00052 #else
00053 static const char sgSearchPathSep = ':';
00054 #endif
00055 
00056 
00057 // If Unix, replace all ":" with "/".  If MacOS, replace all "/" with
00058 // ":" it should go without saying that neither of these characters
00059 // should be used in file or directory names.  In windoze, allow the
00060 // second character to be a ":" for things like c:\foo\bar
00061 
00062 void
00063 SGPath::fix()
00064 {
00065     for ( string::size_type i = 0; i < path.size(); ++i ) {
00066 #if defined( WIN32 )
00067         // for windoze, don't replace the ":" for the second character
00068         if ( i == 1 ) {
00069             continue;
00070         }
00071 #endif
00072         if ( path[i] == sgDirPathSepBad ) {
00073             path[i] = sgDirPathSep;
00074         }
00075     }
00076 }
00077 
00078 
00079 // default constructor
00080 SGPath::SGPath()
00081     : path("")
00082 {
00083 }
00084 
00085 
00086 // create a path based on "path"
00087 SGPath::SGPath( const std::string& p )
00088     : path(p)
00089 {
00090     fix();
00091 }
00092 
00093 
00094 // destructor
00095 SGPath::~SGPath() {
00096 }
00097 
00098 
00099 // set path
00100 void SGPath::set( const string& p ) {
00101     path = p;
00102     fix();
00103 }
00104 
00105 
00106 // append another piece to the existing path
00107 void SGPath::append( const string& p ) {
00108     if ( path.size() == 0 ) {
00109         path = p;
00110     } else {
00111         if ( p[0] != sgDirPathSep ) {
00112             path += sgDirPathSep;
00113         }
00114         path += p;
00115     }
00116     fix();
00117 }
00118 
00119 //add a new path component to the existing path string
00120 void SGPath::add( const string& p ) {
00121     append( sgSearchPathSep+p );
00122 }
00123 
00124 
00125 // concatenate a string to the end of the path without inserting a
00126 // path separator
00127 void SGPath::concat( const string& p ) {
00128     if ( path.size() == 0 ) {
00129         path = p;
00130     } else {
00131         path += p;
00132     }
00133     fix();
00134 }
00135 
00136 
00137 // Get the file part of the path (everything after the last path sep)
00138 string SGPath::file() const {
00139     int index = path.rfind(sgDirPathSep);
00140     if (index >= 0) {
00141         return path.substr(index + 1);
00142     } else {
00143         return "";
00144     }
00145 }
00146   
00147 
00148 // get the directory part of the path.
00149 string SGPath::dir() const {
00150     int index = path.rfind(sgDirPathSep);
00151     if (index >= 0) {
00152         return path.substr(0, index);
00153     } else {
00154         return "";
00155     }
00156 }
00157 
00158 // get the base part of the path (everything but the extension.)
00159 string SGPath::base() const {
00160     int index = path.rfind(".");
00161     if ((index >= 0) && (path.find("/", index) == string::npos)) {
00162         return path.substr(0, index);
00163     } else {
00164         return "";
00165     }
00166 }
00167 
00168 // get the extention (everything after the final ".")
00169 // but make sure no "/" follows the "." character (otherwise it
00170 // is has to be a directory name containing a ".").
00171 string SGPath::extension() const {
00172     int index = path.rfind(".");
00173     if ((index >= 0)  && (path.find("/", index) == string::npos)) {
00174         return path.substr(index + 1);
00175     } else {
00176         return "";
00177     }
00178 }
00179 
00180 bool SGPath::exists() const {
00181     FILE* fp = fopen( path.c_str(), "r");
00182     if (fp == 0) {
00183         return false;
00184     }
00185     fclose(fp);
00186     return true;
00187 }
00188 
00189 #if defined( _MSC_VER) || defined(__MINGW32__)
00190 #  define sgMkDir(d,m)       _mkdir(d)
00191 #else
00192 #  define sgMkDir(d,m)       mkdir(d,m)
00193 #endif
00194 
00195 
00196 void SGPath::create_dir( mode_t mode ) {
00197     string_list dirlist = sgPathSplit(dir());
00198     if ( dirlist.empty() )
00199         return;
00200     string path = dirlist[0];
00201     string_list path_elements = sgPathBranchSplit(path);
00202     bool absolute = !path.empty() && path[0] == sgDirPathSep;
00203 
00204     unsigned int i = 1;
00205     SGPath dir = absolute ? string( 1, sgDirPathSep ) : "";
00206     dir.concat( path_elements[0] );
00207 #if defined( _MSC_VER) || defined(__MINGW32__)
00208     if ( dir.str().find(':') != string::npos && path_elements.size() >= 2 ) {
00209         dir.append( path_elements[1] );
00210         i = 2;
00211     }
00212 #endif
00213     struct stat info;
00214     int r;
00215     for(; ( r = stat( dir.c_str(), &info ) ) == 0 && i < path_elements.size(); i++) {
00216         dir.append(path_elements[i]);
00217     }
00218     if ( r == 0 ) {
00219         return; // Directory already exists
00220     }
00221     if ( sgMkDir( dir.c_str(), mode) ) {
00222         SG_LOG( SG_IO, SG_ALERT, "Error creating directory: " + dir.str() );
00223         return;
00224     }
00225     for(;i < path_elements.size(); i++) {
00226         dir.append(path_elements[i]);
00227         if ( sgMkDir( dir.c_str(), mode) ) {
00228             SG_LOG( SG_IO, SG_ALERT, "Error creating directory: " + dir.str() );
00229             break;
00230         }
00231     }
00232 }
00233 
00234 string_list sgPathBranchSplit( const string &dirpath ) {
00235     string_list path_elements;
00236     string element, path = dirpath;
00237     while ( path.size() ) {
00238         size_t p = path.find( sgDirPathSep );
00239         if ( p != string::npos ) {
00240             element = path.substr( 0, p );
00241             path.erase( 0, p + 1 );
00242         } else {
00243             element = path;
00244             path = "";
00245         }
00246         if ( element.size() )
00247             path_elements.push_back( element );
00248     }
00249     return path_elements;
00250 }
00251 
00252 
00253 string_list sgPathSplit( const string &search_path ) {
00254     string tmp = search_path;
00255     string_list result;
00256     result.clear();
00257 
00258     bool done = false;
00259 
00260     while ( !done ) {
00261         int index = tmp.find(sgSearchPathSep);
00262         if (index >= 0) {
00263             result.push_back( tmp.substr(0, index) );
00264             tmp = tmp.substr( index + 1 );
00265         } else {
00266             if ( !tmp.empty() )
00267                 result.push_back( tmp );
00268             done = true;
00269         }
00270     }
00271 
00272     return result;
00273 }

Generated on Mon Dec 17 09:30:55 2007 for SimGear by  doxygen 1.5.1