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