summaryrefslogtreecommitdiffstats
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.cc54
1 files changed, 54 insertions, 0 deletions
diff --git a/googlemock/src/gmock-internal-utils.cc b/googlemock/src/gmock-internal-utils.cc
index e5b5479..10f688f 100644
--- a/googlemock/src/gmock-internal-utils.cc
+++ b/googlemock/src/gmock-internal-utils.cc
@@ -37,8 +37,14 @@
#include "gmock/internal/gmock-internal-utils.h"
#include <ctype.h>
+
+#include <array>
+#include <cctype>
+#include <cstdint>
+#include <cstring>
#include <ostream> // NOLINT
#include <string>
+
#include "gmock/gmock.h"
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
@@ -196,5 +202,53 @@ GTEST_API_ void IllegalDoDefault(const char* file, int line) {
"the variable in various places.");
}
+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, carry + 1);
+}
+
+template <size_t... I>
+constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>,
+ const char* const base64) {
+ return {{UnBase64Impl(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[src];
+ if (src_bin >= 64) {
+ decoded->clear();
+ return false;
+ }
+ if (bit_pos == 0) {
+ dst |= 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