aboutsummaryrefslogtreecommitdiff
path: root/googlemock/src/gmock-internal-utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'googlemock/src/gmock-internal-utils.cc')
-rw-r--r--googlemock/src/gmock-internal-utils.cc119
1 files changed, 88 insertions, 31 deletions
diff --git a/googlemock/src/gmock-internal-utils.cc b/googlemock/src/gmock-internal-utils.cc
index e5b54798..5c2ce0d5 100644
--- a/googlemock/src/gmock-internal-utils.cc
+++ b/googlemock/src/gmock-internal-utils.cc
@@ -27,7 +27,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
// Google Mock - a framework for writing C++ mock classes.
//
// This file defines some utilities useful for implementing Google
@@ -37,8 +36,16 @@
#include "gmock/internal/gmock-internal-utils.h"
#include <ctype.h>
+
+#include <array>
+#include <cctype>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
#include <ostream> // NOLINT
#include <string>
+#include <vector>
+
#include "gmock/gmock.h"
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
@@ -48,21 +55,22 @@ namespace internal {
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
-GTEST_API_ std::string JoinAsTuple(const Strings& fields) {
- switch (fields.size()) {
- case 0:
- return "";
- case 1:
- return fields[0];
- default:
- std::string result = "(" + fields[0];
- for (size_t i = 1; i < fields.size(); i++) {
- result += ", ";
- result += fields[i];
- }
- result += ")";
- return result;
+GTEST_API_ std::string JoinAsKeyValueTuple(
+ const std::vector<const char*>& names, const Strings& values) {
+ GTEST_CHECK_(names.size() == values.size());
+ if (values.empty()) {
+ return "";
}
+ const auto build_one = [&](const size_t i) {
+ return std::string(names[i]) + ": " + values[i];
+ };
+ std::string result = "(" + build_one(0);
+ for (size_t i = 1; i < values.size(); i++) {
+ result += ", ";
+ result += build_one(i);
+ }
+ result += ")";
+ return result;
}
// Converts an identifier name to a space-separated list of lower-case
@@ -76,12 +84,11 @@ GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) {
// We don't care about the current locale as the input is
// guaranteed to be a valid C++ identifier name.
const bool starts_new_word = IsUpper(*p) ||
- (!IsAlpha(prev_char) && IsLower(*p)) ||
- (!IsDigit(prev_char) && IsDigit(*p));
+ (!IsAlpha(prev_char) && IsLower(*p)) ||
+ (!IsDigit(prev_char) && IsDigit(*p));
if (IsAlNum(*p)) {
- if (starts_new_word && result != "")
- result += ' ';
+ if (starts_new_word && !result.empty()) result += ' ';
result += ToLower(*p);
}
}
@@ -95,12 +102,9 @@ class GoogleTestFailureReporter : public FailureReporterInterface {
public:
void ReportFailure(FailureType type, const char* file, int line,
const std::string& message) override {
- AssertHelper(type == kFatal ?
- TestPartResult::kFatalFailure :
- TestPartResult::kNonFatalFailure,
- file,
- line,
- message.c_str()) = Message();
+ AssertHelper(type == kFatal ? TestPartResult::kFatalFailure
+ : TestPartResult::kNonFatalFailure,
+ file, line, message.c_str()) = Message();
if (type == kFatal) {
posix::Abort();
}
@@ -126,10 +130,10 @@ static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
// Returns true if and only if a log with the given severity is visible
// according to the --gmock_verbose flag.
GTEST_API_ bool LogIsVisible(LogSeverity severity) {
- if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
+ if (GMOCK_FLAG_GET(verbose) == kInfoVerbosity) {
// Always show the log if --gmock_verbose=info.
return true;
- } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
+ } else if (GMOCK_FLAG_GET(verbose) == kErrorVerbosity) {
// Always hide it if --gmock_verbose=error.
return false;
} else {
@@ -148,8 +152,7 @@ GTEST_API_ bool LogIsVisible(LogSeverity severity) {
// conservative.
GTEST_API_ void Log(LogSeverity severity, const std::string& message,
int stack_frames_to_skip) {
- if (!LogIsVisible(severity))
- return;
+ if (!LogIsVisible(severity)) return;
// Ensures that logs from different threads don't interleave.
MutexLock l(&g_log_mutex);
@@ -178,8 +181,8 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
std::cout << "\n";
}
std::cout << "Stack trace:\n"
- << ::testing::internal::GetCurrentOsStackTraceExceptTop(
- ::testing::UnitTest::GetInstance(), actual_to_skip);
+ << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+ actual_to_skip);
}
std::cout << ::std::flush;
}
@@ -196,5 +199,59 @@ GTEST_API_ void IllegalDoDefault(const char* file, int line) {
"the variable in various places.");
}
+constexpr char UndoWebSafeEncoding(char c) {
+ return c == '-' ? '+' : c == '_' ? '/' : c;
+}
+
+constexpr char UnBase64Impl(char c, const char* const base64, char carry) {
+ return *base64 == 0 ? static_cast<char>(65)
+ : *base64 == c
+ ? carry
+ : UnBase64Impl(c, base64 + 1, static_cast<char>(carry + 1));
+}
+
+template <size_t... I>
+constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>,
+ const char* const base64) {
+ return {
+ {UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};
+}
+
+constexpr std::array<char, 256> UnBase64(const char* const base64) {
+ return UnBase64Impl(MakeIndexSequence<256>{}, base64);
+}
+
+static constexpr char kBase64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static constexpr std::array<char, 256> kUnBase64 = UnBase64(kBase64);
+
+bool Base64Unescape(const std::string& encoded, std::string* decoded) {
+ decoded->clear();
+ size_t encoded_len = encoded.size();
+ decoded->reserve(3 * (encoded_len / 4) + (encoded_len % 4));
+ int bit_pos = 0;
+ char dst = 0;
+ for (int src : encoded) {
+ if (std::isspace(src) || src == '=') {
+ continue;
+ }
+ char src_bin = kUnBase64[static_cast<size_t>(src)];
+ if (src_bin >= 64) {
+ decoded->clear();
+ return false;
+ }
+ if (bit_pos == 0) {
+ dst |= static_cast<char>(src_bin << 2);
+ bit_pos = 6;
+ } else {
+ dst |= static_cast<char>(src_bin >> (bit_pos - 2));
+ decoded->push_back(dst);
+ dst = static_cast<char>(src_bin << (10 - bit_pos));
+ bit_pos = (bit_pos + 6) % 8;
+ }
+ }
+ return true;
+}
+
} // namespace internal
} // namespace testing