Remove the implementation of `absl::string_view`, which was only needed
prior to C++17. `absl::string_view` is now an alias for `std::string_view`.
It is recommended that clients simply use `std::string_view`.
PiperOrigin-RevId: 845822478
Change-Id: I220530c84118e5b9ef110baa002c232ac8f2c5f2
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 9145d8b..cc9f792 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -345,8 +345,6 @@
"strings/str_replace.h"
"strings/str_split.cc"
"strings/str_split.h"
- "strings/string_view.cc"
- "strings/string_view.h"
"strings/strip.h"
"strings/substitute.cc"
"strings/substitute.h"
@@ -446,6 +444,7 @@
"types/variant.h"
"utility/utility.h"
"debugging/leak_check.cc"
+ "strings/string_view.h"
)
if(MSVC)
diff --git a/absl/base/config.h b/absl/base/config.h
index e4518ca..39d60e3 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -526,20 +526,11 @@
#define ABSL_USES_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_USES_STD_OPTIONAL 1
+#define ABSL_HAVE_STD_STRING_VIEW 1
+#define ABSL_USES_STD_STRING_VIEW 1
#define ABSL_HAVE_STD_VARIANT 1
#define ABSL_USES_STD_VARIANT 1
-// ABSL_HAVE_STD_STRING_VIEW
-//
-// Deprecated: always defined to 1.
-// std::string_view was added in C++17, which means all versions of C++
-// supported by Abseil have it.
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set."
-#else
-#define ABSL_HAVE_STD_STRING_VIEW 1
-#endif
-
// ABSL_HAVE_STD_ORDERING
//
// Checks whether C++20 std::{partial,weak,strong}_ordering are available.
@@ -556,20 +547,6 @@
#define ABSL_HAVE_STD_ORDERING 1
#endif
-// ABSL_USES_STD_STRING_VIEW
-//
-// Indicates whether absl::string_view is an alias for std::string_view.
-#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
-#error options.h is misconfigured.
-#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0
-#undef ABSL_USES_STD_STRING_VIEW
-#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
- ABSL_OPTION_USE_STD_STRING_VIEW == 2
-#define ABSL_USES_STD_STRING_VIEW 1
-#else
-#error options.h is misconfigured.
-#endif
-
// ABSL_USES_STD_ORDERING
//
// Indicates whether absl::{partial,weak,strong}_ordering are aliases for the
diff --git a/absl/base/options.h b/absl/base/options.h
index 71bafb3..6f48e75 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -73,32 +73,6 @@
// Type Compatibility Options
// -----------------------------------------------------------------------------
-// ABSL_OPTION_USE_STD_STRING_VIEW
-//
-// This option controls whether absl::string_view is implemented as an alias to
-// std::string_view, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation. This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::string_view. This requires that
-// all code using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::string_view is available. This
-// option is useful when you are building your program from source. It should
-// not be used otherwise -- for example, if you are distributing Abseil in a
-// binary package manager -- since in mode 2, absl::string_view will name a
-// different type, with a different mangled name and binary layout, depending on
-// the compiler flags passed by the end user. For more info, see
-// https://abseil.io/about/design/dropin-types.
-//
-// User code should not inspect this macro. To check in the preprocessor if
-// absl::string_view is a typedef of std::string_view, use the feature macro
-// ABSL_USES_STD_STRING_VIEW.
-
-#define ABSL_OPTION_USE_STD_STRING_VIEW 2
-
// ABSL_OPTION_USE_STD_ORDERING
//
// This option controls whether absl::{partial,weak,strong}_ordering are
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 9dde5e5..49051bd 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -36,16 +36,13 @@
cc_library(
name = "string_view",
- srcs = ["string_view.cc"],
hdrs = ["string_view.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:nullability",
- "//absl/base:throw_delegate",
],
)
@@ -410,23 +407,6 @@
],
)
-cc_binary(
- name = "string_view_benchmark",
- testonly = True,
- srcs = ["string_view_benchmark.cc"],
- copts = ABSL_TEST_COPTS,
- tags = ["benchmark"],
- visibility = ["//visibility:private"],
- deps = [
- ":string_view",
- ":strings",
- "//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
- "//absl/random",
- "@google_benchmark//:benchmark_main",
- ],
-)
-
cc_test(
name = "string_view_test",
size = "small",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 2b97fb5..94e58ea 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -19,16 +19,12 @@
string_view
HDRS
"string_view.h"
- SRCS
- "string_view.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::base
absl::config
absl::core_headers
absl::nullability
- absl::throw_delegate
PUBLIC
)
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
deleted file mode 100644
index 33bd1bb..0000000
--- a/absl/strings/string_view.cc
+++ /dev/null
@@ -1,257 +0,0 @@
-// 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
-//
-// https://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_USES_STD_STRING_VIEW
-
-#include <algorithm>
-#include <climits>
-#include <cstring>
-#include <ostream>
-
-#include "absl/base/nullability.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-namespace {
-
-// This is significantly faster for case-sensitive matches with very
-// few possible matches.
-const char* absl_nullable memmatch(const char* absl_nullable phaystack,
- size_t haylen,
- const char* absl_nullable 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 as memchr returns a const void *, and pointer
- // arithmetic is not allowed on pointers to void.
- while (
- (match = static_cast<const char*>(memchr(
- phaystack, pneedle[0], static_cast<size_t>(hayend - phaystack))))) {
- if (memcmp(match, pneedle, neelen) == 0)
- return match;
- else
- phaystack = match + 1;
- }
- return nullptr;
-}
-
-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, static_cast<std::streamsize>(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 = static_cast<size_t>(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(), static_cast<std::streamsize>(piece.size()));
- if (rpad) WritePadding(o, rpad);
- o.width(0);
- }
- return o;
-}
-
-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 = memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
- return result ? static_cast<size_type>(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 ? static_cast<size_type>(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 ? static_cast<size_type>(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;
-}
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#else
-
-// https://github.com/abseil/abseil-cpp/issues/1465
-// CMake builds on Apple platforms error when libraries are empty.
-// Our CMake configuration can avoid this error on header-only libraries,
-// but since this library is conditionally empty, including a single
-// variable is an easy workaround.
-#ifdef __APPLE__
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-extern const char kAvoidEmptyStringViewLibraryWarning;
-const char kAvoidEmptyStringViewLibraryWarning = 0;
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-#endif // __APPLE__
-
-#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 358570e..9daa149 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -1,4 +1,3 @@
-//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,784 +16,24 @@
// 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 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.
+// Historical note: Abseil once provided an implementation of
+// `absl::string_view` as a polyfill for `std::string_view` prior to C++17. Now
+// that C++17 is required, `absl::string_view` is an alias for
+// `std::string_view`
+
#ifndef ABSL_STRINGS_STRING_VIEW_H_
#define ABSL_STRINGS_STRING_VIEW_H_
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-#include <iosfwd>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <string>
-#include <type_traits>
+#include <string_view>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
-#include "absl/base/internal/throw_delegate.h"
-#include "absl/base/macros.h"
#include "absl/base/nullability.h"
-#include "absl/base/optimization.h"
-#include "absl/base/port.h"
-
-#ifdef ABSL_USES_STD_STRING_VIEW
-
-#include <string_view> // IWYU pragma: export
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-using string_view = std::string_view;
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#else // ABSL_USES_STD_STRING_VIEW
-
-#if ABSL_HAVE_ATTRIBUTE(diagnose_if)
-#define ABSL_INTERNAL_DIAGNOSE_IF_NULLPTR(x) \
- __attribute__((diagnose_if( \
- x == nullptr, \
- "null passed to a callee that requires a non-null argument", "error")))
-#else
-#define ABSL_INTERNAL_DIAGNOSE_IF_NULLPTR(x)
-#endif
-
-#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
- (defined(__GNUC__) && !defined(__clang__)) || \
- (defined(_MSC_VER) && _MSC_VER >= 1928)
-#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
-#else // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
-#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-
-// If `std::ranges` is available, mark `string_view` as satisfying the
-// `view` and `borrowed_range` concepts, just like `std::string_view`.
-#ifdef __has_include
-#if __has_include(<version>)
-#include <version>
-#endif
-#endif
-
-#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
-#include <ranges> // NOLINT(build/c++20)
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-class string_view;
-ABSL_NAMESPACE_END
-} // namespace absl
-
-template <>
-// NOLINTNEXTLINE(build/c++20)
-inline constexpr bool std::ranges::enable_view<absl::string_view> = true;
-template <>
-// NOLINTNEXTLINE(build/c++20)
-inline constexpr bool std::ranges::enable_borrowed_range<absl::string_view> =
- true;
-#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
-// absl::string_view
-//
-// A `string_view` provides a lightweight view into the string data provided by
-// a `std::string`, double-quoted string literal, character array, or even
-// another `string_view`. A `string_view` does *not* own the 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 string literal, `const char*`,
-// `std::string`, or another `absl::string_view` argument with no need to copy
-// the 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 string or just part of a string. For
-// example, when splitting a string, `std::vector<absl::string_view>` is a
-// natural data type for the output.
-//
-// For another example, a Cord is a non-contiguous, potentially very
-// long string-like object. The Cord class has an interface that iteratively
-// provides string_view objects that point to the successive pieces of a Cord
-// object.
-//
-// 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 ABSL_ATTRIBUTE_VIEW string_view {
- public:
- using traits_type = std::char_traits<char>;
- using value_type = char;
- using pointer = char* absl_nullable;
- using const_pointer = const char* absl_nullable;
- using reference = char&;
- using const_reference = const char&;
- using const_iterator = const char* absl_nullable;
- 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;
- using absl_internal_is_view = std::true_type;
-
- 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
- ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
- // This is implemented in terms of `string_view(p, n)` so `str.size()`
- // doesn't need to be reevaluated after `ptr_` is set.
- // The length check is also skipped since it is unnecessary and causes
- // code bloat.
- : string_view(str.data(), str.size(), SkipCheckLengthTag{}) {}
-
- // Implicit constructor of a `string_view` from NUL-terminated `str`. When
- // accepting possibly null strings, use `absl::NullSafeStringView(str)`
- // instead (see below).
- // The length check is skipped since it is unnecessary and causes code bloat.
- constexpr string_view( // NOLINT(runtime/explicit)
- const char* absl_nonnull str) ABSL_INTERNAL_DIAGNOSE_IF_NULLPTR(str)
- : ptr_(str), length_(str ? StrlenInternal(str) : 0) {
- ABSL_HARDENING_ASSERT(str != nullptr);
- }
-
- // Constructor of a `string_view` from a `const char*` and length.
- constexpr string_view(const char* absl_nullable data, size_type len)
- : ptr_(data), length_(CheckLengthInternal(len)) {
- ABSL_ASSERT(data != nullptr || len == 0);
- }
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
- template <std::contiguous_iterator It, std::sized_sentinel_for<It> End>
- requires(std::is_same_v<std::iter_value_t<It>, value_type> &&
- !std::is_convertible_v<End, size_type>)
- constexpr string_view(It begin, End end)
- : ptr_(std::to_address(begin)), length_(end - begin) {
- ABSL_HARDENING_ASSERT(end >= begin);
- }
-#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-
- // Deleted constructor from std::nullptr_t from C++23.
- string_view(std::nullptr_t) = delete;
-
- 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; }
-
- // string_view::operator[]
- //
- // Returns the ith element of the `string_view` using the array operator.
- // Note that this operator does not perform any bounds checking.
- constexpr const_reference operator[](size_type i) const {
- ABSL_HARDENING_ASSERT(i < size());
- return ptr_[i];
- }
-
- // string_view::at()
- //
- // Returns the ith element of the `string_view`. Bounds checking is performed,
- // and an exception of type `std::out_of_range` will be thrown on invalid
- // access.
- constexpr const_reference at(size_type i) const {
- if (ABSL_PREDICT_FALSE(i >= size())) {
- base_internal::ThrowStdOutOfRange("absl::string_view::at");
- }
- return ptr_[i];
- }
-
- // string_view::front()
- //
- // Returns the first element of a `string_view`.
- constexpr const_reference front() const {
- ABSL_HARDENING_ASSERT(!empty());
- return ptr_[0];
- }
-
- // string_view::back()
- //
- // Returns the last element of a `string_view`.
- constexpr const_reference back() const {
- ABSL_HARDENING_ASSERT(!empty());
- 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
- // 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 string is not changed, only the view.
- constexpr void remove_prefix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
- ptr_ += n;
- length_ -= n;
- }
-
- // string_view::remove_suffix()
- //
- // Removes the last `n` characters from the `string_view`. Note that the
- // underlying string is not changed, only the view.
- constexpr void remove_suffix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
- length_ -= n;
- }
-
- // string_view::swap()
- //
- // Swaps this `string_view` with another `string_view`.
- constexpr 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* absl_nonnull buf, size_type n, size_type pos = 0) const {
- if (ABSL_PREDICT_FALSE(pos > length_)) {
- base_internal::ThrowStdOutOfRange("absl::string_view::copy");
- }
- size_type rlen = (std::min)(length_ - pos, n);
- if (rlen > 0) {
- const char* start = ptr_ + pos;
- traits_type::copy(buf, start, rlen);
- }
- return rlen;
- }
-
- // 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`.
- // Use absl::ClippedSubstr if you need a truncating substr operation.
- constexpr string_view substr(size_type pos = 0, size_type n = npos) const {
- if (ABSL_PREDICT_FALSE(pos > length_)) {
- base_internal::ThrowStdOutOfRange("absl::string_view::substr");
- }
- return string_view(ptr_ + pos, (std::min)(n, length_ - pos));
- }
-
- // string_view::compare()
- //
- // Performs a lexicographical comparison between this `string_view` and
- // another `string_view` `x`, returning a negative value if `*this` is less
- // than `x`, 0 if `*this` is equal to `x`, and a positive value if `*this`
- // is greater than `x`.
- constexpr int compare(string_view x) const noexcept {
- return CompareImpl(length_, x.length_,
- (std::min)(length_, x.length_) == 0
- ? 0
- : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
- ptr_, x.ptr_, (std::min)(length_, x.length_)));
- }
-
- // Overload of `string_view::compare()` for comparing a substring of the
- // 'string_view` and another `absl::string_view`.
- constexpr 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`.
- constexpr 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 string `s`.
- constexpr int compare(const char* absl_nonnull s) const {
- return compare(string_view(s));
- }
-
- // Overload of `string_view::compare()` for comparing a substring of the
- // `string_view` and a different string C-style string `s`.
- constexpr int compare(size_type pos1, size_type count1,
- const char* absl_nonnull 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 string `s`.
- constexpr int compare(size_type pos1, size_type count1,
- const char* absl_nonnull 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;
-
- // Overload of `string_view::find()` for finding a substring of a different
- // C-style string `s` within the `string_view`.
- size_type find(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return find(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find()` for finding a different C-style string
- // `s` within the `string_view`.
- size_type find(const char* absl_nonnull s, size_type pos = 0) const {
- return find(string_view(s), pos);
- }
-
- // 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 last given character `c`
- // within the `string_view`.
- size_type rfind(char c, size_type pos = npos) const noexcept;
-
- // Overload of `string_view::rfind()` for finding a substring of a different
- // C-style string `s` within the `string_view`.
- size_type rfind(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return rfind(string_view(s, count), pos);
- }
-
- // Overload of `string_view::rfind()` for finding a different C-style string
- // `s` within the `string_view`.
- size_type rfind(const char* absl_nonnull s, size_type pos = npos) const {
- return rfind(string_view(s), pos);
- }
-
- // 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);
- }
-
- // Overload of `string_view::find_first_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_first_of(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return find_first_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_first_of()` for finding a different C-style
- // string `s` within the `string_view`.
- size_type find_first_of(const char* absl_nonnull s, size_type pos = 0) const {
- return find_first_of(string_view(s), 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);
- }
-
- // Overload of `string_view::find_last_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_last_of(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return find_last_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_last_of()` for finding a different C-style
- // string `s` within the `string_view`.
- size_type find_last_of(const char* absl_nonnull s,
- size_type pos = npos) const {
- return find_last_of(string_view(s), 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;
-
- // Overload of `string_view::find_first_not_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_first_not_of(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return find_first_not_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_first_not_of()` for finding a different
- // C-style string `s` within the `string_view`.
- size_type find_first_not_of(const char* absl_nonnull s,
- size_type pos = 0) const {
- return find_first_not_of(string_view(s), pos);
- }
-
- // 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;
-
- // Overload of `string_view::find_last_not_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_last_not_of(const char* absl_nonnull s, size_type pos,
- size_type count) const {
- return find_last_not_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_last_not_of()` for finding a different
- // C-style string `s` within the `string_view`.
- size_type find_last_not_of(const char* absl_nonnull s,
- size_type pos = npos) const {
- return find_last_not_of(string_view(s), pos);
- }
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
- // string_view::starts_with()
- //
- // Returns true if the `string_view` starts with the prefix `s`.
- //
- // This method only exists when targeting at least C++20.
- // If support for C++ prior to C++20 is required, use `absl::StartsWith()`
- // from `//absl/strings/match.h` for compatibility.
- constexpr bool starts_with(string_view s) const noexcept {
- return s.empty() ||
- (size() >= s.size() &&
- ABSL_INTERNAL_STRING_VIEW_MEMCMP(data(), s.data(), s.size()) == 0);
- }
-
- // Overload of `string_view::starts_with()` that returns true if `c` is the
- // first character of the `string_view`.
- constexpr bool starts_with(char c) const noexcept {
- return !empty() && front() == c;
- }
-
- // Overload of `string_view::starts_with()` that returns true if the
- // `string_view` starts with the C-style prefix `s`.
- constexpr bool starts_with(const char* absl_nonnull s) const {
- return starts_with(string_view(s));
- }
-
- // string_view::ends_with()
- //
- // Returns true if the `string_view` ends with the suffix `s`.
- //
- // This method only exists when targeting at least C++20.
- // If support for C++ prior to C++20 is required, use `absl::EndsWith()`
- // from `//absl/strings/match.h` for compatibility.
- constexpr bool ends_with(string_view s) const noexcept {
- return s.empty() || (size() >= s.size() && ABSL_INTERNAL_STRING_VIEW_MEMCMP(
- data() + (size() - s.size()),
- s.data(), s.size()) == 0);
- }
-
- // Overload of `string_view::ends_with()` that returns true if `c` is the
- // last character of the `string_view`.
- constexpr bool ends_with(char c) const noexcept {
- return !empty() && back() == c;
- }
-
- // Overload of `string_view::ends_with()` that returns true if the
- // `string_view` ends with the C-style suffix `s`.
- constexpr bool ends_with(const char* absl_nonnull s) const {
- return ends_with(string_view(s));
- }
-#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-
- private:
- // The constructor from std::string delegates to this constructor.
- // See the comment on that constructor for the rationale.
- struct SkipCheckLengthTag {};
- string_view(const char* absl_nullable data, size_type len,
- SkipCheckLengthTag) noexcept
- : ptr_(data), length_(len) {}
-
- static constexpr size_type kMaxSize =
- (std::numeric_limits<difference_type>::max)();
-
- static constexpr size_type CheckLengthInternal(size_type len) {
- ABSL_HARDENING_ASSERT(len <= kMaxSize);
- return len;
- }
-
- static constexpr size_type StrlenInternal(const char* absl_nonnull str) {
-#if defined(_MSC_VER) && !defined(__clang__)
- // MSVC 2017+ can evaluate this at compile-time.
- const char* begin = str;
- while (*str != '\0') ++str;
- return str - begin;
-#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \
- (defined(__GNUC__) && !defined(__clang__))
- // GCC has __builtin_strlen according to
- // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
- // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
- // __builtin_strlen is constexpr.
- return __builtin_strlen(str);
-#else
- return str ? strlen(str) : 0;
-#endif
- }
-
- static constexpr int CompareImpl(size_type length_a, size_type length_b,
- int compare_result) {
- return compare_result == 0 ? static_cast<int>(length_a > length_b) -
- static_cast<int>(length_a < length_b)
- : (compare_result < 0 ? -1 : 1);
- }
-
- const char* absl_nullable 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.
-constexpr bool operator==(string_view x, string_view y) noexcept {
- return x.size() == y.size() &&
- (x.empty() ||
- ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
-}
-
-constexpr bool operator!=(string_view x, string_view y) noexcept {
- return !(x == y);
-}
-
-constexpr bool operator<(string_view x, string_view y) noexcept {
- return x.compare(y) < 0;
-}
-
-constexpr bool operator>(string_view x, string_view y) noexcept {
- return y < x;
-}
-
-constexpr bool operator<=(string_view x, string_view y) noexcept {
- return !(y < x);
-}
-
-constexpr bool operator>=(string_view x, string_view y) noexcept {
- return !(x < y);
-}
-
-// IO Insertion Operator
-std::ostream& operator<<(std::ostream& o, string_view piece);
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#undef ABSL_INTERNAL_DIAGNOSE_IF_NULLPTR
-#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
-
-#endif // ABSL_USES_STD_STRING_VIEW
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
+using std::string_view;
// ClippedSubstr()
//
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
deleted file mode 100644
index 546f6ed..0000000
--- a/absl/strings/string_view_benchmark.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2018 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
-//
-// https://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 <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <map>
-#include <random>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include "absl/base/attributes.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/macros.h"
-#include "absl/random/random.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "benchmark/benchmark.h"
-
-namespace {
-
-void BM_StringViewFromString(benchmark::State& state) {
- std::string s(state.range(0), 'x');
- std::string* ps = &s;
- struct SV {
- SV() = default;
- explicit SV(const std::string& s) : sv(s) {}
- absl::string_view sv;
- } sv;
- SV* psv = &sv;
- benchmark::DoNotOptimize(ps);
- benchmark::DoNotOptimize(psv);
- for (auto _ : state) {
- new (psv) SV(*ps);
- benchmark::DoNotOptimize(sv);
- }
-}
-BENCHMARK(BM_StringViewFromString)->Arg(12)->Arg(128);
-
-// Provide a forcibly out-of-line wrapper for operator== that can be used in
-// benchmarks to measure the impact of inlining.
-ABSL_ATTRIBUTE_NOINLINE
-bool NonInlinedEq(absl::string_view a, absl::string_view b) { return a == b; }
-
-// We use functions that cannot be inlined to perform the comparison loops so
-// that inlining of the operator== can't optimize away *everything*.
-ABSL_ATTRIBUTE_NOINLINE
-void DoEqualityComparisons(benchmark::State& state, absl::string_view a,
- absl::string_view b) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(a == b);
- }
-}
-
-void BM_EqualIdentical(benchmark::State& state) {
- std::string x(state.range(0), 'a');
- DoEqualityComparisons(state, x, x);
-}
-BENCHMARK(BM_EqualIdentical)->DenseRange(0, 3)->Range(4, 1 << 10);
-
-void BM_EqualSame(benchmark::State& state) {
- std::string x(state.range(0), 'a');
- std::string y = x;
- DoEqualityComparisons(state, x, y);
-}
-BENCHMARK(BM_EqualSame)
- ->DenseRange(0, 10)
- ->Arg(20)
- ->Arg(40)
- ->Arg(70)
- ->Arg(110)
- ->Range(160, 4096);
-
-void BM_EqualDifferent(benchmark::State& state) {
- const int len = state.range(0);
- std::string x(len, 'a');
- std::string y = x;
- if (len > 0) {
- y[len - 1] = 'b';
- }
- DoEqualityComparisons(state, x, y);
-}
-BENCHMARK(BM_EqualDifferent)->DenseRange(0, 3)->Range(4, 1 << 10);
-
-// This benchmark is intended to check that important simplifications can be
-// made with absl::string_view comparisons against constant strings. The idea is
-// that if constant strings cause redundant components of the comparison, the
-// compiler should detect and eliminate them. Here we use 8 different strings,
-// each with the same size. Provided our comparison makes the implementation
-// inline-able by the compiler, it should fold all of these away into a single
-// size check once per loop iteration.
-ABSL_ATTRIBUTE_NOINLINE
-void DoConstantSizeInlinedEqualityComparisons(benchmark::State& state,
- absl::string_view a) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(a == "aaa");
- benchmark::DoNotOptimize(a == "bbb");
- benchmark::DoNotOptimize(a == "ccc");
- benchmark::DoNotOptimize(a == "ddd");
- benchmark::DoNotOptimize(a == "eee");
- benchmark::DoNotOptimize(a == "fff");
- benchmark::DoNotOptimize(a == "ggg");
- benchmark::DoNotOptimize(a == "hhh");
- }
-}
-void BM_EqualConstantSizeInlined(benchmark::State& state) {
- std::string x(state.range(0), 'a');
- DoConstantSizeInlinedEqualityComparisons(state, x);
-}
-// We only need to check for size of 3, and <> 3 as this benchmark only has to
-// do with size differences.
-BENCHMARK(BM_EqualConstantSizeInlined)->DenseRange(2, 4);
-
-// This benchmark exists purely to give context to the above timings: this is
-// what they would look like if the compiler is completely unable to simplify
-// between two comparisons when they are comparing against constant strings.
-ABSL_ATTRIBUTE_NOINLINE
-void DoConstantSizeNonInlinedEqualityComparisons(benchmark::State& state,
- absl::string_view a) {
- for (auto _ : state) {
- // Force these out-of-line to compare with the above function.
- benchmark::DoNotOptimize(NonInlinedEq(a, "aaa"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "bbb"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "ccc"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "ddd"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "eee"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "fff"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "ggg"));
- benchmark::DoNotOptimize(NonInlinedEq(a, "hhh"));
- }
-}
-
-void BM_EqualConstantSizeNonInlined(benchmark::State& state) {
- std::string x(state.range(0), 'a');
- DoConstantSizeNonInlinedEqualityComparisons(state, x);
-}
-// We only need to check for size of 3, and <> 3 as this benchmark only has to
-// do with size differences.
-BENCHMARK(BM_EqualConstantSizeNonInlined)->DenseRange(2, 4);
-
-void BM_CompareSame(benchmark::State& state) {
- const int len = state.range(0);
- std::string x;
- for (int i = 0; i < len; i++) {
- x += 'a';
- }
- std::string y = x;
- absl::string_view a = x;
- absl::string_view b = y;
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- benchmark::DoNotOptimize(a.compare(b));
- }
-}
-BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10);
-
-void BM_CompareFirstOneLess(benchmark::State& state) {
- const int len = state.range(0);
- std::string x(len, 'a');
- std::string y = x;
- y.back() = 'b';
- absl::string_view a = x;
- absl::string_view b = y;
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- benchmark::DoNotOptimize(a.compare(b));
- }
-}
-BENCHMARK(BM_CompareFirstOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
-
-void BM_CompareSecondOneLess(benchmark::State& state) {
- const int len = state.range(0);
- std::string x(len, 'a');
- std::string y = x;
- x.back() = 'b';
- absl::string_view a = x;
- absl::string_view b = y;
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(a);
- benchmark::DoNotOptimize(b);
- benchmark::DoNotOptimize(a.compare(b));
- }
-}
-BENCHMARK(BM_CompareSecondOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
-
-void BM_find_string_view_len_one(benchmark::State& state) {
- std::string haystack(state.range(0), '0');
- absl::string_view s(haystack);
- for (auto _ : state) {
- benchmark::DoNotOptimize(s.find("x")); // not present; length 1
- }
-}
-BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20);
-
-void BM_find_string_view_len_two(benchmark::State& state) {
- std::string haystack(state.range(0), '0');
- absl::string_view s(haystack);
- for (auto _ : state) {
- benchmark::DoNotOptimize(s.find("xx")); // not present; length 2
- }
-}
-BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20);
-
-void BM_find_one_char(benchmark::State& state) {
- std::string haystack(state.range(0), '0');
- absl::string_view s(haystack);
- for (auto _ : state) {
- benchmark::DoNotOptimize(s.find('x')); // not present
- }
-}
-BENCHMARK(BM_find_one_char)->Range(1, 1 << 20);
-
-void BM_rfind_one_char(benchmark::State& state) {
- std::string haystack(state.range(0), '0');
- absl::string_view s(haystack);
- for (auto _ : state) {
- benchmark::DoNotOptimize(s.rfind('x')); // not present
- }
-}
-BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20);
-
-void BM_worst_case_find_first_of(benchmark::State& state, int haystack_len) {
- const int needle_len = state.range(0);
- std::string needle;
- for (int i = 0; i < needle_len; ++i) {
- needle += 'a' + i;
- }
- std::string haystack(haystack_len, '0'); // 1000 zeros.
-
- absl::string_view s(haystack);
- for (auto _ : state) {
- benchmark::DoNotOptimize(s.find_first_of(needle));
- }
-}
-
-void BM_find_first_of_short(benchmark::State& state) {
- BM_worst_case_find_first_of(state, 10);
-}
-
-void BM_find_first_of_medium(benchmark::State& state) {
- BM_worst_case_find_first_of(state, 100);
-}
-
-void BM_find_first_of_long(benchmark::State& state) {
- BM_worst_case_find_first_of(state, 1000);
-}
-
-BENCHMARK(BM_find_first_of_short)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
-BENCHMARK(BM_find_first_of_medium)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
-BENCHMARK(BM_find_first_of_long)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32);
-
-struct EasyMap : public std::map<absl::string_view, uint64_t> {
- explicit EasyMap(size_t) {}
-};
-
-// This templated benchmark helper function is intended to stress operator== or
-// operator< in a realistic test. It surely isn't entirely realistic, but it's
-// a start. The test creates a map of type Map, a template arg, and populates
-// it with table_size key/value pairs. Each key has WordsPerKey words. After
-// creating the map, a number of lookups are done in random order. Some keys
-// are used much more frequently than others in this phase of the test.
-template <typename Map, int WordsPerKey>
-void StringViewMapBenchmark(benchmark::State& state) {
- const int table_size = state.range(0);
- const double kFractionOfKeysThatAreHot = 0.2;
- const int kNumLookupsOfHotKeys = 20;
- const int kNumLookupsOfColdKeys = 1;
- const char* words[] = {"the", "quick", "brown", "fox", "jumped",
- "over", "the", "lazy", "dog", "and",
- "found", "a", "large", "mushroom", "and",
- "a", "couple", "crickets", "eating", "pie"};
- // Create some keys that consist of words in random order.
- absl::InsecureBitGen rng;
- std::vector<std::string> keys(table_size);
- std::vector<int> all_indices;
- const int kBlockSize = 1 << 12;
- std::unordered_set<std::string> t(kBlockSize);
- std::uniform_int_distribution<int> uniform(0, ABSL_ARRAYSIZE(words) - 1);
- for (int i = 0; i < table_size; i++) {
- all_indices.push_back(i);
- do {
- keys[i].clear();
- for (int j = 0; j < WordsPerKey; j++) {
- absl::StrAppend(&keys[i], j > 0 ? " " : "", words[uniform(rng)]);
- }
- } while (!t.insert(keys[i]).second);
- }
-
- // Create a list of strings to lookup: a permutation of the array of
- // keys we just created, with repeats. "Hot" keys get repeated more.
- std::shuffle(all_indices.begin(), all_indices.end(), rng);
- const int num_hot = table_size * kFractionOfKeysThatAreHot;
- const int num_cold = table_size - num_hot;
- std::vector<int> hot_indices(all_indices.begin(),
- all_indices.begin() + num_hot);
- std::vector<int> indices;
- for (int i = 0; i < kNumLookupsOfColdKeys; i++) {
- indices.insert(indices.end(), all_indices.begin(), all_indices.end());
- }
- for (int i = 0; i < kNumLookupsOfHotKeys - kNumLookupsOfColdKeys; i++) {
- indices.insert(indices.end(), hot_indices.begin(), hot_indices.end());
- }
- std::shuffle(indices.begin(), indices.end(), rng);
- ABSL_RAW_CHECK(
- num_cold * kNumLookupsOfColdKeys + num_hot * kNumLookupsOfHotKeys ==
- indices.size(),
- "");
- // After constructing the array we probe it with absl::string_views built from
- // test_strings. This means operator== won't see equal pointers, so
- // it'll have to check for equal lengths and equal characters.
- std::vector<std::string> test_strings(indices.size());
- for (int i = 0; i < indices.size(); i++) {
- test_strings[i] = keys[indices[i]];
- }
-
- // Run the benchmark. It includes map construction but is mostly
- // map lookups.
- for (auto _ : state) {
- Map h(table_size);
- for (int i = 0; i < table_size; i++) {
- h[keys[i]] = i * 2;
- }
- ABSL_RAW_CHECK(h.size() == table_size, "");
- uint64_t sum = 0;
- for (int i = 0; i < indices.size(); i++) {
- sum += h[test_strings[i]];
- }
- benchmark::DoNotOptimize(sum);
- }
-}
-
-void BM_StdMap_4(benchmark::State& state) {
- StringViewMapBenchmark<EasyMap, 4>(state);
-}
-BENCHMARK(BM_StdMap_4)->Range(1 << 10, 1 << 16);
-
-void BM_StdMap_8(benchmark::State& state) {
- StringViewMapBenchmark<EasyMap, 8>(state);
-}
-BENCHMARK(BM_StdMap_8)->Range(1 << 10, 1 << 16);
-
-void BM_CopyToStringNative(benchmark::State& state) {
- std::string src(state.range(0), 'x');
- absl::string_view sv(src);
- std::string dst;
- for (auto _ : state) {
- dst.assign(sv.begin(), sv.end());
- }
-}
-BENCHMARK(BM_CopyToStringNative)->Range(1 << 3, 1 << 12);
-
-void BM_AppendToStringNative(benchmark::State& state) {
- std::string src(state.range(0), 'x');
- absl::string_view sv(src);
- std::string dst;
- for (auto _ : state) {
- dst.clear();
- dst.insert(dst.end(), sv.begin(), sv.end());
- }
-}
-BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12);
-
-} // namespace
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index 390173f..d6cec6f 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -14,8 +14,6 @@
#include "absl/strings/string_view.h"
-#include <stdlib.h>
-
#include <array>
#include <cstddef>
#include <cstdlib>
@@ -35,740 +33,8 @@
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
-#ifdef __has_include
-#if __has_include(<version>)
-#include <version> // NOLINT(misc-include-cleaner)
-#endif
-#endif
-
-#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
-#include <ranges> // NOLINT(build/c++20)
-#endif
-
-#if defined(ABSL_USES_STD_STRING_VIEW) || defined(__ANDROID__)
-// We don't control the death messaging when using std::string_view.
-// Android assert messages only go to system log, so death tests cannot inspect
-// the message for matching.
-#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
- EXPECT_DEATH_IF_SUPPORTED(statement, ".*")
-#else
-#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
- EXPECT_DEATH_IF_SUPPORTED(statement, regex)
-#endif
-
namespace {
-static_assert(!absl::type_traits_internal::IsOwner<absl::string_view>::value &&
- absl::type_traits_internal::IsView<absl::string_view>::value,
- "string_view is a view, not an owner");
-
-static_assert(absl::type_traits_internal::IsLifetimeBoundAssignment<
- absl::string_view, std::string>::value,
- "lifetimebound assignment not detected");
-
-#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
-// NOLINTNEXTLINE(build/c++20)
-static_assert(std::ranges::enable_view<absl::string_view>,
- "std::ranges::view not enabled");
-// NOLINTNEXTLINE(build/c++20)
-static_assert(std::ranges::enable_borrowed_range<absl::string_view>,
- "std::ranges::borrowed_range not enabled");
-#endif
-
-// 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;
- template <class U>
- Mallocator(const Mallocator<U>&) {} // NOLINT(runtime/explicit)
-
- 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(0u, s10.length());
- }
-
- {
- // const char* without length.
- const char* hello = "hello";
- absl::string_view s20(hello);
- EXPECT_TRUE(s20.data() == hello);
- EXPECT_EQ(5u, s20.length());
-
- // const char* with length.
- absl::string_view s21(hello, 4);
- EXPECT_TRUE(s21.data() == hello);
- EXPECT_EQ(4u, s21.length());
-
- // Not recommended, but valid C++
- absl::string_view s22(hello, 6);
- EXPECT_TRUE(s22.data() == hello);
- EXPECT_EQ(6u, s22.length());
- }
-
- {
- // std::string.
- std::string hola = "hola";
- absl::string_view s30(hola);
- EXPECT_TRUE(s30.data() == hola.data());
- EXPECT_EQ(4u, 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(8u, s31.length());
- }
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
- {
- // Iterator constructor
- std::string str = "hello";
- absl::string_view s1(str.begin(), str.end());
- EXPECT_EQ(s1, "hello");
-
- std::array<char, 3> arr = { '1', '2', '3' };
- absl::string_view s2(arr.begin(), arr.end());
- EXPECT_EQ(s2, "123");
-
- const char carr[] = "carr";
- absl::string_view s3(carr, carr + strlen(carr));
- EXPECT_EQ(s3, "carr");
- }
-#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-
- {
- 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(), 3u);
-
- 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(), 2u);
-
- 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 (size_t i = 0; i < 256; i++) {
- x += 'a';
- std::string y = x;
- COMPARE(true, ==, x, y);
- for (size_t 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(), 26u);
- EXPECT_EQ(b.size(), 3u);
- EXPECT_EQ(c.size(), 3u);
- EXPECT_EQ(d.size(), 6u);
- EXPECT_EQ(e.size(), 0u);
- EXPECT_EQ(f.size(), 7u);
-
- 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), 4u);
- 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), 3u);
- 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), 3u);
- EXPECT_EQ(buf[0], c[0]);
- EXPECT_EQ(buf[1], c[1]);
- EXPECT_EQ(buf[2], c[2]);
- EXPECT_EQ(buf[3], a[3]);
-#ifdef ABSL_HAVE_EXCEPTIONS
- EXPECT_THROW(a.copy(buf, 1, 27), std::out_of_range);
-#else
- ABSL_EXPECT_DEATH_IF_SUPPORTED(a.copy(buf, 1, 27), "absl::string_view::copy");
-#endif
-}
-
-// 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(), 0u);
- EXPECT_TRUE(d.empty());
- EXPECT_TRUE(d.data() == nullptr);
- EXPECT_TRUE(d.begin() == d.end());
-
- EXPECT_EQ(a.find(b), 0u);
- EXPECT_EQ(a.find(b, 1), absl::string_view::npos);
- EXPECT_EQ(a.find(c), 23u);
- EXPECT_EQ(a.find(c, 9), 23u);
- 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), 0u);
- EXPECT_EQ(a.find(e), 0u);
- EXPECT_EQ(a.find(d, 12), 12u);
- EXPECT_EQ(a.find(e, 17), 17u);
- absl::string_view g("xx not found bb");
- EXPECT_EQ(a.find(g), absl::string_view::npos);
- // empty 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'), 0u);
- EXPECT_EQ(a.find('c'), 2u);
- EXPECT_EQ(a.find('z'), 25u);
- EXPECT_EQ(a.find('$'), absl::string_view::npos);
- EXPECT_EQ(a.find('\0'), absl::string_view::npos);
- EXPECT_EQ(f.find('\0'), 3u);
- EXPECT_EQ(f.find('3'), 2u);
- EXPECT_EQ(f.find('5'), 5u);
- EXPECT_EQ(g.find('o'), 4u);
- EXPECT_EQ(g.find('o', 4), 4u);
- EXPECT_EQ(g.find('o', 5), 8u);
- EXPECT_EQ(a.find('b', 5), absl::string_view::npos);
- // empty 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.find(b.data(), 1, 0), 1u);
- EXPECT_EQ(a.find(c.data(), 9, 0), 9u);
- EXPECT_EQ(a.find(c.data(), absl::string_view::npos, 0),
- absl::string_view::npos);
- EXPECT_EQ(b.find(c.data(), absl::string_view::npos, 0),
- absl::string_view::npos);
- // empty string nonsense
- EXPECT_EQ(d.find(b.data(), 4, 0), absl::string_view::npos);
- EXPECT_EQ(e.find(b.data(), 7, 0), absl::string_view::npos);
-
- EXPECT_EQ(a.find(b.data(), 1), absl::string_view::npos);
- EXPECT_EQ(a.find(c.data(), 9), 23u);
- EXPECT_EQ(a.find(c.data(), absl::string_view::npos), absl::string_view::npos);
- EXPECT_EQ(b.find(c.data(), absl::string_view::npos), absl::string_view::npos);
- // empty string nonsense
- EXPECT_EQ(d.find(b.data(), 4), absl::string_view::npos);
- EXPECT_EQ(e.find(b.data(), 7), absl::string_view::npos);
-
- EXPECT_EQ(a.rfind(b), 0u);
- EXPECT_EQ(a.rfind(b, 1), 0u);
- EXPECT_EQ(a.rfind(c), 23u);
- 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), 12u);
- EXPECT_EQ(a.rfind(e, 17), 17u);
- 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 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'), 8u);
- EXPECT_EQ(g.rfind('q'), absl::string_view::npos);
- EXPECT_EQ(g.rfind('o', 8), 8u);
- EXPECT_EQ(g.rfind('o', 7), 4u);
- EXPECT_EQ(g.rfind('o', 3), absl::string_view::npos);
- EXPECT_EQ(f.rfind('\0'), 3u);
- EXPECT_EQ(f.rfind('\0', 12), 3u);
- EXPECT_EQ(f.rfind('3'), 2u);
- EXPECT_EQ(f.rfind('5'), 5u);
- // empty 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);
-
- EXPECT_EQ(a.rfind(b.data(), 1, 0), 1u);
- EXPECT_EQ(a.rfind(c.data(), 22, 0), 22u);
- EXPECT_EQ(a.rfind(c.data(), 1, 0), 1u);
- EXPECT_EQ(a.rfind(c.data(), 0, 0), 0u);
- EXPECT_EQ(b.rfind(c.data(), 0, 0), 0u);
- EXPECT_EQ(d.rfind(b.data(), 4, 0), 0u);
- EXPECT_EQ(e.rfind(b.data(), 7, 0), 0u);
-}
-
-// 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), 0u);
- EXPECT_EQ(a.find_first_of(b, 0), 0u);
- EXPECT_EQ(a.find_first_of(b, 1), 1u);
- EXPECT_EQ(a.find_first_of(b, 2), 2u);
- EXPECT_EQ(a.find_first_of(b, 3), absl::string_view::npos);
- EXPECT_EQ(a.find_first_of(c), 23u);
- EXPECT_EQ(a.find_first_of(c, 23), 23u);
- EXPECT_EQ(a.find_first_of(c, 24), 24u);
- EXPECT_EQ(a.find_first_of(c, 25), 25u);
- EXPECT_EQ(a.find_first_of(c, 26), absl::string_view::npos);
- EXPECT_EQ(g.find_first_of(b), 13u);
- EXPECT_EQ(g.find_first_of(c), 0u);
- EXPECT_EQ(a.find_first_of(f), absl::string_view::npos);
- EXPECT_EQ(f.find_first_of(a), absl::string_view::npos);
- // empty 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), 3u);
- EXPECT_EQ(a.find_first_not_of(c), 0u);
- 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), 0u);
- EXPECT_EQ(a.find_first_not_of(f), 0u);
- EXPECT_EQ(a.find_first_not_of(d), 0u);
- EXPECT_EQ(a.find_first_not_of(e), 0u);
- // empty string nonsense
- EXPECT_EQ(a.find_first_not_of(d), 0u);
- EXPECT_EQ(a.find_first_not_of(e), 0u);
- EXPECT_EQ(a.find_first_not_of(d, 1), 1u);
- EXPECT_EQ(a.find_first_not_of(e, 1), 1u);
- 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'), 0u);
- EXPECT_EQ(g.find_first_not_of('x'), 2u);
- EXPECT_EQ(f.find_first_not_of('\0'), 0u);
- EXPECT_EQ(f.find_first_not_of('\0', 3), 4u);
- EXPECT_EQ(f.find_first_not_of('\0', 2), 2u);
- // empty 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), 2u);
- EXPECT_EQ(a.find_last_of(c), a.size() - 1);
- EXPECT_EQ(f.find_last_of(i), 6u);
- EXPECT_EQ(a.find_last_of('a'), 0u);
- EXPECT_EQ(a.find_last_of('b'), 1u);
- EXPECT_EQ(a.find_last_of('z'), 25u);
- EXPECT_EQ(a.find_last_of('a', 5), 0u);
- EXPECT_EQ(a.find_last_of('b', 5), 1u);
- EXPECT_EQ(a.find_last_of('b', 0), absl::string_view::npos);
- EXPECT_EQ(a.find_last_of('z', 25), 25u);
- EXPECT_EQ(a.find_last_of('z', 24), absl::string_view::npos);
- EXPECT_EQ(f.find_last_of(i, 5), 5u);
- EXPECT_EQ(f.find_last_of(i, 6), 6u);
- EXPECT_EQ(f.find_last_of(a, 4), absl::string_view::npos);
- // empty 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), 22u);
- 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), 4u);
- EXPECT_EQ(a.find_last_not_of(c, 24), 22u);
- EXPECT_EQ(a.find_last_not_of(b, 3), 3u);
- EXPECT_EQ(a.find_last_not_of(b, 2), absl::string_view::npos);
- // empty 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), 4u);
- EXPECT_EQ(f.find_last_not_of(e, 4), 4u);
- 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'), 1u);
- EXPECT_EQ(h.find_last_not_of('x', 2), 2u);
- EXPECT_EQ(h.find_last_not_of('=', 2), absl::string_view::npos);
- EXPECT_EQ(b.find_last_not_of('b', 1), 0u);
- // empty 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(), a);
- EXPECT_EQ(a.substr(3, 2), "de");
- // empty 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((void)a.substr(99, 2), std::out_of_range);
-#else
- ABSL_EXPECT_DEATH_IF_SUPPORTED((void)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));
@@ -780,272 +46,6 @@
EXPECT_EQ("", absl::ClippedSubstr(hi, 3, 2)); // truncation
}
-TEST(StringViewTest, UTF8) {
- std::string utf8 = "\u00E1";
- std::string utf8_twice = utf8 + " " + utf8;
- size_t utf8_len = strlen(utf8.data());
- EXPECT_EQ(utf8_len, absl::string_view(utf8_twice).find_first_of(" "));
- EXPECT_EQ(utf8_len, absl::string_view(utf8_twice).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 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, FrontBackEmpty) {
-#ifndef ABSL_USES_STD_STRING_VIEW
-#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
- // Abseil's string_view implementation has debug assertions that check that
- // front() and back() are not called on an empty string_view.
- absl::string_view sv;
- ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.front(), "");
- ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.back(), "");
-#endif
-#endif
-}
-
-TEST(StringViewTest, DefaultConstructor) {
- absl::string_view s;
- EXPECT_EQ(s.data(), nullptr);
- EXPECT_EQ(s.size(), 0u);
-}
-
-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
-}
-
-TEST(StringViewTest, At) {
- absl::string_view abc = "abc";
- EXPECT_EQ(abc.at(0), 'a');
- EXPECT_EQ(abc.at(1), 'b');
- EXPECT_EQ(abc.at(2), 'c');
-#ifdef ABSL_HAVE_EXCEPTIONS
- EXPECT_THROW((void)abc.at(3), std::out_of_range);
-#else
- ABSL_EXPECT_DEATH_IF_SUPPORTED((void)abc.at(3), "absl::string_view::at");
-#endif
-}
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-TEST(StringViewTest, StartsWith) {
- const absl::string_view a("foobar");
- const absl::string_view b("123\0abc", 7);
- const absl::string_view e;
- EXPECT_TRUE(a.starts_with(a));
- EXPECT_TRUE(a.starts_with("foo"));
- EXPECT_TRUE(a.starts_with('f'));
- EXPECT_TRUE(a.starts_with(e));
- EXPECT_TRUE(b.starts_with(b));
- EXPECT_TRUE(b.starts_with('1'));
- EXPECT_TRUE(b.starts_with(e));
- EXPECT_TRUE(e.starts_with(""));
- EXPECT_FALSE(a.starts_with(b));
- EXPECT_FALSE(b.starts_with(a));
- EXPECT_FALSE(e.starts_with(a));
- EXPECT_FALSE(a.starts_with('r'));
- EXPECT_FALSE(a.starts_with('\0'));
- EXPECT_FALSE(e.starts_with('r'));
- EXPECT_FALSE(e.starts_with('\0'));
-
- // Test that constexpr compiles.
- constexpr absl::string_view kFooBar("foobar");
- constexpr absl::string_view kFoo("foo");
- constexpr absl::string_view kBar("bar");
- constexpr bool k1 = kFooBar.starts_with(kFoo);
- EXPECT_TRUE(k1);
- constexpr bool k2 = kFooBar.starts_with(kBar);
- EXPECT_FALSE(k2);
- constexpr bool k3 = kFooBar.starts_with('f');
- EXPECT_TRUE(k3);
- constexpr bool k4 = kFooBar.starts_with("fo");
- EXPECT_TRUE(k4);
-}
-
-TEST(StringViewTest, EndsWith) {
- const absl::string_view a("foobar");
- const absl::string_view b("123\0abc", 7);
- const absl::string_view e;
- EXPECT_TRUE(a.ends_with(a));
- EXPECT_TRUE(a.ends_with('r'));
- EXPECT_TRUE(a.ends_with("bar"));
- EXPECT_TRUE(a.ends_with(e));
- EXPECT_TRUE(b.ends_with(b));
- EXPECT_TRUE(b.ends_with('c'));
- EXPECT_TRUE(b.ends_with(e));
- EXPECT_TRUE(e.ends_with(""));
- EXPECT_FALSE(a.ends_with(b));
- EXPECT_FALSE(b.ends_with(a));
- EXPECT_FALSE(e.ends_with(a));
- EXPECT_FALSE(a.ends_with('f'));
- EXPECT_FALSE(a.ends_with('\0'));
- EXPECT_FALSE(e.ends_with('r'));
- EXPECT_FALSE(e.ends_with('\0'));
-
- // Test that constexpr compiles.
- constexpr absl::string_view kFooBar("foobar");
- constexpr absl::string_view kFoo("foo");
- constexpr absl::string_view kBar("bar");
- constexpr bool k1 = kFooBar.ends_with(kFoo);
- EXPECT_FALSE(k1);
- constexpr bool k2 = kFooBar.ends_with(kBar);
- EXPECT_TRUE(k2);
- constexpr bool k3 = kFooBar.ends_with('r');
- EXPECT_TRUE(k3);
- constexpr bool k4 = kFooBar.ends_with("ar");
- EXPECT_TRUE(k4);
-}
-#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-
-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);
@@ -1083,317 +83,4 @@
}
}
-TEST(StringViewTest, ConstexprCompiles) {
- constexpr absl::string_view sp;
- // With `-Wnonnull` turned on, there is no way to test the defensive null
- // check in the `string_view(const char*)` constructor in a constexpr context,
- // as the argument needs to be constexpr. The compiler will therefore always
- // know at compile time that the argument is nullptr and complain because the
- // parameter is annotated nonnull. We hence turn the warning off for this
- // test.
- constexpr absl::string_view cstr_len("cstr", 4);
-
-#if defined(ABSL_USES_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 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_USES_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
-
-// MSVC 2017+ should be able to construct a constexpr string_view from a cstr.
-#if defined(_MSC_VER)
-#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
-#endif
-
-#endif // ABSL_USES_STD_STRING_VIEW
-
-#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR
- constexpr absl::string_view cstr_strlen("foo");
- EXPECT_EQ(cstr_strlen.length(), 3u);
- constexpr absl::string_view cstr_strlen2 = "bar";
- EXPECT_EQ(cstr_strlen2, "bar");
-
-#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
- (defined(__GNUC__) && !defined(__clang__))
-#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON 1
-#endif
-#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON
- constexpr absl::string_view foo = "foo";
- constexpr absl::string_view bar = "bar";
- constexpr bool foo_eq_bar = foo == bar;
- constexpr bool foo_ne_bar = foo != bar;
- constexpr bool foo_lt_bar = foo < bar;
- constexpr bool foo_le_bar = foo <= bar;
- constexpr bool foo_gt_bar = foo > bar;
- constexpr bool foo_ge_bar = foo >= bar;
- constexpr int foo_compare_bar = foo.compare(bar);
- EXPECT_FALSE(foo_eq_bar);
- EXPECT_TRUE(foo_ne_bar);
- EXPECT_FALSE(foo_lt_bar);
- EXPECT_FALSE(foo_le_bar);
- EXPECT_TRUE(foo_gt_bar);
- EXPECT_TRUE(foo_ge_bar);
- EXPECT_GT(foo_compare_bar, 0);
-#endif
-#endif
-
- 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 = 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();
- static_assert(const_begin + const_size == const_end,
- "pointer arithmetic check");
- static_assert(const_begin + const_length == const_end,
- "pointer arithmetic check");
-#ifndef _MSC_VER
- // MSVC has bugs doing constexpr pointer arithmetic.
- // https://developercommunity.visualstudio.com/content/problem/482192/bad-pointer-arithmetic-in-constepxr-2019-rc1-svc1.html
- EXPECT_EQ(const_begin + const_size, const_end);
- EXPECT_EQ(const_begin + const_length, const_end);
-#endif
-
- 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, static_cast<size_t>(-1));
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
- {
- static constexpr std::array<char, 3> arr = { '1', '2', '3' };
- constexpr absl::string_view s2(arr.begin(), arr.end());
- EXPECT_EQ(s2, "123");
-
- static constexpr char carr[] = "carr";
- constexpr absl::string_view s3(carr, carr + 4);
- EXPECT_EQ(s3, "carr");
- }
-#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
-}
-
-constexpr char ConstexprMethodsHelper() {
-#if defined(__cplusplus) && __cplusplus >= 201402L
- absl::string_view str("123", 3);
- str.remove_prefix(1);
- str.remove_suffix(1);
- absl::string_view bar;
- str.swap(bar);
- return bar.front();
-#else
- return '2';
-#endif
-}
-
-TEST(StringViewTest, ConstexprMethods) {
- // remove_prefix, remove_suffix, swap
- static_assert(ConstexprMethodsHelper() == '2', "");
-
- // substr
- constexpr absl::string_view foobar("foobar", 6);
- constexpr absl::string_view foo = foobar.substr(0, 3);
- constexpr absl::string_view bar = foobar.substr(3);
- EXPECT_EQ(foo, "foo");
- EXPECT_EQ(bar, "bar");
-}
-
-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(StringViewTest, BoundsCheck) {
-#ifndef ABSL_USES_STD_STRING_VIEW
-#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
- // Abseil's string_view implementation has bounds-checking in debug mode.
- absl::string_view h = "hello";
- ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], "");
- ABSL_EXPECT_DEATH_IF_SUPPORTED(h[static_cast<size_t>(-1)], "");
-#endif
-#endif
-}
-
-TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
- EXPECT_EQ("hello", std::string("hello"));
- EXPECT_LT("hello", std::string("world"));
-}
-
-TEST(ComparisonOpsTest, HeterogeneousStringViewEquals) {
- 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(0u, a.find('x'));
- EXPECT_EQ(0u, a.find('x', 0));
- EXPECT_EQ(4u, a.find('x', 1));
- EXPECT_EQ(4u, a.find('x', 4));
- EXPECT_EQ(absl::string_view::npos, a.find('x', 5));
-
- EXPECT_EQ(4u, a.rfind('x'));
- EXPECT_EQ(4u, a.rfind('x', 5));
- EXPECT_EQ(4u, a.rfind('x', 4));
- EXPECT_EQ(0u, a.rfind('x', 3));
- EXPECT_EQ(0u, 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 ABSL_HAVE_THREAD_SANITIZER // Allocates too much memory for tsan.
-TEST(HugeStringView, TwoPointTwoGB) {
- if (sizeof(size_t) <= 4)
- return;
- // Try a huge 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 // ABSL_HAVE_THREAD_SANITIZER
-
-#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
-TEST(NonNegativeLenTest, NonNegativeLen) {
- ABSL_EXPECT_DEATH_IF_SUPPORTED(
- absl::string_view("xyz", static_cast<size_t>(-1)), "len <= kMaxSize");
-}
-
-TEST(LenExceedsMaxSizeTest, LenExceedsMaxSize) {
- auto max_size = absl::string_view().max_size();
-
- // This should construct ok (although the view itself is obviously invalid).
- absl::string_view ok_view("", max_size);
-
- // Adding one to the max should trigger an assertion.
- ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("", max_size + 1),
- "len <= kMaxSize");
-}
-#endif // !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
-
-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
diff --git a/ci/absl_alternate_options.h b/ci/absl_alternate_options.h
index 20bf010..d5567f3 100644
--- a/ci/absl_alternate_options.h
+++ b/ci/absl_alternate_options.h
@@ -20,7 +20,6 @@
#ifndef ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_
#define ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_
-#define ABSL_OPTION_USE_STD_STRING_VIEW 0
#define ABSL_OPTION_USE_STD_ORDERING 0
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
#define ABSL_OPTION_INLINE_NAMESPACE_NAME ns