#ifndef GFLAGS_UTIL_H_
#define GFLAGS_UTIL_H_
#include "config.h"
#include <assert.h>
#include <config.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <errno.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
namespace GFLAGS_NAMESPACE {
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
#if defined(strtoll) || defined(HAVE_STRTOLL)
# define strto64 strtoll
# define strtou64 strtoull
#elif defined(HAVE_STRTOQ)
# define strto64 strtoq
# define strtou64 strtouq
#else
# define strto64 strtol
# define strtou64 strtoul
#endif
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
typedef signed char int8;
typedef unsigned char uint8;
template <bool b> struct CompileAssert;
template <> struct CompileAssert<true> {};
#define COMPILE_ASSERT(expr, msg) \
enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
#define LOG(level) std::cerr
#define VLOG(level) if (true) {} else std::cerr
#define DVLOG(level) if (true) {} else std::cerr
#define EXPECT_TRUE(condition) \
if (true) { \
if (!(condition)) { \
fprintf(stderr, "Check failed: %s\n", #condition); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_OP(op, val1, val2) \
if (true) { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#ifdef isnan
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_NAN(arg)
#endif
#ifdef isinf
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_INF(arg)
#endif
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define TEST_INIT \
static std::vector<void (*)()> g_testlist; \
static int RUN_ALL_TESTS() { \
std::vector<void (*)()>::const_iterator it; \
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
(*it)(); \
} \
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
static_cast<int>(g_testlist.size())); \
return 0; \
}
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { \
FlagSaver fs; \
fprintf(stderr, "Running test %s/%s\n", #a, #b); \
RunTest(); \
} \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
namespace testing {
class Test {};
}
#define EXPECT_DEATH_INIT \
static bool g_called_exit; \
static void CalledExit(int) { g_called_exit = true; }
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
gflags_exitfunc = &CalledExit; \
fn; \
gflags_exitfunc = &exit; \
if (!g_called_exit) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
#define GTEST_HAS_DEATH_TEST 1
#if defined(__MINGW32__)
#include <io.h>
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
path->append("/gflags_unittest_testdir");
int err = mkdir(path->c_str());
if (err == 0 || errno == EEXIST) return;
}
*path = "./gflags_unittest";
mkdir(path->c_str());
}
#elif defined(_MSC_VER)
#include <direct.h>
#include <windows.h>
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
int err = _mkdir(path->c_str());
if (err == 0 || errno == EEXIST) return;
}
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); *path = std::string(tmppath_buffer) + "gflags_unittest";
_mkdir(path->c_str());
}
#else
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
int err = mkdir(path->c_str(), 0755);
if (err == 0 || errno == EEXIST) return;
}
mkdir("/tmp/gflags_unittest", 0755);
}
#endif
inline void InternalStringPrintf(std::string* output, const char* format,
va_list ap) {
char space[128];
va_list backup_ap;
va_copy(backup_ap, ap);
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
output->append(space, bytes_written);
return;
}
int length = sizeof(space);
while (true) {
if (bytes_written < 0) {
length *= 2;
} else {
length = bytes_written+1;
}
char* buf = new char[length];
va_copy(backup_ap, ap);
bytes_written = vsnprintf(buf, length, format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (bytes_written < length)) {
output->append(buf, bytes_written);
delete[] buf;
return;
}
delete[] buf;
}
}
inline void SStringPrintf(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
output->clear();
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline void StringAppendF(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline std::string StringPrintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
std::string output;
InternalStringPrintf(&output, format, ap);
va_end(ap);
return output;
}
inline bool SafeGetEnv(const char *varname, std::string &valstr)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
char *val;
size_t sz;
if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
valstr = val;
free(val);
#else
const char * const val = getenv(varname);
if (!val) return false;
valstr = val;
#endif
return true;
}
inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
return fopen_s(fp, fname, mode);
#else
assert(fp != NULL);
*fp = fopen(fname, mode);
return ((*fp == NULL) ? errno : 0);
#endif
}
}
#endif