| // 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_ |