_stringf.h

Go to the documentation of this file.
00001 /* =========================================================================
00002 ** Extended Template and Library
00003 ** stringf Prodecure Implementation
00004 ** $Id: _stringf.h,v 1.1.1.1 2005/01/04 01:31:48 darco Exp $
00005 **
00006 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
00007 **
00008 ** This package is free software; you can redistribute it and/or
00009 ** modify it under the terms of the GNU General Public License as
00010 ** published by the Free Software Foundation; either version 2 of
00011 ** the License, or (at your option) any later version.
00012 **
00013 ** This package 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 ** General Public License for more details.
00017 **
00018 ** === N O T E S ===========================================================
00019 **
00020 ** This is an internal header file, included by other ETL headers.
00021 ** You should not attempt to use it directly.
00022 **
00023 ** ========================================================================= */
00024 
00025 /* === S T A R T =========================================================== */
00026 
00027 #ifndef __ETL__STRINGF_H
00028 #define __ETL__STRINGF_H
00029 
00030 /* === H E A D E R S ======================================================= */
00031 
00032 #include <string>
00033 #include <cstdarg>
00034 
00035 /* === M A C R O S ========================================================= */
00036 
00037 #ifndef ETL_STRPRINTF_MAX_LENGTH
00038 #define ETL_STRPRINTF_MAX_LENGTH    (800)
00039 #endif
00040 
00041 /* === T Y P E D E F S ===================================================== */
00042 
00043 _ETL_BEGIN_CDECLS
00044 
00045 #if defined(__APPLE__) || defined(__CYGWIN__) || defined(_WIN32)
00046 #define ETL_NO_THROW
00047 #else
00048 #define ETL_NO_THROW throw()
00049 #endif
00050 
00051 #ifdef HAVE_VASPRINTF   // This is the prefered method
00052  extern int vasprintf(char **,const char *,va_list)ETL_NO_THROW;
00053 #else
00054 
00055 # ifdef HAVE_VSNPRINTF  // This is the secondary method
00056  extern int vsnprintf(char *,size_t,const char*,va_list)ETL_NO_THROW;
00057 # endif
00058 
00059 #endif
00060 
00061 #ifdef HAVE_VSSCANF
00062 extern int vsscanf(const char *,const char *,va_list)ETL_NO_THROW;
00063 #else
00064 #define ETL_NO_VSTRSCANF
00065 #ifdef HAVE_SSCANF
00066 extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW;
00067 #endif
00068 #endif
00069 
00070 #include <unistd.h>
00071 
00072 _ETL_END_CDECLS
00073 
00074 /* === C L A S S E S & S T R U C T S ======================================= */
00075 
00076 _ETL_BEGIN_NAMESPACE
00077 
00078 inline std::string
00079 vstrprintf(const char *format, va_list args)
00080 {
00081 #ifdef HAVE_VASPRINTF   // This is the prefered method (and safest)
00082     char *buffer;
00083     std::string ret;
00084     vasprintf(&buffer,format,args);
00085     ret=buffer;
00086     free(buffer);
00087     return ret;
00088 #else
00089 #ifdef HAVE_VSNPRINTF   // This is the secondary method (Safe, but bulky)
00090 #warning etl::vstrprintf() has a maximum size of ETL_STRPRINTF_MAX_LENGTH in this configuration.
00091 #ifdef ETL_THREAD_SAFE
00092     char buffer[ETL_STRPRINTF_MAX_LENGTH];
00093 #else
00094     static char buffer[ETL_STRPRINTF_MAX_LENGTH];
00095 #endif
00096     vsnprintf(buffer,sizeof(buffer),format,args);
00097     return buffer;
00098 #else                   // This is the worst method (UNSAFE, but "works")
00099 #warning Potential for Buffer-overflow bug using vsprintf
00100 #define ETL_UNSAFE_STRPRINTF    (true)
00101 // Here, we are doubling the size of the buffer to make this case
00102 // slightly more safe.
00103 #ifdef ETL_THREAD_SAFE
00104     char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
00105 #else
00106     static char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
00107 #endif
00108     vsprintf(buffer,format,args);
00109     return buffer;
00110 #endif
00111 #endif
00112 }
00113 
00114 inline std::string
00115 strprintf(const char *format, ...)
00116 {
00117     va_list args;
00118     va_start(args,format);
00119     return vstrprintf(format,args);
00120 }
00121 
00122 #ifndef ETL_NO_VSTRSCANF
00123 inline int
00124 vstrscanf(const std::string &data, const char*format, va_list args)
00125 {
00126     return vsscanf(data.c_str(),format,args);
00127 }
00128 
00129 inline int
00130 strscanf(const std::string &data, const char*format, ...)
00131 {
00132     va_list args;
00133     va_start(args,format);
00134     return vstrscanf(data, format,args);
00135 }
00136 #else
00137 
00138 #if defined (HAVE_SSCANF) && defined (__GNUC__)
00139 #define strscanf(data,format,...) sscanf(data.c_str(),format,__VA_ARGS__)
00140 #endif
00141 #endif
00142 
00143 
00144 #define stratof(X) (atof((X).c_str()))
00145 #define stratoi(X) (atoi((X).c_str()))
00146 
00147 inline std::string
00148 basename(const std::string &str)
00149 {
00150     std::string::const_iterator iter;
00151 
00152     if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
00153         iter=str.end()-2;
00154     else
00155         iter=str.end()-1;
00156 
00157     for(;iter!=str.begin();iter--)
00158         if(*iter==ETL_DIRECTORY_SEPERATOR)
00159             break;
00160 
00161     if(iter==str.begin())
00162         return str;
00163 
00164     iter++;
00165 
00166     if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
00167         return std::string(iter,str.end()-1);
00168 
00169     return std::string(iter,str.end());
00170 }
00171 
00172 inline std::string
00173 dirname(const std::string &str)
00174 {
00175     std::string::const_iterator iter;
00176 
00177     if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
00178         iter=str.end()-2;
00179     else
00180         iter=str.end()-1;
00181 
00182     for(;iter!=str.begin();iter--)
00183         if(*iter==ETL_DIRECTORY_SEPERATOR)
00184             break;
00185 
00186     if(iter==str.begin())
00187         return ".";
00188 
00189     return std::string(str.begin(),iter);
00190 }
00191 
00192 inline bool
00193 is_absolute_path(const std::string &path)
00194 {
00195 #ifdef WIN32
00196     if(path.size()>=3 && path[1]==':' && (path[2]=='\\' || path[2]=='/'))
00197         return true;
00198 #endif  
00199     if(!path.empty() && path[0]==ETL_DIRECTORY_SEPERATOR)
00200         return true;
00201     return false;
00202 }
00203 
00204 inline std::string
00205 unix_to_local_path(const std::string &path)
00206 {
00207     std::string ret;
00208     std::string::const_iterator iter;
00209     for(iter=path.begin();iter!=path.end();iter++)
00210         switch(*iter)
00211         {
00212         case '/':
00213             ret+=ETL_DIRECTORY_SEPERATOR;
00214             break;
00215         case '~':
00216             ret+='~';
00217             break;
00218         default:
00219             ret+=*iter;
00220             break;
00221         }
00222     return ret;
00223 }
00224 
00225 inline std::string
00226 current_working_directory()
00227 {
00228     char dir[256];
00229     std::string ret(getcwd(dir,sizeof(dir)));
00230     return ret;
00231 }
00232 
00233 inline std::string
00234 get_root_from_path(std::string path)
00235 {
00236     std::string ret;
00237     std::string::const_iterator iter;
00238     
00239     for(iter=path.begin();iter!=path.end();++iter)
00240     {
00241         if(*iter==ETL_DIRECTORY_SEPERATOR)
00242             break;
00243         ret+=*iter;
00244     }
00245     //if(iter!=path.end())
00246         ret+=ETL_DIRECTORY_SEPERATOR;
00247     return ret;
00248 }
00249 
00250 inline std::string
00251 remove_root_from_path(std::string path)
00252 {
00253     while(!path.empty())
00254     {
00255         if(path[0]==ETL_DIRECTORY_SEPERATOR)
00256         {
00257             path.erase(path.begin());
00258             return path;
00259         }
00260         path.erase(path.begin());
00261     }
00262     return path;
00263 }
00264 
00265 inline std::string
00266 cleanup_path(std::string path)
00267 {
00268     std::string ret;
00269 
00270     while(basename(path)==".")path=dirname(path);
00271     
00272     while(!path.empty())
00273     {
00274         std::string dir(get_root_from_path(path));
00275         if((dir=="../" || dir=="..\\") && ret.size())
00276         {
00277             ret=dirname(ret)+ETL_DIRECTORY_SEPERATOR;
00278         }
00279         else if((dir!="./" && dir!=".\\") && dir!=".")
00280         {
00281             ret+=dir;
00282         }
00283         path=remove_root_from_path(path);
00284     }
00285     
00286     // Remove any trailing directory seperators
00287     if(ret.size() && ret[ret.size()-1]==ETL_DIRECTORY_SEPERATOR)
00288     {
00289         ret.erase(ret.begin()+ret.size()-1);
00290     }
00291     return ret;
00292 }
00293 
00294 inline std::string
00295 absolute_path(std::string path)
00296 {
00297     std::string ret(current_working_directory());
00298     
00299     if(path.empty())
00300         return cleanup_path(ret);
00301     if(is_absolute_path(path))
00302         return cleanup_path(path);
00303     // TODO: This needs to be written
00304     return cleanup_path(ret+ETL_DIRECTORY_SEPERATOR+path);
00305 }
00306 
00307 inline std::string
00308 relative_path(std::string curr_path,std::string dest_path)
00309 {   
00310     // If dest_path is already a relative path,
00311     // then there is no need to do anything.
00312     if(!is_absolute_path(dest_path))
00313         dest_path=absolute_path(dest_path);
00314     else
00315         dest_path=cleanup_path(dest_path);
00316     
00317     if(!is_absolute_path(curr_path))
00318         curr_path=absolute_path(curr_path);
00319     else
00320         curr_path=cleanup_path(curr_path);
00321 
00322 #ifdef WIN32
00323     // If we are on windows and the dest path is on a different drive,
00324     // then there is no way to make a relative path to it.
00325     if(dest_path.size()>=3 && dest_path[1]==':' && dest_path[0]!=curr_path[0])
00326     {
00327         return dest_path;
00328     }
00329 #endif
00330 
00331     if(curr_path==dirname(dest_path))
00332     {
00333         return basename(dest_path);
00334     }
00335     
00336     while(!dest_path.empty() && !curr_path.empty() && get_root_from_path(dest_path)==get_root_from_path(curr_path))
00337     {
00338         dest_path=remove_root_from_path(dest_path);
00339         curr_path=remove_root_from_path(curr_path);
00340     }
00341 
00342     while(!curr_path.empty())
00343     {
00344         dest_path=std::string("..")+ETL_DIRECTORY_SEPERATOR+dest_path;
00345         curr_path=remove_root_from_path(curr_path);
00346     }
00347     
00348     return dest_path;
00349 }
00350 
00351 _ETL_END_NAMESPACE
00352 
00353 /* === E N D =============================================================== */
00354 
00355 #endif

Generated on Fri Nov 3 21:07:28 2006 for ETL by  doxygen 1.4.7