X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2Ftrunk%2FETL%2F_stringf.h;h=3d0c020106dfb4bb373051cd9922d1d72b25d81c;hb=ff41dd1b88fdfa95018d056163396dd269997857;hp=dc450fb77bc215eb3274eec174d1bc80d21452fd;hpb=d9aa9c4b742dc15bca38d06dc2f1998d5d705801;p=synfig.git diff --git a/ETL/trunk/ETL/_stringf.h b/ETL/trunk/ETL/_stringf.h index dc450fb..3d0c020 100644 --- a/ETL/trunk/ETL/_stringf.h +++ b/ETL/trunk/ETL/_stringf.h @@ -1,9 +1,10 @@ /* ========================================================================= ** Extended Template and Library -** stringf Prodecure Implementation +** stringf Procedure Implementation ** $Id$ ** ** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** Copyright (c) 2007 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -29,9 +30,14 @@ /* === H E A D E R S ======================================================= */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include #include -#include +#include +#include /* === M A C R O S ========================================================= */ @@ -39,6 +45,14 @@ #define ETL_STRPRINTF_MAX_LENGTH (800) #endif +#ifdef WIN32 +#define POPEN_BINARY_READ_TYPE "rb" +#define POPEN_BINARY_WRITE_TYPE "wb" +#else +#define POPEN_BINARY_READ_TYPE "r" +#define POPEN_BINARY_WRITE_TYPE "w" +#endif + /* === T Y P E D E F S ===================================================== */ _ETL_BEGIN_CDECLS @@ -49,22 +63,33 @@ _ETL_BEGIN_CDECLS #define ETL_NO_THROW throw() #endif -#ifdef HAVE_VASPRINTF // This is the prefered method - extern int vasprintf(char **,const char *,va_list)ETL_NO_THROW; +// Prefer prototypes from glibc headers, since defining them ourselves +// works around glibc security mechanisms + +#ifdef HAVE_VASPRINTF // This is the preferred method + #ifndef __GLIBC__ + extern int vasprintf(char **,const char *,va_list)ETL_NO_THROW; + #endif #else # ifdef HAVE_VSNPRINTF // This is the secondary method - extern int vsnprintf(char *,size_t,const char*,va_list)ETL_NO_THROW; + #ifndef __GLIBC__ + extern int vsnprintf(char *,size_t,const char*,va_list)ETL_NO_THROW; + #endif # endif #endif #ifdef HAVE_VSSCANF -extern int vsscanf(const char *,const char *,va_list)ETL_NO_THROW; + #ifndef __GLIBC__ + extern int vsscanf(const char *,const char *,va_list)ETL_NO_THROW; + #endif #else #define ETL_NO_VSTRSCANF #ifdef HAVE_SSCANF -extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW; + #ifndef __GLIBC__ + extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW; + #endif #endif #endif @@ -79,12 +104,15 @@ _ETL_BEGIN_NAMESPACE inline std::string vstrprintf(const char *format, va_list args) { -#ifdef HAVE_VASPRINTF // This is the prefered method (and safest) +#ifdef HAVE_VASPRINTF // This is the preferred method (and safest) char *buffer; std::string ret; - vasprintf(&buffer,format,args); - ret=buffer; - free(buffer); + int i=vasprintf(&buffer,format,args); + if (i>-1) + { + ret=buffer; + free(buffer); + } return ret; #else #ifdef HAVE_VSNPRINTF // This is the secondary method (Safe, but bulky) @@ -150,21 +178,22 @@ basename(const std::string &str) { std::string::const_iterator iter; - if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR) + if(str.size() == 1 && str[0] == ETL_DIRECTORY_SEPARATOR) + return str; + + if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR) iter=str.end()-2; else iter=str.end()-1; for(;iter!=str.begin();iter--) - if(*iter==ETL_DIRECTORY_SEPERATOR) + if(*iter==ETL_DIRECTORY_SEPARATOR) break; - if(iter==str.begin()) - return str; - - iter++; + if (*iter==ETL_DIRECTORY_SEPARATOR) + iter++; - if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR) + if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR) return std::string(iter,str.end()-1); return std::string(iter,str.end()); @@ -175,21 +204,51 @@ dirname(const std::string &str) { std::string::const_iterator iter; - if(str.end()[-1]==ETL_DIRECTORY_SEPERATOR) + if(str.size() == 1 && str[0] == ETL_DIRECTORY_SEPARATOR) + return str; + + if(str.end()[-1]==ETL_DIRECTORY_SEPARATOR) iter=str.end()-2; else iter=str.end()-1; for(;iter!=str.begin();iter--) - if(*iter==ETL_DIRECTORY_SEPERATOR) + if(*iter==ETL_DIRECTORY_SEPARATOR) break; if(iter==str.begin()) - return "."; + { + if (*iter==ETL_DIRECTORY_SEPARATOR) + return "/"; + else + return "."; + } return std::string(str.begin(),iter); } +// filename_extension("/f.e/d.c") => ".c" +inline std::string +filename_extension(const std::string &str) +{ + std::string base = basename(str); + std::string::size_type pos = base.find_last_of('.'); + if (pos == std::string::npos) return std::string(); + return base.substr(pos); +} + +// filename_sans_extension("/f.e/d.c") => "/f.e/d" +inline std::string +filename_sans_extension(const std::string &str) +{ + std::string base = basename(str); + std::string::size_type pos = base.find_last_of('.'); + if (pos == std::string::npos) return str; + std::string dir = dirname(str); + if (dir == ".") return base.substr(0,pos); + return dir + ETL_DIRECTORY_SEPARATOR + base.substr(0,pos); +} + inline bool is_absolute_path(const std::string &path) { @@ -197,7 +256,7 @@ is_absolute_path(const std::string &path) if(path.size()>=3 && path[1]==':' && (path[2]=='\\' || path[2]=='/')) return true; #endif - if(!path.empty() && path[0]==ETL_DIRECTORY_SEPERATOR) + if(!path.empty() && path[0]==ETL_DIRECTORY_SEPARATOR) return true; return false; } @@ -211,7 +270,7 @@ unix_to_local_path(const std::string &path) switch(*iter) { case '/': - ret+=ETL_DIRECTORY_SEPERATOR; + ret+=ETL_DIRECTORY_SEPARATOR; break; case '~': ret+='~'; @@ -239,12 +298,12 @@ get_root_from_path(std::string path) for(iter=path.begin();iter!=path.end();++iter) { - if(*iter==ETL_DIRECTORY_SEPERATOR) + if(*iter==ETL_DIRECTORY_SEPARATOR) break; ret+=*iter; } //if(iter!=path.end()) - ret+=ETL_DIRECTORY_SEPERATOR; + ret+=ETL_DIRECTORY_SEPARATOR; return ret; } @@ -253,7 +312,7 @@ remove_root_from_path(std::string path) { while(!path.empty()) { - if(path[0]==ETL_DIRECTORY_SEPERATOR) + if(path[0]==ETL_DIRECTORY_SEPARATOR) { path.erase(path.begin()); return path; @@ -268,27 +327,26 @@ cleanup_path(std::string path) { std::string ret; - while(basename(path)==".")path=dirname(path); + while(basename(path)=="."&&path.size()!=1)path=dirname(path); while(!path.empty()) { std::string dir(get_root_from_path(path)); if((dir=="../" || dir=="..\\") && ret.size()) { - ret=dirname(ret)+ETL_DIRECTORY_SEPERATOR; + ret=dirname(ret); + if (*(ret.end()-1)!=ETL_DIRECTORY_SEPARATOR) + ret+=ETL_DIRECTORY_SEPARATOR; } else if((dir!="./" && dir!=".\\") && dir!=".") - { ret+=dir; - } path=remove_root_from_path(path); } + if (ret.size()==0)ret+='.'; - // Remove any trailing directory seperators - if(ret.size() && ret[ret.size()-1]==ETL_DIRECTORY_SEPERATOR) - { + // Remove any trailing directory separators + if(ret.size() && ret[ret.size()-1]==ETL_DIRECTORY_SEPARATOR) ret.erase(ret.begin()+ret.size()-1); - } return ret; } @@ -301,8 +359,7 @@ absolute_path(std::string path) return cleanup_path(ret); if(is_absolute_path(path)) return cleanup_path(path); - // TODO: This needs to be written - return cleanup_path(ret+ETL_DIRECTORY_SEPERATOR+path); + return cleanup_path(ret+ETL_DIRECTORY_SEPARATOR+path); } inline std::string @@ -324,15 +381,11 @@ relative_path(std::string curr_path,std::string dest_path) // If we are on windows and the dest path is on a different drive, // then there is no way to make a relative path to it. if(dest_path.size()>=3 && dest_path[1]==':' && dest_path[0]!=curr_path[0]) - { return dest_path; - } #endif if(curr_path==dirname(dest_path)) - { return basename(dest_path); - } while(!dest_path.empty() && !curr_path.empty() && get_root_from_path(dest_path)==get_root_from_path(curr_path)) { @@ -342,7 +395,7 @@ relative_path(std::string curr_path,std::string dest_path) while(!curr_path.empty()) { - dest_path=std::string("..")+ETL_DIRECTORY_SEPERATOR+dest_path; + dest_path=std::string("..")+ETL_DIRECTORY_SEPARATOR+dest_path; curr_path=remove_root_from_path(curr_path); }