mirror of
https://github.com/OlafvdSpek/ctemplate.git
synced 2025-09-28 19:05:49 +08:00

the opensource shims to be able to compile that. This is a bit of a hack. R=chandlerc DELTA=5 (5 added, 0 deleted, 0 changed) Revision created by MOE tool push_codebase. MOE_MIGRATION=3313
236 lines
9.2 KiB
C++
236 lines
9.2 KiB
C++
// Copyright (c) 2011, Google Inc.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
// in the documentation and/or other materials provided with the
|
|
// distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
// ---
|
|
//
|
|
// Some generically useful utility routines that in google-land would
|
|
// be their own projects. We make a shortened version here.
|
|
|
|
#ifndef TEMPLATE_UTIL_H_
|
|
#define TEMPLATE_UTIL_H_
|
|
|
|
#include <config.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
// -- utility macros ---------------------------------------------------------
|
|
|
|
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
|
TypeName(const TypeName&); \
|
|
void operator=(const TypeName&)
|
|
|
|
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE.
|
|
#if !defined(_MSC_VER) || _MSC_VER < 1400
|
|
#define ARRAYSIZE(a) \
|
|
((sizeof(a) / sizeof(*(a))) / \
|
|
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
|
#endif
|
|
|
|
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
|
inline To down_cast(From* f) { // so we only accept pointers
|
|
return static_cast<To>(f);
|
|
}
|
|
|
|
// -- CHECK macros ---------------------------------------------------------
|
|
|
|
// CHECK dies with a fatal error if condition is not true. It is *not*
|
|
// controlled by NDEBUG, so the check will be executed regardless of
|
|
// compilation mode. Therefore, it is safe to do things like:
|
|
// CHECK(fp->Write(x) == 4)
|
|
// We allow stream-like objects after this for debugging, but they're ignored.
|
|
#define CHECK(condition) \
|
|
if (true) { \
|
|
if (!(condition)) { \
|
|
fprintf(stderr, "Check failed: %s\n", #condition); \
|
|
exit(1); \
|
|
} \
|
|
} else std::cerr << ""
|
|
|
|
#define CHECK_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 CHECK_EQ(val1, val2) CHECK_OP(==, val1, val2)
|
|
#define CHECK_NE(val1, val2) CHECK_OP(!=, val1, val2)
|
|
#define CHECK_LE(val1, val2) CHECK_OP(<=, val1, val2)
|
|
#define CHECK_LT(val1, val2) CHECK_OP(< , val1, val2)
|
|
#define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
|
|
#define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
|
|
// Synonyms for CHECK_* that are used in some unittests.
|
|
#define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2)
|
|
#define EXPECT_NE(val1, val2) CHECK_NE(val1, val2)
|
|
#define EXPECT_LE(val1, val2) CHECK_LE(val1, val2)
|
|
#define EXPECT_LT(val1, val2) CHECK_LT(val1, val2)
|
|
#define EXPECT_GE(val1, val2) CHECK_GE(val1, val2)
|
|
#define EXPECT_GT(val1, val2) CHECK_GT(val1, val2)
|
|
#define EXPECT_TRUE(cond) CHECK(cond)
|
|
#define EXPECT_FALSE(cond) CHECK(!(cond))
|
|
#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
|
|
#define ASSERT_TRUE(cond) EXPECT_TRUE(cond)
|
|
// LOG(FATAL) is an alias for CHECK(FALSE). We define FATAL, but no
|
|
// other value that is reasonable inside LOG(), so the compile will
|
|
// fail if someone tries to use LOG(DEBUG) or the like.
|
|
#define LOG(x) INTERNAL_DO_LOG_ ## x
|
|
#define INTERNAL_DO_LOG_FATAL CHECK(false)
|
|
|
|
// These are used only in debug mode.
|
|
#ifdef NDEBUG
|
|
#define DCHECK(condition) CHECK(condition)
|
|
#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
|
|
#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
|
|
#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
|
|
#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
|
|
#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
|
|
#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
|
|
#else
|
|
#define DCHECK(condition) if (true) {} else std::cerr << ""
|
|
#define DCHECK_EQ(val1, val2) if (true) {} else std::cerr << ""
|
|
#define DCHECK_NE(val1, val2) if (true) {} else std::cerr << ""
|
|
#define DCHECK_LE(val1, val2) if (true) {} else std::cerr << ""
|
|
#define DCHECK_LT(val1, val2) if (true) {} else std::cerr << ""
|
|
#define DCHECK_GE(val1, val2) if (true) {} else std::cerr << ""
|
|
#define DCHECK_GT(val1, val2) if (true) {} else std::cerr << ""
|
|
#endif
|
|
|
|
#define PCHECK(cond) CHECK(cond) << ": " << strerror(errno)
|
|
#define PFATAL(s) do { perror(s); exit(1); } while (0)
|
|
|
|
// -- testing-related macros --------------------------------------------------
|
|
|
|
// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
|
|
#define TEST_INIT \
|
|
static std::vector<void (*)()> g_testlist; /* the tests to run */ \
|
|
static int RUN_ALL_TESTS() { \
|
|
std::vector<void (*)()>::const_iterator it; \
|
|
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
|
|
(*it)(); /* The test will error-exit if there's a problem. */ \
|
|
} \
|
|
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
|
|
static_cast<int>(g_testlist.size())); \
|
|
return 0; \
|
|
}
|
|
|
|
#define TEST(a, b) \
|
|
class Test_##a##_##b { \
|
|
public: \
|
|
Test_##a##_##b() { g_testlist.push_back(&Run); } \
|
|
static void Run(); \
|
|
}; \
|
|
static Test_##a##_##b g_test_##a##_##b; \
|
|
void Test_##a##_##b::Run()
|
|
|
|
// This is a dummy class that eases the google->opensource transition.
|
|
namespace testing {
|
|
class Test {};
|
|
}
|
|
|
|
// -- template-related macros ----------------------------------------------
|
|
|
|
#ifndef DEFAULT_TEMPLATE_ROOTDIR
|
|
# define DEFAULT_TEMPLATE_ROOTDIR "."
|
|
#endif
|
|
|
|
// -- string-related functions ----------------------------------------------
|
|
|
|
inline bool safe_strto32(const std::string& s, int* i) {
|
|
char* error_pos;
|
|
if (s.empty()) return false; // no input at all
|
|
errno = 0; // just to be sure
|
|
*i = strtol(s.c_str(), &error_pos, 10);
|
|
return *error_pos == '\0' && errno == 0;
|
|
}
|
|
|
|
inline int atoi32(const char* s) {
|
|
return atoi(s);
|
|
}
|
|
|
|
inline void StripWhiteSpace(std::string* str) {
|
|
int str_length = str->length();
|
|
|
|
// Strip off leading whitespace.
|
|
int first = 0;
|
|
while (first < str_length && isspace(str->at(first))) {
|
|
++first;
|
|
}
|
|
// If entire string is white space.
|
|
if (first == str_length) {
|
|
str->clear();
|
|
return;
|
|
}
|
|
if (first > 0) {
|
|
str->erase(0, first);
|
|
str_length -= first;
|
|
}
|
|
|
|
// Strip off trailing whitespace.
|
|
int last = str_length - 1;
|
|
while (last >= 0 && isspace(str->at(last))) {
|
|
--last;
|
|
}
|
|
if (last != (str_length - 1) && last >= 0) {
|
|
str->erase(last + 1, std::string::npos);
|
|
}
|
|
}
|
|
|
|
inline void SplitStringIntoKeyValuePairs(
|
|
const std::string& s,
|
|
const char* kv_split, // For instance: "="
|
|
const char* pair_split, // For instance: ","
|
|
std::vector< std::pair<std::string, std::string> > *pairs) {
|
|
std::string key, value;
|
|
std::string* add_to = &key;
|
|
for (std::string::size_type i = 0; i < s.length(); ++i) {
|
|
if (s[i] == kv_split[0]) {
|
|
add_to = &value;
|
|
} else if (s[i] == pair_split[0]) {
|
|
if (!key.empty())
|
|
pairs->push_back(std::pair<std::string, std::string>(key, value));
|
|
key.clear();
|
|
value.clear();
|
|
add_to = &key;
|
|
} else {
|
|
*add_to += s[i];
|
|
}
|
|
}
|
|
if (!key.empty())
|
|
pairs->push_back(std::pair<std::string, std::string>(key, value));
|
|
}
|
|
|
|
#endif // TEMPLATE_UTIL_H_
|