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 #include <cstdlib>
00035
00036
00037
00038 #ifndef ETL_STRPRINTF_MAX_LENGTH
00039 #define ETL_STRPRINTF_MAX_LENGTH (800)
00040 #endif
00041
00042
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
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
00103
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
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
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
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
00312
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
00325
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
00355
00356 #endif