_stringf.h

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

Generated on Sun Oct 28 01:59:33 2007 for ETL by  doxygen 1.5.3-20071008