1 /* =========================================================================
2 ** Extended Template and Library
3 ** stringf Prodecure Implementation
4 ** $Id: _stringf.h,v 1.1.1.1 2005/01/04 01:31:48 darco Exp $
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** General Public License for more details.
18 ** === N O T E S ===========================================================
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
23 ** ========================================================================= */
25 /* === S T A R T =========================================================== */
27 #ifndef __ETL__STRINGF_H
28 #define __ETL__STRINGF_H
30 /* === H E A D E R S ======================================================= */
35 /* === M A C R O S ========================================================= */
37 #ifndef ETL_STRPRINTF_MAX_LENGTH
38 #define ETL_STRPRINTF_MAX_LENGTH (800)
41 /* === T Y P E D E F S ===================================================== */
45 #if defined(__APPLE__) || defined(__CYGWIN__) || defined(_WIN32)
48 #define ETL_NO_THROW throw()
51 #ifdef HAVE_VASPRINTF // This is the prefered method
52 extern int vasprintf(char **,const char *,va_list)ETL_NO_THROW;
55 # ifdef HAVE_VSNPRINTF // This is the secondary method
56 # if defined(__CYGWIN__) || defined(_WIN32)
57 extern int vsnprintf(char *,unsigned int,const char*,va_list)ETL_NO_THROW;
59 extern int vsnprintf(char *,int,const char*,va_list)ETL_NO_THROW;
66 extern int vsscanf(const char *,const char *,va_list)ETL_NO_THROW;
68 #define ETL_NO_VSTRSCANF
70 extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW;
78 /* === C L A S S E S & S T R U C T S ======================================= */
83 vstrprintf(const char *format, va_list args)
85 #ifdef HAVE_VASPRINTF // This is the prefered method (and safest)
88 vasprintf(&buffer,format,args);
93 #ifdef HAVE_VSNPRINTF // This is the secondary method (Safe, but bulky)
94 #warning etl::vstrprintf() has a maximum size of ETL_STRPRINTF_MAX_LENGTH in this configuration.
95 #ifdef ETL_THREAD_SAFE
96 char buffer[ETL_STRPRINTF_MAX_LENGTH];
98 static char buffer[ETL_STRPRINTF_MAX_LENGTH];
100 vsnprintf(buffer,sizeof(buffer),format,args);
102 #else // This is the worst method (UNSAFE, but "works")
103 #warning Potential for Buffer-overflow bug using vsprintf
104 #define ETL_UNSAFE_STRPRINTF (true)
105 // Here, we are doubling the size of the buffer to make this case
106 // slightly more safe.
107 #ifdef ETL_THREAD_SAFE
108 char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
110 static char buffer[ETL_STRPRINTF_MAX_LENGTH*2];
112 vsprintf(buffer,format,args);
119 strprintf(const char *format, ...)
122 va_start(args,format);
123 return vstrprintf(format,args);
126 #ifndef ETL_NO_VSTRSCANF
128 vstrscanf(const std::string &data, const char*format, va_list args)
130 return vsscanf(data.c_str(),format,args);
134 strscanf(const std::string &data, const char*format, ...)
137 va_start(args,format);
138 return vstrscanf(data, format,args);
142 #if defined (HAVE_SSCANF) && defined (__GNUC__)
143 #define strscanf(data,format,...) sscanf(data.c_str(),format,__VA_ARGS__)
148 #define stratof(X) (atof((X).c_str()))
149 #define stratoi(X) (atoi((X).c_str()))
152 basename(const std::string &str)
154 std::string::const_iterator iter;
156 if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
161 for(;iter!=str.begin();iter--)
162 if(*iter==ETL_DIRECTORY_SEPERATOR)
165 if(iter==str.begin())
170 if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
171 return std::string(iter,str.end()-1);
173 return std::string(iter,str.end());
177 dirname(const std::string &str)
179 std::string::const_iterator iter;
181 if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR)
186 for(;iter!=str.begin();iter--)
187 if(*iter==ETL_DIRECTORY_SEPERATOR)
190 if(iter==str.begin())
193 return std::string(str.begin(),iter);
197 is_absolute_path(const std::string &path)
200 if(path.size()>=3 && path[1]==':' && (path[2]=='\\' || path[2]=='/'))
204 if(!path.empty() && path[0]==ETL_DIRECTORY_SEPERATOR)
211 unix_to_local_path(const std::string &path)
214 std::string::const_iterator iter;
215 for(iter=path.begin();iter!=path.end();iter++)
219 ret+=ETL_DIRECTORY_SEPERATOR;
232 current_working_directory()
235 std::string ret(getcwd(dir,sizeof(dir)));
240 get_root_from_path(std::string path)
243 std::string::const_iterator iter;
245 for(iter=path.begin();iter!=path.end();++iter)
247 if(*iter==ETL_DIRECTORY_SEPERATOR)
251 //if(iter!=path.end())
252 ret+=ETL_DIRECTORY_SEPERATOR;
257 remove_root_from_path(std::string path)
261 if(path[0]==ETL_DIRECTORY_SEPERATOR)
263 path.erase(path.begin());
266 path.erase(path.begin());
272 cleanup_path(std::string path)
276 while(basename(path)==".")path=dirname(path);
280 std::string dir(get_root_from_path(path));
281 if(dir=="../" && ret.size())
283 ret=dirname(ret)+ETL_DIRECTORY_SEPERATOR;
285 else if(dir!="./" && dir!=".")
289 path=remove_root_from_path(path);
292 // Remove any trailing directory seperators
293 if(ret.size() && ret[ret.size()-1]==ETL_DIRECTORY_SEPERATOR)
295 ret.erase(ret.begin()+ret.size()-1);
301 absolute_path(std::string path)
303 std::string ret(current_working_directory());
306 return cleanup_path(ret);
307 if(is_absolute_path(path))
308 return cleanup_path(path);
309 // TODO: This needs to be written
310 return cleanup_path(ret+ETL_DIRECTORY_SEPERATOR+path);
314 relative_path(std::string curr_path,std::string dest_path)
316 // If dest_path is already a relative path,
317 // then there is no need to do anything.
318 if(!is_absolute_path(dest_path))
319 dest_path=absolute_path(dest_path);
321 dest_path=cleanup_path(dest_path);
323 if(!is_absolute_path(curr_path))
324 curr_path=absolute_path(curr_path);
326 curr_path=cleanup_path(curr_path);
329 // If we are on windows and the dest path is on a different drive,
330 // then there is no way to make a relative path to it.
331 if(dest_path.size()>=3 && dest_path[1]==':' && dest_path[0]!=curr_path[0])
337 if(curr_path==dirname(dest_path))
339 return basename(dest_path);
342 while(!dest_path.empty() && !curr_path.empty() && get_root_from_path(dest_path)==get_root_from_path(curr_path))
344 dest_path=remove_root_from_path(dest_path);
345 curr_path=remove_root_from_path(curr_path);
348 while(!curr_path.empty())
350 dest_path="../"+dest_path;
351 curr_path=remove_root_from_path(curr_path);
359 /* === E N D =============================================================== */