webkit  2cdf99a9e3038c7e01b3c37e8ad903ecbe5eecf1
https://github.com/WebKit/webkit
util.h
Go to the documentation of this file.
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 #include <config.h>
41 #ifdef HAVE_INTTYPES_H
42 # include <inttypes.h>
43 #endif
44 #include <stdarg.h> // for va_*
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <iostream>
48 #include <string>
49 #include <errno.h>
50 #ifdef HAVE_SYS_STAT_H
51 # include <sys/stat.h> // for mkdir
52 #endif
53 
54 
55 namespace GFLAGS_NAMESPACE {
56 
57 
58 // This is used for unittests for death-testing. It is defined in gflags.cc.
60 
61 // Work properly if either strtoll or strtoq is on this system.
62 #if defined(strtoll) || defined(HAVE_STRTOLL)
63 # define strto64 strtoll
64 # define strtou64 strtoull
65 #elif defined(HAVE_STRTOQ)
66 # define strto64 strtoq
67 # define strtou64 strtouq
68 // Neither strtoll nor strtoq are defined. I hope strtol works!
69 #else
70 # define strto64 strtol
71 # define strtou64 strtoul
72 #endif
73 
74 // If we have inttypes.h, it will have defined PRId32/etc for us.
75 // If not, take our best guess.
76 #ifndef PRId32
77 # define PRId32 "d"
78 #endif
79 #ifndef PRId64
80 # define PRId64 "lld"
81 #endif
82 #ifndef PRIu64
83 # define PRIu64 "llu"
84 #endif
85 
86 typedef signed char int8;
87 typedef unsigned char uint8;
88 
89 // -- utility macros ---------------------------------------------------------
90 
91 template <bool b> struct CompileAssert;
92 template <> struct CompileAssert<true> {};
93 #define COMPILE_ASSERT(expr, msg) \
94  enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
95 
96 // Returns the number of elements in an array.
97 #define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
98 
99 
100 // -- logging and testing ---------------------------------------------------
101 
102 // For now, we ignore the level for logging, and don't show *VLOG's at
103 // all, except by hand-editing the lines below
104 #define LOG(level) std::cerr
105 #define VLOG(level) if (true) {} else std::cerr
106 #define DVLOG(level) if (true) {} else std::cerr
107 
108 // CHECK dies with a fatal error if condition is not true. It is *not*
109 // controlled by NDEBUG, so the check will be executed regardless of
110 // compilation mode. Therefore, it is safe to do things like:
111 // CHECK(fp->Write(x) == 4)
112 // We allow stream-like objects after this for debugging, but they're ignored.
113 #define EXPECT_TRUE(condition) \
114  if (true) { \
115  if (!(condition)) { \
116  fprintf(stderr, "Check failed: %s\n", #condition); \
117  exit(1); \
118  } \
119  } else std::cerr << ""
120 
121 #define EXPECT_OP(op, val1, val2) \
122  if (true) { \
123  if (!((val1) op (val2))) { \
124  fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
125  exit(1); \
126  } \
127  } else std::cerr << ""
128 
129 #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
130 #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
131 #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
132 #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
133 #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
134 #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
135 #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
136 
137 // C99 declares isnan and isinf should be macros, so the #ifdef test
138 // should be reliable everywhere. Of course, it's not, but these
139 // are testing pertty marginal functionality anyway, so it's ok to
140 // not-run them even in situations they might, with effort, be made to work.
141 #ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
142 #define EXPECT_NAN(arg) \
143  do { \
144  if (!isnan(arg)) { \
145  fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
146  exit(1); \
147  } \
148  } while (0)
149 #else
150 #define EXPECT_NAN(arg)
151 #endif
152 
153 #ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
154 #define EXPECT_INF(arg) \
155  do { \
156  if (!isinf(arg)) { \
157  fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
158  exit(1); \
159  } \
160  } while (0)
161 #else
162 #define EXPECT_INF(arg)
163 #endif
164 
165 #define EXPECT_DOUBLE_EQ(val1, val2) \
166  do { \
167  if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
168  fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
169  exit(1); \
170  } \
171  } while (0)
172 
173 #define EXPECT_STREQ(val1, val2) \
174  do { \
175  if (strcmp((val1), (val2)) != 0) { \
176  fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
177  exit(1); \
178  } \
179  } while (0)
180 
181 // Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
182 #define TEST_INIT \
183  static std::vector<void (*)()> g_testlist; /* the tests to run */ \
184  static int RUN_ALL_TESTS() { \
185  std::vector<void (*)()>::const_iterator it; \
186  for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
187  (*it)(); /* The test will error-exit if there's a problem. */ \
188  } \
189  fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
190  static_cast<int>(g_testlist.size())); \
191  return 0; \
192  }
193 
194 // Note that this macro uses a FlagSaver to keep tests isolated.
195 #define TEST(a, b) \
196  struct Test_##a##_##b { \
197  Test_##a##_##b() { g_testlist.push_back(&Run); } \
198  static void Run() { \
199  FlagSaver fs; \
200  fprintf(stderr, "Running test %s/%s\n", #a, #b); \
201  RunTest(); \
202  } \
203  static void RunTest(); \
204  }; \
205  static Test_##a##_##b g_test_##a##_##b; \
206  void Test_##a##_##b::RunTest()
207 
208 // This is a dummy class that eases the google->opensource transition.
209 namespace testing {
210 class Test {};
211 }
212 
213 // Call this in a .cc file where you will later call EXPECT_DEATH
214 #define EXPECT_DEATH_INIT \
215  static bool g_called_exit; \
216  static void CalledExit(int) { g_called_exit = true; }
217 
218 #define EXPECT_DEATH(fn, msg) \
219  do { \
220  g_called_exit = false; \
221  gflags_exitfunc = &CalledExit; \
222  fn; \
223  gflags_exitfunc = &exit; /* set back to its default */ \
224  if (!g_called_exit) { \
225  fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
226  exit(1); \
227  } \
228  } while (0)
229 
230 #define GTEST_HAS_DEATH_TEST 1
231 
232 // -- path routines ----------------------------------------------------------
233 
234 // Tries to create the directory path as a temp-dir. If it fails,
235 // changes path to some directory it *can* create.
236 #if defined(__MINGW32__)
237 #include <io.h>
238 inline void MakeTmpdir(std::string* path) {
239  if (!path->empty()) {
240  path->append("/gflags_unittest_testdir");
241  int err = mkdir(path->c_str());
242  if (err == 0 || errno == EEXIST) return;
243  }
244  // I had trouble creating a directory in /tmp from mingw
245  *path = "./gflags_unittest";
246  mkdir(path->c_str());
247 }
248 #elif defined(_MSC_VER)
249 #include <direct.h>
250 inline void MakeTmpdir(std::string* path) {
251  if (!path->empty()) {
252  int err = _mkdir(path->c_str());
253  if (err == 0 || errno == EEXIST) return;
254  }
255  char tmppath_buffer[1024];
256  int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
257  assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
258  assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
259  *path = std::string(tmppath_buffer) + "gflags_unittest";
260  _mkdir(path->c_str());
261 }
262 #else
263 inline void MakeTmpdir(std::string* path) {
264  if (!path->empty()) {
265  int err = mkdir(path->c_str(), 0755);
266  if (err == 0 || errno == EEXIST) return;
267  }
268  mkdir("/tmp/gflags_unittest", 0755);
269 }
270 #endif
271 
272 // -- string routines --------------------------------------------------------
273 
274 inline void InternalStringPrintf(std::string* output, const char* format,
275  va_list ap) {
276  char space[128]; // try a small buffer and hope it fits
277 
278  // It's possible for methods that use a va_list to invalidate
279  // the data in it upon use. The fix is to make a copy
280  // of the structure before using it and use that copy instead.
281  va_list backup_ap;
282  va_copy(backup_ap, ap);
283  int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
284  va_end(backup_ap);
285 
286  if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
287  output->append(space, bytes_written);
288  return;
289  }
290 
291  // Repeatedly increase buffer size until it fits.
292  int length = sizeof(space);
293  while (true) {
294  if (bytes_written < 0) {
295  // Older snprintf() behavior. :-( Just try doubling the buffer size
296  length *= 2;
297  } else {
298  // We need exactly "bytes_written+1" characters
299  length = bytes_written+1;
300  }
301  char* buf = new char[length];
302 
303  // Restore the va_list before we use it again
304  va_copy(backup_ap, ap);
305  bytes_written = vsnprintf(buf, length, format, backup_ap);
306  va_end(backup_ap);
307 
308  if ((bytes_written >= 0) && (bytes_written < length)) {
309  output->append(buf, bytes_written);
310  delete[] buf;
311  return;
312  }
313  delete[] buf;
314  }
315 }
316 
317 // Clears output before writing to it.
318 inline void SStringPrintf(std::string* output, const char* format, ...) {
319  va_list ap;
320  va_start(ap, format);
321  output->clear();
322  InternalStringPrintf(output, format, ap);
323  va_end(ap);
324 }
325 
326 inline void StringAppendF(std::string* output, const char* format, ...) {
327  va_list ap;
328  va_start(ap, format);
329  InternalStringPrintf(output, format, ap);
330  va_end(ap);
331 }
332 
333 inline std::string StringPrintf(const char* format, ...) {
334  va_list ap;
335  va_start(ap, format);
337  InternalStringPrintf(&output, format, ap);
338  va_end(ap);
339  return output;
340 }
341 
342 inline bool SafeGetEnv(const char *varname, std::string &valstr)
343 {
344 #if defined(_MSC_VER) && _MSC_VER >= 1400
345  char *val;
346  size_t sz;
347  if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
348  valstr = val;
349  free(val);
350 #else
351  const char * const val = getenv(varname);
352  if (!val) return false;
353  valstr = val;
354 #endif
355  return true;
356 }
357 
358 inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
359 {
360 #if defined(_MSC_VER) && _MSC_VER >= 1400
361  return fopen_s(fp, fname, mode);
362 #else
363  assert(fp != NULL);
364  *fp = fopen(fname, mode);
365  // errno only guaranteed to be set on failure
366  return ((*fp == NULL) ? errno : 0);
367 #endif
368 }
369 
370 
371 } // namespace GFLAGS_NAMESPACE
372 
373 
374 #endif // GFLAGS_UTIL_H_
std::string StringPrintf(const char *format,...)
Definition: util.h:333
Definition: testutils.h:40
Definition: gflags.h:97
void GFLAGS_DLL_DECL(* gflags_exitfunc)(int)
Definition: gflags.cc:138
GLint GLint GLint GLsizei GLsizei GLenum format
Definition: gl2.h:403
signed char int8
Definition: util.h:86
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: gl2ext.h:134
path
Definition: generate.py:74
int FILE
Definition: antglob.py:49
Definition: util.h:91
GLenum mode
Definition: gl2.h:461
const UChar space
Definition: CharacterNames.h:87
#define output
Definition: wire_format_lite.h:418
#define va_copy(dst, src)
Definition: windows_port.h:72
void
Definition: AVFoundationCFSoftLinking.h:81
int
Definition: runtests.py:53
Definition: util.h:210
void MakeTmpdir(std::string *path)
Definition: util.h:263
#define true
Definition: float-mm.c:6
#define GFLAGS_DLL_DECL
Definition: gflags_declare.h:53
int SafeFOpen(FILE **fp, const char *fname, const char *mode)
Definition: util.h:358
GLsizei const GLchar *const * string
Definition: gl2.h:479
#define vsnprintf(str, size, format, ap)
Definition: windows_port.h:71
#define NULL
Definition: common_types.h:41
unsigned char uint8
Definition: util.h:87
bool SafeGetEnv(const char *varname, std::string &valstr)
Definition: util.h:342
void SStringPrintf(std::string *output, const char *format,...)
Definition: util.h:318
#define free
Definition: mbmalloc.h:50
GLuint GLsizei GLsizei GLfloat * val
Definition: gl2ext.h:3301
void InternalStringPrintf(std::string *output, const char *format, va_list ap)
Definition: util.h:274
GLuint GLsizei GLsizei * length
Definition: gl2.h:435
void StringAppendF(std::string *output, const char *format,...)
Definition: util.h:326