/* === H E A D E R S ======================================================= */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <string>
#include <cstdarg>
#include <cstdlib>
+#include <cstdio>
/* === M A C R O S ========================================================= */
#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
+
+#ifdef __ETL_HAS__VSNPRINTF
+#ifndef __ETL_HAS_VSNPRINTF
+#define vnsprintf _vnsprintf
+#define __ETL_HAS_VSNPRINTF
+#endif
+#endif
+
/* === T Y P E D E F S ===================================================== */
_ETL_BEGIN_CDECLS
#define ETL_NO_THROW throw()
#endif
-#ifdef HAVE_VASPRINTF // This is the preferred 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 __ETL_HAS_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;
+# ifdef __ETL_HAS_VSNPRINTF // This is the secondary method
+ #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;
+#ifdef __ETL_HAS_VSSCANF
+ #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;
+#ifdef __ETL_HAS_SSCANF
+ #ifndef __GLIBC__
+ extern int sscanf(const char *buf, const char *format, ...)ETL_NO_THROW;
+ #endif
#endif
#endif
inline std::string
vstrprintf(const char *format, va_list args)
{
-#ifdef HAVE_VASPRINTF // This is the preferred method (and safest)
+#ifdef __ETL_HAS_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)
+#ifdef __ETL_HAS_VSNPRINTF // This is the secondary method (Safe, but bulky)
#warning etl::vstrprintf() has a maximum size of ETL_STRPRINTF_MAX_LENGTH in this configuration.
#ifdef ETL_THREAD_SAFE
char buffer[ETL_STRPRINTF_MAX_LENGTH];
}
#else
-#if defined (HAVE_SSCANF) && defined (__GNUC__)
+#if defined (__ETL_HAS_SSCANF) && defined (__GNUC__)
#define strscanf(data,format,...) sscanf(data.c_str(),format,__VA_ARGS__)
#endif
#endif
break;
if(iter==str.begin())
+ {
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)
{