1 // Copyright (c) 2011, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Some generically useful utility routines that in google-land would
32 // be their own projects. We make a shortened version here.
34 #ifndef GFLAGS_UTIL_H_
35 #define GFLAGS_UTIL_H_
40 #ifdef HAVE_INTTYPES_H
41 # include <inttypes.h>
43 #include <stdarg.h> // for va_*
49 #ifdef HAVE_SYS_STAT_H
50 # include <sys/stat.h> // for mkdir
54 namespace GFLAGS_NAMESPACE {
57 // This is used for unittests for death-testing. It is defined in gflags.cc.
58 extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
60 // Work properly if either strtoll or strtoq is on this system.
61 #if defined(strtoll) || defined(HAVE_STRTOLL)
62 # define strto64 strtoll
63 # define strtou64 strtoull
64 #elif defined(HAVE_STRTOQ)
65 # define strto64 strtoq
66 # define strtou64 strtouq
67 // Neither strtoll nor strtoq are defined. I hope strtol works!
69 # define strto64 strtol
70 # define strtou64 strtoul
73 // If we have inttypes.h, it will have defined PRId32/etc for us.
74 // If not, take our best guess.
85 typedef signed char int8;
86 typedef unsigned char uint8;
88 // -- utility macros ---------------------------------------------------------
90 template <bool b> struct CompileAssert;
91 template <> struct CompileAssert<true> {};
92 #define COMPILE_ASSERT(expr, msg) \
93 enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
95 // Returns the number of elements in an array.
96 #define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
99 // -- logging and testing ---------------------------------------------------
101 // For now, we ignore the level for logging, and don't show *VLOG's at
102 // all, except by hand-editing the lines below
103 #define LOG(level) std::cerr
104 #define VLOG(level) if (true) {} else std::cerr
105 #define DVLOG(level) if (true) {} else std::cerr
107 // CHECK dies with a fatal error if condition is not true. It is *not*
108 // controlled by NDEBUG, so the check will be executed regardless of
109 // compilation mode. Therefore, it is safe to do things like:
110 // CHECK(fp->Write(x) == 4)
111 // We allow stream-like objects after this for debugging, but they're ignored.
112 #define EXPECT_TRUE(condition) \
114 if (!(condition)) { \
115 fprintf(stderr, "Check failed: %s\n", #condition); \
118 } else std::cerr << ""
120 #define EXPECT_OP(op, val1, val2) \
122 if (!((val1) op (val2))) { \
123 fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
126 } else std::cerr << ""
128 #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
129 #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
130 #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
131 #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
132 #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
133 #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
134 #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
136 // C99 declares isnan and isinf should be macros, so the #ifdef test
137 // should be reliable everywhere. Of course, it's not, but these
138 // are testing pertty marginal functionality anyway, so it's ok to
139 // not-run them even in situations they might, with effort, be made to work.
140 #ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
141 #define EXPECT_NAN(arg) \
144 fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
149 #define EXPECT_NAN(arg)
152 #ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
153 #define EXPECT_INF(arg) \
156 fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
161 #define EXPECT_INF(arg)
164 #define EXPECT_DOUBLE_EQ(val1, val2) \
166 if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
167 fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
172 #define EXPECT_STREQ(val1, val2) \
174 if (strcmp((val1), (val2)) != 0) { \
175 fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
180 // Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
182 static std::vector<void (*)()> g_testlist; /* the tests to run */ \
183 static int RUN_ALL_TESTS() { \
184 std::vector<void (*)()>::const_iterator it; \
185 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
186 (*it)(); /* The test will error-exit if there's a problem. */ \
188 fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
189 static_cast<int>(g_testlist.size())); \
193 // Note that this macro uses a FlagSaver to keep tests isolated.
195 struct Test_##a##_##b { \
196 Test_##a##_##b() { g_testlist.push_back(&Run); } \
197 static void Run() { \
199 fprintf(stderr, "Running test %s/%s\n", #a, #b); \
202 static void RunTest(); \
204 static Test_##a##_##b g_test_##a##_##b; \
205 void Test_##a##_##b::RunTest()
207 // This is a dummy class that eases the google->opensource transition.
212 // Call this in a .cc file where you will later call EXPECT_DEATH
213 #define EXPECT_DEATH_INIT \
214 static bool g_called_exit; \
215 static void CalledExit(int) { g_called_exit = true; }
217 #define EXPECT_DEATH(fn, msg) \
219 g_called_exit = false; \
220 gflags_exitfunc = &CalledExit; \
222 gflags_exitfunc = &exit; /* set back to its default */ \
223 if (!g_called_exit) { \
224 fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
229 #define GTEST_HAS_DEATH_TEST 1
231 // -- path routines ----------------------------------------------------------
233 // Tries to create the directory path as a temp-dir. If it fails,
234 // changes path to some directory it *can* create.
235 #if defined(__MINGW32__)
237 inline void MakeTmpdir(std::string* path) {
238 if (!path->empty()) {
239 path->append("/gflags_unittest_testdir");
240 int err = mkdir(path->c_str());
241 if (err == 0 || errno == EEXIST) return;
243 // I had trouble creating a directory in /tmp from mingw
244 *path = "./gflags_unittest";
245 mkdir(path->c_str());
247 #elif defined(_MSC_VER)
249 inline void MakeTmpdir(std::string* path) {
250 if (!path->empty()) {
251 int err = _mkdir(path->c_str());
252 if (err == 0 || errno == EEXIST) return;
254 char tmppath_buffer[1024];
255 int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
256 assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
257 assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
258 *path = std::string(tmppath_buffer) + "gflags_unittest";
259 _mkdir(path->c_str());
262 inline void MakeTmpdir(std::string* path) {
263 if (!path->empty()) {
264 int err = mkdir(path->c_str(), 0755);
265 if (err == 0 || errno == EEXIST) return;
267 mkdir("/tmp/gflags_unittest", 0755);
271 // -- string routines --------------------------------------------------------
273 inline void InternalStringPrintf(std::string* output, const char* format,
275 char space[128]; // try a small buffer and hope it fits
277 // It's possible for methods that use a va_list to invalidate
278 // the data in it upon use. The fix is to make a copy
279 // of the structure before using it and use that copy instead.
281 va_copy(backup_ap, ap);
282 int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
285 if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
286 output->append(space, bytes_written);
290 // Repeatedly increase buffer size until it fits.
291 int length = sizeof(space);
293 if (bytes_written < 0) {
294 // Older snprintf() behavior. :-( Just try doubling the buffer size
297 // We need exactly "bytes_written+1" characters
298 length = bytes_written+1;
300 char* buf = new char[length];
302 // Restore the va_list before we use it again
303 va_copy(backup_ap, ap);
304 bytes_written = vsnprintf(buf, length, format, backup_ap);
307 if ((bytes_written >= 0) && (bytes_written < length)) {
308 output->append(buf, bytes_written);
316 // Clears output before writing to it.
317 inline void SStringPrintf(std::string* output, const char* format, ...) {
319 va_start(ap, format);
321 InternalStringPrintf(output, format, ap);
325 inline void StringAppendF(std::string* output, const char* format, ...) {
327 va_start(ap, format);
328 InternalStringPrintf(output, format, ap);
332 inline std::string StringPrintf(const char* format, ...) {
334 va_start(ap, format);
336 InternalStringPrintf(&output, format, ap);
341 inline bool SafeGetEnv(const char *varname, std::string &valstr)
343 #if defined(_MSC_VER) && _MSC_VER >= 1400
346 if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
350 const char * const val = getenv(varname);
351 if (!val) return false;
357 inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
359 #if defined(_MSC_VER) && _MSC_VER >= 1400
360 return fopen_s(fp, fname, mode);
363 *fp = fopen(fname, mode);
364 // errno only guaranteed to be set on failure
365 return ((*fp == NULL) ? errno : 0);
370 } // namespace GFLAGS_NAMESPACE
373 #endif // GFLAGS_UTIL_H_