_stringf.h

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

Generated on Fri Jun 22 14:33:39 2007 for ETL by  doxygen 1.5.2