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