Merge pull request #143 from schuhschuh/fix-bazel-bulid-osx
[platform/upstream/gflags.git] / src / util.h
1 // Copyright (c) 2011, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
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
13 // distribution.
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.
17 //
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.
29 // ---
30 //
31 // Some generically useful utility routines that in google-land would
32 // be their own projects.  We make a shortened version here.
33
34 #ifndef GFLAGS_UTIL_H_
35 #define GFLAGS_UTIL_H_
36
37 #include "config.h"
38
39 #include <assert.h>
40 #ifdef HAVE_INTTYPES_H
41 #  include <inttypes.h>
42 #endif
43 #include <stdarg.h>     // for va_*
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <iostream>
47 #include <string>
48 #include <errno.h>
49 #ifdef HAVE_SYS_STAT_H
50 #  include <sys/stat.h> // for mkdir
51 #endif
52
53
54 namespace GFLAGS_NAMESPACE {
55
56
57 // This is used for unittests for death-testing.  It is defined in gflags.cc.
58 extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
59
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!
68 #else
69 #  define strto64  strtol
70 #  define strtou64 strtoul
71 #endif
72
73 // If we have inttypes.h, it will have defined PRId32/etc for us.
74 // If not, take our best guess.
75 #ifndef PRId32
76 #  define PRId32 "d"
77 #endif
78 #ifndef PRId64
79 #  define PRId64 "lld"
80 #endif
81 #ifndef PRIu64
82 #  define PRIu64 "llu"
83 #endif
84
85 typedef signed char int8;
86 typedef unsigned char uint8;
87
88 // -- utility macros ---------------------------------------------------------
89
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)>) }
94
95 // Returns the number of elements in an array.
96 #define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
97
98
99 // -- logging and testing ---------------------------------------------------
100
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
106
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)                                  \
113   if (true) {                                                   \
114     if (!(condition)) {                                         \
115       fprintf(stderr, "Check failed: %s\n", #condition);        \
116       exit(1);                                                  \
117     }                                                           \
118   } else std::cerr << ""
119
120 #define EXPECT_OP(op, val1, val2)                                       \
121   if (true) {                                                           \
122     if (!((val1) op (val2))) {                                          \
123       fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2);   \
124       exit(1);                                                          \
125     }                                                                   \
126   } else std::cerr << ""
127
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))
135
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)                                         \
142   do {                                                          \
143     if (!isnan(arg)) {                                          \
144       fprintf(stderr, "Check failed: isnan(%s)\n", #arg);       \
145       exit(1);                                                  \
146     }                                                           \
147   } while (0)
148 #else
149 #define EXPECT_NAN(arg)
150 #endif
151
152 #ifdef isinf  // Some compilers, like sun's for Solaris 10, don't define this
153 #define EXPECT_INF(arg)                                         \
154   do {                                                          \
155     if (!isinf(arg)) {                                          \
156       fprintf(stderr, "Check failed: isinf(%s)\n", #arg);       \
157       exit(1);                                                  \
158     }                                                           \
159   } while (0)
160 #else
161 #define EXPECT_INF(arg)
162 #endif
163
164 #define EXPECT_DOUBLE_EQ(val1, val2)                                    \
165   do {                                                                  \
166     if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) {         \
167       fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2);        \
168       exit(1);                                                          \
169     }                                                                   \
170   } while (0)
171
172 #define EXPECT_STREQ(val1, val2)                                        \
173   do {                                                                  \
174     if (strcmp((val1), (val2)) != 0) {                                  \
175       fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2);   \
176       exit(1);                                                          \
177     }                                                                   \
178   } while (0)
179
180 // Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
181 #define TEST_INIT                                                       \
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. */   \
187     }                                                                   \
188     fprintf(stderr, "\nPassed %d tests\n\nPASS\n",                      \
189             static_cast<int>(g_testlist.size()));                       \
190     return 0;                                                           \
191   }
192
193 // Note that this macro uses a FlagSaver to keep tests isolated.
194 #define TEST(a, b)                                      \
195   struct Test_##a##_##b {                               \
196     Test_##a##_##b() { g_testlist.push_back(&Run); }    \
197     static void Run() {                                 \
198       FlagSaver fs;                                     \
199       fprintf(stderr, "Running test %s/%s\n", #a, #b);  \
200       RunTest();                                        \
201     }                                                   \
202     static void RunTest();                              \
203   };                                                    \
204   static Test_##a##_##b g_test_##a##_##b;               \
205   void Test_##a##_##b::RunTest()
206
207 // This is a dummy class that eases the google->opensource transition.
208 namespace testing {
209 class Test {};
210 }
211
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; }
216
217 #define EXPECT_DEATH(fn, msg)                                           \
218   do {                                                                  \
219     g_called_exit = false;                                              \
220     gflags_exitfunc = &CalledExit;                            \
221     fn;                                                                 \
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);      \
225       exit(1);                                                          \
226     }                                                                   \
227   } while (0)
228
229 #define GTEST_HAS_DEATH_TEST 1
230
231 // -- path routines ----------------------------------------------------------
232
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__)
236 #include <io.h>
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;
242   }
243   // I had trouble creating a directory in /tmp from mingw
244   *path = "./gflags_unittest";
245   mkdir(path->c_str());
246 }
247 #elif defined(_MSC_VER)
248 #include <direct.h>
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;
253   }
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());
260 }
261 #else
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;
266   }
267   mkdir("/tmp/gflags_unittest", 0755);
268 }
269 #endif
270
271 // -- string routines --------------------------------------------------------
272
273 inline void InternalStringPrintf(std::string* output, const char* format,
274                                  va_list ap) {
275   char space[128];    // try a small buffer and hope it fits
276
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.
280   va_list backup_ap;
281   va_copy(backup_ap, ap);
282   int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
283   va_end(backup_ap);
284
285   if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
286     output->append(space, bytes_written);
287     return;
288   }
289
290   // Repeatedly increase buffer size until it fits.
291   int length = sizeof(space);
292   while (true) {
293     if (bytes_written < 0) {
294       // Older snprintf() behavior. :-(  Just try doubling the buffer size
295       length *= 2;
296     } else {
297       // We need exactly "bytes_written+1" characters
298       length = bytes_written+1;
299     }
300     char* buf = new char[length];
301
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);
305     va_end(backup_ap);
306
307     if ((bytes_written >= 0) && (bytes_written < length)) {
308       output->append(buf, bytes_written);
309       delete[] buf;
310       return;
311     }
312     delete[] buf;
313   }
314 }
315
316 // Clears output before writing to it.
317 inline void SStringPrintf(std::string* output, const char* format, ...) {
318   va_list ap;
319   va_start(ap, format);
320   output->clear();
321   InternalStringPrintf(output, format, ap);
322   va_end(ap);
323 }
324
325 inline void StringAppendF(std::string* output, const char* format, ...) {
326   va_list ap;
327   va_start(ap, format);
328   InternalStringPrintf(output, format, ap);
329   va_end(ap);
330 }
331
332 inline std::string StringPrintf(const char* format, ...) {
333   va_list ap;
334   va_start(ap, format);
335   std::string output;
336   InternalStringPrintf(&output, format, ap);
337   va_end(ap);
338   return output;
339 }
340
341 inline bool SafeGetEnv(const char *varname, std::string &valstr)
342 {
343 #if defined(_MSC_VER) && _MSC_VER >= 1400
344         char  *val;
345         size_t sz;
346         if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
347         valstr = val;
348         free(val);
349 #else
350         const char * const val = getenv(varname);
351         if (!val) return false;
352         valstr = val;
353 #endif
354         return true;
355 }
356
357 inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
358 {
359 #if defined(_MSC_VER) && _MSC_VER >= 1400
360         return fopen_s(fp, fname, mode);
361 #else
362         assert(fp != NULL);
363         *fp = fopen(fname, mode);
364     // errno only guaranteed to be set on failure
365         return ((*fp == NULL) ? errno : 0);
366 #endif
367 }
368
369
370 } // namespace GFLAGS_NAMESPACE
371
372
373 #endif  // GFLAGS_UTIL_H_