Copy //third_party/quic string libraries to //third_party/quiche
* quic_str_cat_lib -> quiche_str_cat_lib
* quic_string_piece_lib -> quiche_string_piece_lib
* quic_text_utils -> quiche_text_utils
To keep CLs small, a series of followup CLs will modify consumers of
these libraries to use the quiche variant. A final followup CL will
remove the originals from //third_party/quic.
The motivation is to expose base64 functions to our HTTPSSVC parsing
library, which will eventually land in //third_party and be shared
with Chromium via //third_party/quiche.
PiperOrigin-RevId: 284975905
Change-Id: I78d0b65f7a3afb5613d8f9de1c98b4e3bfd9ed8e
diff --git a/common/platform/api/quiche_str_cat.h b/common/platform/api/quiche_str_cat.h
new file mode 100644
index 0000000..36d054f
--- /dev/null
+++ b/common/platform/api/quiche_str_cat.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
+
+#include <string>
+#include <utility>
+
+#include "net/quiche/common/platform/impl/quiche_str_cat_impl.h"
+
+namespace quiche {
+
+// Merges given strings or numbers with no delimiter.
+template <typename... Args>
+inline std::string QuicheStrCat(const Args&... args) {
+ return quiche::QuicheStrCatImpl(std::forward<const Args&>(args)...);
+}
+
+template <typename... Args>
+inline std::string QuicheStringPrintf(const Args&... args) {
+ return QuicheStringPrintfImpl(std::forward<const Args&>(args)...);
+}
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
diff --git a/common/platform/api/quiche_str_cat_test.cc b/common/platform/api/quiche_str_cat_test.cc
new file mode 100644
index 0000000..7085b8a
--- /dev/null
+++ b/common/platform/api/quiche_str_cat_test.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+class QuicheStrCatTest : public QuicheTest {};
+
+TEST_F(QuicheStrCatTest, Ints) {
+ const int16_t s = -1;
+ const uint16_t us = 2;
+ const int i = -3;
+ const uint32_t ui = 4;
+ const int64_t l = -5;
+ const uint64_t ul = 6;
+ const ptrdiff_t ptrdiff = -7;
+ const size_t size = 8;
+ const intptr_t intptr = -9;
+ const uintptr_t uintptr = 10;
+ std::string answer;
+ answer = QuicheStrCat(s, us);
+ EXPECT_EQ(answer, "-12");
+ answer = QuicheStrCat(i, ui);
+ EXPECT_EQ(answer, "-34");
+ answer = QuicheStrCat(l, ul);
+ EXPECT_EQ(answer, "-56");
+ answer = QuicheStrCat(ptrdiff, size);
+ EXPECT_EQ(answer, "-78");
+ answer = QuicheStrCat(size, intptr);
+ EXPECT_EQ(answer, "8-9");
+ answer = QuicheStrCat(uintptr, 0);
+ EXPECT_EQ(answer, "100");
+}
+
+TEST_F(QuicheStrCatTest, Basics) {
+ std::string result;
+
+ std::string strs[] = {"Hello", "Cruel", "World"};
+
+ QuicheStringPiece pieces[] = {"Hello", "Cruel", "World"};
+
+ const char* c_strs[] = {"Hello", "Cruel", "World"};
+
+ int32_t i32s[] = {'H', 'C', 'W'};
+ uint64_t ui64s[] = {12345678910LL, 10987654321LL};
+
+ result = QuicheStrCat(false, true, 2, 3);
+ EXPECT_EQ(result, "0123");
+
+ result = QuicheStrCat(-1);
+ EXPECT_EQ(result, "-1");
+
+ result = QuicheStrCat(0.5);
+ EXPECT_EQ(result, "0.5");
+
+ result = QuicheStrCat(strs[1], pieces[2]);
+ EXPECT_EQ(result, "CruelWorld");
+
+ result = QuicheStrCat(strs[0], ", ", pieces[2]);
+ EXPECT_EQ(result, "Hello, World");
+
+ result = QuicheStrCat(strs[0], ", ", strs[1], " ", strs[2], "!");
+ EXPECT_EQ(result, "Hello, Cruel World!");
+
+ result = QuicheStrCat(pieces[0], ", ", pieces[1], " ", pieces[2]);
+ EXPECT_EQ(result, "Hello, Cruel World");
+
+ result = QuicheStrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]);
+ EXPECT_EQ(result, "Hello, Cruel World");
+
+ result = QuicheStrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!");
+ EXPECT_EQ(result, "ASCII 72, 67 87!");
+
+ result = QuicheStrCat(ui64s[0], ", ", ui64s[1], "!");
+ EXPECT_EQ(result, "12345678910, 10987654321!");
+
+ std::string one = "1";
+ result = QuicheStrCat("And a ", one.size(), " and a ",
+ &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
+ EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
+
+ result =
+ QuicheStrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0);
+ EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33");
+
+ float f = 10000.5;
+ result = QuicheStrCat("Ten K and a half is ", f);
+ EXPECT_EQ(result, "Ten K and a half is 10000.5");
+
+ double d = 99999.9;
+ result = QuicheStrCat("This double number is ", d);
+ EXPECT_EQ(result, "This double number is 99999.9");
+
+ result = QuicheStrCat(1, 22, 333, 4444, 55555, 666666, 7777777, 88888888,
+ 999999999);
+ EXPECT_EQ(result, "122333444455555666666777777788888888999999999");
+}
+
+TEST_F(QuicheStrCatTest, MaxArgs) {
+ std::string result;
+ // Test 10 up to 26 arguments, the current maximum
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a");
+ EXPECT_EQ(result, "123456789a");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b");
+ EXPECT_EQ(result, "123456789ab");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c");
+ EXPECT_EQ(result, "123456789abc");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d");
+ EXPECT_EQ(result, "123456789abcd");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e");
+ EXPECT_EQ(result, "123456789abcde");
+ result =
+ QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f");
+ EXPECT_EQ(result, "123456789abcdef");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g");
+ EXPECT_EQ(result, "123456789abcdefg");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h");
+ EXPECT_EQ(result, "123456789abcdefgh");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i");
+ EXPECT_EQ(result, "123456789abcdefghi");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j");
+ EXPECT_EQ(result, "123456789abcdefghij");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k");
+ EXPECT_EQ(result, "123456789abcdefghijk");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l");
+ EXPECT_EQ(result, "123456789abcdefghijkl");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m");
+ EXPECT_EQ(result, "123456789abcdefghijklm");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n");
+ EXPECT_EQ(result, "123456789abcdefghijklmn");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o");
+ EXPECT_EQ(result, "123456789abcdefghijklmno");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o", "p");
+ EXPECT_EQ(result, "123456789abcdefghijklmnop");
+ result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q");
+ EXPECT_EQ(result, "123456789abcdefghijklmnopq");
+ // No limit thanks to C++11's variadic templates
+ result = QuicheStrCat(
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h",
+ "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+ "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
+ EXPECT_EQ(result,
+ "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+}
+
+} // namespace
+} // namespace test
+} // namespace quiche
diff --git a/common/platform/api/quiche_string_piece.h b/common/platform/api/quiche_string_piece.h
new file mode 100644
index 0000000..9def942
--- /dev/null
+++ b/common/platform/api/quiche_string_piece.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
+
+#include "net/quiche/common/platform/impl/quiche_string_piece_impl.h"
+
+namespace quiche {
+
+using QuicheStringPiece = quiche::QuicheStringPieceImpl;
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
diff --git a/common/platform/api/quiche_text_utils.h b/common/platform/api/quiche_text_utils.h
new file mode 100644
index 0000000..c58c676
--- /dev/null
+++ b/common/platform/api/quiche_text_utils.h
@@ -0,0 +1,133 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/quiche/common/platform/impl/quiche_text_utils_impl.h"
+
+namespace quiche {
+
+// Various utilities for manipulating text.
+class QUICHE_EXPORT QuicheTextUtils {
+ public:
+ // Returns true if |data| starts with |prefix|, case sensitively.
+ static bool StartsWith(quiche::QuicheStringPiece data,
+ quiche::QuicheStringPiece prefix) {
+ return quiche::QuicheTextUtilsImpl::StartsWith(data, prefix);
+ }
+
+ // Returns true if |data| ends with |suffix|, case insensitively.
+ static bool EndsWithIgnoreCase(quiche::QuicheStringPiece data,
+ quiche::QuicheStringPiece suffix) {
+ return quiche::QuicheTextUtilsImpl::EndsWithIgnoreCase(data, suffix);
+ }
+
+ // Returns a new string in which |data| has been converted to lower case.
+ static std::string ToLower(quiche::QuicheStringPiece data) {
+ return quiche::QuicheTextUtilsImpl::ToLower(data);
+ }
+
+ // Removes leading and trailing whitespace from |data|.
+ static void RemoveLeadingAndTrailingWhitespace(
+ quiche::QuicheStringPiece* data) {
+ quiche::QuicheTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
+ }
+
+ // Returns true if |in| represents a valid uint64, and stores that value in
+ // |out|.
+ static bool StringToUint64(quiche::QuicheStringPiece in, uint64_t* out) {
+ return quiche::QuicheTextUtilsImpl::StringToUint64(in, out);
+ }
+
+ // Returns true if |in| represents a valid int, and stores that value in
+ // |out|.
+ static bool StringToInt(quiche::QuicheStringPiece in, int* out) {
+ return quiche::QuicheTextUtilsImpl::StringToInt(in, out);
+ }
+
+ // Returns true if |in| represents a valid uint32, and stores that value in
+ // |out|.
+ static bool StringToUint32(quiche::QuicheStringPiece in, uint32_t* out) {
+ return quiche::QuicheTextUtilsImpl::StringToUint32(in, out);
+ }
+
+ // Returns true if |in| represents a valid size_t, and stores that value in
+ // |out|.
+ static bool StringToSizeT(quiche::QuicheStringPiece in, size_t* out) {
+ return quiche::QuicheTextUtilsImpl::StringToSizeT(in, out);
+ }
+
+ // Returns a new string representing |in|.
+ static std::string Uint64ToString(uint64_t in) {
+ return quiche::QuicheTextUtilsImpl::Uint64ToString(in);
+ }
+
+ // This converts |length| bytes of binary to a 2*|length|-character
+ // hexadecimal representation.
+ // Return value: 2*|length| characters of ASCII string.
+ static std::string HexEncode(const char* data, size_t length) {
+ return HexEncode(quiche::QuicheStringPiece(data, length));
+ }
+
+ // This converts |data.length()| bytes of binary to a
+ // 2*|data.length()|-character hexadecimal representation.
+ // Return value: 2*|data.length()| characters of ASCII string.
+ static std::string HexEncode(quiche::QuicheStringPiece data) {
+ return quiche::QuicheTextUtilsImpl::HexEncode(data);
+ }
+
+ // This converts a uint32 into an 8-character hexidecimal
+ // representation. Return value: 8 characters of ASCII string.
+ static std::string Hex(uint32_t v) {
+ return quiche::QuicheTextUtilsImpl::Hex(v);
+ }
+
+ // Converts |data| from a hexadecimal ASCII string to a binary string
+ // that is |data.length()/2| bytes long.
+ static std::string HexDecode(quiche::QuicheStringPiece data) {
+ return quiche::QuicheTextUtilsImpl::HexDecode(data);
+ }
+
+ // Base64 encodes with no padding |data_len| bytes of |data| into |output|.
+ static void Base64Encode(const uint8_t* data,
+ size_t data_len,
+ std::string* output) {
+ return quiche::QuicheTextUtilsImpl::Base64Encode(data, data_len, output);
+ }
+
+ // Returns a string containing hex and ASCII representations of |binary|,
+ // side-by-side in the style of hexdump. Non-printable characters will be
+ // printed as '.' in the ASCII output.
+ // For example, given the input "Hello, QUIC!\01\02\03\04", returns:
+ // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...."
+ static std::string HexDump(quiche::QuicheStringPiece binary_data) {
+ return quiche::QuicheTextUtilsImpl::HexDump(binary_data);
+ }
+
+ // Returns true if |data| contains any uppercase characters.
+ static bool ContainsUpperCase(quiche::QuicheStringPiece data) {
+ return quiche::QuicheTextUtilsImpl::ContainsUpperCase(data);
+ }
+
+ // Returns true if |data| contains only decimal digits.
+ static bool IsAllDigits(quiche::QuicheStringPiece data) {
+ return quiche::QuicheTextUtilsImpl::IsAllDigits(data);
+ }
+
+ // Splits |data| into a vector of pieces delimited by |delim|.
+ static std::vector<quiche::QuicheStringPiece> Split(
+ quiche::QuicheStringPiece data,
+ char delim) {
+ return quiche::QuicheTextUtilsImpl::Split(data, delim);
+ }
+};
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
diff --git a/common/platform/api/quiche_text_utils_test.cc b/common/platform/api/quiche_text_utils_test.cc
new file mode 100644
index 0000000..1ca75d2
--- /dev/null
+++ b/common/platform/api/quiche_text_utils_test.cc
@@ -0,0 +1,231 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+
+#include <string>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+
+class QuicheTextUtilsTest : public QuicheTest {};
+
+TEST_F(QuicheTextUtilsTest, StartsWith) {
+ EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", "hello"));
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::StartsWith("hello world", "hello world"));
+ EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", ""));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "Hello"));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "world"));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "bar"));
+}
+
+TEST_F(QuicheTextUtilsTest, EndsWithIgnoreCase) {
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "world"));
+ EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world",
+ "hello world"));
+ EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", ""));
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "WORLD"));
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "hello"));
+}
+
+TEST_F(QuicheTextUtilsTest, ToLower) {
+ EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("LOWER"));
+ EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lower"));
+ EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lOwEr"));
+ EXPECT_EQ("123", quiche::QuicheTextUtils::ToLower("123"));
+ EXPECT_EQ("", quiche::QuicheTextUtils::ToLower(""));
+}
+
+TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
+ std::string input;
+
+ for (auto* input : {"text", " text", " text", "text ", "text ", " text ",
+ " text ", "\r\n\ttext", "text\n\r\t"}) {
+ quiche::QuicheStringPiece piece(input);
+ quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&piece);
+ EXPECT_EQ("text", piece);
+ }
+}
+
+TEST_F(QuicheTextUtilsTest, StringToNumbers) {
+ const std::string kMaxInt32Plus1 = "2147483648";
+ const std::string kMinInt32Minus1 = "-2147483649";
+ const std::string kMaxUint32Plus1 = "4294967296";
+
+ {
+ // StringToUint64
+ uint64_t uint64_val = 0;
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("123", &uint64_val));
+ EXPECT_EQ(123u, uint64_val);
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("1234", &uint64_val));
+ EXPECT_EQ(1234u, uint64_val);
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("", &uint64_val));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("-123", &uint64_val));
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToUint64("-123.0", &uint64_val));
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::StringToUint64(kMaxUint32Plus1, &uint64_val));
+ EXPECT_EQ(4294967296u, uint64_val);
+ }
+
+ {
+ // StringToint
+ int int_val = 0;
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("123", &int_val));
+ EXPECT_EQ(123, int_val);
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("1234", &int_val));
+ EXPECT_EQ(1234, int_val);
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("", &int_val));
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("-123", &int_val));
+ EXPECT_EQ(-123, int_val);
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("-123.0", &int_val));
+ if (sizeof(int) > 4) {
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val));
+ EXPECT_EQ(-2147483649ll, int_val);
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
+ EXPECT_EQ(2147483648ll, int_val);
+ } else {
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val));
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
+ }
+ }
+
+ {
+ // StringToUint32
+ uint32_t uint32_val = 0;
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("123", &uint32_val));
+ EXPECT_EQ(123u, uint32_val);
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("1234", &uint32_val));
+ EXPECT_EQ(1234u, uint32_val);
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("", &uint32_val));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("-123", &uint32_val));
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToUint32("-123.0", &uint32_val));
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToUint32(kMaxUint32Plus1, &uint32_val));
+ }
+
+ {
+ // StringToSizeT
+ size_t size_t_val = 0;
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("123", &size_t_val));
+ EXPECT_EQ(123u, size_t_val);
+ EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("1234", &size_t_val));
+ EXPECT_EQ(1234u, size_t_val);
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("", &size_t_val));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123", &size_t_val));
+ EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123.0", &size_t_val));
+ if (sizeof(size_t) > 4) {
+ EXPECT_TRUE(
+ quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
+ EXPECT_EQ(4294967296ull, size_t_val);
+ } else {
+ EXPECT_FALSE(
+ quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
+ }
+ }
+}
+
+TEST_F(QuicheTextUtilsTest, Uint64ToString) {
+ EXPECT_EQ("123", quiche::QuicheTextUtils::Uint64ToString(123));
+ EXPECT_EQ("1234", quiche::QuicheTextUtils::Uint64ToString(1234));
+}
+
+TEST_F(QuicheTextUtilsTest, HexEncode) {
+ EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello", 5));
+ EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello World", 5));
+ EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello"));
+ EXPECT_EQ("0102779cfa",
+ quiche::QuicheTextUtils::HexEncode("\x01\x02\x77\x9c\xfa"));
+}
+
+TEST_F(QuicheTextUtilsTest, HexDecode) {
+ EXPECT_EQ("Hello", quiche::QuicheTextUtils::HexDecode("48656c6c6f"));
+ EXPECT_EQ("", quiche::QuicheTextUtils::HexDecode(""));
+ EXPECT_EQ("\x01\x02\x77\x9c\xfa",
+ quiche::QuicheTextUtils::HexDecode("0102779cfa"));
+}
+
+TEST_F(QuicheTextUtilsTest, HexDump) {
+ // Verify output of the HexDump method is as expected.
+ char packet[] = {
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c,
+ 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74,
+ 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00,
+ };
+ EXPECT_EQ(
+ quiche::QuicheTextUtils::HexDump(packet),
+ "0x0000: 4865 6c6c 6f2c 2051 5549 4321 2054 6869 Hello,.QUIC!.Thi\n"
+ "0x0010: 7320 7374 7269 6e67 2073 686f 756c 6420 s.string.should.\n"
+ "0x0020: 6265 206c 6f6e 6720 656e 6f75 6768 2074 be.long.enough.t\n"
+ "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n"
+ "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n"
+ "0x0050: 0102 03 ...\n");
+ // Verify that 0x21 and 0x7e are printable, 0x20 and 0x7f are not.
+ EXPECT_EQ("0x0000: 2021 7e7f .!~.\n",
+ quiche::QuicheTextUtils::HexDump(
+ quiche::QuicheTextUtils::HexDecode("20217e7f")));
+ // Verify that values above numeric_limits<unsigned char>::max() are formatted
+ // properly on platforms where char is unsigned.
+ EXPECT_EQ("0x0000: 90aa ff ...\n",
+ quiche::QuicheTextUtils::HexDump(
+ quiche::QuicheTextUtils::HexDecode("90aaff")));
+}
+
+TEST_F(QuicheTextUtilsTest, Base64Encode) {
+ std::string output;
+ std::string input = "Hello";
+ quiche::QuicheTextUtils::Base64Encode(
+ reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output);
+ EXPECT_EQ("SGVsbG8", output);
+
+ input =
+ "Hello, QUIC! This string should be long enough to span"
+ "multiple lines of output\n";
+ quiche::QuicheTextUtils::Base64Encode(
+ reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output);
+ EXPECT_EQ(
+ "SGVsbG8sIFFVSUMhIFRoaXMgc3RyaW5nIHNob3VsZCBiZSBsb25n"
+ "IGVub3VnaCB0byBzcGFubXVsdGlwbGUgbGluZXMgb2Ygb3V0cHV0Cg",
+ output);
+}
+
+TEST_F(QuicheTextUtilsTest, ContainsUpperCase) {
+ EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("abc"));
+ EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase(""));
+ EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("123"));
+ EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("ABC"));
+ EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("aBc"));
+}
+
+TEST_F(QuicheTextUtilsTest, Split) {
+ EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+ quiche::QuicheTextUtils::Split("a,b,c", ','));
+ EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+ quiche::QuicheTextUtils::Split("a:b:c", ':'));
+ EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a:b:c"}),
+ quiche::QuicheTextUtils::Split("a:b:c", ','));
+ // Leading and trailing whitespace is preserved.
+ EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}),
+ quiche::QuicheTextUtils::Split("a,b,c", ','));
+ EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({" a", "b ", " c "}),
+ quiche::QuicheTextUtils::Split(" a:b : c ", ':'));
+}
+
+} // namespace test
+} // namespace quiche