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

Generated on Thu Jan 12 22:17:45 2006 for ETL by  doxygen 1.4.6