00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef __ETL__STRINGF_H
00028 #define __ETL__STRINGF_H
00029
00030
00031
00032 #include <string>
00033 #include <cstdarg>
00034
00035
00036
00037 #ifndef ETL_STRPRINTF_MAX_LENGTH
00038 #define ETL_STRPRINTF_MAX_LENGTH (800)
00039 #endif
00040
00041
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
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
00106
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
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
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
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
00315
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
00328
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
00358
00359 #endif