aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/third_party/abseil-cpp/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'Firestore/third_party/abseil-cpp/absl/strings')
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/CMakeLists.txt299
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/ascii.cc198
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/ascii.h239
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/ascii_test.cc354
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.cc110
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.h146
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/internal/memutil_test.cc179
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h69
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc68
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/match.cc40
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/match.h84
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/match_test.cc99
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/string_view.cc247
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/string_view.h570
-rw-r--r--Firestore/third_party/abseil-cpp/absl/strings/string_view_test.cc1101
15 files changed, 3803 insertions, 0 deletions
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/CMakeLists.txt b/Firestore/third_party/abseil-cpp/absl/strings/CMakeLists.txt
new file mode 100644
index 0000000..dcd4974
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/CMakeLists.txt
@@ -0,0 +1,299 @@
+#
+# Copyright 2017 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+list(APPEND STRINGS_PUBLIC_HEADERS
+ "ascii.h"
+ "escaping.h"
+ "match.h"
+ "numbers.h"
+ "str_cat.h"
+ "string_view.h"
+ "strip.h"
+ "str_join.h"
+ "str_replace.h"
+ "str_split.h"
+ "substitute.h"
+)
+
+
+list(APPEND STRINGS_INTERNAL_HEADERS
+ "internal/char_map.h"
+ "internal/memutil.h"
+ "internal/ostringstream.h"
+ "internal/resize_uninitialized.h"
+ "internal/str_join_internal.h"
+ "internal/str_split_internal.h"
+ "internal/utf8.h"
+)
+
+
+
+# add string library
+list(APPEND STRINGS_SRC
+ "ascii.cc"
+ "escaping.cc"
+ "internal/memutil.cc"
+ "internal/memutil.h"
+ "internal/utf8.cc"
+ "match.cc"
+ "numbers.cc"
+ "str_cat.cc"
+ "str_replace.cc"
+ "str_split.cc"
+ "string_view.cc"
+ "substitute.cc"
+ ${STRINGS_PUBLIC_HEADERS}
+ ${STRINGS_INTERNAL_HEADERS}
+)
+set(STRINGS_PUBLIC_LIBRARIES absl::base absl_throw_delegate)
+
+absl_library(
+ TARGET
+ absl_strings
+ SOURCES
+ ${STRINGS_SRC}
+ PUBLIC_LIBRARIES
+ ${STRINGS_PUBLIC_LIBRARIES}
+ EXPORT_NAME
+ strings
+)
+
+
+#
+## TESTS
+#
+
+# test match_test
+set(MATCH_TEST_SRC "match_test.cc")
+set(MATCH_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ match_test
+ SOURCES
+ ${MATCH_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${MATCH_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test escaping_test
+set(ESCAPING_TEST_SRC "escaping_test.cc")
+set(ESCAPING_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
+
+absl_test(
+ TARGET
+ escaping_test
+ SOURCES
+ ${ESCAPING_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${ESCAPING_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test ascii_test
+set(ASCII_TEST_SRC "ascii_test.cc")
+set(ASCII_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ ascii_test
+ SOURCES
+ ${ASCII_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${ASCII_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test memutil_test
+set(MEMUTIL_TEST_SRC "internal/memutil_test.cc")
+set(MEMUTIL_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ memutil_test
+ SOURCES
+ ${MEMUTIL_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${MEMUTIL_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test utf8_test
+set(UTF8_TEST_SRC "internal/utf8_test.cc")
+set(UTF8_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
+
+absl_test(
+ TARGET
+ utf8_test
+ SOURCES
+ ${UTF8_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${UTF8_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test string_view_test
+set(STRING_VIEW_TEST_SRC "string_view_test.cc")
+set(STRING_VIEW_TEST_PUBLIC_LIBRARIES absl::strings absl_throw_delegate absl::base)
+
+absl_test(
+ TARGET
+ string_view_test
+ SOURCES
+ ${STRING_VIEW_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STRING_VIEW_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test substitute_test
+set(SUBSTITUTE_TEST_SRC "substitute_test.cc")
+set(SUBSTITUTE_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
+
+absl_test(
+ TARGET
+ substitute_test
+ SOURCES
+ ${SUBSTITUTE_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${SUBSTITUTE_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test str_replace_test
+set(STR_REPLACE_TEST_SRC "str_replace_test.cc")
+set(STR_REPLACE_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
+
+absl_test(
+ TARGET
+ str_replace_test
+ SOURCES
+ ${STR_REPLACE_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STR_REPLACE_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test str_split_test
+set(STR_SPLIT_TEST_SRC "str_split_test.cc")
+set(STR_SPLIT_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
+
+absl_test(
+ TARGET
+ str_split_test
+ SOURCES
+ ${STR_SPLIT_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STR_SPLIT_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test ostringstream_test
+set(OSTRINGSTREAM_TEST_SRC "internal/ostringstream_test.cc")
+
+absl_test(
+ TARGET
+ ostringstream_test
+ SOURCES
+ ${OSTRINGSTREAM_TEST_SRC}
+)
+
+
+# test resize_uninitialized_test
+set(RESIZE_UNINITIALIZED_TEST_SRC "internal/resize_uninitialized_test.cc")
+
+absl_test(
+ TARGET
+ resize_uninitialized_test
+ SOURCES
+ ${RESIZE_UNINITIALIZED_TEST_SRC}
+)
+
+
+# test str_join_test
+set(STR_JOIN_TEST_SRC "str_join_test.cc")
+set(STR_JOIN_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ str_join_test
+ SOURCES
+ ${STR_JOIN_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STR_JOIN_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test str_cat_test
+set(STR_CAT_TEST_SRC "str_cat_test.cc")
+set(STR_CAT_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ str_cat_test
+ SOURCES
+ ${STR_CAT_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STR_CAT_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test numbers_test
+set(NUMBERS_TEST_SRC "numbers_test.cc")
+set(NUMBERS_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ numbers_test
+ SOURCES
+ ${NUMBERS_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${NUMBERS_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test strip_test
+set(STRIP_TEST_SRC "strip_test.cc")
+set(STRIP_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ strip_test
+ SOURCES
+ ${STRIP_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${STRIP_TEST_PUBLIC_LIBRARIES}
+)
+
+
+# test char_map_test
+set(CHAR_MAP_TEST_SRC "internal/char_map_test.cc")
+set(CHAR_MAP_TEST_PUBLIC_LIBRARIES absl::strings)
+
+absl_test(
+ TARGET
+ char_map_test
+ SOURCES
+ ${CHAR_MAP_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${CHAR_MAP_TEST_PUBLIC_LIBRARIES}
+)
+
+
+
+
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/ascii.cc b/Firestore/third_party/abseil-cpp/absl/strings/ascii.cc
new file mode 100644
index 0000000..c9481e8
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/ascii.cc
@@ -0,0 +1,198 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/ascii.h"
+
+namespace absl {
+namespace ascii_internal {
+
+// # Table generated by this Python code (bit 0x02 is currently unused):
+// TODO(mbar) Move Python code for generation of table to BUILD and link here.
+
+// NOTE: The kAsciiPropertyBits table used within this code was generated by
+// Python code of the following form. (Bit 0x02 is currently unused and
+// available.)
+//
+// def Hex2(n):
+// return '0x' + hex(n/16)[2:] + hex(n%16)[2:]
+// def IsPunct(ch):
+// return (ord(ch) >= 32 and ord(ch) < 127 and
+// not ch.isspace() and not ch.isalnum())
+// def IsBlank(ch):
+// return ch in ' \t'
+// def IsCntrl(ch):
+// return ord(ch) < 32 or ord(ch) == 127
+// def IsXDigit(ch):
+// return ch.isdigit() or ch.lower() in 'abcdef'
+// for i in range(128):
+// ch = chr(i)
+// mask = ((ch.isalpha() and 0x01 or 0) |
+// (ch.isalnum() and 0x04 or 0) |
+// (ch.isspace() and 0x08 or 0) |
+// (IsPunct(ch) and 0x10 or 0) |
+// (IsBlank(ch) and 0x20 or 0) |
+// (IsCntrl(ch) and 0x40 or 0) |
+// (IsXDigit(ch) and 0x80 or 0))
+// print Hex2(mask) + ',',
+// if i % 16 == 7:
+// print ' //', Hex2(i & 0x78)
+// elif i % 16 == 15:
+// print
+
+// clang-format off
+// Array of bitfields holding character information. Each bit value corresponds
+// to a particular character feature. For readability, and because the value
+// of these bits is tightly coupled to this implementation, the individual bits
+// are not named. Note that bitfields for all characters above ASCII 127 are
+// zero-initialized.
+const unsigned char kPropertyBits[256] = {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
+ 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, // 0x30
+ 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
+};
+
+// Array of characters for the ascii_tolower() function. For values 'A'
+// through 'Z', return the lower-case character; otherwise, return the
+// identity of the passed character.
+const char kToLower[256] = {
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+ '\x40', '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', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
+ '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
+ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
+ '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
+};
+
+// Array of characters for the ascii_toupper() function. For values 'a'
+// through 'z', return the upper-case character; otherwise, return the
+// identity of the passed character.
+const char kToUpper[256] = {
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
+ '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
+ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
+ '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+ '\x60', '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', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff',
+};
+// clang-format on
+
+} // namespace ascii_internal
+
+void AsciiStrToLower(std::string* s) {
+ for (auto& ch : *s) {
+ ch = absl::ascii_tolower(ch);
+ }
+}
+
+void AsciiStrToUpper(std::string* s) {
+ for (auto& ch : *s) {
+ ch = absl::ascii_toupper(ch);
+ }
+}
+
+void RemoveExtraAsciiWhitespace(std::string* str) {
+ auto stripped = StripAsciiWhitespace(*str);
+
+ if (stripped.empty()) {
+ str->clear();
+ return;
+ }
+
+ auto input_it = stripped.begin();
+ auto input_end = stripped.end();
+ auto output_it = &(*str)[0];
+ bool is_ws = false;
+
+ for (; input_it < input_end; ++input_it) {
+ if (is_ws) {
+ // Consecutive whitespace? Keep only the last.
+ is_ws = absl::ascii_isspace(*input_it);
+ if (is_ws) --output_it;
+ } else {
+ is_ws = absl::ascii_isspace(*input_it);
+ }
+
+ *output_it = *input_it;
+ ++output_it;
+ }
+
+ str->erase(output_it - &(*str)[0]);
+}
+
+} // namespace absl
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/ascii.h b/Firestore/third_party/abseil-cpp/absl/strings/ascii.h
new file mode 100644
index 0000000..fc2bb33
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/ascii.h
@@ -0,0 +1,239 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: ascii.h
+// -----------------------------------------------------------------------------
+//
+// This package contains functions operating on characters and strings
+// restricted to standard ASCII. These include character classification
+// functions analogous to those found in the ANSI C Standard Library <ctype.h>
+// header file.
+//
+// C++ implementations provide <ctype.h> functionality based on their
+// C environment locale. In general, reliance on such a locale is not ideal, as
+// the locale standard is problematic (and may not return invariant information
+// for the same character set, for example). These `ascii_*()` functions are
+// hard-wired for standard ASCII, much faster, and guaranteed to behave
+// consistently. They will never be overloaded, nor will their function
+// signature change.
+//
+// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`,
+// `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`,
+// `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`,
+// `ascii_isxdigit()`
+// Analagous to the <ctype.h> functions with similar names, these
+// functions take an unsigned char and return a bool, based on whether the
+// character matches the condition specified.
+//
+// If the input character has a numerical value greater than 127, these
+// functions return `false`.
+//
+// `ascii_tolower()`, `ascii_toupper()`
+// Analagous to the <ctype.h> functions with similar names, these functions
+// take an unsigned char and return a char.
+//
+// If the input character is not an ASCII {lower,upper}-case letter (including
+// numerical values greater than 127) then the functions return the same value
+// as the input character.
+
+#ifndef ABSL_STRINGS_ASCII_H_
+#define ABSL_STRINGS_ASCII_H_
+
+#include <algorithm>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace ascii_internal {
+
+// Declaration for an array of bitfields holding character information.
+extern const unsigned char kPropertyBits[256];
+
+// Declaration for the array of characters to upper-case characters.
+extern const char kToUpper[256];
+
+// Declaration for the array of characters to lower-case characters.
+extern const char kToLower[256];
+
+} // namespace ascii_internal
+
+// ascii_isalpha()
+//
+// Determines whether the given character is an alphabetic character.
+inline bool ascii_isalpha(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x01) != 0;
+}
+
+// ascii_isalnum()
+//
+// Determines whether the given character is an alphanumeric character.
+inline bool ascii_isalnum(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x04) != 0;
+}
+
+// ascii_isspace()
+//
+// Determines whether the given character is a whitespace character (space,
+// tab, vertical tab, formfeed, linefeed, or carriage return).
+inline bool ascii_isspace(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x08) != 0;
+}
+
+// ascii_ispunct()
+//
+// Determines whether the given character is a punctuation character.
+inline bool ascii_ispunct(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x10) != 0;
+}
+
+// ascii_isblank()
+//
+// Determines whether the given character is a blank character (tab or space).
+inline bool ascii_isblank(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x20) != 0;
+}
+
+// ascii_iscntrl()
+//
+// Determines whether the given character is a control character.
+inline bool ascii_iscntrl(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x40) != 0;
+}
+
+// ascii_isxdigit()
+//
+// Determines whether the given character can be represented as a hexadecimal
+// digit character (i.e. {0-9} or {A-F}).
+inline bool ascii_isxdigit(unsigned char c) {
+ return (ascii_internal::kPropertyBits[c] & 0x80) != 0;
+}
+
+// ascii_isdigit()
+//
+// Determines whether the given character can be represented as a decimal
+// digit character (i.e. {0-9}).
+inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; }
+
+// ascii_isprint()
+//
+// Determines whether the given character is printable, including whitespace.
+inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; }
+
+// ascii_isgraph()
+//
+// Determines whether the given character has a graphical representation.
+inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; }
+
+// ascii_isupper()
+//
+// Determines whether the given character is uppercase.
+inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; }
+
+// ascii_islower()
+//
+// Determines whether the given character is lowercase.
+inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; }
+
+// ascii_isascii()
+//
+// Determines whether the given character is ASCII.
+inline bool ascii_isascii(unsigned char c) { return c < 128; }
+
+// ascii_tolower()
+//
+// Returns an ASCII character, converting to lowercase if uppercase is
+// passed. Note that character values > 127 are simply returned.
+inline char ascii_tolower(unsigned char c) {
+ return ascii_internal::kToLower[c];
+}
+
+// Converts the characters in `s` to lowercase, changing the contents of `s`.
+void AsciiStrToLower(std::string* s);
+
+// Creates a lowercase std::string from a given absl::string_view.
+ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) {
+ std::string result(s);
+ absl::AsciiStrToLower(&result);
+ return result;
+}
+
+// ascii_toupper()
+//
+// Returns the ASCII character, converting to upper-case if lower-case is
+// passed. Note that characters values > 127 are simply returned.
+inline char ascii_toupper(unsigned char c) {
+ return ascii_internal::kToUpper[c];
+}
+
+// Converts the characters in `s` to uppercase, changing the contents of `s`.
+void AsciiStrToUpper(std::string* s);
+
+// Creates an uppercase std::string from a given absl::string_view.
+ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) {
+ std::string result(s);
+ absl::AsciiStrToUpper(&result);
+ return result;
+}
+
+// Returns absl::string_view with whitespace stripped from the beginning of the
+// given string_view.
+ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace(
+ absl::string_view str) {
+ auto it = std::find_if_not(str.begin(), str.end(), absl::ascii_isspace);
+ return absl::string_view(it, str.end() - it);
+}
+
+// Strips in place whitespace from the beginning of the given std::string.
+inline void StripLeadingAsciiWhitespace(std::string* str) {
+ auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace);
+ str->erase(str->begin(), it);
+}
+
+// Returns absl::string_view with whitespace stripped from the end of the given
+// string_view.
+ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace(
+ absl::string_view str) {
+ auto it = std::find_if_not(str.rbegin(), str.rend(), absl::ascii_isspace);
+ return absl::string_view(str.begin(), str.rend() - it);
+}
+
+// Strips in place whitespace from the end of the given std::string
+inline void StripTrailingAsciiWhitespace(std::string* str) {
+ auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace);
+ str->erase(str->rend() - it);
+}
+
+// Returns absl::string_view with whitespace stripped from both ends of the
+// given string_view.
+ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace(
+ absl::string_view str) {
+ return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str));
+}
+
+// Strips in place whitespace from both ends of the given std::string
+inline void StripAsciiWhitespace(std::string* str) {
+ StripTrailingAsciiWhitespace(str);
+ StripLeadingAsciiWhitespace(str);
+}
+
+// Removes leading, trailing, and consecutive internal whitespace.
+void RemoveExtraAsciiWhitespace(std::string*);
+
+} // namespace absl
+
+#endif // ABSL_STRINGS_ASCII_H_
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/ascii_test.cc b/Firestore/third_party/abseil-cpp/absl/strings/ascii_test.cc
new file mode 100644
index 0000000..97f3601
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/ascii_test.cc
@@ -0,0 +1,354 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/ascii.h"
+
+#include <cctype>
+#include <clocale>
+#include <cstring>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+
+namespace {
+
+TEST(AsciiIsFoo, All) {
+ for (int i = 0; i < 256; i++) {
+ if ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z'))
+ EXPECT_TRUE(absl::ascii_isalpha(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isalpha(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if ((i >= '0' && i <= '9'))
+ EXPECT_TRUE(absl::ascii_isdigit(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isdigit(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (absl::ascii_isalpha(i) || absl::ascii_isdigit(i))
+ EXPECT_TRUE(absl::ascii_isalnum(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isalnum(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i != '\0' && strchr(" \r\n\t\v\f", i))
+ EXPECT_TRUE(absl::ascii_isspace(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isspace(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i >= 32 && i < 127)
+ EXPECT_TRUE(absl::ascii_isprint(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isprint(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (absl::ascii_isprint(i) && !absl::ascii_isspace(i) &&
+ !absl::ascii_isalnum(i))
+ EXPECT_TRUE(absl::ascii_ispunct(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_ispunct(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i == ' ' || i == '\t')
+ EXPECT_TRUE(absl::ascii_isblank(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isblank(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i < 32 || i == 127)
+ EXPECT_TRUE(absl::ascii_iscntrl(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_iscntrl(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (absl::ascii_isdigit(i) || (i >= 'A' && i <= 'F') ||
+ (i >= 'a' && i <= 'f'))
+ EXPECT_TRUE(absl::ascii_isxdigit(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isxdigit(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i > 32 && i < 127)
+ EXPECT_TRUE(absl::ascii_isgraph(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isgraph(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i >= 'A' && i <= 'Z')
+ EXPECT_TRUE(absl::ascii_isupper(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_isupper(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 256; i++) {
+ if (i >= 'a' && i <= 'z')
+ EXPECT_TRUE(absl::ascii_islower(i)) << ": failed on " << i;
+ else
+ EXPECT_TRUE(!absl::ascii_islower(i)) << ": failed on " << i;
+ }
+ for (int i = 0; i < 128; i++) {
+ EXPECT_TRUE(absl::ascii_isascii(i)) << ": failed on " << i;
+ }
+ for (int i = 128; i < 256; i++) {
+ EXPECT_TRUE(!absl::ascii_isascii(i)) << ": failed on " << i;
+ }
+
+ // The official is* functions don't accept negative signed chars, but
+ // our absl::ascii_is* functions do.
+ for (int i = 0; i < 256; i++) {
+ signed char sc = static_cast<signed char>(static_cast<unsigned char>(i));
+ EXPECT_EQ(absl::ascii_isalpha(i), absl::ascii_isalpha(sc)) << i;
+ EXPECT_EQ(absl::ascii_isdigit(i), absl::ascii_isdigit(sc)) << i;
+ EXPECT_EQ(absl::ascii_isalnum(i), absl::ascii_isalnum(sc)) << i;
+ EXPECT_EQ(absl::ascii_isspace(i), absl::ascii_isspace(sc)) << i;
+ EXPECT_EQ(absl::ascii_ispunct(i), absl::ascii_ispunct(sc)) << i;
+ EXPECT_EQ(absl::ascii_isblank(i), absl::ascii_isblank(sc)) << i;
+ EXPECT_EQ(absl::ascii_iscntrl(i), absl::ascii_iscntrl(sc)) << i;
+ EXPECT_EQ(absl::ascii_isxdigit(i), absl::ascii_isxdigit(sc)) << i;
+ EXPECT_EQ(absl::ascii_isprint(i), absl::ascii_isprint(sc)) << i;
+ EXPECT_EQ(absl::ascii_isgraph(i), absl::ascii_isgraph(sc)) << i;
+ EXPECT_EQ(absl::ascii_isupper(i), absl::ascii_isupper(sc)) << i;
+ EXPECT_EQ(absl::ascii_islower(i), absl::ascii_islower(sc)) << i;
+ EXPECT_EQ(absl::ascii_isascii(i), absl::ascii_isascii(sc)) << i;
+ }
+}
+
+// Checks that absl::ascii_isfoo returns the same value as isfoo in the C
+// locale.
+TEST(AsciiIsFoo, SameAsIsFoo) {
+ // temporarily change locale to C. It should already be C, but just for safety
+ std::string old_locale = setlocale(LC_CTYPE, nullptr);
+ ASSERT_TRUE(setlocale(LC_CTYPE, "C"));
+
+ for (int i = 0; i < 256; i++) {
+ EXPECT_EQ(isalpha(i) != 0, absl::ascii_isalpha(i)) << i;
+ EXPECT_EQ(isdigit(i) != 0, absl::ascii_isdigit(i)) << i;
+ EXPECT_EQ(isalnum(i) != 0, absl::ascii_isalnum(i)) << i;
+ EXPECT_EQ(isspace(i) != 0, absl::ascii_isspace(i)) << i;
+ EXPECT_EQ(ispunct(i) != 0, absl::ascii_ispunct(i)) << i;
+ EXPECT_EQ(isblank(i) != 0, absl::ascii_isblank(i)) << i;
+ EXPECT_EQ(iscntrl(i) != 0, absl::ascii_iscntrl(i)) << i;
+ EXPECT_EQ(isxdigit(i) != 0, absl::ascii_isxdigit(i)) << i;
+ EXPECT_EQ(isprint(i) != 0, absl::ascii_isprint(i)) << i;
+ EXPECT_EQ(isgraph(i) != 0, absl::ascii_isgraph(i)) << i;
+ EXPECT_EQ(isupper(i) != 0, absl::ascii_isupper(i)) << i;
+ EXPECT_EQ(islower(i) != 0, absl::ascii_islower(i)) << i;
+ EXPECT_EQ(isascii(i) != 0, absl::ascii_isascii(i)) << i;
+ }
+
+ // restore the old locale.
+ ASSERT_TRUE(setlocale(LC_CTYPE, old_locale.c_str()));
+}
+
+TEST(AsciiToFoo, All) {
+ // temporarily change locale to C. It should already be C, but just for safety
+ std::string old_locale = setlocale(LC_CTYPE, nullptr);
+ ASSERT_TRUE(setlocale(LC_CTYPE, "C"));
+
+ for (int i = 0; i < 256; i++) {
+ if (absl::ascii_islower(i))
+ EXPECT_EQ(absl::ascii_toupper(i), 'A' + (i - 'a')) << i;
+ else
+ EXPECT_EQ(absl::ascii_toupper(i), static_cast<char>(i)) << i;
+
+ if (absl::ascii_isupper(i))
+ EXPECT_EQ(absl::ascii_tolower(i), 'a' + (i - 'A')) << i;
+ else
+ EXPECT_EQ(absl::ascii_tolower(i), static_cast<char>(i)) << i;
+
+ // These CHECKs only hold in a C locale.
+ EXPECT_EQ(static_cast<char>(tolower(i)), absl::ascii_tolower(i)) << i;
+ EXPECT_EQ(static_cast<char>(toupper(i)), absl::ascii_toupper(i)) << i;
+
+ // The official to* functions don't accept negative signed chars, but
+ // our absl::ascii_to* functions do.
+ signed char sc = static_cast<signed char>(static_cast<unsigned char>(i));
+ EXPECT_EQ(absl::ascii_tolower(i), absl::ascii_tolower(sc)) << i;
+ EXPECT_EQ(absl::ascii_toupper(i), absl::ascii_toupper(sc)) << i;
+ }
+
+ // restore the old locale.
+ ASSERT_TRUE(setlocale(LC_CTYPE, old_locale.c_str()));
+}
+
+TEST(AsciiStrTo, Lower) {
+ const char buf[] = "ABCDEF";
+ const std::string str("GHIJKL");
+ const std::string str2("MNOPQR");
+ const absl::string_view sp(str2);
+
+ EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf));
+ EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str));
+ EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp));
+
+ char mutable_buf[] = "Mutable";
+ std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
+ mutable_buf, absl::ascii_tolower);
+ EXPECT_STREQ("mutable", mutable_buf);
+}
+
+TEST(AsciiStrTo, Upper) {
+ const char buf[] = "abcdef";
+ const std::string str("ghijkl");
+ const std::string str2("mnopqr");
+ const absl::string_view sp(str2);
+
+ EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf));
+ EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str));
+ EXPECT_EQ("MNOPQR", absl::AsciiStrToUpper(sp));
+
+ char mutable_buf[] = "Mutable";
+ std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
+ mutable_buf, absl::ascii_toupper);
+ EXPECT_STREQ("MUTABLE", mutable_buf);
+}
+
+TEST(StripLeadingAsciiWhitespace, FromStringView) {
+ EXPECT_EQ(absl::string_view{},
+ absl::StripLeadingAsciiWhitespace(absl::string_view{}));
+ EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"foo"}));
+ EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo"}));
+ EXPECT_EQ("foo foo\n ",
+ absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo foo\n "}));
+ EXPECT_EQ(absl::string_view{}, absl::StripLeadingAsciiWhitespace(
+ {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
+}
+
+TEST(StripLeadingAsciiWhitespace, InPlace) {
+ std::string str;
+
+ absl::StripLeadingAsciiWhitespace(&str);
+ EXPECT_EQ("", str);
+
+ str = "foo";
+ absl::StripLeadingAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = "\t \n\f\r\n\vfoo";
+ absl::StripLeadingAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = "\t \n\f\r\n\vfoo foo\n ";
+ absl::StripLeadingAsciiWhitespace(&str);
+ EXPECT_EQ("foo foo\n ", str);
+
+ str = "\t \n\f\r\v\n\t \n\f\r\v\n";
+ absl::StripLeadingAsciiWhitespace(&str);
+ EXPECT_EQ(absl::string_view{}, str);
+}
+
+TEST(StripTrailingAsciiWhitespace, FromStringView) {
+ EXPECT_EQ(absl::string_view{},
+ absl::StripTrailingAsciiWhitespace(absl::string_view{}));
+ EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo"}));
+ EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo\t \n\f\r\n\v"}));
+ EXPECT_EQ(" \nfoo foo",
+ absl::StripTrailingAsciiWhitespace({" \nfoo foo\t \n\f\r\n\v"}));
+ EXPECT_EQ(absl::string_view{}, absl::StripTrailingAsciiWhitespace(
+ {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
+}
+
+TEST(StripTrailingAsciiWhitespace, InPlace) {
+ std::string str;
+
+ absl::StripTrailingAsciiWhitespace(&str);
+ EXPECT_EQ("", str);
+
+ str = "foo";
+ absl::StripTrailingAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = "foo\t \n\f\r\n\v";
+ absl::StripTrailingAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = " \nfoo foo\t \n\f\r\n\v";
+ absl::StripTrailingAsciiWhitespace(&str);
+ EXPECT_EQ(" \nfoo foo", str);
+
+ str = "\t \n\f\r\v\n\t \n\f\r\v\n";
+ absl::StripTrailingAsciiWhitespace(&str);
+ EXPECT_EQ(absl::string_view{}, str);
+}
+
+TEST(StripAsciiWhitespace, FromStringView) {
+ EXPECT_EQ(absl::string_view{},
+ absl::StripAsciiWhitespace(absl::string_view{}));
+ EXPECT_EQ("foo", absl::StripAsciiWhitespace({"foo"}));
+ EXPECT_EQ("foo",
+ absl::StripAsciiWhitespace({"\t \n\f\r\n\vfoo\t \n\f\r\n\v"}));
+ EXPECT_EQ("foo foo", absl::StripAsciiWhitespace(
+ {"\t \n\f\r\n\vfoo foo\t \n\f\r\n\v"}));
+ EXPECT_EQ(absl::string_view{},
+ absl::StripAsciiWhitespace({"\t \n\f\r\v\n\t \n\f\r\v\n"}));
+}
+
+TEST(StripAsciiWhitespace, InPlace) {
+ std::string str;
+
+ absl::StripAsciiWhitespace(&str);
+ EXPECT_EQ("", str);
+
+ str = "foo";
+ absl::StripAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = "\t \n\f\r\n\vfoo\t \n\f\r\n\v";
+ absl::StripAsciiWhitespace(&str);
+ EXPECT_EQ("foo", str);
+
+ str = "\t \n\f\r\n\vfoo foo\t \n\f\r\n\v";
+ absl::StripAsciiWhitespace(&str);
+ EXPECT_EQ("foo foo", str);
+
+ str = "\t \n\f\r\v\n\t \n\f\r\v\n";
+ absl::StripAsciiWhitespace(&str);
+ EXPECT_EQ(absl::string_view{}, str);
+}
+
+TEST(RemoveExtraAsciiWhitespace, InPlace) {
+ const char* inputs[] = {"No extra space",
+ " Leading whitespace",
+ "Trailing whitespace ",
+ " Leading and trailing ",
+ " Whitespace \t in\v middle ",
+ "'Eeeeep! \n Newlines!\n",
+ "nospaces",
+ "",
+ "\n\t a\t\n\nb \t\n"};
+
+ const char* outputs[] = {
+ "No extra space",
+ "Leading whitespace",
+ "Trailing whitespace",
+ "Leading and trailing",
+ "Whitespace in middle",
+ "'Eeeeep! Newlines!",
+ "nospaces",
+ "",
+ "a\nb",
+ };
+ const int NUM_TESTS = ABSL_ARRAYSIZE(inputs);
+
+ for (int i = 0; i < NUM_TESTS; i++) {
+ std::string s(inputs[i]);
+ absl::RemoveExtraAsciiWhitespace(&s);
+ EXPECT_EQ(outputs[i], s);
+ }
+}
+
+} // namespace
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.cc b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.cc
new file mode 100644
index 0000000..a0de70d
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.cc
@@ -0,0 +1,110 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/memutil.h"
+
+#include <cstdlib>
+
+namespace absl {
+namespace strings_internal {
+
+int memcasecmp(const char* s1, const char* s2, size_t len) {
+ const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1);
+ const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2);
+
+ for (size_t i = 0; i < len; i++) {
+ const int diff =
+ int{static_cast<unsigned char>(absl::ascii_tolower(us1[i]))} -
+ int{static_cast<unsigned char>(absl::ascii_tolower(us2[i]))};
+ if (diff != 0) return diff;
+ }
+ return 0;
+}
+
+char* memdup(const char* s, size_t slen) {
+ void* copy;
+ if ((copy = malloc(slen)) == nullptr) return nullptr;
+ memcpy(copy, s, slen);
+ return reinterpret_cast<char*>(copy);
+}
+
+char* memrchr(const char* s, int c, size_t slen) {
+ for (const char* e = s + slen - 1; e >= s; e--) {
+ if (*e == c) return const_cast<char*>(e);
+ }
+ return nullptr;
+}
+
+size_t memspn(const char* s, size_t slen, const char* accept) {
+ const char* p = s;
+ const char* spanp;
+ char c, sc;
+
+cont:
+ c = *p++;
+ if (slen-- == 0) return p - 1 - s;
+ for (spanp = accept; (sc = *spanp++) != '\0';)
+ if (sc == c) goto cont;
+ return p - 1 - s;
+}
+
+size_t memcspn(const char* s, size_t slen, const char* reject) {
+ const char* p = s;
+ const char* spanp;
+ char c, sc;
+
+ while (slen-- != 0) {
+ c = *p++;
+ for (spanp = reject; (sc = *spanp++) != '\0';)
+ if (sc == c) return p - 1 - s;
+ }
+ return p - s;
+}
+
+char* mempbrk(const char* s, size_t slen, const char* accept) {
+ const char* scanp;
+ int sc;
+
+ for (; slen; ++s, --slen) {
+ for (scanp = accept; (sc = *scanp++) != '\0';)
+ if (sc == *s) return const_cast<char*>(s);
+ }
+ return nullptr;
+}
+
+// This is significantly faster for case-sensitive matches with very
+// few possible matches. See unit test for benchmarks.
+const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
+ size_t neelen) {
+ if (0 == neelen) {
+ return phaystack; // even if haylen is 0
+ }
+ if (haylen < neelen) return nullptr;
+
+ const char* match;
+ const char* hayend = phaystack + haylen - neelen + 1;
+ // A static cast is used here to work around the fact that memchr returns
+ // a void* on Posix-compliant systems and const void* on Windows.
+ while ((match = static_cast<const char*>(
+ memchr(phaystack, pneedle[0], hayend - phaystack)))) {
+ if (memcmp(match, pneedle, neelen) == 0)
+ return match;
+ else
+ phaystack = match + 1;
+ }
+ return nullptr;
+}
+
+} // namespace strings_internal
+} // namespace absl
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.h b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.h
new file mode 100644
index 0000000..a6f1c69
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil.h
@@ -0,0 +1,146 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// These routines provide mem versions of standard C std::string routines,
+// such as strpbrk. They function exactly the same as the str versions,
+// so if you wonder what they are, replace the word "mem" by
+// "str" and check out the man page. I could return void*, as the
+// strutil.h mem*() routines tend to do, but I return char* instead
+// since this is by far the most common way these functions are called.
+//
+// The difference between the mem and str versions is the mem version
+// takes a pointer and a length, rather than a '\0'-terminated std::string.
+// The memcase* routines defined here assume the locale is "C"
+// (they use absl::ascii_tolower instead of tolower).
+//
+// These routines are based on the BSD library.
+//
+// Here's a list of routines from std::string.h, and their mem analogues.
+// Functions in lowercase are defined in std::string.h; those in UPPERCASE
+// are defined here:
+//
+// strlen --
+// strcat strncat MEMCAT
+// strcpy strncpy memcpy
+// -- memccpy (very cool function, btw)
+// -- memmove
+// -- memset
+// strcmp strncmp memcmp
+// strcasecmp strncasecmp MEMCASECMP
+// strchr memchr
+// strcoll --
+// strxfrm --
+// strdup strndup MEMDUP
+// strrchr MEMRCHR
+// strspn MEMSPN
+// strcspn MEMCSPN
+// strpbrk MEMPBRK
+// strstr MEMSTR MEMMEM
+// (g)strcasestr MEMCASESTR MEMCASEMEM
+// strtok --
+// strprefix MEMPREFIX (strprefix is from strutil.h)
+// strcaseprefix MEMCASEPREFIX (strcaseprefix is from strutil.h)
+// strsuffix MEMSUFFIX (strsuffix is from strutil.h)
+// strcasesuffix MEMCASESUFFIX (strcasesuffix is from strutil.h)
+// -- MEMIS
+// -- MEMCASEIS
+// strcount MEMCOUNT (strcount is from strutil.h)
+
+#ifndef ABSL_STRINGS_INTERNAL_MEMUTIL_H_
+#define ABSL_STRINGS_INTERNAL_MEMUTIL_H_
+
+#include <cstddef>
+#include <cstring>
+
+#include "absl/base/port.h" // disable some warnings on Windows
+#include "absl/strings/ascii.h" // for absl::ascii_tolower
+
+namespace absl {
+namespace strings_internal {
+
+inline char* memcat(char* dest, size_t destlen, const char* src,
+ size_t srclen) {
+ return reinterpret_cast<char*>(memcpy(dest + destlen, src, srclen));
+}
+
+int memcasecmp(const char* s1, const char* s2, size_t len);
+char* memdup(const char* s, size_t slen);
+char* memrchr(const char* s, int c, size_t slen);
+size_t memspn(const char* s, size_t slen, const char* accept);
+size_t memcspn(const char* s, size_t slen, const char* reject);
+char* mempbrk(const char* s, size_t slen, const char* accept);
+
+// This is for internal use only. Don't call this directly
+template <bool case_sensitive>
+const char* int_memmatch(const char* haystack, size_t haylen,
+ const char* needle, size_t neelen) {
+ if (0 == neelen) {
+ return haystack; // even if haylen is 0
+ }
+ const char* hayend = haystack + haylen;
+ const char* needlestart = needle;
+ const char* needleend = needlestart + neelen;
+
+ for (; haystack < hayend; ++haystack) {
+ char hay = case_sensitive
+ ? *haystack
+ : absl::ascii_tolower(static_cast<unsigned char>(*haystack));
+ char nee = case_sensitive
+ ? *needle
+ : absl::ascii_tolower(static_cast<unsigned char>(*needle));
+ if (hay == nee) {
+ if (++needle == needleend) {
+ return haystack + 1 - neelen;
+ }
+ } else if (needle != needlestart) {
+ // must back up haystack in case a prefix matched (find "aab" in "aaab")
+ haystack -= needle - needlestart; // for loop will advance one more
+ needle = needlestart;
+ }
+ }
+ return nullptr;
+}
+
+// These are the guys you can call directly
+inline const char* memstr(const char* phaystack, size_t haylen,
+ const char* pneedle) {
+ return int_memmatch<true>(phaystack, haylen, pneedle, strlen(pneedle));
+}
+
+inline const char* memcasestr(const char* phaystack, size_t haylen,
+ const char* pneedle) {
+ return int_memmatch<false>(phaystack, haylen, pneedle, strlen(pneedle));
+}
+
+inline const char* memmem(const char* phaystack, size_t haylen,
+ const char* pneedle, size_t needlelen) {
+ return int_memmatch<true>(phaystack, haylen, pneedle, needlelen);
+}
+
+inline const char* memcasemem(const char* phaystack, size_t haylen,
+ const char* pneedle, size_t needlelen) {
+ return int_memmatch<false>(phaystack, haylen, pneedle, needlelen);
+}
+
+// This is significantly faster for case-sensitive matches with very
+// few possible matches. See unit test for benchmarks.
+const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
+ size_t neelen);
+
+} // namespace strings_internal
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil_test.cc b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil_test.cc
new file mode 100644
index 0000000..09424de
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/internal/memutil_test.cc
@@ -0,0 +1,179 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Unit test for memutil.cc
+
+#include "absl/strings/internal/memutil.h"
+
+#include <cstdlib>
+
+#include "gtest/gtest.h"
+#include "absl/strings/ascii.h"
+
+namespace {
+
+static char* memcasechr(const char* s, int c, size_t slen) {
+ c = absl::ascii_tolower(c);
+ for (; slen; ++s, --slen) {
+ if (absl::ascii_tolower(*s) == c) return const_cast<char*>(s);
+ }
+ return nullptr;
+}
+
+static const char* memcasematch(const char* phaystack, size_t haylen,
+ const char* pneedle, size_t neelen) {
+ if (0 == neelen) {
+ return phaystack; // even if haylen is 0
+ }
+ if (haylen < neelen) return nullptr;
+
+ const char* match;
+ const char* hayend = phaystack + haylen - neelen + 1;
+ while ((match = static_cast<char*>(
+ memcasechr(phaystack, pneedle[0], hayend - phaystack)))) {
+ if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0)
+ return match;
+ else
+ phaystack = match + 1;
+ }
+ return nullptr;
+}
+
+TEST(MemUtilTest, AllTests) {
+ // check memutil functions
+ char a[1000];
+ absl::strings_internal::memcat(a, 0, "hello", sizeof("hello") - 1);
+ absl::strings_internal::memcat(a, 5, " there", sizeof(" there") - 1);
+
+ EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO there",
+ sizeof("hello there") - 1),
+ 0);
+ EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO therf",
+ sizeof("hello there") - 1),
+ -1);
+ EXPECT_EQ(absl::strings_internal::memcasecmp(a, "heLLO therf",
+ sizeof("hello there") - 2),
+ 0);
+ EXPECT_EQ(absl::strings_internal::memcasecmp(a, "whatever", 0), 0);
+
+ char* p = absl::strings_internal::memdup("hello", 5);
+ free(p);
+
+ p = absl::strings_internal::memrchr("hello there", 'e',
+ sizeof("hello there") - 1);
+ EXPECT_TRUE(p && p[-1] == 'r');
+ p = absl::strings_internal::memrchr("hello there", 'e',
+ sizeof("hello there") - 2);
+ EXPECT_TRUE(p && p[-1] == 'h');
+ p = absl::strings_internal::memrchr("hello there", 'u',
+ sizeof("hello there") - 1);
+ EXPECT_TRUE(p == nullptr);
+
+ int len = absl::strings_internal::memspn("hello there",
+ sizeof("hello there") - 1, "hole");
+ EXPECT_EQ(len, sizeof("hello") - 1);
+ len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1,
+ "u");
+ EXPECT_EQ(len, 0);
+ len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1,
+ "");
+ EXPECT_EQ(len, 0);
+ len = absl::strings_internal::memspn("hello there", sizeof("hello there") - 1,
+ "trole h");
+ EXPECT_EQ(len, sizeof("hello there") - 1);
+ len = absl::strings_internal::memspn("hello there!",
+ sizeof("hello there!") - 1, "trole h");
+ EXPECT_EQ(len, sizeof("hello there") - 1);
+ len = absl::strings_internal::memspn("hello there!",
+ sizeof("hello there!") - 2, "trole h!");
+ EXPECT_EQ(len, sizeof("hello there!") - 2);
+
+ len = absl::strings_internal::memcspn("hello there",
+ sizeof("hello there") - 1, "leho");
+ EXPECT_EQ(len, 0);
+ len = absl::strings_internal::memcspn("hello there",
+ sizeof("hello there") - 1, "u");
+ EXPECT_EQ(len, sizeof("hello there") - 1);
+ len = absl::strings_internal::memcspn("hello there",
+ sizeof("hello there") - 1, "");
+ EXPECT_EQ(len, sizeof("hello there") - 1);
+ len = absl::strings_internal::memcspn("hello there",
+ sizeof("hello there") - 1, " ");
+ EXPECT_EQ(len, 5);
+
+ p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1,
+ "leho");
+ EXPECT_TRUE(p && p[1] == 'e' && p[2] == 'l');
+ p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1,
+ "nu");
+ EXPECT_TRUE(p == nullptr);
+ p = absl::strings_internal::mempbrk("hello there!",
+ sizeof("hello there!") - 2, "!");
+ EXPECT_TRUE(p == nullptr);
+ p = absl::strings_internal::mempbrk("hello there", sizeof("hello there") - 1,
+ " t ");
+ EXPECT_TRUE(p && p[-1] == 'o' && p[1] == 't');
+
+ {
+ const char kHaystack[] = "0123456789";
+ EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 0, "", 0), kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "012", 3),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "0xx", 1),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "789", 3),
+ kHaystack + 7);
+ EXPECT_EQ(absl::strings_internal::memmem(kHaystack, 10, "9xx", 1),
+ kHaystack + 9);
+ EXPECT_TRUE(absl::strings_internal::memmem(kHaystack, 10, "9xx", 3) ==
+ nullptr);
+ EXPECT_TRUE(absl::strings_internal::memmem(kHaystack, 10, "xxx", 1) ==
+ nullptr);
+ }
+ {
+ const char kHaystack[] = "aBcDeFgHiJ";
+ EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 0, "", 0),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "Abc", 3),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "Axx", 1),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "hIj", 3),
+ kHaystack + 7);
+ EXPECT_EQ(absl::strings_internal::memcasemem(kHaystack, 10, "jxx", 1),
+ kHaystack + 9);
+ EXPECT_TRUE(absl::strings_internal::memcasemem(kHaystack, 10, "jxx", 3) ==
+ nullptr);
+ EXPECT_TRUE(absl::strings_internal::memcasemem(kHaystack, 10, "xxx", 1) ==
+ nullptr);
+ }
+ {
+ const char kHaystack[] = "0123456789";
+ EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 0, "", 0), kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "012", 3),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "0xx", 1),
+ kHaystack);
+ EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "789", 3),
+ kHaystack + 7);
+ EXPECT_EQ(absl::strings_internal::memmatch(kHaystack, 10, "9xx", 1),
+ kHaystack + 9);
+ EXPECT_TRUE(absl::strings_internal::memmatch(kHaystack, 10, "9xx", 3) ==
+ nullptr);
+ EXPECT_TRUE(absl::strings_internal::memmatch(kHaystack, 10, "xxx", 1) ==
+ nullptr);
+ }
+}
+
+} // namespace
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h b/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h
new file mode 100644
index 0000000..0157ca0
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h
@@ -0,0 +1,69 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
+#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
+
+#include <string>
+#include <utility>
+
+#include "absl/base/port.h"
+#include "absl/meta/type_traits.h" // for void_t
+
+namespace absl {
+namespace strings_internal {
+
+// Is a subclass of true_type or false_type, depending on whether or not
+// T has a resize_uninitialized member.
+template <typename T, typename = void>
+struct HasResizeUninitialized : std::false_type {};
+template <typename T>
+struct HasResizeUninitialized<
+ T, absl::void_t<decltype(std::declval<T>().resize_uninitialized(237))>>
+ : std::true_type {};
+
+template <typename string_type>
+void ResizeUninit(string_type* s, size_t new_size, std::true_type) {
+ s->resize_uninitialized(new_size);
+}
+template <typename string_type>
+void ResizeUninit(string_type* s, size_t new_size, std::false_type) {
+ s->resize(new_size);
+}
+
+// Returns true if the std::string implementation supports a resize where
+// the new characters added to the std::string are left untouched.
+//
+// (A better name might be "STLStringSupportsUninitializedResize", alluding to
+// the previous function.)
+template <typename string_type>
+inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
+ return HasResizeUninitialized<string_type>();
+}
+
+// Like str->resize(new_size), except any new characters added to "*str" as a
+// result of resizing may be left uninitialized, rather than being filled with
+// '0' bytes. Typically used when code is then going to overwrite the backing
+// store of the std::string with known data. Uses a Google extension to std::string.
+template <typename string_type, typename = void>
+inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
+ ResizeUninit(s, new_size, HasResizeUninitialized<string_type>());
+}
+
+} // namespace strings_internal
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc b/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
new file mode 100644
index 0000000..ad282ef
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
@@ -0,0 +1,68 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/resize_uninitialized.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+int resize_call_count = 0;
+
+struct resizable_string {
+ void resize(size_t) { resize_call_count += 1; }
+};
+
+int resize_uninitialized_call_count = 0;
+
+struct resize_uninitializable_string {
+ void resize(size_t) { resize_call_count += 1; }
+ void resize_uninitialized(size_t) { resize_uninitialized_call_count += 1; }
+};
+
+TEST(ResizeUninit, WithAndWithout) {
+ resize_call_count = 0;
+ resize_uninitialized_call_count = 0;
+ {
+ resizable_string rs;
+
+ EXPECT_EQ(resize_call_count, 0);
+ EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_FALSE(
+ absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
+ EXPECT_EQ(resize_call_count, 0);
+ EXPECT_EQ(resize_uninitialized_call_count, 0);
+ absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
+ EXPECT_EQ(resize_call_count, 1);
+ EXPECT_EQ(resize_uninitialized_call_count, 0);
+ }
+
+ resize_call_count = 0;
+ resize_uninitialized_call_count = 0;
+ {
+ resize_uninitializable_string rus;
+
+ EXPECT_EQ(resize_call_count, 0);
+ EXPECT_EQ(resize_uninitialized_call_count, 0);
+ EXPECT_TRUE(
+ absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
+ EXPECT_EQ(resize_call_count, 0);
+ EXPECT_EQ(resize_uninitialized_call_count, 0);
+ absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
+ EXPECT_EQ(resize_call_count, 0);
+ EXPECT_EQ(resize_uninitialized_call_count, 1);
+ }
+}
+
+} // namespace
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/match.cc b/Firestore/third_party/abseil-cpp/absl/strings/match.cc
new file mode 100644
index 0000000..25bd7f0
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/match.cc
@@ -0,0 +1,40 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/match.h"
+
+#include "absl/strings/internal/memutil.h"
+
+namespace absl {
+
+namespace {
+bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
+ return (piece1.size() == piece2.size() &&
+ 0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
+ piece1.size()));
+ // memcasecmp uses ascii_tolower().
+}
+} // namespace
+
+bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
+ return (text.size() >= prefix.size()) &&
+ CaseEqual(text.substr(0, prefix.size()), prefix);
+}
+
+bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
+ return (text.size() >= suffix.size()) &&
+ CaseEqual(text.substr(text.size() - suffix.size()), suffix);
+}
+
+} // namespace absl
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/match.h b/Firestore/third_party/abseil-cpp/absl/strings/match.h
new file mode 100644
index 0000000..6005533
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/match.h
@@ -0,0 +1,84 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: match.h
+// -----------------------------------------------------------------------------
+//
+// This file contains simple utilities for performing std::string matching checks.
+// All of these function parameters are specified as `absl::string_view`,
+// meaning that these functions can accept `std::string`, `absl::string_view` or
+// nul-terminated C-style strings.
+//
+// Examples:
+// std::string s = "foo";
+// absl::string_view sv = "f";
+// assert(absl::StrContains(s, sv));
+//
+// Note: The order of parameters in these functions is designed to mimic the
+// order an equivalent member function would exhibit;
+// e.g. `s.Contains(x)` ==> `absl::StrContains(s, x).
+#ifndef ABSL_STRINGS_MATCH_H_
+#define ABSL_STRINGS_MATCH_H_
+
+#include <cstring>
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+
+// StrContains()
+//
+// Returns whether a given std::string `haystack` contains the substring `needle`.
+inline bool StrContains(absl::string_view haystack, absl::string_view needle) {
+ return static_cast<absl::string_view::size_type>(haystack.find(needle, 0)) !=
+ haystack.npos;
+}
+
+// StartsWith()
+//
+// Returns whether a given std::string `text` begins with `prefix`.
+inline bool StartsWith(absl::string_view text, absl::string_view prefix) {
+ return prefix.empty() ||
+ (text.size() >= prefix.size() &&
+ memcmp(text.data(), prefix.data(), prefix.size()) == 0);
+}
+
+// EndsWith()
+//
+// Returns whether a given std::string `text` ends with `suffix`.
+inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
+ return suffix.empty() ||
+ (text.size() >= suffix.size() &&
+ memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
+ suffix.size()) == 0
+ );
+}
+
+// StartsWithIgnoreCase()
+//
+// Returns whether a given std::string `text` starts with `starts_with`, ignoring
+// case in the comparison.
+bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
+
+// EndsWithIgnoreCase()
+//
+// Returns whether a given std::string `text` ends with `ends_with`, ignoring case
+// in the comparison.
+bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
+
+} // namespace absl
+
+#endif // ABSL_STRINGS_MATCH_H_
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/match_test.cc b/Firestore/third_party/abseil-cpp/absl/strings/match_test.cc
new file mode 100644
index 0000000..d194f0e
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/match_test.cc
@@ -0,0 +1,99 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/match.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(MatchTest, StartsWith) {
+ const std::string s1("123" "\0" "456", 7);
+ const absl::string_view a("foobar");
+ const absl::string_view b(s1);
+ const absl::string_view e;
+ EXPECT_TRUE(absl::StartsWith(a, a));
+ EXPECT_TRUE(absl::StartsWith(a, "foo"));
+ EXPECT_TRUE(absl::StartsWith(a, e));
+ EXPECT_TRUE(absl::StartsWith(b, s1));
+ EXPECT_TRUE(absl::StartsWith(b, b));
+ EXPECT_TRUE(absl::StartsWith(b, e));
+ EXPECT_TRUE(absl::StartsWith(e, ""));
+ EXPECT_FALSE(absl::StartsWith(a, b));
+ EXPECT_FALSE(absl::StartsWith(b, a));
+ EXPECT_FALSE(absl::StartsWith(e, a));
+}
+
+TEST(MatchTest, EndsWith) {
+ const std::string s1("123" "\0" "456", 7);
+ const absl::string_view a("foobar");
+ const absl::string_view b(s1);
+ const absl::string_view e;
+ EXPECT_TRUE(absl::EndsWith(a, a));
+ EXPECT_TRUE(absl::EndsWith(a, "bar"));
+ EXPECT_TRUE(absl::EndsWith(a, e));
+ EXPECT_TRUE(absl::EndsWith(b, s1));
+ EXPECT_TRUE(absl::EndsWith(b, b));
+ EXPECT_TRUE(absl::EndsWith(b, e));
+ EXPECT_TRUE(absl::EndsWith(e, ""));
+ EXPECT_FALSE(absl::EndsWith(a, b));
+ EXPECT_FALSE(absl::EndsWith(b, a));
+ EXPECT_FALSE(absl::EndsWith(e, a));
+}
+
+TEST(MatchTest, Contains) {
+ absl::string_view a("abcdefg");
+ absl::string_view b("abcd");
+ absl::string_view c("efg");
+ absl::string_view d("gh");
+ EXPECT_TRUE(absl::StrContains(a, a));
+ EXPECT_TRUE(absl::StrContains(a, b));
+ EXPECT_TRUE(absl::StrContains(a, c));
+ EXPECT_FALSE(absl::StrContains(a, d));
+ EXPECT_TRUE(absl::StrContains("", ""));
+ EXPECT_TRUE(absl::StrContains("abc", ""));
+ EXPECT_FALSE(absl::StrContains("", "a"));
+}
+
+TEST(MatchTest, ContainsNull) {
+ const std::string s = "foo";
+ const char* cs = "foo";
+ const absl::string_view sv("foo");
+ const absl::string_view sv2("foo\0bar", 4);
+ EXPECT_EQ(s, "foo");
+ EXPECT_EQ(sv, "foo");
+ EXPECT_NE(sv2, "foo");
+ EXPECT_TRUE(absl::EndsWith(s, sv));
+ EXPECT_TRUE(absl::StartsWith(cs, sv));
+ EXPECT_TRUE(absl::StrContains(cs, sv));
+ EXPECT_FALSE(absl::StrContains(cs, sv2));
+}
+
+TEST(MatchTest, StartsWithIgnoreCase) {
+ EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "foo"));
+ EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "Fo"));
+ EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", ""));
+ EXPECT_FALSE(absl::StartsWithIgnoreCase("foo", "fooo"));
+ EXPECT_FALSE(absl::StartsWithIgnoreCase("", "fo"));
+}
+
+TEST(MatchTest, EndsWithIgnoreCase) {
+ EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", "foo"));
+ EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", "Oo"));
+ EXPECT_TRUE(absl::EndsWithIgnoreCase("foo", ""));
+ EXPECT_FALSE(absl::EndsWithIgnoreCase("foo", "fooo"));
+ EXPECT_FALSE(absl::EndsWithIgnoreCase("", "fo"));
+}
+
+} // namespace
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/string_view.cc b/Firestore/third_party/abseil-cpp/absl/strings/string_view.cc
new file mode 100644
index 0000000..0e17295
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/string_view.cc
@@ -0,0 +1,247 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/string_view.h"
+
+#ifndef ABSL_HAVE_STD_STRING_VIEW
+
+#include <algorithm>
+#include <climits>
+#include <cstring>
+#include <ostream>
+
+#include "absl/strings/internal/memutil.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/match.h"
+
+namespace absl {
+
+namespace {
+void WritePadding(std::ostream& o, size_t pad) {
+ char fill_buf[32];
+ memset(fill_buf, o.fill(), sizeof(fill_buf));
+ while (pad) {
+ size_t n = std::min(pad, sizeof(fill_buf));
+ o.write(fill_buf, n);
+ pad -= n;
+ }
+}
+
+class LookupTable {
+ public:
+ // For each character in wanted, sets the index corresponding
+ // to the ASCII code of that character. This is used by
+ // the find_.*_of methods below to tell whether or not a character is in
+ // the lookup table in constant time.
+ explicit LookupTable(string_view wanted) {
+ for (char c : wanted) {
+ table_[Index(c)] = true;
+ }
+ }
+ bool operator[](char c) const { return table_[Index(c)]; }
+
+ private:
+ static unsigned char Index(char c) { return static_cast<unsigned char>(c); }
+ bool table_[UCHAR_MAX + 1] = {};
+};
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& o, string_view piece) {
+ std::ostream::sentry sentry(o);
+ if (sentry) {
+ size_t lpad = 0;
+ size_t rpad = 0;
+ if (static_cast<size_t>(o.width()) > piece.size()) {
+ size_t pad = o.width() - piece.size();
+ if ((o.flags() & o.adjustfield) == o.left) {
+ rpad = pad;
+ } else {
+ lpad = pad;
+ }
+ }
+ if (lpad) WritePadding(o, lpad);
+ o.write(piece.data(), piece.size());
+ if (rpad) WritePadding(o, rpad);
+ o.width(0);
+ }
+ return o;
+}
+
+string_view::size_type string_view::copy(char* buf, size_type n,
+ size_type pos) const {
+ size_type ulen = length_;
+ assert(pos <= ulen);
+ size_type rlen = std::min(ulen - pos, n);
+ if (rlen > 0) {
+ const char* start = ptr_ + pos;
+ std::copy(start, start + rlen, buf);
+ }
+ return rlen;
+}
+
+string_view::size_type string_view::find(string_view s, size_type pos) const
+ noexcept {
+ if (empty() || pos > length_) {
+ if (empty() && pos == 0 && s.empty()) return 0;
+ return npos;
+ }
+ const char* result =
+ strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
+ return result ? result - ptr_ : npos;
+}
+
+string_view::size_type string_view::find(char c, size_type pos) const noexcept {
+ if (empty() || pos >= length_) {
+ return npos;
+ }
+ const char* result =
+ static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos));
+ return result != nullptr ? result - ptr_ : npos;
+}
+
+string_view::size_type string_view::rfind(string_view s, size_type pos) const
+ noexcept {
+ if (length_ < s.length_) return npos;
+ if (s.empty()) return std::min(length_, pos);
+ const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
+ const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
+ return result != last ? result - ptr_ : npos;
+}
+
+// Search range is [0..pos] inclusive. If pos == npos, search everything.
+string_view::size_type string_view::rfind(char c, size_type pos) const
+ noexcept {
+ // Note: memrchr() is not available on Windows.
+ if (empty()) return npos;
+ for (size_type i = std::min(pos, length_ - 1);; --i) {
+ if (ptr_[i] == c) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_first_of(string_view s,
+ size_type pos) const
+ noexcept {
+ if (empty() || s.empty()) {
+ return npos;
+ }
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = pos; i < length_; ++i) {
+ if (tbl[ptr_[i]]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_first_not_of(string_view s,
+ size_type pos) const
+ noexcept {
+ if (empty()) return npos;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = pos; i < length_; ++i) {
+ if (!tbl[ptr_[i]]) {
+ return i;
+ }
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_first_not_of(char c,
+ size_type pos) const
+ noexcept {
+ if (empty()) return npos;
+ for (; pos < length_; ++pos) {
+ if (ptr_[pos] != c) {
+ return pos;
+ }
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_last_of(string_view s,
+ size_type pos) const noexcept {
+ if (empty() || s.empty()) return npos;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (size_type i = std::min(pos, length_ - 1);; --i) {
+ if (tbl[ptr_[i]]) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_last_not_of(string_view s,
+ size_type pos) const
+ noexcept {
+ if (empty()) return npos;
+ size_type i = std::min(pos, length_ - 1);
+ if (s.empty()) return i;
+ // Avoid the cost of LookupTable() for a single-character search.
+ if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
+ LookupTable tbl(s);
+ for (;; --i) {
+ if (!tbl[ptr_[i]]) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
+string_view::size_type string_view::find_last_not_of(char c,
+ size_type pos) const
+ noexcept {
+ if (empty()) return npos;
+ size_type i = std::min(pos, length_ - 1);
+ for (;; --i) {
+ if (ptr_[i] != c) {
+ return i;
+ }
+ if (i == 0) break;
+ }
+ return npos;
+}
+
+// MSVC has non-standard behavior that implicitly creates definitions for static
+// const members. These implicit definitions conflict with explicit out-of-class
+// member definitions that are required by the C++ standard, resulting in
+// LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
+// MSVC to choose only one definition for the symbol it decorates. See details
+// at http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
+#ifdef _MSC_VER
+#define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
+#else
+#define ABSL_STRING_VIEW_SELECTANY
+#endif
+
+ABSL_STRING_VIEW_SELECTANY
+constexpr string_view::size_type string_view::npos;
+ABSL_STRING_VIEW_SELECTANY
+constexpr string_view::size_type string_view::kMaxSize;
+
+} // namespace absl
+
+#endif // ABSL_HAVE_STD_STRING_VIEW
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/string_view.h b/Firestore/third_party/abseil-cpp/absl/strings/string_view.h
new file mode 100644
index 0000000..c3acd72
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/string_view.h
@@ -0,0 +1,570 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: string_view.h
+// -----------------------------------------------------------------------------
+//
+// This file contains the definition of the `absl::string_view` class. A
+// `string_view` points to a contiguous span of characters, often part or all of
+// another `std::string`, double-quoted std::string literal, character array, or even
+// another `string_view`.
+//
+// This `absl::string_view` abstraction is designed to be a drop-in
+// replacement for the C++17 `std::string_view` abstraction.
+#ifndef ABSL_STRINGS_STRING_VIEW_H_
+#define ABSL_STRINGS_STRING_VIEW_H_
+
+#include <algorithm>
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_STD_STRING_VIEW
+
+#include <string_view>
+
+namespace absl {
+using std::string_view;
+};
+
+#else // ABSL_HAVE_STD_STRING_VIEW
+
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <limits>
+#include <string>
+
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+
+namespace absl {
+
+// absl::string_view
+//
+// A `string_view` provides a lightweight view into the std::string data provided by
+// a `std::string`, double-quoted std::string literal, character array, or even
+// another `string_view`. A `string_view` does *not* own the std::string to which it
+// points, and that data cannot be modified through the view.
+//
+// You can use `string_view` as a function or method parameter anywhere a
+// parameter can receive a double-quoted std::string literal, `const char*`,
+// `std::string`, or another `absl::string_view` argument with no need to copy
+// the std::string data. Systematic use of `string_view` within function arguments
+// reduces data copies and `strlen()` calls.
+//
+// Because of its small size, prefer passing `string_view` by value:
+//
+// void MyFunction(absl::string_view arg);
+//
+// If circumstances require, you may also pass one by const reference:
+//
+// void MyFunction(const absl::string_view& arg); // not preferred
+//
+// Passing by value generates slightly smaller code for many architectures.
+//
+// In either case, the source data of the `string_view` must outlive the
+// `string_view` itself.
+//
+// A `string_view` is also suitable for local variables if you know that the
+// lifetime of the underlying object is longer than the lifetime of your
+// `string_view` variable. However, beware of binding a `string_view` to a
+// temporary value:
+//
+// // BAD use of string_view: lifetime problem
+// absl::string_view sv = obj.ReturnAString();
+//
+// // GOOD use of string_view: str outlives sv
+// std::string str = obj.ReturnAString();
+// absl::string_view sv = str;
+//
+// Due to lifetime issues, a `string_view` is sometimes a poor choice for a
+// return value and usually a poor choice for a data member. If you do use a
+// `string_view` this way, it is your responsibility to ensure that the object
+// pointed to by the `string_view` outlives the `string_view`.
+//
+// A `string_view` may represent a whole std::string or just part of a std::string. For
+// example, when splitting a std::string, `std::vector<absl::string_view>` is a
+// natural data type for the output.
+//
+//
+// When constructed from a source which is nul-terminated, the `string_view`
+// itself will not include the nul-terminator unless a specific size (including
+// the nul) is passed to the constructor. As a result, common idioms that work
+// on nul-terminated strings do not work on `string_view` objects. If you write
+// code that scans a `string_view`, you must check its length rather than test
+// for nul, for example. Note, however, that nuls may still be embedded within
+// a `string_view` explicitly.
+//
+// You may create a null `string_view` in two ways:
+//
+// absl::string_view sv();
+// absl::string_view sv(nullptr, 0);
+//
+// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
+// `sv.empty() == true`. Also, if you create a `string_view` with a non-null
+// pointer then `sv.data() != nullptr`. Thus, you can use `string_view()` to
+// signal an undefined value that is different from other `string_view` values
+// in a similar fashion to how `const char* p1 = nullptr;` is different from
+// `const char* p2 = "";`. However, in practice, it is not recommended to rely
+// on this behavior.
+//
+// Be careful not to confuse a null `string_view` with an empty one. A null
+// `string_view` is an empty `string_view`, but some empty `string_view`s are
+// not null. Prefer checking for emptiness over checking for null.
+//
+// There are many ways to create an empty string_view:
+//
+// const char* nullcp = nullptr;
+// // string_view.size() will return 0 in all cases.
+// absl::string_view();
+// absl::string_view(nullcp, 0);
+// absl::string_view("");
+// absl::string_view("", 0);
+// absl::string_view("abcdef", 0);
+// absl::string_view("abcdef" + 6, 0);
+//
+// All empty `string_view` objects whether null or not, are equal:
+//
+// absl::string_view() == absl::string_view("", 0)
+// absl::string_view(nullptr, 0) == absl:: string_view("abcdef"+6, 0)
+class string_view {
+ public:
+ using traits_type = std::char_traits<char>;
+ using value_type = char;
+ using pointer = char*;
+ using const_pointer = const char*;
+ using reference = char&;
+ using const_reference = const char&;
+ using const_iterator = const char*;
+ using iterator = const_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = const_reverse_iterator;
+ using size_type = size_t;
+ using difference_type = std::ptrdiff_t;
+
+ static constexpr size_type npos = static_cast<size_type>(-1);
+
+ // Null `string_view` constructor
+ constexpr string_view() noexcept : ptr_(nullptr), length_(0) {}
+
+ // Implicit constructors
+
+ template <typename Allocator>
+ string_view( // NOLINT(runtime/explicit)
+ const std::basic_string<char, std::char_traits<char>, Allocator>&
+ str) noexcept
+ : ptr_(str.data()), length_(str.size()) {}
+
+ // Implicit constructor of a `string_view` from nul-terminated `str`. When
+ // accepting possibly null strings, use `absl::NullSafeStringView(str)`
+ // instead (see below).
+ constexpr string_view(const char* str) // NOLINT(runtime/explicit)
+ : ptr_(str), length_(StrLenInternal(str)) {}
+
+ // Implicit constructor of a `string_view` from a `const char*` and length.
+ constexpr string_view(const char* data, size_type len)
+ : ptr_(data), length_(CheckLengthInternal(len)) {}
+
+ // NOTE: Harmlessly omitted to work around gdb bug.
+ // constexpr string_view(const string_view&) noexcept = default;
+ // string_view& operator=(const string_view&) noexcept = default;
+
+ // Iterators
+
+ // string_view::begin()
+ //
+ // Returns an iterator pointing to the first character at the beginning of the
+ // `string_view`, or `end()` if the `string_view` is empty.
+ constexpr const_iterator begin() const noexcept { return ptr_; }
+
+ // string_view::end()
+ //
+ // Returns an iterator pointing just beyond the last character at the end of
+ // the `string_view`. This iterator acts as a placeholder; attempting to
+ // access it results in undefined behavior.
+ constexpr const_iterator end() const noexcept { return ptr_ + length_; }
+
+ // string_view::cbegin()
+ //
+ // Returns a const iterator pointing to the first character at the beginning
+ // of the `string_view`, or `end()` if the `string_view` is empty.
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ // string_view::cend()
+ //
+ // Returns a const iterator pointing just beyond the last character at the end
+ // of the `string_view`. This pointer acts as a placeholder; attempting to
+ // access its element results in undefined behavior.
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ // string_view::rbegin()
+ //
+ // Returns a reverse iterator pointing to the last character at the end of the
+ // `string_view`, or `rend()` if the `string_view` is empty.
+ const_reverse_iterator rbegin() const noexcept {
+ return const_reverse_iterator(end());
+ }
+
+ // string_view::rend()
+ //
+ // Returns a reverse iterator pointing just before the first character at the
+ // beginning of the `string_view`. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
+ const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator(begin());
+ }
+
+ // string_view::crbegin()
+ //
+ // Returns a const reverse iterator pointing to the last character at the end
+ // of the `string_view`, or `crend()` if the `string_view` is empty.
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+ // string_view::crend()
+ //
+ // Returns a const reverse iterator pointing just before the first character
+ // at the beginning of the `string_view`. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // Capacity Utilities
+
+ // string_view::size()
+ //
+ // Returns the number of characters in the `string_view`.
+ constexpr size_type size() const noexcept {
+ return length_;
+ }
+
+ // string_view::length()
+ //
+ // Returns the number of characters in the `string_view`. Alias for `size()`.
+ constexpr size_type length() const noexcept { return size(); }
+
+ // string_view::max_size()
+ //
+ // Returns the maximum number of characters the `string_view` can hold.
+ constexpr size_type max_size() const noexcept { return kMaxSize; }
+
+ // string_view::empty()
+ //
+ // Checks if the `string_view` is empty (refers to no characters).
+ constexpr bool empty() const noexcept { return length_ == 0; }
+
+ // std::string:view::operator[]
+ //
+ // Returns the ith element of an `string_view` using the array operator.
+ // Note that this operator does not perform any bounds checking.
+ constexpr const_reference operator[](size_type i) const { return ptr_[i]; }
+
+ // string_view::front()
+ //
+ // Returns the first element of a `string_view`.
+ constexpr const_reference front() const { return ptr_[0]; }
+
+ // string_view::back()
+ //
+ // Returns the last element of a `string_view`.
+ constexpr const_reference back() const { return ptr_[size() - 1]; }
+
+ // string_view::data()
+ //
+ // Returns a pointer to the underlying character array (which is of course
+ // stored elsewhere). Note that `string_view::data()` may contain embedded nul
+ // characters, but the returned buffer may or may not be nul-terminated;
+ // therefore, do not pass `data()` to a routine that expects a nul-terminated
+ // std::string.
+ constexpr const_pointer data() const noexcept { return ptr_; }
+
+ // Modifiers
+
+ // string_view::remove_prefix()
+ //
+ // Removes the first `n` characters from the `string_view`. Note that the
+ // underlying std::string is not changed, only the view.
+ void remove_prefix(size_type n) {
+ assert(n <= length_);
+ ptr_ += n;
+ length_ -= n;
+ }
+
+ // string_view::remove_suffix()
+ //
+ // Removes the last `n` characters from the `string_view`. Note that the
+ // underlying std::string is not changed, only the view.
+ void remove_suffix(size_type n) {
+ assert(n <= length_);
+ length_ -= n;
+ }
+
+ // string_view::swap()
+ //
+ // Swaps this `string_view` with another `string_view`.
+ void swap(string_view& s) noexcept {
+ auto t = *this;
+ *this = s;
+ s = t;
+ }
+
+ // Explicit conversion operators
+
+ // Converts to `std::basic_string`.
+ template <typename A>
+ explicit operator std::basic_string<char, traits_type, A>() const {
+ if (!data()) return {};
+ return std::basic_string<char, traits_type, A>(data(), size());
+ }
+
+ // string_view::copy()
+ //
+ // Copies the contents of the `string_view` at offset `pos` and length `n`
+ // into `buf`.
+ size_type copy(char* buf, size_type n, size_type pos = 0) const;
+
+ // string_view::substr()
+ //
+ // Returns a "substring" of the `string_view` (at offset `pos` and length
+ // `n`) as another string_view. This function throws `std::out_of_bounds` if
+ // `pos > size'.
+ string_view substr(size_type pos, size_type n = npos) const {
+ if (ABSL_PREDICT_FALSE(pos > length_))
+ base_internal::ThrowStdOutOfRange("absl::string_view::substr");
+ n = std::min(n, length_ - pos);
+ return string_view(ptr_ + pos, n);
+ }
+
+ // string_view::compare()
+ //
+ // Performs a lexicographical comparison between the `string_view` and
+ // another `absl::string_view), returning -1 if `this` is less than, 0 if
+ // `this` is equal to, and 1 if `this` is greater than the passed std::string
+ // view. Note that in the case of data equality, a further comparison is made
+ // on the respective sizes of the two `string_view`s to determine which is
+ // smaller, equal, or greater.
+ int compare(string_view x) const noexcept {
+ auto min_length = std::min(length_, x.length_);
+ if (min_length > 0) {
+ int r = memcmp(ptr_, x.ptr_, min_length);
+ if (r < 0) return -1;
+ if (r > 0) return 1;
+ }
+ if (length_ < x.length_) return -1;
+ if (length_ > x.length_) return 1;
+ return 0;
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
+ // 'string_view` and another `absl::string_view`.
+ int compare(size_type pos1, size_type count1, string_view v) const {
+ return substr(pos1, count1).compare(v);
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
+ // `string_view` and a substring of another `absl::string_view`.
+ int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
+ size_type count2) const {
+ return substr(pos1, count1).compare(v.substr(pos2, count2));
+ }
+
+ // Overload of `string_view::compare()` for comparing a `string_view` and a
+ // a different C-style std::string `s`.
+ int compare(const char* s) const { return compare(string_view(s)); }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
+ // `string_view` and a different std::string C-style std::string `s`.
+ int compare(size_type pos1, size_type count1, const char* s) const {
+ return substr(pos1, count1).compare(string_view(s));
+ }
+
+ // Overload of `string_view::compare()` for comparing a substring of the
+ // `string_view` and a substring of a different C-style std::string `s`.
+ int compare(size_type pos1, size_type count1, const char* s,
+ size_type count2) const {
+ return substr(pos1, count1).compare(string_view(s, count2));
+ }
+
+ // Find Utilities
+
+ // string_view::find()
+ //
+ // Finds the first occurrence of the substring `s` within the `string_view`,
+ // returning the position of the first character's match, or `npos` if no
+ // match was found.
+ size_type find(string_view s, size_type pos = 0) const noexcept;
+
+ // Overload of `string_view::find()` for finding the given character `c`
+ // within the `string_view`.
+ size_type find(char c, size_type pos = 0) const noexcept;
+
+ // string_view::rfind()
+ //
+ // Finds the last occurrence of a substring `s` within the `string_view`,
+ // returning the position of the first character's match, or `npos` if no
+ // match was found.
+ size_type rfind(string_view s, size_type pos = npos) const
+ noexcept;
+
+ // Overload of `string_view::rfind()` for finding the given character `c`
+ // within the `string_view`.
+ size_type rfind(char c, size_type pos = npos) const noexcept;
+
+ // string_view::find_first_of()
+ //
+ // Finds the first occurrence of any of the characters in `s` within the
+ // `string_view`, returning the start position of the match, or `npos` if no
+ // match was found.
+ size_type find_first_of(string_view s, size_type pos = 0) const
+ noexcept;
+
+ // Overload of `string_view::find_first_of()` for finding a character `c`
+ // within the `string_view`.
+ size_type find_first_of(char c, size_type pos = 0) const
+ noexcept {
+ return find(c, pos);
+ }
+
+ // string_view::find_last_of()
+ //
+ // Finds the last occurrence of any of the characters in `s` within the
+ // `string_view`, returning the start position of the match, or `npos` if no
+ // match was found.
+ size_type find_last_of(string_view s, size_type pos = npos) const
+ noexcept;
+
+ // Overload of `string_view::find_last_of()` for finding a character `c`
+ // within the `string_view`.
+ size_type find_last_of(char c, size_type pos = npos) const
+ noexcept {
+ return rfind(c, pos);
+ }
+
+ // string_view::find_first_not_of()
+ //
+ // Finds the first occurrence of any of the characters not in `s` within the
+ // `string_view`, returning the start position of the first non-match, or
+ // `npos` if no non-match was found.
+ size_type find_first_not_of(string_view s, size_type pos = 0) const noexcept;
+
+ // Overload of `string_view::find_first_not_of()` for finding a character
+ // that is not `c` within the `string_view`.
+ size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
+
+ // string_view::find_last_not_of()
+ //
+ // Finds the last occurrence of any of the characters not in `s` within the
+ // `string_view`, returning the start position of the last non-match, or
+ // `npos` if no non-match was found.
+ size_type find_last_not_of(string_view s,
+ size_type pos = npos) const noexcept;
+
+ // Overload of `string_view::find_last_not_of()` for finding a character
+ // that is not `c` within the `string_view`.
+ size_type find_last_not_of(char c, size_type pos = npos) const
+ noexcept;
+
+ private:
+ static constexpr size_type kMaxSize =
+ std::numeric_limits<size_type>::max() / 2 + 1;
+
+ // check whether __builtin_strlen is provided by the compiler.
+ // GCC doesn't have __has_builtin()
+ // (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970),
+ // but has __builtin_strlen according to
+ // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html.
+#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
+ (defined(__GNUC__) && !defined(__clang__))
+ static constexpr size_type StrLenInternal(const char* str) {
+ return str ? __builtin_strlen(str) : 0;
+ }
+#else
+ static constexpr size_type StrLenInternal(const char* str) {
+ return str ? strlen(str) : 0;
+ }
+#endif
+
+ static constexpr size_type CheckLengthInternal(size_type len) {
+ return ABSL_ASSERT(len <= kMaxSize), len;
+ }
+
+ const char* ptr_;
+ size_type length_;
+};
+
+// This large function is defined inline so that in a fairly common case where
+// one of the arguments is a literal, the compiler can elide a lot of the
+// following comparisons.
+inline bool operator==(string_view x, string_view y) noexcept {
+ auto len = x.size();
+ if (len != y.size()) {
+ return false;
+ }
+ return x.data() == y.data() || len <= 0 ||
+ memcmp(x.data(), y.data(), len) == 0;
+}
+
+inline bool operator!=(string_view x, string_view y) noexcept {
+ return !(x == y);
+}
+
+inline bool operator<(string_view x, string_view y) noexcept {
+ auto min_size = std::min(x.size(), y.size());
+ const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
+ return (r < 0) || (r == 0 && x.size() < y.size());
+}
+
+inline bool operator>(string_view x, string_view y) noexcept { return y < x; }
+
+inline bool operator<=(string_view x, string_view y) noexcept {
+ return !(y < x);
+}
+
+inline bool operator>=(string_view x, string_view y) noexcept {
+ return !(x < y);
+}
+
+// IO Insertion Operator
+std::ostream& operator<<(std::ostream& o, string_view piece);
+
+} // namespace absl
+
+#endif // ABSL_HAVE_STD_STRING_VIEW
+
+namespace absl {
+
+// ClippedSubstr()
+//
+// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`.
+// Provided because std::string_view::substr throws if `pos > size()`
+inline string_view ClippedSubstr(string_view s, size_t pos,
+ size_t n = string_view::npos) {
+ pos = std::min(pos, static_cast<size_t>(s.size()));
+ return s.substr(pos, n);
+}
+
+// NullSafeStringView()
+//
+// Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
+// This function should be used where an `absl::string_view` can be created from
+// a possibly-null pointer.
+inline string_view NullSafeStringView(const char* p) {
+ return p ? string_view(p) : string_view();
+}
+
+} // namespace absl
+
+#endif // ABSL_STRINGS_STRING_VIEW_H_
diff --git a/Firestore/third_party/abseil-cpp/absl/strings/string_view_test.cc b/Firestore/third_party/abseil-cpp/absl/strings/string_view_test.cc
new file mode 100644
index 0000000..13fc214
--- /dev/null
+++ b/Firestore/third_party/abseil-cpp/absl/strings/string_view_test.cc
@@ -0,0 +1,1101 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/string_view.h"
+
+#include <stdlib.h>
+#include <iomanip>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/dynamic_annotations.h"
+
+namespace {
+
+// A minimal allocator that uses malloc().
+template <typename T>
+struct Mallocator {
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+
+ size_type max_size() const {
+ return size_t(std::numeric_limits<size_type>::max()) / sizeof(value_type);
+ }
+ template <typename U>
+ struct rebind {
+ typedef Mallocator<U> other;
+ };
+ Mallocator() = default;
+
+ T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); }
+ void deallocate(T* p, size_t) { std::free(p); }
+};
+template <typename T, typename U>
+bool operator==(const Mallocator<T>&, const Mallocator<U>&) {
+ return true;
+}
+template <typename T, typename U>
+bool operator!=(const Mallocator<T>&, const Mallocator<U>&) {
+ return false;
+}
+
+TEST(StringViewTest, Ctor) {
+ {
+ // Null.
+ absl::string_view s10;
+ EXPECT_TRUE(s10.data() == nullptr);
+ EXPECT_EQ(0, s10.length());
+ }
+
+ {
+ // const char* without length.
+ const char* hello = "hello";
+ absl::string_view s20(hello);
+ EXPECT_TRUE(s20.data() == hello);
+ EXPECT_EQ(5, s20.length());
+
+ // const char* with length.
+ absl::string_view s21(hello, 4);
+ EXPECT_TRUE(s21.data() == hello);
+ EXPECT_EQ(4, s21.length());
+
+ // Not recommended, but valid C++
+ absl::string_view s22(hello, 6);
+ EXPECT_TRUE(s22.data() == hello);
+ EXPECT_EQ(6, s22.length());
+ }
+
+ {
+ // std::string.
+ std::string hola = "hola";
+ absl::string_view s30(hola);
+ EXPECT_TRUE(s30.data() == hola.data());
+ EXPECT_EQ(4, s30.length());
+
+ // std::string with embedded '\0'.
+ hola.push_back('\0');
+ hola.append("h2");
+ hola.push_back('\0');
+ absl::string_view s31(hola);
+ EXPECT_TRUE(s31.data() == hola.data());
+ EXPECT_EQ(8, s31.length());
+ }
+
+ {
+ using mstring =
+ std::basic_string<char, std::char_traits<char>, Mallocator<char>>;
+ mstring str1("BUNGIE-JUMPING!");
+ const mstring str2("SLEEPING!");
+
+ absl::string_view s1(str1);
+ s1.remove_prefix(strlen("BUNGIE-JUM"));
+
+ absl::string_view s2(str2);
+ s2.remove_prefix(strlen("SLEE"));
+
+ EXPECT_EQ(s1, s2);
+ EXPECT_EQ(s1, "PING!");
+ }
+
+ // TODO(mec): absl::string_view(const absl::string_view&);
+}
+
+TEST(StringViewTest, Swap) {
+ absl::string_view a("a");
+ absl::string_view b("bbb");
+ EXPECT_TRUE(noexcept(a.swap(b)));
+ a.swap(b);
+ EXPECT_EQ(a, "bbb");
+ EXPECT_EQ(b, "a");
+ a.swap(b);
+ EXPECT_EQ(a, "a");
+ EXPECT_EQ(b, "bbb");
+}
+
+TEST(StringViewTest, STLComparator) {
+ std::string s1("foo");
+ std::string s2("bar");
+ std::string s3("baz");
+
+ absl::string_view p1(s1);
+ absl::string_view p2(s2);
+ absl::string_view p3(s3);
+
+ typedef std::map<absl::string_view, int> TestMap;
+ TestMap map;
+
+ map.insert(std::make_pair(p1, 0));
+ map.insert(std::make_pair(p2, 1));
+ map.insert(std::make_pair(p3, 2));
+ EXPECT_EQ(map.size(), 3);
+
+ TestMap::const_iterator iter = map.begin();
+ EXPECT_EQ(iter->second, 1);
+ ++iter;
+ EXPECT_EQ(iter->second, 2);
+ ++iter;
+ EXPECT_EQ(iter->second, 0);
+ ++iter;
+ EXPECT_TRUE(iter == map.end());
+
+ TestMap::iterator new_iter = map.find("zot");
+ EXPECT_TRUE(new_iter == map.end());
+
+ new_iter = map.find("bar");
+ EXPECT_TRUE(new_iter != map.end());
+
+ map.erase(new_iter);
+ EXPECT_EQ(map.size(), 2);
+
+ iter = map.begin();
+ EXPECT_EQ(iter->second, 2);
+ ++iter;
+ EXPECT_EQ(iter->second, 0);
+ ++iter;
+ EXPECT_TRUE(iter == map.end());
+}
+
+#define COMPARE(result, op, x, y) \
+ EXPECT_EQ(result, absl::string_view((x)) op absl::string_view((y))); \
+ EXPECT_EQ(result, absl::string_view((x)).compare(absl::string_view((y))) op 0)
+
+TEST(StringViewTest, ComparisonOperators) {
+ COMPARE(true, ==, "", "");
+ COMPARE(true, ==, "", absl::string_view());
+ COMPARE(true, ==, absl::string_view(), "");
+ COMPARE(true, ==, "a", "a");
+ COMPARE(true, ==, "aa", "aa");
+ COMPARE(false, ==, "a", "");
+ COMPARE(false, ==, "", "a");
+ COMPARE(false, ==, "a", "b");
+ COMPARE(false, ==, "a", "aa");
+ COMPARE(false, ==, "aa", "a");
+
+ COMPARE(false, !=, "", "");
+ COMPARE(false, !=, "a", "a");
+ COMPARE(false, !=, "aa", "aa");
+ COMPARE(true, !=, "a", "");
+ COMPARE(true, !=, "", "a");
+ COMPARE(true, !=, "a", "b");
+ COMPARE(true, !=, "a", "aa");
+ COMPARE(true, !=, "aa", "a");
+
+ COMPARE(true, <, "a", "b");
+ COMPARE(true, <, "a", "aa");
+ COMPARE(true, <, "aa", "b");
+ COMPARE(true, <, "aa", "bb");
+ COMPARE(false, <, "a", "a");
+ COMPARE(false, <, "b", "a");
+ COMPARE(false, <, "aa", "a");
+ COMPARE(false, <, "b", "aa");
+ COMPARE(false, <, "bb", "aa");
+
+ COMPARE(true, <=, "a", "a");
+ COMPARE(true, <=, "a", "b");
+ COMPARE(true, <=, "a", "aa");
+ COMPARE(true, <=, "aa", "b");
+ COMPARE(true, <=, "aa", "bb");
+ COMPARE(false, <=, "b", "a");
+ COMPARE(false, <=, "aa", "a");
+ COMPARE(false, <=, "b", "aa");
+ COMPARE(false, <=, "bb", "aa");
+
+ COMPARE(false, >=, "a", "b");
+ COMPARE(false, >=, "a", "aa");
+ COMPARE(false, >=, "aa", "b");
+ COMPARE(false, >=, "aa", "bb");
+ COMPARE(true, >=, "a", "a");
+ COMPARE(true, >=, "b", "a");
+ COMPARE(true, >=, "aa", "a");
+ COMPARE(true, >=, "b", "aa");
+ COMPARE(true, >=, "bb", "aa");
+
+ COMPARE(false, >, "a", "a");
+ COMPARE(false, >, "a", "b");
+ COMPARE(false, >, "a", "aa");
+ COMPARE(false, >, "aa", "b");
+ COMPARE(false, >, "aa", "bb");
+ COMPARE(true, >, "b", "a");
+ COMPARE(true, >, "aa", "a");
+ COMPARE(true, >, "b", "aa");
+ COMPARE(true, >, "bb", "aa");
+}
+
+TEST(StringViewTest, ComparisonOperatorsByCharacterPosition) {
+ std::string x;
+ for (int i = 0; i < 256; i++) {
+ x += 'a';
+ std::string y = x;
+ COMPARE(true, ==, x, y);
+ for (int j = 0; j < i; j++) {
+ std::string z = x;
+ z[j] = 'b'; // Differs in position 'j'
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ if (j + 1 < i) {
+ z[j + 1] = 'A'; // Differs in position 'j+1' as well
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ z[j + 1] = 'z'; // Differs in position 'j+1' as well
+ COMPARE(false, ==, x, z);
+ COMPARE(true, <, x, z);
+ COMPARE(true, >, z, x);
+ }
+ }
+ }
+}
+#undef COMPARE
+
+// Sadly, our users often confuse std::string::npos with absl::string_view::npos;
+// So much so that we test here that they are the same. They need to
+// both be unsigned, and both be the maximum-valued integer of their type.
+
+template <typename T>
+struct is_type {
+ template <typename U>
+ static bool same(U) {
+ return false;
+ }
+ static bool same(T) { return true; }
+};
+
+TEST(StringViewTest, NposMatchesStdStringView) {
+ EXPECT_EQ(absl::string_view::npos, std::string::npos);
+
+ EXPECT_TRUE(is_type<size_t>::same(absl::string_view::npos));
+ EXPECT_FALSE(is_type<size_t>::same(""));
+
+ // Make sure absl::string_view::npos continues to be a header constant.
+ char test[absl::string_view::npos & 1] = {0};
+ EXPECT_EQ(0, test[0]);
+}
+
+TEST(StringViewTest, STL1) {
+ const absl::string_view a("abcdefghijklmnopqrstuvwxyz");
+ const absl::string_view b("abc");
+ const absl::string_view c("xyz");
+ const absl::string_view d("foobar");
+ const absl::string_view e;
+ std::string temp("123");
+ temp += '\0';
+ temp += "456";
+ const absl::string_view f(temp);
+
+ EXPECT_EQ(a[6], 'g');
+ EXPECT_EQ(b[0], 'a');
+ EXPECT_EQ(c[2], 'z');
+ EXPECT_EQ(f[3], '\0');
+ EXPECT_EQ(f[5], '5');
+
+ EXPECT_EQ(*d.data(), 'f');
+ EXPECT_EQ(d.data()[5], 'r');
+ EXPECT_TRUE(e.data() == nullptr);
+
+ EXPECT_EQ(*a.begin(), 'a');
+ EXPECT_EQ(*(b.begin() + 2), 'c');
+ EXPECT_EQ(*(c.end() - 1), 'z');
+
+ EXPECT_EQ(*a.rbegin(), 'z');
+ EXPECT_EQ(*(b.rbegin() + 2), 'a');
+ EXPECT_EQ(*(c.rend() - 1), 'x');
+ EXPECT_TRUE(a.rbegin() + 26 == a.rend());
+
+ EXPECT_EQ(a.size(), 26);
+ EXPECT_EQ(b.size(), 3);
+ EXPECT_EQ(c.size(), 3);
+ EXPECT_EQ(d.size(), 6);
+ EXPECT_EQ(e.size(), 0);
+ EXPECT_EQ(f.size(), 7);
+
+ EXPECT_TRUE(!d.empty());
+ EXPECT_TRUE(d.begin() != d.end());
+ EXPECT_TRUE(d.begin() + 6 == d.end());
+
+ EXPECT_TRUE(e.empty());
+ EXPECT_TRUE(e.begin() == e.end());
+
+ char buf[4] = { '%', '%', '%', '%' };
+ EXPECT_EQ(a.copy(buf, 4), 4);
+ EXPECT_EQ(buf[0], a[0]);
+ EXPECT_EQ(buf[1], a[1]);
+ EXPECT_EQ(buf[2], a[2]);
+ EXPECT_EQ(buf[3], a[3]);
+ EXPECT_EQ(a.copy(buf, 3, 7), 3);
+ EXPECT_EQ(buf[0], a[7]);
+ EXPECT_EQ(buf[1], a[8]);
+ EXPECT_EQ(buf[2], a[9]);
+ EXPECT_EQ(buf[3], a[3]);
+ EXPECT_EQ(c.copy(buf, 99), 3);
+ EXPECT_EQ(buf[0], c[0]);
+ EXPECT_EQ(buf[1], c[1]);
+ EXPECT_EQ(buf[2], c[2]);
+ EXPECT_EQ(buf[3], a[3]);
+}
+
+// Separated from STL1() because some compilers produce an overly
+// large stack frame for the combined function.
+TEST(StringViewTest, STL2) {
+ const absl::string_view a("abcdefghijklmnopqrstuvwxyz");
+ const absl::string_view b("abc");
+ const absl::string_view c("xyz");
+ absl::string_view d("foobar");
+ const absl::string_view e;
+ const absl::string_view f(
+ "123"
+ "\0"
+ "456",
+ 7);
+
+ d = absl::string_view();
+ EXPECT_EQ(d.size(), 0);
+ EXPECT_TRUE(d.empty());
+ EXPECT_TRUE(d.data() == nullptr);
+ EXPECT_TRUE(d.begin() == d.end());
+
+ EXPECT_EQ(a.find(b), 0);
+ EXPECT_EQ(a.find(b, 1), absl::string_view::npos);
+ EXPECT_EQ(a.find(c), 23);
+ EXPECT_EQ(a.find(c, 9), 23);
+ EXPECT_EQ(a.find(c, absl::string_view::npos), absl::string_view::npos);
+ EXPECT_EQ(b.find(c), absl::string_view::npos);
+ EXPECT_EQ(b.find(c, absl::string_view::npos), absl::string_view::npos);
+ EXPECT_EQ(a.find(d), 0);
+ EXPECT_EQ(a.find(e), 0);
+ EXPECT_EQ(a.find(d, 12), 12);
+ EXPECT_EQ(a.find(e, 17), 17);
+ absl::string_view g("xx not found bb");
+ EXPECT_EQ(a.find(g), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(d.find(b), absl::string_view::npos);
+ EXPECT_EQ(e.find(b), absl::string_view::npos);
+ EXPECT_EQ(d.find(b, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find(b, 7), absl::string_view::npos);
+
+ size_t empty_search_pos = std::string().find(std::string());
+ EXPECT_EQ(d.find(d), empty_search_pos);
+ EXPECT_EQ(d.find(e), empty_search_pos);
+ EXPECT_EQ(e.find(d), empty_search_pos);
+ EXPECT_EQ(e.find(e), empty_search_pos);
+ EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4));
+ EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4));
+ EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4));
+ EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
+
+ EXPECT_EQ(a.find('a'), 0);
+ EXPECT_EQ(a.find('c'), 2);
+ EXPECT_EQ(a.find('z'), 25);
+ EXPECT_EQ(a.find('$'), absl::string_view::npos);
+ EXPECT_EQ(a.find('\0'), absl::string_view::npos);
+ EXPECT_EQ(f.find('\0'), 3);
+ EXPECT_EQ(f.find('3'), 2);
+ EXPECT_EQ(f.find('5'), 5);
+ EXPECT_EQ(g.find('o'), 4);
+ EXPECT_EQ(g.find('o', 4), 4);
+ EXPECT_EQ(g.find('o', 5), 8);
+ EXPECT_EQ(a.find('b', 5), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(d.find('\0'), absl::string_view::npos);
+ EXPECT_EQ(e.find('\0'), absl::string_view::npos);
+ EXPECT_EQ(d.find('\0', 4), absl::string_view::npos);
+ EXPECT_EQ(e.find('\0', 7), absl::string_view::npos);
+ EXPECT_EQ(d.find('x'), absl::string_view::npos);
+ EXPECT_EQ(e.find('x'), absl::string_view::npos);
+ EXPECT_EQ(d.find('x', 4), absl::string_view::npos);
+ EXPECT_EQ(e.find('x', 7), absl::string_view::npos);
+
+ EXPECT_EQ(a.rfind(b), 0);
+ EXPECT_EQ(a.rfind(b, 1), 0);
+ EXPECT_EQ(a.rfind(c), 23);
+ EXPECT_EQ(a.rfind(c, 22), absl::string_view::npos);
+ EXPECT_EQ(a.rfind(c, 1), absl::string_view::npos);
+ EXPECT_EQ(a.rfind(c, 0), absl::string_view::npos);
+ EXPECT_EQ(b.rfind(c), absl::string_view::npos);
+ EXPECT_EQ(b.rfind(c, 0), absl::string_view::npos);
+ EXPECT_EQ(a.rfind(d), std::string(a).rfind(std::string()));
+ EXPECT_EQ(a.rfind(e), std::string(a).rfind(std::string()));
+ EXPECT_EQ(a.rfind(d, 12), 12);
+ EXPECT_EQ(a.rfind(e, 17), 17);
+ EXPECT_EQ(a.rfind(g), absl::string_view::npos);
+ EXPECT_EQ(d.rfind(b), absl::string_view::npos);
+ EXPECT_EQ(e.rfind(b), absl::string_view::npos);
+ EXPECT_EQ(d.rfind(b, 4), absl::string_view::npos);
+ EXPECT_EQ(e.rfind(b, 7), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
+ EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
+ EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
+ EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
+ EXPECT_EQ(d.rfind(d), std::string().rfind(std::string()));
+ EXPECT_EQ(e.rfind(d), std::string().rfind(std::string()));
+ EXPECT_EQ(d.rfind(e), std::string().rfind(std::string()));
+ EXPECT_EQ(e.rfind(e), std::string().rfind(std::string()));
+
+ EXPECT_EQ(g.rfind('o'), 8);
+ EXPECT_EQ(g.rfind('q'), absl::string_view::npos);
+ EXPECT_EQ(g.rfind('o', 8), 8);
+ EXPECT_EQ(g.rfind('o', 7), 4);
+ EXPECT_EQ(g.rfind('o', 3), absl::string_view::npos);
+ EXPECT_EQ(f.rfind('\0'), 3);
+ EXPECT_EQ(f.rfind('\0', 12), 3);
+ EXPECT_EQ(f.rfind('3'), 2);
+ EXPECT_EQ(f.rfind('5'), 5);
+ // empty std::string nonsense
+ EXPECT_EQ(d.rfind('o'), absl::string_view::npos);
+ EXPECT_EQ(e.rfind('o'), absl::string_view::npos);
+ EXPECT_EQ(d.rfind('o', 4), absl::string_view::npos);
+ EXPECT_EQ(e.rfind('o', 7), absl::string_view::npos);
+}
+
+// Continued from STL2
+TEST(StringViewTest, STL2FindFirst) {
+ const absl::string_view a("abcdefghijklmnopqrstuvwxyz");
+ const absl::string_view b("abc");
+ const absl::string_view c("xyz");
+ absl::string_view d("foobar");
+ const absl::string_view e;
+ const absl::string_view f(
+ "123"
+ "\0"
+ "456",
+ 7);
+ absl::string_view g("xx not found bb");
+
+ d = absl::string_view();
+ EXPECT_EQ(a.find_first_of(b), 0);
+ EXPECT_EQ(a.find_first_of(b, 0), 0);
+ EXPECT_EQ(a.find_first_of(b, 1), 1);
+ EXPECT_EQ(a.find_first_of(b, 2), 2);
+ EXPECT_EQ(a.find_first_of(b, 3), absl::string_view::npos);
+ EXPECT_EQ(a.find_first_of(c), 23);
+ EXPECT_EQ(a.find_first_of(c, 23), 23);
+ EXPECT_EQ(a.find_first_of(c, 24), 24);
+ EXPECT_EQ(a.find_first_of(c, 25), 25);
+ EXPECT_EQ(a.find_first_of(c, 26), absl::string_view::npos);
+ EXPECT_EQ(g.find_first_of(b), 13);
+ EXPECT_EQ(g.find_first_of(c), 0);
+ EXPECT_EQ(a.find_first_of(f), absl::string_view::npos);
+ EXPECT_EQ(f.find_first_of(a), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(a.find_first_of(d), absl::string_view::npos);
+ EXPECT_EQ(a.find_first_of(e), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_of(b), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_of(b), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_of(d), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_of(d), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_of(e), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_of(e), absl::string_view::npos);
+
+ EXPECT_EQ(a.find_first_not_of(b), 3);
+ EXPECT_EQ(a.find_first_not_of(c), 0);
+ EXPECT_EQ(b.find_first_not_of(a), absl::string_view::npos);
+ EXPECT_EQ(c.find_first_not_of(a), absl::string_view::npos);
+ EXPECT_EQ(f.find_first_not_of(a), 0);
+ EXPECT_EQ(a.find_first_not_of(f), 0);
+ EXPECT_EQ(a.find_first_not_of(d), 0);
+ EXPECT_EQ(a.find_first_not_of(e), 0);
+ // empty std::string nonsense
+ EXPECT_EQ(a.find_first_not_of(d), 0);
+ EXPECT_EQ(a.find_first_not_of(e), 0);
+ EXPECT_EQ(a.find_first_not_of(d, 1), 1);
+ EXPECT_EQ(a.find_first_not_of(e, 1), 1);
+ EXPECT_EQ(a.find_first_not_of(d, a.size() - 1), a.size() - 1);
+ EXPECT_EQ(a.find_first_not_of(e, a.size() - 1), a.size() - 1);
+ EXPECT_EQ(a.find_first_not_of(d, a.size()), absl::string_view::npos);
+ EXPECT_EQ(a.find_first_not_of(e, a.size()), absl::string_view::npos);
+ EXPECT_EQ(a.find_first_not_of(d, absl::string_view::npos),
+ absl::string_view::npos);
+ EXPECT_EQ(a.find_first_not_of(e, absl::string_view::npos),
+ absl::string_view::npos);
+ EXPECT_EQ(d.find_first_not_of(a), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_not_of(a), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_not_of(d), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_not_of(d), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_not_of(e), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_not_of(e), absl::string_view::npos);
+
+ absl::string_view h("====");
+ EXPECT_EQ(h.find_first_not_of('='), absl::string_view::npos);
+ EXPECT_EQ(h.find_first_not_of('=', 3), absl::string_view::npos);
+ EXPECT_EQ(h.find_first_not_of('\0'), 0);
+ EXPECT_EQ(g.find_first_not_of('x'), 2);
+ EXPECT_EQ(f.find_first_not_of('\0'), 0);
+ EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
+ EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
+ // empty std::string nonsense
+ EXPECT_EQ(d.find_first_not_of('x'), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_not_of('x'), absl::string_view::npos);
+ EXPECT_EQ(d.find_first_not_of('\0'), absl::string_view::npos);
+ EXPECT_EQ(e.find_first_not_of('\0'), absl::string_view::npos);
+}
+
+// Continued from STL2
+TEST(StringViewTest, STL2FindLast) {
+ const absl::string_view a("abcdefghijklmnopqrstuvwxyz");
+ const absl::string_view b("abc");
+ const absl::string_view c("xyz");
+ absl::string_view d("foobar");
+ const absl::string_view e;
+ const absl::string_view f(
+ "123"
+ "\0"
+ "456",
+ 7);
+ absl::string_view g("xx not found bb");
+ absl::string_view h("====");
+ absl::string_view i("56");
+
+ d = absl::string_view();
+ EXPECT_EQ(h.find_last_of(a), absl::string_view::npos);
+ EXPECT_EQ(g.find_last_of(a), g.size()-1);
+ EXPECT_EQ(a.find_last_of(b), 2);
+ EXPECT_EQ(a.find_last_of(c), a.size()-1);
+ EXPECT_EQ(f.find_last_of(i), 6);
+ EXPECT_EQ(a.find_last_of('a'), 0);
+ EXPECT_EQ(a.find_last_of('b'), 1);
+ EXPECT_EQ(a.find_last_of('z'), 25);
+ EXPECT_EQ(a.find_last_of('a', 5), 0);
+ EXPECT_EQ(a.find_last_of('b', 5), 1);
+ EXPECT_EQ(a.find_last_of('b', 0), absl::string_view::npos);
+ EXPECT_EQ(a.find_last_of('z', 25), 25);
+ EXPECT_EQ(a.find_last_of('z', 24), absl::string_view::npos);
+ EXPECT_EQ(f.find_last_of(i, 5), 5);
+ EXPECT_EQ(f.find_last_of(i, 6), 6);
+ EXPECT_EQ(f.find_last_of(a, 4), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(f.find_last_of(d), absl::string_view::npos);
+ EXPECT_EQ(f.find_last_of(e), absl::string_view::npos);
+ EXPECT_EQ(f.find_last_of(d, 4), absl::string_view::npos);
+ EXPECT_EQ(f.find_last_of(e, 4), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(d), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(e), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(d), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(e), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(f), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(f), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(d, 4), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(e, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(d, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(e, 4), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_of(f, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_of(f, 4), absl::string_view::npos);
+
+ EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
+ EXPECT_EQ(a.find_last_not_of(c), 22);
+ EXPECT_EQ(b.find_last_not_of(a), absl::string_view::npos);
+ EXPECT_EQ(b.find_last_not_of(b), absl::string_view::npos);
+ EXPECT_EQ(f.find_last_not_of(i), 4);
+ EXPECT_EQ(a.find_last_not_of(c, 24), 22);
+ EXPECT_EQ(a.find_last_not_of(b, 3), 3);
+ EXPECT_EQ(a.find_last_not_of(b, 2), absl::string_view::npos);
+ // empty std::string nonsense
+ EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
+ EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
+ EXPECT_EQ(f.find_last_not_of(d, 4), 4);
+ EXPECT_EQ(f.find_last_not_of(e, 4), 4);
+ EXPECT_EQ(d.find_last_not_of(d), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of(e), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(d), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(e), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of(f), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(f), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of(d, 4), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of(e, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(d, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(e, 4), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of(f, 4), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of(f, 4), absl::string_view::npos);
+
+ EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
+ EXPECT_EQ(h.find_last_not_of('='), absl::string_view::npos);
+ EXPECT_EQ(b.find_last_not_of('c'), 1);
+ EXPECT_EQ(h.find_last_not_of('x', 2), 2);
+ EXPECT_EQ(h.find_last_not_of('=', 2), absl::string_view::npos);
+ EXPECT_EQ(b.find_last_not_of('b', 1), 0);
+ // empty std::string nonsense
+ EXPECT_EQ(d.find_last_not_of('x'), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of('x'), absl::string_view::npos);
+ EXPECT_EQ(d.find_last_not_of('\0'), absl::string_view::npos);
+ EXPECT_EQ(e.find_last_not_of('\0'), absl::string_view::npos);
+}
+
+// Continued from STL2
+TEST(StringViewTest, STL2Substr) {
+ const absl::string_view a("abcdefghijklmnopqrstuvwxyz");
+ const absl::string_view b("abc");
+ const absl::string_view c("xyz");
+ absl::string_view d("foobar");
+ const absl::string_view e;
+
+ d = absl::string_view();
+ EXPECT_EQ(a.substr(0, 3), b);
+ EXPECT_EQ(a.substr(23), c);
+ EXPECT_EQ(a.substr(23, 3), c);
+ EXPECT_EQ(a.substr(23, 99), c);
+ EXPECT_EQ(a.substr(0), a);
+ EXPECT_EQ(a.substr(3, 2), "de");
+ // empty std::string nonsense
+ EXPECT_EQ(d.substr(0, 99), e);
+ // use of npos
+ EXPECT_EQ(a.substr(0, absl::string_view::npos), a);
+ EXPECT_EQ(a.substr(23, absl::string_view::npos), c);
+ // throw exception
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(a.substr(99, 2), std::out_of_range);
+#else
+ EXPECT_DEATH(a.substr(99, 2), "absl::string_view::substr");
+#endif
+}
+
+TEST(StringViewTest, TruncSubstr) {
+ const absl::string_view hi("hi");
+ EXPECT_EQ("", absl::ClippedSubstr(hi, 0, 0));
+ EXPECT_EQ("h", absl::ClippedSubstr(hi, 0, 1));
+ EXPECT_EQ("hi", absl::ClippedSubstr(hi, 0));
+ EXPECT_EQ("i", absl::ClippedSubstr(hi, 1));
+ EXPECT_EQ("", absl::ClippedSubstr(hi, 2));
+ EXPECT_EQ("", absl::ClippedSubstr(hi, 3)); // truncation
+ EXPECT_EQ("", absl::ClippedSubstr(hi, 3, 2)); // truncation
+}
+
+TEST(StringViewTest, UTF8) {
+ EXPECT_EQ(strlen("á"), absl::string_view("á á").find_first_of(" "));
+ EXPECT_EQ(strlen("á"), absl::string_view("á á").find_first_of(" \t"));
+}
+
+TEST(StringViewTest, FindConformance) {
+ struct {
+ std::string haystack;
+ std::string needle;
+ } specs[] = {
+ {"", ""},
+ {"", "a"},
+ {"a", ""},
+ {"a", "a"},
+ {"a", "b"},
+ {"aa", ""},
+ {"aa", "a"},
+ {"aa", "b"},
+ {"ab", "a"},
+ {"ab", "b"},
+ {"abcd", ""},
+ {"abcd", "a"},
+ {"abcd", "d"},
+ {"abcd", "ab"},
+ {"abcd", "bc"},
+ {"abcd", "cd"},
+ {"abcd", "abcd"},
+ };
+ for (const auto& s : specs) {
+ SCOPED_TRACE(s.haystack);
+ SCOPED_TRACE(s.needle);
+ std::string st = s.haystack;
+ absl::string_view sp = s.haystack;
+ for (size_t i = 0; i <= sp.size(); ++i) {
+ size_t pos = (i == sp.size()) ? absl::string_view::npos : i;
+ SCOPED_TRACE(pos);
+ EXPECT_EQ(sp.find(s.needle, pos),
+ st.find(s.needle, pos));
+ EXPECT_EQ(sp.rfind(s.needle, pos),
+ st.rfind(s.needle, pos));
+ EXPECT_EQ(sp.find_first_of(s.needle, pos),
+ st.find_first_of(s.needle, pos));
+ EXPECT_EQ(sp.find_first_not_of(s.needle, pos),
+ st.find_first_not_of(s.needle, pos));
+ EXPECT_EQ(sp.find_last_of(s.needle, pos),
+ st.find_last_of(s.needle, pos));
+ EXPECT_EQ(sp.find_last_not_of(s.needle, pos),
+ st.find_last_not_of(s.needle, pos));
+ }
+ }
+}
+
+TEST(StringViewTest, Remove) {
+ absl::string_view a("foobar");
+ std::string s1("123");
+ s1 += '\0';
+ s1 += "456";
+ absl::string_view b(s1);
+ absl::string_view e;
+ std::string s2;
+
+ // remove_prefix
+ absl::string_view c(a);
+ c.remove_prefix(3);
+ EXPECT_EQ(c, "bar");
+ c = a;
+ c.remove_prefix(0);
+ EXPECT_EQ(c, a);
+ c.remove_prefix(c.size());
+ EXPECT_EQ(c, e);
+
+ // remove_suffix
+ c = a;
+ c.remove_suffix(3);
+ EXPECT_EQ(c, "foo");
+ c = a;
+ c.remove_suffix(0);
+ EXPECT_EQ(c, a);
+ c.remove_suffix(c.size());
+ EXPECT_EQ(c, e);
+}
+
+TEST(StringViewTest, Set) {
+ absl::string_view a("foobar");
+ absl::string_view empty;
+ absl::string_view b;
+
+ // set
+ b = absl::string_view("foobar", 6);
+ EXPECT_EQ(b, a);
+ b = absl::string_view("foobar", 0);
+ EXPECT_EQ(b, empty);
+ b = absl::string_view("foobar", 7);
+ EXPECT_NE(b, a);
+
+ b = absl::string_view("foobar");
+ EXPECT_EQ(b, a);
+}
+
+TEST(StringViewTest, FrontBack) {
+ static const char arr[] = "abcd";
+ const absl::string_view csp(arr, 4);
+ EXPECT_EQ(&arr[0], &csp.front());
+ EXPECT_EQ(&arr[3], &csp.back());
+}
+
+TEST(StringViewTest, FrontBackSingleChar) {
+ static const char c = 'a';
+ const absl::string_view csp(&c, 1);
+ EXPECT_EQ(&c, &csp.front());
+ EXPECT_EQ(&c, &csp.back());
+}
+
+TEST(StringViewTest, NULLInput) {
+ absl::string_view s;
+ EXPECT_EQ(s.data(), nullptr);
+ EXPECT_EQ(s.size(), 0);
+
+ s = absl::string_view(nullptr);
+ EXPECT_EQ(s.data(), nullptr);
+ EXPECT_EQ(s.size(), 0);
+
+ // .ToString() on a absl::string_view with nullptr should produce the empty
+ // std::string.
+ EXPECT_EQ("", std::string(s));
+}
+
+TEST(StringViewTest, Comparisons2) {
+ // The `compare` member has 6 overloads (v: string_view, s: const char*):
+ // (1) compare(v)
+ // (2) compare(pos1, count1, v)
+ // (3) compare(pos1, count1, v, pos2, count2)
+ // (4) compare(s)
+ // (5) compare(pos1, count1, s)
+ // (6) compare(pos1, count1, s, count2)
+
+ absl::string_view abc("abcdefghijklmnopqrstuvwxyz");
+
+ // check comparison operations on strings longer than 4 bytes.
+ EXPECT_EQ(abc, absl::string_view("abcdefghijklmnopqrstuvwxyz"));
+ EXPECT_EQ(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxyz")), 0);
+
+ EXPECT_LT(abc, absl::string_view("abcdefghijklmnopqrstuvwxzz"));
+ EXPECT_LT(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxzz")), 0);
+
+ EXPECT_GT(abc, absl::string_view("abcdefghijklmnopqrstuvwxyy"));
+ EXPECT_GT(abc.compare(absl::string_view("abcdefghijklmnopqrstuvwxyy")), 0);
+
+ // The "substr" variants of `compare`.
+ absl::string_view digits("0123456789");
+ auto npos = absl::string_view::npos;
+
+ // Taking string_view
+ EXPECT_EQ(digits.compare(3, npos, absl::string_view("3456789")), 0); // 2
+ EXPECT_EQ(digits.compare(3, 4, absl::string_view("3456")), 0); // 2
+ EXPECT_EQ(digits.compare(10, 0, absl::string_view()), 0); // 2
+ EXPECT_EQ(digits.compare(3, 4, absl::string_view("0123456789"), 3, 4),
+ 0); // 3
+ EXPECT_LT(digits.compare(3, 4, absl::string_view("0123456789"), 3, 5),
+ 0); // 3
+ EXPECT_LT(digits.compare(0, npos, absl::string_view("0123456789"), 3, 5),
+ 0); // 3
+ // Taking const char*
+ EXPECT_EQ(digits.compare(3, 4, "3456"), 0); // 5
+ EXPECT_EQ(digits.compare(3, npos, "3456789"), 0); // 5
+ EXPECT_EQ(digits.compare(10, 0, ""), 0); // 5
+ EXPECT_EQ(digits.compare(3, 4, "0123456789", 3, 4), 0); // 6
+ EXPECT_LT(digits.compare(3, 4, "0123456789", 3, 5), 0); // 6
+ EXPECT_LT(digits.compare(0, npos, "0123456789", 3, 5), 0); // 6
+}
+
+struct MyCharAlloc : std::allocator<char> {};
+
+TEST(StringViewTest, ExplicitConversionOperator) {
+ absl::string_view sp = "hi";
+ EXPECT_EQ(sp, std::string(sp));
+}
+
+TEST(StringViewTest, NullSafeStringView) {
+ {
+ absl::string_view s = absl::NullSafeStringView(nullptr);
+ EXPECT_EQ(nullptr, s.data());
+ EXPECT_EQ(0, s.size());
+ EXPECT_EQ(absl::string_view(), s);
+ }
+ {
+ static const char kHi[] = "hi";
+ absl::string_view s = absl::NullSafeStringView(kHi);
+ EXPECT_EQ(kHi, s.data());
+ EXPECT_EQ(strlen(kHi), s.size());
+ EXPECT_EQ(absl::string_view("hi"), s);
+ }
+}
+
+TEST(StringViewTest, ConstexprCompiles) {
+ constexpr absl::string_view sp;
+ constexpr absl::string_view cstr(nullptr);
+ constexpr absl::string_view cstr_len("cstr", 4);
+
+#if defined(ABSL_HAVE_STD_STRING_VIEW)
+ // In libstdc++ (as of 7.2), `std::string_view::string_view(const char*)`
+ // calls `std::char_traits<char>::length(const char*)` to get the std::string
+ // length, but it is not marked constexpr yet. See GCC bug:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78156
+ // Also, there is a LWG issue that adds constexpr to length() which was just
+ // resolved 2017-06-02. See
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2232
+ // TODO(zhangxy): Update the condition when libstdc++ adopts the constexpr
+ // length().
+#if !defined(__GLIBCXX__)
+#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
+#endif // !__GLIBCXX__
+
+#else // ABSL_HAVE_STD_STRING_VIEW
+
+// This duplicates the check for __builtin_strlen in the header.
+#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
+#elif defined(__GNUC__) // GCC or clang
+#error GCC/clang should have constexpr string_view.
+#endif
+
+#endif // ABSL_HAVE_STD_STRING_VIEW
+
+#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR
+ constexpr absl::string_view cstr_strlen("foo");
+ EXPECT_EQ(cstr_strlen.length(), 3);
+ constexpr absl::string_view cstr_strlen2 = "bar";
+ EXPECT_EQ(cstr_strlen2, "bar");
+#endif
+
+#if !defined(__clang__) || 3 < __clang_major__ || \
+ (3 == __clang_major__ && 4 < __clang_minor__)
+ // older clang versions (< 3.5) complain that:
+ // "cannot perform pointer arithmetic on null pointer"
+ constexpr absl::string_view::iterator const_begin_empty = sp.begin();
+ constexpr absl::string_view::iterator const_end_empty = sp.end();
+ EXPECT_EQ(const_begin_empty, const_end_empty);
+
+ constexpr absl::string_view::iterator const_begin_nullptr = cstr.begin();
+ constexpr absl::string_view::iterator const_end_nullptr = cstr.end();
+ EXPECT_EQ(const_begin_nullptr, const_end_nullptr);
+#endif
+
+ constexpr absl::string_view::iterator const_begin = cstr_len.begin();
+ constexpr absl::string_view::iterator const_end = cstr_len.end();
+ constexpr absl::string_view::size_type const_size = cstr_len.size();
+ constexpr absl::string_view::size_type const_length = cstr_len.length();
+ EXPECT_EQ(const_begin + const_size, const_end);
+ EXPECT_EQ(const_begin + const_length, const_end);
+
+ constexpr bool isempty = sp.empty();
+ EXPECT_TRUE(isempty);
+
+ constexpr const char c = cstr_len[2];
+ EXPECT_EQ(c, 't');
+
+ constexpr const char cfront = cstr_len.front();
+ constexpr const char cback = cstr_len.back();
+ EXPECT_EQ(cfront, 'c');
+ EXPECT_EQ(cback, 'r');
+
+ constexpr const char* np = sp.data();
+ constexpr const char* cstr_ptr = cstr_len.data();
+ EXPECT_EQ(np, nullptr);
+ EXPECT_NE(cstr_ptr, nullptr);
+
+ constexpr size_t sp_npos = sp.npos;
+ EXPECT_EQ(sp_npos, -1);
+}
+
+TEST(StringViewTest, Noexcept) {
+ EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
+ const std::string&>::value));
+ EXPECT_TRUE(
+ (std::is_nothrow_constructible<absl::string_view, const std::string&>::value));
+ EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value);
+ constexpr absl::string_view sp;
+ EXPECT_TRUE(noexcept(sp.begin()));
+ EXPECT_TRUE(noexcept(sp.end()));
+ EXPECT_TRUE(noexcept(sp.cbegin()));
+ EXPECT_TRUE(noexcept(sp.cend()));
+ EXPECT_TRUE(noexcept(sp.rbegin()));
+ EXPECT_TRUE(noexcept(sp.rend()));
+ EXPECT_TRUE(noexcept(sp.crbegin()));
+ EXPECT_TRUE(noexcept(sp.crend()));
+ EXPECT_TRUE(noexcept(sp.size()));
+ EXPECT_TRUE(noexcept(sp.length()));
+ EXPECT_TRUE(noexcept(sp.empty()));
+ EXPECT_TRUE(noexcept(sp.data()));
+ EXPECT_TRUE(noexcept(sp.compare(sp)));
+ EXPECT_TRUE(noexcept(sp.find(sp)));
+ EXPECT_TRUE(noexcept(sp.find('f')));
+ EXPECT_TRUE(noexcept(sp.rfind(sp)));
+ EXPECT_TRUE(noexcept(sp.rfind('f')));
+ EXPECT_TRUE(noexcept(sp.find_first_of(sp)));
+ EXPECT_TRUE(noexcept(sp.find_first_of('f')));
+ EXPECT_TRUE(noexcept(sp.find_last_of(sp)));
+ EXPECT_TRUE(noexcept(sp.find_last_of('f')));
+ EXPECT_TRUE(noexcept(sp.find_first_not_of(sp)));
+ EXPECT_TRUE(noexcept(sp.find_first_not_of('f')));
+ EXPECT_TRUE(noexcept(sp.find_last_not_of(sp)));
+ EXPECT_TRUE(noexcept(sp.find_last_not_of('f')));
+}
+
+TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
+ EXPECT_EQ("hello", std::string("hello"));
+ EXPECT_LT("hello", std::string("world"));
+}
+
+TEST(ComparisonOpsTest, HeterogenousStringViewEquals) {
+ EXPECT_EQ(absl::string_view("hello"), std::string("hello"));
+ EXPECT_EQ("hello", absl::string_view("hello"));
+}
+
+TEST(FindOneCharTest, EdgeCases) {
+ absl::string_view a("xxyyyxx");
+
+ // Set a = "xyyyx".
+ a.remove_prefix(1);
+ a.remove_suffix(1);
+
+ EXPECT_EQ(0, a.find('x'));
+ EXPECT_EQ(0, a.find('x', 0));
+ EXPECT_EQ(4, a.find('x', 1));
+ EXPECT_EQ(4, a.find('x', 4));
+ EXPECT_EQ(absl::string_view::npos, a.find('x', 5));
+
+ EXPECT_EQ(4, a.rfind('x'));
+ EXPECT_EQ(4, a.rfind('x', 5));
+ EXPECT_EQ(4, a.rfind('x', 4));
+ EXPECT_EQ(0, a.rfind('x', 3));
+ EXPECT_EQ(0, a.rfind('x', 0));
+
+ // Set a = "yyy".
+ a.remove_prefix(1);
+ a.remove_suffix(1);
+
+ EXPECT_EQ(absl::string_view::npos, a.find('x'));
+ EXPECT_EQ(absl::string_view::npos, a.rfind('x'));
+}
+
+#ifndef THREAD_SANITIZER // Allocates too much memory for tsan.
+TEST(HugeStringView, TwoPointTwoGB) {
+ if (sizeof(size_t) <= 4 || RunningOnValgrind())
+ return;
+ // Try a huge std::string piece.
+ const size_t size = size_t{2200} * 1000 * 1000;
+ std::string s(size, 'a');
+ absl::string_view sp(s);
+ EXPECT_EQ(size, sp.length());
+ sp.remove_prefix(1);
+ EXPECT_EQ(size - 1, sp.length());
+ sp.remove_suffix(2);
+ EXPECT_EQ(size - 1 - 2, sp.length());
+}
+#endif // THREAD_SANITIZER
+
+#ifndef NDEBUG
+TEST(NonNegativeLenTest, NonNegativeLen) {
+ EXPECT_DEATH_IF_SUPPORTED(absl::string_view("xyz", -1), "len <= kMaxSize");
+}
+#endif // NDEBUG
+
+class StringViewStreamTest : public ::testing::Test {
+ public:
+ // Set negative 'width' for right justification.
+ template <typename T>
+ std::string Pad(const T& s, int width, char fill = 0) {
+ std::ostringstream oss;
+ if (fill != 0) {
+ oss << std::setfill(fill);
+ }
+ if (width < 0) {
+ width = -width;
+ oss << std::right;
+ }
+ oss << std::setw(width) << s;
+ return oss.str();
+ }
+};
+
+TEST_F(StringViewStreamTest, Padding) {
+ std::string s("hello");
+ absl::string_view sp(s);
+ for (int w = -64; w < 64; ++w) {
+ SCOPED_TRACE(w);
+ EXPECT_EQ(Pad(s, w), Pad(sp, w));
+ }
+ for (int w = -64; w < 64; ++w) {
+ SCOPED_TRACE(w);
+ EXPECT_EQ(Pad(s, w, '#'), Pad(sp, w, '#'));
+ }
+}
+
+TEST_F(StringViewStreamTest, ResetsWidth) {
+ // Width should reset after one formatted write.
+ // If we weren't resetting width after formatting the string_view,
+ // we'd have width=5 carrying over to the printing of the "]",
+ // creating "[###hi####]".
+ std::string s = "hi";
+ absl::string_view sp = s;
+ {
+ std::ostringstream oss;
+ oss << "[" << std::setfill('#') << std::setw(5) << s << "]";
+ ASSERT_EQ("[###hi]", oss.str());
+ }
+ {
+ std::ostringstream oss;
+ oss << "[" << std::setfill('#') << std::setw(5) << sp << "]";
+ EXPECT_EQ("[###hi]", oss.str());
+ }
+}
+
+} // namespace