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
00028 #ifndef __ETL__STRINGF_H
00029 #define __ETL__STRINGF_H
00030
00031
00032
00033 #ifndef _GNU_SOURCE
00034 #define _GNU_SOURCE
00035 #endif
00036
00037 #include <string>
00038 #include <cstdarg>
00039 #include <cstdlib>
00040 #include <cstdio>
00041
00042
00043
00044 #ifndef ETL_STRPRINTF_MAX_LENGTH
00045 #define ETL_STRPRINTF_MAX_LENGTH (800)
00046 #endif
00047
00048 #ifdef WIN32
00049 #define POPEN_BINARY_READ_TYPE "rb"
00050 #define POPEN_BINARY_WRITE_TYPE "wb"
00051 #else
00052 #define POPEN_BINARY_READ_TYPE "r"
00053 #define POPEN_BINARY_WRITE_TYPE "w"
00054 #endif
00055
00056
00057
00058 _ETL_BEGIN_CDECLS
00059
00060 #if defined(__APPLE__) || defined(__CYGWIN__) || defined(_WIN32)
00061 #define ETL_NO_THROW
00062 #else
00063 #define ETL_NO_THROW throw()
00064 #endif
00065
00066
00067
00068
00069 #ifdef HAVE_VASPRINTF // This is the preferred method
00070 #ifndef __GLIBC__
00071 extern int vasprintf(char **,const char *,va_list)ETL_NO_THROW;
00072 #endif
00073 #else
00074
00075 # ifdef HAVE_VSNPRINTF // This is the secondary method
00076 #ifndef __GLIBC__
00077 extern int vsnprintf(char *,size_t,const char*,va_list)ETL_NO_THROW;
00078 #endif
00079 # endif
00080
00081 #endif
00082
00083 #ifdef HAVE_VSSCANF
00084 #ifndef __GLIBC__
00085 extern int vsscanf(const char *,const char *,va_list)ETL_NO_THROW;
00086 #endif
00087 #else
00088 #define ETL_NO_VSTRSCANF
00089 #ifdef HAVE_SSCANF
00090 #ifndef __GLIBC__
00091 extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW;
00092 #endif
00093 #endif
00094 #endif
00095
00096 #include <unistd.h>
00097
00098 _ETL_END_CDECLS
00099
00100
00101
00102 _ETL_BEGIN_NAMESPACE
00103
00104 inline std::string
00105 vstrprintf(const char *format, va_list args)
00106 {
00107 #ifdef HAVE_VASPRINTF // This is the preferred method (and safest)
00108 char *buffer;
00109 std::string ret;
00110 int i=vasprintf(&buffer,format,args);
00111 if (i>-1)
00112 {
00113 ret=buffer;
00114 free(buffer);
00115 }
00116 return ret;
00117 #else
00118 #ifdef HAVE_VSNPRINTF // This is the secondary method (Safe, but bulky)
00119 #warning etl::vstrprintf() has a maximum size of ETL_STRPRINTF_MAX_LENGTH in this configuration.
00120 #ifdef ETL_THREAD_SAFE
00121 char buffer[ETL_STRPRINTF_MAX_LENGTH];
00122 #else
00123 static char buffer[ETL_STRPRINTF_MAX_LENGTH];
00124 #endif
00125 vsnprintf(buffer,sizeof(buffer),format,args);
00126 return buffer;
00127 #else // This is the worst method (UNSAFE, but "works")
00128 #warning Potential for Buffer-overflow bug using vsprintf
00129 #define ETL_UNSAFE_STRPRINTF (true)
00130
00131
00132 #ifdef ETL_THREAD_SAFE
00133 char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
00134 #else
00135 static char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
00136 #endif
00137 vsprintf(buffer,format,args);
00138 return buffer;
00139 #endif
00140 #endif
00141 }
00142
00143 inline std::string
00144 strprintf(const char *format, ...)
00145 {
00146 va_list args;
00147 va_start(args,format);
00148 return vstrprintf(format,args);
00149 }
00150
00151 #ifndef ETL_NO_VSTRSCANF
00152 inline int
00153 vstrscanf(const std::string &data, const char*format, va_list args)
00154 {
00155 return vsscanf(data.c_str(),format,args);
00156 }
00157
00158 inline int
00159 strscanf(const std::string &data, const char*format, ...)
00160 {
00161 va_list args;
00162 va_start(args,format);
00163 return vstrscanf(data, format,args);
00164 }
00165 #else
00166
00167 #if defined (HAVE_SSCANF) && defined (__GNUC__)
00168 #define strscanf(data,format,...) sscanf(data.c_str(),format,__VA_ARGS__)
00169 #endif
00170 #endif
00171
00172
00173 #define stratof(X) (atof((X).c_str()))
00174 #define stratoi(X) (atoi((X).c_str()))
00175
00176 inline std::string
00177 basename(const std::string &str)
00178 {
00179 std::string::const_iterator iter;
00180
00181 if(str.size() == 1 && str[0] == ETL_DIRECTORY_SEPARATOR)
00182 return str;
00183
00184 if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR)
00185 iter=str.end()-2;
00186 else
00187 iter=str.end()-1;
00188
00189 for(;iter!=str.begin();iter--)
00190 if(*iter==ETL_DIRECTORY_SEPARATOR)
00191 break;
00192
00193 if (*iter==ETL_DIRECTORY_SEPARATOR)
00194 iter++;
00195
00196 if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR)
00197 return std::string(iter,str.end()-1);
00198
00199 return std::string(iter,str.end());
00200 }
00201
00202 inline std::string
00203 dirname(const std::string &str)
00204 {
00205 std::string::const_iterator iter;
00206
00207 if(str.size() == 1 && str[0] == ETL_DIRECTORY_SEPARATOR)
00208 return str;
00209
00210 if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR)
00211 iter=str.end()-2;
00212 else
00213 iter=str.end()-1;
00214
00215 for(;iter!=str.begin();iter--)
00216 if(*iter==ETL_DIRECTORY_SEPARATOR)
00217 break;
00218
00219 if(iter==str.begin())
00220 {
00221 if (*iter==ETL_DIRECTORY_SEPARATOR)
00222 return "/";
00223 else
00224 return ".";
00225 }
00226
00227 return std::string(str.begin(),iter);
00228 }
00229
00230
00231 inline std::string
00232 filename_extension(const std::string &str)
00233 {
00234 std::string base = basename(str);
00235 std::string::size_type pos = base.find_last_of('.');
00236 if (pos == std::string::npos) return std::string();
00237 return base.substr(pos);
00238 }
00239
00240
00241 inline std::string
00242 filename_sans_extension(const std::string &str)
00243 {
00244 std::string base = basename(str);
00245 std::string::size_type pos = base.find_last_of('.');
00246 if (pos == std::string::npos) return str;
00247 std::string dir = dirname(str);
00248 if (dir == ".") return base.substr(0,pos);
00249 return dir + ETL_DIRECTORY_SEPARATOR + base.substr(0,pos);
00250 }
00251
00252 inline bool
00253 is_absolute_path(const std::string &path)
00254 {
00255 #ifdef WIN32
00256 if(path.size()>=3 && path[1]==':' && (path[2]=='\\' || path[2]=='/'))
00257 return true;
00258 #endif
00259 if(!path.empty() && path[0]==ETL_DIRECTORY_SEPARATOR)
00260 return true;
00261 return false;
00262 }
00263
00264 inline std::string
00265 unix_to_local_path(const std::string &path)
00266 {
00267 std::string ret;
00268 std::string::const_iterator iter;
00269 for(iter=path.begin();iter!=path.end();iter++)
00270 switch(*iter)
00271 {
00272 case '/':
00273 ret+=ETL_DIRECTORY_SEPARATOR;
00274 break;
00275 case '~':
00276 ret+='~';
00277 break;
00278 default:
00279 ret+=*iter;
00280 break;
00281 }
00282 return ret;
00283 }
00284
00285 inline std::string
00286 current_working_directory()
00287 {
00288 char dir[256];
00289 std::string ret(getcwd(dir,sizeof(dir)));
00290 return ret;
00291 }
00292
00293 inline std::string
00294 get_root_from_path(std::string path)
00295 {
00296 std::string ret;
00297 std::string::const_iterator iter;
00298
00299 for(iter=path.begin();iter!=path.end();++iter)
00300 {
00301 if(*iter==ETL_DIRECTORY_SEPARATOR)
00302 break;
00303 ret+=*iter;
00304 }
00305
00306 ret+=ETL_DIRECTORY_SEPARATOR;
00307 return ret;
00308 }
00309
00310 inline std::string
00311 remove_root_from_path(std::string path)
00312 {
00313 while(!path.empty())
00314 {
00315 if(path[0]==ETL_DIRECTORY_SEPARATOR)
00316 {
00317 path.erase(path.begin());
00318 return path;
00319 }
00320 path.erase(path.begin());
00321 }
00322 return path;
00323 }
00324
00325 inline std::string
00326 cleanup_path(std::string path)
00327 {
00328 std::string ret;
00329
00330 while(basename(path)=="."&&path.size()!=1)path=dirname(path);
00331
00332 while(!path.empty())
00333 {
00334 std::string dir(get_root_from_path(path));
00335 if((dir=="../" || dir=="..\\") && ret.size())
00336 {
00337 ret=dirname(ret);
00338 if (*(ret.end()-1)!=ETL_DIRECTORY_SEPARATOR)
00339 ret+=ETL_DIRECTORY_SEPARATOR;
00340 }
00341 else if((dir!="./" && dir!=".\\") && dir!=".")
00342 ret+=dir;
00343 path=remove_root_from_path(path);
00344 }
00345 if (ret.size()==0)ret+='.';
00346
00347
00348 if(ret.size() && ret[ret.size()-1]==ETL_DIRECTORY_SEPARATOR)
00349 ret.erase(ret.begin()+ret.size()-1);
00350 return ret;
00351 }
00352
00353 inline std::string
00354 absolute_path(std::string path)
00355 {
00356 std::string ret(current_working_directory());
00357
00358 if(path.empty())
00359 return cleanup_path(ret);
00360 if(is_absolute_path(path))
00361 return cleanup_path(path);
00362 return cleanup_path(ret+ETL_DIRECTORY_SEPARATOR+path);
00363 }
00364
00365 inline std::string
00366 relative_path(std::string curr_path,std::string dest_path)
00367 {
00368
00369
00370 if(!is_absolute_path(dest_path))
00371 dest_path=absolute_path(dest_path);
00372 else
00373 dest_path=cleanup_path(dest_path);
00374
00375 if(!is_absolute_path(curr_path))
00376 curr_path=absolute_path(curr_path);
00377 else
00378 curr_path=cleanup_path(curr_path);
00379
00380 #ifdef WIN32
00381
00382
00383 if(dest_path.size()>=3 && dest_path[1]==':' && dest_path[0]!=curr_path[0])
00384 return dest_path;
00385 #endif
00386
00387 if(curr_path==dirname(dest_path))
00388 return basename(dest_path);
00389
00390 while(!dest_path.empty() && !curr_path.empty() && get_root_from_path(dest_path)==get_root_from_path(curr_path))
00391 {
00392 dest_path=remove_root_from_path(dest_path);
00393 curr_path=remove_root_from_path(curr_path);
00394 }
00395
00396 while(!curr_path.empty())
00397 {
00398 dest_path=std::string("..")+ETL_DIRECTORY_SEPARATOR+dest_path;
00399 curr_path=remove_root_from_path(curr_path);
00400 }
00401
00402 return dest_path;
00403 }
00404
00405 _ETL_END_NAMESPACE
00406
00407
00408
00409 #endif