aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp/absl/strings
diff options
context:
space:
mode:
authorayles <ayles@yandex-team.ru>2022-02-10 16:46:11 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:11 +0300
commitd55028e9d9708f94c2d0d35b54ed50d4d7af0456 (patch)
treed69fdff3b2be7d190a1efa078721d25139d0b030 /contrib/restricted/abseil-cpp/absl/strings
parentbaa58daefa91fde4b4769facdbd2903763b9c6a8 (diff)
downloadydb-d55028e9d9708f94c2d0d35b54ed50d4d7af0456.tar.gz
Restoring authorship annotation for <ayles@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/abseil-cpp/absl/strings')
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/ascii.cc10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/ascii.h12
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/charconv.cc8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/charconv.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord.cc2858
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord.h2388
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h120
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/escaping.cc58
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/escaping.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal/ya.make20
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h16
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h314
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions/ya.make8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc360
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h116
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/memutil.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/resize_uninitialized.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/stl_type_traits.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc480
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h324
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc60
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h54
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h54
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc62
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h404
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc1998
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.h38
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.h12
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc114
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h78
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_join_internal.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/utf8.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/match.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/match.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/numbers.cc110
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/numbers.h40
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_cat.cc12
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_cat.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_format.h584
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_join.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_replace.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_replace.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_split.cc8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_split.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/string_view.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/string_view.h132
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/strip.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/substitute.cc14
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/substitute.h36
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/ya.make20
63 files changed, 5539 insertions, 5539 deletions
diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
index 93bb03e958..facfb50bc0 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
@@ -15,7 +15,7 @@
#include "absl/strings/ascii.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace ascii_internal {
// # Table generated by this Python code (bit 0x02 is currently unused):
@@ -57,7 +57,7 @@ namespace ascii_internal {
// of these bits is tightly coupled to this implementation, the individual bits
// are not named. Note that bitfields for all characters above ASCII 127 are
// zero-initialized.
-ABSL_DLL const unsigned char kPropertyBits[256] = {
+ABSL_DLL const unsigned char kPropertyBits[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
@@ -79,7 +79,7 @@ ABSL_DLL const unsigned char kPropertyBits[256] = {
// Array of characters for the ascii_tolower() function. For values 'A'
// through 'Z', return the lower-case character; otherwise, return the
// identity of the passed character.
-ABSL_DLL const char kToLower[256] = {
+ABSL_DLL const char kToLower[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -117,7 +117,7 @@ ABSL_DLL const char kToLower[256] = {
// Array of characters for the ascii_toupper() function. For values 'a'
// through 'z', return the upper-case character; otherwise, return the
// identity of the passed character.
-ABSL_DLL const char kToUpper[256] = {
+ABSL_DLL const char kToUpper[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -196,5 +196,5 @@ void RemoveExtraAsciiWhitespace(std::string* str) {
str->erase(output_it - &(*str)[0]);
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.h b/contrib/restricted/abseil-cpp/absl/strings/ascii.h
index b46bc71f35..699c209c9d 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/ascii.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.h
@@ -56,21 +56,21 @@
#include <string>
#include "absl/base/attributes.h"
-#include "absl/base/config.h"
+#include "absl/base/config.h"
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace ascii_internal {
// Declaration for an array of bitfields holding character information.
-ABSL_DLL extern const unsigned char kPropertyBits[256];
+ABSL_DLL extern const unsigned char kPropertyBits[256];
// Declaration for the array of characters to upper-case characters.
-ABSL_DLL extern const char kToUpper[256];
+ABSL_DLL extern const char kToUpper[256];
// Declaration for the array of characters to lower-case characters.
-ABSL_DLL extern const char kToLower[256];
+ABSL_DLL extern const char kToLower[256];
} // namespace ascii_internal
@@ -236,7 +236,7 @@ inline void StripAsciiWhitespace(std::string* str) {
// Removes leading, trailing, and consecutive internal whitespace.
void RemoveExtraAsciiWhitespace(std::string*);
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_ASCII_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
index fefcfc90a5..870461ce96 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
@@ -57,7 +57,7 @@
// narrower mantissas.
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace {
template <typename FloatType>
@@ -619,10 +619,10 @@ from_chars_result FromCharsImpl(const char* first, const char* last,
// Either we failed to parse a hex float after the "0x", or we read
// "0xinf" or "0xnan" which we don't want to match.
//
- // However, a string that begins with "0x" also begins with "0", which
+ // However, a string that begins with "0x" also begins with "0", which
// is normally a valid match for the number zero. So we want these
// strings to match zero unless fmt_flags is `scientific`. (This flag
- // means an exponent is required, which the string "0" does not have.)
+ // means an exponent is required, which the string "0" does not have.)
if (fmt_flags == chars_format::scientific) {
result.ec = std::errc::invalid_argument;
} else {
@@ -980,5 +980,5 @@ const int16_t kPower10ExponentTable[] = {
};
} // namespace
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.h b/contrib/restricted/abseil-cpp/absl/strings/charconv.h
index 7c50981245..be05e34d08 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/charconv.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.h
@@ -17,10 +17,10 @@
#include <system_error> // NOLINT(build/c++11)
-#include "absl/base/config.h"
-
+#include "absl/base/config.h"
+
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// Workalike compatibilty version of std::chars_format from C++17.
//
@@ -114,7 +114,7 @@ inline chars_format& operator^=(chars_format& lhs, chars_format rhs) {
return lhs;
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_CHARCONV_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.cc b/contrib/restricted/abseil-cpp/absl/strings/cord.cc
index 854047ca98..a353a9facf 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord.cc
@@ -1,209 +1,209 @@
-// Copyright 2020 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/cord.h"
-
-#include <algorithm>
-#include <atomic>
-#include <cstddef>
-#include <cstdio>
-#include <cstdlib>
-#include <iomanip>
-#include <iostream>
-#include <limits>
-#include <ostream>
-#include <sstream>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include "absl/base/casts.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
-#include "absl/container/fixed_array.h"
-#include "absl/container/inlined_vector.h"
-#include "absl/strings/escaping.h"
-#include "absl/strings/internal/cord_internal.h"
+// Copyright 2020 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/cord.h"
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <sstream>
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include "absl/base/casts.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/fixed_array.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/internal/cordz_statistics.h"
#include "absl/strings/internal/cordz_update_scope.h"
#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/internal/resize_uninitialized.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_format.h"
-#include "absl/strings/str_join.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-using ::absl::cord_internal::CordRep;
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+using ::absl::cord_internal::CordRep;
using ::absl::cord_internal::CordRepBtree;
-using ::absl::cord_internal::CordRepConcat;
-using ::absl::cord_internal::CordRepExternal;
+using ::absl::cord_internal::CordRepConcat;
+using ::absl::cord_internal::CordRepExternal;
using ::absl::cord_internal::CordRepFlat;
-using ::absl::cord_internal::CordRepSubstring;
+using ::absl::cord_internal::CordRepSubstring;
using ::absl::cord_internal::CordzUpdateTracker;
using ::absl::cord_internal::InlineData;
using ::absl::cord_internal::kMaxFlatLength;
using ::absl::cord_internal::kMinFlatLength;
-
+
using ::absl::cord_internal::kInlinedVectorSize;
using ::absl::cord_internal::kMaxBytesToCopy;
-
-constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
- return n == 0 ? a : Fibonacci(n - 1, b, a + b);
-}
-
-static_assert(Fibonacci(63) == 6557470319842,
- "Fibonacci values computed incorrectly");
-
-// Minimum length required for a given depth tree -- a tree is considered
-// balanced if
-// length(t) >= min_length[depth(t)]
-// The root node depth is allowed to become twice as large to reduce rebalancing
-// for larger strings (see IsRootBalanced).
-static constexpr uint64_t min_length[] = {
- Fibonacci(2), Fibonacci(3), Fibonacci(4), Fibonacci(5),
- Fibonacci(6), Fibonacci(7), Fibonacci(8), Fibonacci(9),
- Fibonacci(10), Fibonacci(11), Fibonacci(12), Fibonacci(13),
- Fibonacci(14), Fibonacci(15), Fibonacci(16), Fibonacci(17),
- Fibonacci(18), Fibonacci(19), Fibonacci(20), Fibonacci(21),
- Fibonacci(22), Fibonacci(23), Fibonacci(24), Fibonacci(25),
- Fibonacci(26), Fibonacci(27), Fibonacci(28), Fibonacci(29),
- Fibonacci(30), Fibonacci(31), Fibonacci(32), Fibonacci(33),
- Fibonacci(34), Fibonacci(35), Fibonacci(36), Fibonacci(37),
- Fibonacci(38), Fibonacci(39), Fibonacci(40), Fibonacci(41),
- Fibonacci(42), Fibonacci(43), Fibonacci(44), Fibonacci(45),
- Fibonacci(46), Fibonacci(47),
- 0xffffffffffffffffull, // Avoid overflow
-};
-
-static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
-
+
+constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
+ return n == 0 ? a : Fibonacci(n - 1, b, a + b);
+}
+
+static_assert(Fibonacci(63) == 6557470319842,
+ "Fibonacci values computed incorrectly");
+
+// Minimum length required for a given depth tree -- a tree is considered
+// balanced if
+// length(t) >= min_length[depth(t)]
+// The root node depth is allowed to become twice as large to reduce rebalancing
+// for larger strings (see IsRootBalanced).
+static constexpr uint64_t min_length[] = {
+ Fibonacci(2), Fibonacci(3), Fibonacci(4), Fibonacci(5),
+ Fibonacci(6), Fibonacci(7), Fibonacci(8), Fibonacci(9),
+ Fibonacci(10), Fibonacci(11), Fibonacci(12), Fibonacci(13),
+ Fibonacci(14), Fibonacci(15), Fibonacci(16), Fibonacci(17),
+ Fibonacci(18), Fibonacci(19), Fibonacci(20), Fibonacci(21),
+ Fibonacci(22), Fibonacci(23), Fibonacci(24), Fibonacci(25),
+ Fibonacci(26), Fibonacci(27), Fibonacci(28), Fibonacci(29),
+ Fibonacci(30), Fibonacci(31), Fibonacci(32), Fibonacci(33),
+ Fibonacci(34), Fibonacci(35), Fibonacci(36), Fibonacci(37),
+ Fibonacci(38), Fibonacci(39), Fibonacci(40), Fibonacci(41),
+ Fibonacci(42), Fibonacci(43), Fibonacci(44), Fibonacci(45),
+ Fibonacci(46), Fibonacci(47),
+ 0xffffffffffffffffull, // Avoid overflow
+};
+
+static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
+
static inline bool btree_enabled() {
return cord_internal::cord_btree_enabled.load(
std::memory_order_relaxed);
}
-
-static inline bool IsRootBalanced(CordRep* node) {
+
+static inline bool IsRootBalanced(CordRep* node) {
if (!node->IsConcat()) {
- return true;
- } else if (node->concat()->depth() <= 15) {
- return true;
- } else if (node->concat()->depth() > kMinLengthSize) {
- return false;
- } else {
- // Allow depth to become twice as large as implied by fibonacci rule to
- // reduce rebalancing for larger strings.
- return (node->length >= min_length[node->concat()->depth() / 2]);
- }
-}
-
-static CordRep* Rebalance(CordRep* node);
+ return true;
+ } else if (node->concat()->depth() <= 15) {
+ return true;
+ } else if (node->concat()->depth() > kMinLengthSize) {
+ return false;
+ } else {
+ // Allow depth to become twice as large as implied by fibonacci rule to
+ // reduce rebalancing for larger strings.
+ return (node->length >= min_length[node->concat()->depth() / 2]);
+ }
+}
+
+static CordRep* Rebalance(CordRep* node);
static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
int indent = 0);
-static bool VerifyNode(CordRep* root, CordRep* start_node,
- bool full_validation);
-
-static inline CordRep* VerifyTree(CordRep* node) {
- // Verification is expensive, so only do it in debug mode.
- // Even in debug mode we normally do only light validation.
- // If you are debugging Cord itself, you should define the
- // macro EXTRA_CORD_VALIDATION, e.g. by adding
- // --copt=-DEXTRA_CORD_VALIDATION to the blaze line.
-#ifdef EXTRA_CORD_VALIDATION
- assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true));
-#else // EXTRA_CORD_VALIDATION
- assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false));
-#endif // EXTRA_CORD_VALIDATION
- static_cast<void>(&VerifyNode);
-
- return node;
-}
-
-// Return the depth of a node
-static int Depth(const CordRep* rep) {
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+ bool full_validation);
+
+static inline CordRep* VerifyTree(CordRep* node) {
+ // Verification is expensive, so only do it in debug mode.
+ // Even in debug mode we normally do only light validation.
+ // If you are debugging Cord itself, you should define the
+ // macro EXTRA_CORD_VALIDATION, e.g. by adding
+ // --copt=-DEXTRA_CORD_VALIDATION to the blaze line.
+#ifdef EXTRA_CORD_VALIDATION
+ assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true));
+#else // EXTRA_CORD_VALIDATION
+ assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false));
+#endif // EXTRA_CORD_VALIDATION
+ static_cast<void>(&VerifyNode);
+
+ return node;
+}
+
+// Return the depth of a node
+static int Depth(const CordRep* rep) {
if (rep->IsConcat()) {
- return rep->concat()->depth();
- } else {
- return 0;
- }
-}
-
-static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
- CordRep* right) {
- concat->left = left;
- concat->right = right;
-
- concat->length = left->length + right->length;
- concat->set_depth(1 + std::max(Depth(left), Depth(right)));
-}
-
-// Create a concatenation of the specified nodes.
-// Does not change the refcounts of "left" and "right".
-// The returned node has a refcount of 1.
-static CordRep* RawConcat(CordRep* left, CordRep* right) {
- // Avoid making degenerate concat nodes (one child is empty)
+ return rep->concat()->depth();
+ } else {
+ return 0;
+ }
+}
+
+static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
+ CordRep* right) {
+ concat->left = left;
+ concat->right = right;
+
+ concat->length = left->length + right->length;
+ concat->set_depth(1 + std::max(Depth(left), Depth(right)));
+}
+
+// Create a concatenation of the specified nodes.
+// Does not change the refcounts of "left" and "right".
+// The returned node has a refcount of 1.
+static CordRep* RawConcat(CordRep* left, CordRep* right) {
+ // Avoid making degenerate concat nodes (one child is empty)
if (left == nullptr) return right;
if (right == nullptr) return left;
if (left->length == 0) {
CordRep::Unref(left);
- return right;
- }
+ return right;
+ }
if (right->length == 0) {
CordRep::Unref(right);
- return left;
- }
-
- CordRepConcat* rep = new CordRepConcat();
+ return left;
+ }
+
+ CordRepConcat* rep = new CordRepConcat();
rep->tag = cord_internal::CONCAT;
- SetConcatChildren(rep, left, right);
-
- return rep;
-}
-
-static CordRep* Concat(CordRep* left, CordRep* right) {
- CordRep* rep = RawConcat(left, right);
- if (rep != nullptr && !IsRootBalanced(rep)) {
- rep = Rebalance(rep);
- }
- return VerifyTree(rep);
-}
-
-// Make a balanced tree out of an array of leaf nodes.
-static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
- // Make repeated passes over the array, merging adjacent pairs
- // until we are left with just a single node.
- while (n > 1) {
- size_t dst = 0;
- for (size_t src = 0; src < n; src += 2) {
- if (src + 1 < n) {
- reps[dst] = Concat(reps[src], reps[src + 1]);
- } else {
- reps[dst] = reps[src];
- }
- dst++;
- }
- n = dst;
- }
-
- return reps[0];
-}
-
+ SetConcatChildren(rep, left, right);
+
+ return rep;
+}
+
+static CordRep* Concat(CordRep* left, CordRep* right) {
+ CordRep* rep = RawConcat(left, right);
+ if (rep != nullptr && !IsRootBalanced(rep)) {
+ rep = Rebalance(rep);
+ }
+ return VerifyTree(rep);
+}
+
+// Make a balanced tree out of an array of leaf nodes.
+static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
+ // Make repeated passes over the array, merging adjacent pairs
+ // until we are left with just a single node.
+ while (n > 1) {
+ size_t dst = 0;
+ for (size_t src = 0; src < n; src += 2) {
+ if (src + 1 < n) {
+ reps[dst] = Concat(reps[src], reps[src + 1]);
+ } else {
+ reps[dst] = reps[src];
+ }
+ dst++;
+ }
+ n = dst;
+ }
+
+ return reps[0];
+}
+
static CordRepFlat* CreateFlat(const char* data, size_t length,
size_t alloc_hint) {
CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
@@ -217,63 +217,63 @@ static CordRepFlat* CreateFlat(const char* data, size_t length,
static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) {
if (length <= kMaxFlatLength) {
return CreateFlat(data, length, alloc_hint);
- }
+ }
CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
data += kMaxFlatLength;
length -= kMaxFlatLength;
auto* root = CordRepBtree::Create(flat);
return CordRepBtree::Append(root, {data, length}, alloc_hint);
-}
-
-// Create a new tree out of the specified array.
-// The returned node has a refcount of 1.
+}
+
+// Create a new tree out of the specified array.
+// The returned node has a refcount of 1.
static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) {
- if (length == 0) return nullptr;
+ if (length == 0) return nullptr;
if (btree_enabled()) {
return NewBtree(data, length, alloc_hint);
}
- absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
- size_t n = 0;
- do {
- const size_t len = std::min(length, kMaxFlatLength);
+ absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
+ size_t n = 0;
+ do {
+ const size_t len = std::min(length, kMaxFlatLength);
CordRepFlat* rep = CordRepFlat::New(len + alloc_hint);
- rep->length = len;
+ rep->length = len;
memcpy(rep->Data(), data, len);
- reps[n++] = VerifyTree(rep);
- data += len;
- length -= len;
- } while (length != 0);
- return MakeBalancedTree(reps.data(), n);
-}
-
-namespace cord_internal {
-
-void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
- assert(!data.empty());
- rep->length = data.size();
- rep->tag = EXTERNAL;
- rep->base = data.data();
- VerifyTree(rep);
-}
-
-} // namespace cord_internal
-
-static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
- // Never create empty substring nodes
- if (length == 0) {
+ reps[n++] = VerifyTree(rep);
+ data += len;
+ length -= len;
+ } while (length != 0);
+ return MakeBalancedTree(reps.data(), n);
+}
+
+namespace cord_internal {
+
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
+ assert(!data.empty());
+ rep->length = data.size();
+ rep->tag = EXTERNAL;
+ rep->base = data.data();
+ VerifyTree(rep);
+}
+
+} // namespace cord_internal
+
+static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
+ // Never create empty substring nodes
+ if (length == 0) {
CordRep::Unref(child);
- return nullptr;
- } else {
- CordRepSubstring* rep = new CordRepSubstring();
- assert((offset + length) <= child->length);
- rep->length = length;
+ return nullptr;
+ } else {
+ CordRepSubstring* rep = new CordRepSubstring();
+ assert((offset + length) <= child->length);
+ rep->length = length;
rep->tag = cord_internal::SUBSTRING;
- rep->start = offset;
- rep->child = child;
- return VerifyTree(rep);
- }
-}
-
+ rep->start = offset;
+ rep->child = child;
+ return VerifyTree(rep);
+ }
+}
+
// Creates a CordRep from the provided string. If the string is large enough,
// and not wasteful, we move the string into an external cord rep, preserving
// the already allocated string contents.
@@ -303,41 +303,41 @@ static CordRep* CordRepFromString(std::string&& src) {
return rep;
}
-// --------------------------------------------------------------------
-// Cord::InlineRep functions
-
-constexpr unsigned char Cord::InlineRep::kMaxInline;
-
-inline void Cord::InlineRep::set_data(const char* data, size_t n,
- bool nullify_tail) {
- static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
-
+// --------------------------------------------------------------------
+// Cord::InlineRep functions
+
+constexpr unsigned char Cord::InlineRep::kMaxInline;
+
+inline void Cord::InlineRep::set_data(const char* data, size_t n,
+ bool nullify_tail) {
+ static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
+
cord_internal::SmallMemmove(data_.as_chars(), data, n, nullify_tail);
set_inline_size(n);
-}
-
-inline char* Cord::InlineRep::set_data(size_t n) {
- assert(n <= kMaxInline);
- ResetToEmpty();
+}
+
+inline char* Cord::InlineRep::set_data(size_t n) {
+ assert(n <= kMaxInline);
+ ResetToEmpty();
set_inline_size(n);
return data_.as_chars();
-}
-
-inline void Cord::InlineRep::reduce_size(size_t n) {
+}
+
+inline void Cord::InlineRep::reduce_size(size_t n) {
size_t tag = inline_size();
- assert(tag <= kMaxInline);
- assert(tag >= n);
- tag -= n;
+ assert(tag <= kMaxInline);
+ assert(tag >= n);
+ tag -= n;
memset(data_.as_chars() + tag, 0, n);
set_inline_size(static_cast<char>(tag));
-}
-
-inline void Cord::InlineRep::remove_prefix(size_t n) {
+}
+
+inline void Cord::InlineRep::remove_prefix(size_t n) {
cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,
inline_size() - n);
- reduce_size(n);
-}
-
+ reduce_size(n);
+}
+
// Returns `rep` converted into a CordRepBtree.
// Directly returns `rep` if `rep` is already a CordRepBtree.
static CordRepBtree* ForceBtree(CordRep* rep) {
@@ -370,14 +370,14 @@ void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) {
}
void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) {
- if (tree == nullptr) return;
+ if (tree == nullptr) return;
if (data_.is_tree()) {
AppendTreeToTree(tree, method);
- } else {
+ } else {
AppendTreeToInlined(tree, method);
- }
-}
-
+ }
+}
+
void Cord::InlineRep::PrependTreeToInlined(CordRep* tree,
MethodIdentifier method) {
assert(!is_tree());
@@ -405,20 +405,20 @@ void Cord::InlineRep::PrependTreeToTree(CordRep* tree,
}
void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
- assert(tree != nullptr);
+ assert(tree != nullptr);
if (data_.is_tree()) {
PrependTreeToTree(tree, method);
- } else {
+ } else {
PrependTreeToInlined(tree, method);
- }
-}
-
-// Searches for a non-full flat node at the rightmost leaf of the tree. If a
-// suitable leaf is found, the function will update the length field for all
-// nodes to account for the size increase. The append region address will be
-// written to region and the actual size increase will be written to size.
-static inline bool PrepareAppendRegion(CordRep* root, char** region,
- size_t* size, size_t max_length) {
+ }
+}
+
+// Searches for a non-full flat node at the rightmost leaf of the tree. If a
+// suitable leaf is found, the function will update the length field for all
+// nodes to account for the size increase. The append region address will be
+// written to region and the actual size increase will be written to size.
+static inline bool PrepareAppendRegion(CordRep* root, char** region,
+ size_t* size, size_t max_length) {
if (root->IsBtree() && root->refcount.IsMutable()) {
Span<char> span = root->btree()->GetAppendBuffer(max_length);
if (!span.empty()) {
@@ -428,44 +428,44 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
}
}
- // Search down the right-hand path for a non-full FLAT node.
- CordRep* dst = root;
+ // Search down the right-hand path for a non-full FLAT node.
+ CordRep* dst = root;
while (dst->IsConcat() && dst->refcount.IsMutable()) {
- dst = dst->concat()->right;
- }
-
+ dst = dst->concat()->right;
+ }
+
if (!dst->IsFlat() || !dst->refcount.IsMutable()) {
- *region = nullptr;
- *size = 0;
- return false;
- }
-
- const size_t in_use = dst->length;
+ *region = nullptr;
+ *size = 0;
+ return false;
+ }
+
+ const size_t in_use = dst->length;
const size_t capacity = dst->flat()->Capacity();
- if (in_use == capacity) {
- *region = nullptr;
- *size = 0;
- return false;
- }
-
- size_t size_increase = std::min(capacity - in_use, max_length);
-
- // We need to update the length fields for all nodes, including the leaf node.
- for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) {
- rep->length += size_increase;
- }
- dst->length += size_increase;
-
+ if (in_use == capacity) {
+ *region = nullptr;
+ *size = 0;
+ return false;
+ }
+
+ size_t size_increase = std::min(capacity - in_use, max_length);
+
+ // We need to update the length fields for all nodes, including the leaf node.
+ for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) {
+ rep->length += size_increase;
+ }
+ dst->length += size_increase;
+
*region = dst->flat()->Data() + in_use;
- *size = size_increase;
- return true;
-}
-
+ *size = size_increase;
+ return true;
+}
+
template <bool has_length>
-void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
+void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
size_t length) {
auto constexpr method = CordzUpdateTracker::kGetAppendRegion;
-
+
CordRep* root = tree();
size_t sz = root ? root->length : inline_size();
if (root == nullptr) {
@@ -476,21 +476,21 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
set_inline_size(has_length ? sz + length : kMaxInline);
return;
}
- }
-
+ }
+
size_t extra = has_length ? length : (std::max)(sz, kMinFlatLength);
CordRep* rep = root ? root : MakeFlatWithExtraCapacity(extra);
CordzUpdateScope scope(root ? data_.cordz_info() : nullptr, method);
if (PrepareAppendRegion(rep, region, size, length)) {
CommitTree(root, rep, scope, method);
- return;
- }
-
- // Allocate new node.
+ return;
+ }
+
+ // Allocate new node.
CordRepFlat* new_node = CordRepFlat::New(extra);
new_node->length = std::min(new_node->Capacity(), length);
*region = new_node->Data();
- *size = new_node->length;
+ *size = new_node->length;
if (btree_enabled()) {
rep = CordRepBtree::Append(ForceBtree(rep), new_node);
@@ -498,8 +498,8 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
rep = Concat(rep, new_node);
}
CommitTree(root, rep, scope, method);
-}
-
+}
+
// Computes the memory side of the provided edge which must be a valid data edge
// for a btrtee, i.e., a FLAT, EXTERNAL or SUBSTRING of a FLAT or EXTERNAL node.
static bool RepMemoryUsageDataEdge(const CordRep* rep,
@@ -508,11 +508,11 @@ static bool RepMemoryUsageDataEdge(const CordRep* rep,
if (ABSL_PREDICT_FALSE(rep->IsSubstring())) {
maybe_sub_size = sizeof(cord_internal::CordRepSubstring);
rep = rep->substring()->child;
- }
+ }
if (rep->IsFlat()) {
*total_mem_usage += maybe_sub_size + rep->flat()->AllocatedSize();
return true;
- }
+ }
if (rep->IsExternal()) {
// We don't know anything about the embedded / bound data, but we can safely
// assume it is 'at least' a word / pointer to data. In the future we may
@@ -524,15 +524,15 @@ static bool RepMemoryUsageDataEdge(const CordRep* rep,
return true;
}
return false;
-}
-
-// If the rep is a leaf, this will increment the value at total_mem_usage and
-// will return true.
-static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
+}
+
+// If the rep is a leaf, this will increment the value at total_mem_usage and
+// will return true.
+static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
if (rep->IsFlat()) {
*total_mem_usage += rep->flat()->AllocatedSize();
- return true;
- }
+ return true;
+ }
if (rep->IsExternal()) {
// We don't know anything about the embedded / bound data, but we can safely
// assume it is 'at least' a word / pointer to data. In the future we may
@@ -540,12 +540,12 @@ static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
// well-known externals, such as a std::string instance.
*total_mem_usage +=
sizeof(cord_internal::CordRepExternalImpl<intptr_t>) + rep->length;
- return true;
- }
- return false;
-}
-
-void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
+ return true;
+ }
+ return false;
+}
+
+void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
assert(&src != this);
assert(is_tree() || src.is_tree());
auto constexpr method = CordzUpdateTracker::kAssignCord;
@@ -553,7 +553,7 @@ void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
EmplaceTree(CordRep::Ref(src.as_tree()), src.data_, method);
return;
}
-
+
CordRep* tree = as_tree();
if (CordRep* src_tree = src.tree()) {
// Leave any existing `cordz_info` in place, and let MaybeTrackCord()
@@ -563,60 +563,60 @@ void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
} else {
CordzInfo::MaybeUntrackCord(data_.cordz_info());
data_ = src.data_;
- }
+ }
CordRep::Unref(tree);
-}
-
+}
+
void Cord::InlineRep::UnrefTree() {
- if (is_tree()) {
+ if (is_tree()) {
CordzInfo::MaybeUntrackCord(data_.cordz_info());
CordRep::Unref(tree());
- }
-}
-
-// --------------------------------------------------------------------
-// Constructors and destructors
-
+ }
+}
+
+// --------------------------------------------------------------------
+// Constructors and destructors
+
Cord::Cord(absl::string_view src, MethodIdentifier method)
: contents_(InlineData::kDefaultInit) {
- const size_t n = src.size();
- if (n <= InlineRep::kMaxInline) {
+ const size_t n = src.size();
+ if (n <= InlineRep::kMaxInline) {
contents_.set_data(src.data(), n, true);
- } else {
+ } else {
CordRep* rep = NewTree(src.data(), n, 0);
contents_.EmplaceTree(rep, method);
- }
-}
-
-template <typename T, Cord::EnableIfString<T>>
+ }
+}
+
+template <typename T, Cord::EnableIfString<T>>
Cord::Cord(T&& src) : contents_(InlineData::kDefaultInit) {
if (src.size() <= InlineRep::kMaxInline) {
contents_.set_data(src.data(), src.size(), true);
- } else {
+ } else {
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.EmplaceTree(rep, CordzUpdateTracker::kConstructorString);
- }
-}
-
-template Cord::Cord(std::string&& src);
-
-// The destruction code is separate so that the compiler can determine
-// that it does not need to call the destructor on a moved-from Cord.
-void Cord::DestroyCordSlow() {
+ }
+}
+
+template Cord::Cord(std::string&& src);
+
+// The destruction code is separate so that the compiler can determine
+// that it does not need to call the destructor on a moved-from Cord.
+void Cord::DestroyCordSlow() {
assert(contents_.is_tree());
CordzInfo::MaybeUntrackCord(contents_.cordz_info());
CordRep::Unref(VerifyTree(contents_.as_tree()));
-}
-
-// --------------------------------------------------------------------
-// Mutators
-
-void Cord::Clear() {
+}
+
+// --------------------------------------------------------------------
+// Mutators
+
+void Cord::Clear() {
if (CordRep* tree = contents_.clear()) {
CordRep::Unref(tree);
}
-}
-
+}
+
Cord& Cord::AssignLargeString(std::string&& src) {
auto constexpr method = CordzUpdateTracker::kAssignString;
assert(src.size() > kMaxBytesToCopy);
@@ -631,21 +631,21 @@ Cord& Cord::AssignLargeString(std::string&& src) {
return *this;
}
-Cord& Cord::operator=(absl::string_view src) {
+Cord& Cord::operator=(absl::string_view src) {
auto constexpr method = CordzUpdateTracker::kAssignString;
- const char* data = src.data();
- size_t length = src.size();
- CordRep* tree = contents_.tree();
- if (length <= InlineRep::kMaxInline) {
+ const char* data = src.data();
+ size_t length = src.size();
+ CordRep* tree = contents_.tree();
+ if (length <= InlineRep::kMaxInline) {
// Embed into this->contents_, which is somewhat subtle:
// - MaybeUntrackCord must be called before Unref(tree).
// - MaybeUntrackCord must be called before set_data() clobbers cordz_info.
// - set_data() must be called before Unref(tree) as it may reference tree.
if (tree != nullptr) CordzInfo::MaybeUntrackCord(contents_.cordz_info());
- contents_.set_data(data, length, true);
+ contents_.set_data(data, length, true);
if (tree != nullptr) CordRep::Unref(tree);
- return *this;
- }
+ return *this;
+ }
if (tree != nullptr) {
CordzUpdateScope scope(contents_.cordz_info(), method);
if (tree->IsFlat() && tree->flat()->Capacity() >= length &&
@@ -658,28 +658,28 @@ Cord& Cord::operator=(absl::string_view src) {
}
contents_.SetTree(NewTree(data, length, 0), scope);
CordRep::Unref(tree);
- } else {
+ } else {
contents_.EmplaceTree(NewTree(data, length, 0), method);
- }
- return *this;
-}
-
-// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
-// we keep it here to make diffs easier.
+ }
+ return *this;
+}
+
+// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
+// we keep it here to make diffs easier.
void Cord::InlineRep::AppendArray(absl::string_view src,
MethodIdentifier method) {
if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
-
- size_t appended = 0;
+
+ size_t appended = 0;
CordRep* rep = tree();
const CordRep* const root = rep;
CordzUpdateScope scope(root ? cordz_info() : nullptr, method);
if (root != nullptr) {
- char* region;
+ char* region;
if (PrepareAppendRegion(rep, &region, &appended, src.size())) {
memcpy(region, src.data(), appended);
- }
- } else {
+ }
+ } else {
// Try to fit in the inline buffer if possible.
size_t inline_length = inline_size();
if (src.size() <= kMaxInline - inline_length) {
@@ -697,14 +697,14 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
memcpy(rep->flat()->Data(), data_.as_chars(), inline_length);
memcpy(rep->flat()->Data() + inline_length, src.data(), appended);
rep->length = inline_length + appended;
- }
-
+ }
+
src.remove_prefix(appended);
if (src.empty()) {
CommitTree(root, rep, scope, method);
- return;
- }
-
+ return;
+ }
+
if (btree_enabled()) {
// TODO(b/192061034): keep legacy 10% growth rate: consider other rates.
rep = ForceBtree(rep);
@@ -727,22 +727,22 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
rep = Concat(rep, NewTree(src.data(), src.size(), length - src.size()));
}
CommitTree(root, rep, scope, method);
-}
-
-inline CordRep* Cord::TakeRep() const& {
+}
+
+inline CordRep* Cord::TakeRep() const& {
return CordRep::Ref(contents_.tree());
-}
-
-inline CordRep* Cord::TakeRep() && {
- CordRep* rep = contents_.tree();
- contents_.clear();
- return rep;
-}
-
-template <typename C>
-inline void Cord::AppendImpl(C&& src) {
+}
+
+inline CordRep* Cord::TakeRep() && {
+ CordRep* rep = contents_.tree();
+ contents_.clear();
+ return rep;
+}
+
+template <typename C>
+inline void Cord::AppendImpl(C&& src) {
auto constexpr method = CordzUpdateTracker::kAppendCord;
- if (empty()) {
+ if (empty()) {
// Since destination is empty, we can avoid allocating a node,
if (src.contents_.is_tree()) {
// by taking the tree directly
@@ -752,75 +752,75 @@ inline void Cord::AppendImpl(C&& src) {
// or copying over inline data
contents_.data_ = src.contents_.data_;
}
- return;
- }
-
- // For short cords, it is faster to copy data if there is room in dst.
- const size_t src_size = src.contents_.size();
- if (src_size <= kMaxBytesToCopy) {
- CordRep* src_tree = src.contents_.tree();
- if (src_tree == nullptr) {
- // src has embedded data.
+ return;
+ }
+
+ // For short cords, it is faster to copy data if there is room in dst.
+ const size_t src_size = src.contents_.size();
+ if (src_size <= kMaxBytesToCopy) {
+ CordRep* src_tree = src.contents_.tree();
+ if (src_tree == nullptr) {
+ // src has embedded data.
contents_.AppendArray({src.contents_.data(), src_size}, method);
- return;
- }
+ return;
+ }
if (src_tree->IsFlat()) {
- // src tree just has one flat node.
+ // src tree just has one flat node.
contents_.AppendArray({src_tree->flat()->Data(), src_size}, method);
- return;
- }
- if (&src == this) {
- // ChunkIterator below assumes that src is not modified during traversal.
- Append(Cord(src));
- return;
- }
- // TODO(mec): Should we only do this if "dst" has space?
- for (absl::string_view chunk : src.Chunks()) {
- Append(chunk);
- }
- return;
- }
-
+ return;
+ }
+ if (&src == this) {
+ // ChunkIterator below assumes that src is not modified during traversal.
+ Append(Cord(src));
+ return;
+ }
+ // TODO(mec): Should we only do this if "dst" has space?
+ for (absl::string_view chunk : src.Chunks()) {
+ Append(chunk);
+ }
+ return;
+ }
+
// Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
CordRep* rep = std::forward<C>(src).TakeRep();
contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
-}
-
+}
+
void Cord::Append(const Cord& src) {
AppendImpl(src);
}
-
+
void Cord::Append(Cord&& src) {
AppendImpl(std::move(src));
}
-
-template <typename T, Cord::EnableIfString<T>>
-void Cord::Append(T&& src) {
- if (src.size() <= kMaxBytesToCopy) {
- Append(absl::string_view(src));
- } else {
+
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(absl::string_view(src));
+ } else {
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.AppendTree(rep, CordzUpdateTracker::kAppendString);
- }
-}
-
-template void Cord::Append(std::string&& src);
-
-void Cord::Prepend(const Cord& src) {
- CordRep* src_tree = src.contents_.tree();
- if (src_tree != nullptr) {
+ }
+}
+
+template void Cord::Append(std::string&& src);
+
+void Cord::Prepend(const Cord& src) {
+ CordRep* src_tree = src.contents_.tree();
+ if (src_tree != nullptr) {
CordRep::Ref(src_tree);
contents_.PrependTree(src_tree, CordzUpdateTracker::kPrependCord);
- return;
- }
-
- // `src` cord is inlined.
- absl::string_view src_contents(src.contents_.data(), src.contents_.size());
- return Prepend(src_contents);
-}
-
+ return;
+ }
+
+ // `src` cord is inlined.
+ absl::string_view src_contents(src.contents_.data(), src.contents_.size());
+ return Prepend(src_contents);
+}
+
void Cord::PrependArray(absl::string_view src, MethodIdentifier method) {
- if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
+ if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
if (!contents_.is_tree()) {
size_t cur_size = contents_.inline_size();
if (cur_size + src.size() <= InlineRep::kMaxInline) {
@@ -832,116 +832,116 @@ void Cord::PrependArray(absl::string_view src, MethodIdentifier method) {
contents_.set_inline_size(cur_size + src.size());
return;
}
- }
+ }
CordRep* rep = NewTree(src.data(), src.size(), 0);
contents_.PrependTree(rep, method);
-}
-
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Prepend(T&& src) {
- if (src.size() <= kMaxBytesToCopy) {
- Prepend(absl::string_view(src));
- } else {
+}
+
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(absl::string_view(src));
+ } else {
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);
- }
-}
-
-template void Cord::Prepend(std::string&& src);
-
-static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
- if (n >= node->length) return nullptr;
+ }
+}
+
+template void Cord::Prepend(std::string&& src);
+
+static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
+ if (n >= node->length) return nullptr;
if (n == 0) return CordRep::Ref(node);
- absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
-
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
+
while (node->IsConcat()) {
- assert(n <= node->length);
- if (n < node->concat()->left->length) {
- // Push right to stack, descend left.
- rhs_stack.push_back(node->concat()->right);
- node = node->concat()->left;
- } else {
- // Drop left, descend right.
- n -= node->concat()->left->length;
- node = node->concat()->right;
- }
- }
- assert(n <= node->length);
-
- if (n == 0) {
+ assert(n <= node->length);
+ if (n < node->concat()->left->length) {
+ // Push right to stack, descend left.
+ rhs_stack.push_back(node->concat()->right);
+ node = node->concat()->left;
+ } else {
+ // Drop left, descend right.
+ n -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+ assert(n <= node->length);
+
+ if (n == 0) {
CordRep::Ref(node);
- } else {
- size_t start = n;
- size_t len = node->length - n;
+ } else {
+ size_t start = n;
+ size_t len = node->length - n;
if (node->IsSubstring()) {
- // Consider in-place update of node, similar to in RemoveSuffixFrom().
- start += node->substring()->start;
- node = node->substring()->child;
- }
+ // Consider in-place update of node, similar to in RemoveSuffixFrom().
+ start += node->substring()->start;
+ node = node->substring()->child;
+ }
node = NewSubstring(CordRep::Ref(node), start, len);
- }
- while (!rhs_stack.empty()) {
+ }
+ while (!rhs_stack.empty()) {
node = Concat(node, CordRep::Ref(rhs_stack.back()));
- rhs_stack.pop_back();
- }
- return node;
-}
-
-// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
-// exception that removing a suffix has an optimization where a node may be
-// edited in place iff that node and all its ancestors have a refcount of 1.
-static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
- if (n >= node->length) return nullptr;
+ rhs_stack.pop_back();
+ }
+ return node;
+}
+
+// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
+// exception that removing a suffix has an optimization where a node may be
+// edited in place iff that node and all its ancestors have a refcount of 1.
+static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
+ if (n >= node->length) return nullptr;
if (n == 0) return CordRep::Ref(node);
- absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
bool inplace_ok = node->refcount.IsMutable();
-
+
while (node->IsConcat()) {
- assert(n <= node->length);
- if (n < node->concat()->right->length) {
- // Push left to stack, descend right.
- lhs_stack.push_back(node->concat()->left);
- node = node->concat()->right;
- } else {
- // Drop right, descend left.
- n -= node->concat()->right->length;
- node = node->concat()->left;
- }
+ assert(n <= node->length);
+ if (n < node->concat()->right->length) {
+ // Push left to stack, descend right.
+ lhs_stack.push_back(node->concat()->left);
+ node = node->concat()->right;
+ } else {
+ // Drop right, descend left.
+ n -= node->concat()->right->length;
+ node = node->concat()->left;
+ }
inplace_ok = inplace_ok && node->refcount.IsMutable();
- }
- assert(n <= node->length);
-
- if (n == 0) {
+ }
+ assert(n <= node->length);
+
+ if (n == 0) {
CordRep::Ref(node);
} else if (inplace_ok && !node->IsExternal()) {
- // Consider making a new buffer if the current node capacity is much
- // larger than the new length.
+ // Consider making a new buffer if the current node capacity is much
+ // larger than the new length.
CordRep::Ref(node);
- node->length -= n;
- } else {
- size_t start = 0;
- size_t len = node->length - n;
+ node->length -= n;
+ } else {
+ size_t start = 0;
+ size_t len = node->length - n;
if (node->IsSubstring()) {
- start = node->substring()->start;
- node = node->substring()->child;
- }
+ start = node->substring()->start;
+ node = node->substring()->child;
+ }
node = NewSubstring(CordRep::Ref(node), start, len);
- }
- while (!lhs_stack.empty()) {
+ }
+ while (!lhs_stack.empty()) {
node = Concat(CordRep::Ref(lhs_stack.back()), node);
- lhs_stack.pop_back();
- }
- return node;
-}
-
-void Cord::RemovePrefix(size_t n) {
- ABSL_INTERNAL_CHECK(n <= size(),
- absl::StrCat("Requested prefix size ", n,
- " exceeds Cord's size ", size()));
- CordRep* tree = contents_.tree();
- if (tree == nullptr) {
- contents_.remove_prefix(n);
- } else {
+ lhs_stack.pop_back();
+ }
+ return node;
+}
+
+void Cord::RemovePrefix(size_t n) {
+ ABSL_INTERNAL_CHECK(n <= size(),
+ absl::StrCat("Requested prefix size ", n,
+ " exceeds Cord's size ", size()));
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ contents_.remove_prefix(n);
+ } else {
auto constexpr method = CordzUpdateTracker::kRemovePrefix;
CordzUpdateScope scope(contents_.cordz_info(), method);
if (tree->IsBtree()) {
@@ -954,17 +954,17 @@ void Cord::RemovePrefix(size_t n) {
tree = VerifyTree(newrep);
}
contents_.SetTreeOrEmpty(tree, scope);
- }
-}
-
-void Cord::RemoveSuffix(size_t n) {
- ABSL_INTERNAL_CHECK(n <= size(),
- absl::StrCat("Requested suffix size ", n,
- " exceeds Cord's size ", size()));
- CordRep* tree = contents_.tree();
- if (tree == nullptr) {
- contents_.reduce_size(n);
- } else {
+ }
+}
+
+void Cord::RemoveSuffix(size_t n) {
+ ABSL_INTERNAL_CHECK(n <= size(),
+ absl::StrCat("Requested suffix size ", n,
+ " exceeds Cord's size ", size()));
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ contents_.reduce_size(n);
+ } else {
auto constexpr method = CordzUpdateTracker::kRemoveSuffix;
CordzUpdateScope scope(contents_.cordz_info(), method);
if (tree->IsBtree()) {
@@ -975,296 +975,296 @@ void Cord::RemoveSuffix(size_t n) {
tree = VerifyTree(newrep);
}
contents_.SetTreeOrEmpty(tree, scope);
- }
-}
-
-// Work item for NewSubRange().
-struct SubRange {
- SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
- : node(a_node), pos(a_pos), n(a_n) {}
- CordRep* node; // nullptr means concat last 2 results.
- size_t pos;
- size_t n;
-};
-
-static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
- absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
- absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
- todo.push_back(SubRange(node, pos, n));
- do {
- const SubRange& sr = todo.back();
- node = sr.node;
- pos = sr.pos;
- n = sr.n;
- todo.pop_back();
-
- if (node == nullptr) {
- assert(results.size() >= 2);
- CordRep* right = results.back();
- results.pop_back();
- CordRep* left = results.back();
- results.pop_back();
- results.push_back(Concat(left, right));
- } else if (pos == 0 && n == node->length) {
+ }
+}
+
+// Work item for NewSubRange().
+struct SubRange {
+ SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
+ : node(a_node), pos(a_pos), n(a_n) {}
+ CordRep* node; // nullptr means concat last 2 results.
+ size_t pos;
+ size_t n;
+};
+
+static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
+ absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
+ todo.push_back(SubRange(node, pos, n));
+ do {
+ const SubRange& sr = todo.back();
+ node = sr.node;
+ pos = sr.pos;
+ n = sr.n;
+ todo.pop_back();
+
+ if (node == nullptr) {
+ assert(results.size() >= 2);
+ CordRep* right = results.back();
+ results.pop_back();
+ CordRep* left = results.back();
+ results.pop_back();
+ results.push_back(Concat(left, right));
+ } else if (pos == 0 && n == node->length) {
results.push_back(CordRep::Ref(node));
} else if (!node->IsConcat()) {
if (node->IsSubstring()) {
- pos += node->substring()->start;
- node = node->substring()->child;
- }
+ pos += node->substring()->start;
+ node = node->substring()->child;
+ }
results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
- } else if (pos + n <= node->concat()->left->length) {
- todo.push_back(SubRange(node->concat()->left, pos, n));
- } else if (pos >= node->concat()->left->length) {
- pos -= node->concat()->left->length;
- todo.push_back(SubRange(node->concat()->right, pos, n));
- } else {
- size_t left_n = node->concat()->left->length - pos;
- todo.push_back(SubRange(nullptr, 0, 0)); // Concat()
- todo.push_back(SubRange(node->concat()->right, 0, n - left_n));
- todo.push_back(SubRange(node->concat()->left, pos, left_n));
- }
- } while (!todo.empty());
- assert(results.size() == 1);
- return results[0];
-}
-
-Cord Cord::Subcord(size_t pos, size_t new_size) const {
- Cord sub_cord;
- size_t length = size();
- if (pos > length) pos = length;
- if (new_size > length - pos) new_size = length - pos;
+ } else if (pos + n <= node->concat()->left->length) {
+ todo.push_back(SubRange(node->concat()->left, pos, n));
+ } else if (pos >= node->concat()->left->length) {
+ pos -= node->concat()->left->length;
+ todo.push_back(SubRange(node->concat()->right, pos, n));
+ } else {
+ size_t left_n = node->concat()->left->length - pos;
+ todo.push_back(SubRange(nullptr, 0, 0)); // Concat()
+ todo.push_back(SubRange(node->concat()->right, 0, n - left_n));
+ todo.push_back(SubRange(node->concat()->left, pos, left_n));
+ }
+ } while (!todo.empty());
+ assert(results.size() == 1);
+ return results[0];
+}
+
+Cord Cord::Subcord(size_t pos, size_t new_size) const {
+ Cord sub_cord;
+ size_t length = size();
+ if (pos > length) pos = length;
+ if (new_size > length - pos) new_size = length - pos;
if (new_size == 0) return sub_cord;
- CordRep* tree = contents_.tree();
- if (tree == nullptr) {
- // sub_cord is newly constructed, no need to re-zero-out the tail of
- // contents_ memory.
- sub_cord.contents_.set_data(contents_.data() + pos, new_size, false);
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ // sub_cord is newly constructed, no need to re-zero-out the tail of
+ // contents_ memory.
+ sub_cord.contents_.set_data(contents_.data() + pos, new_size, false);
return sub_cord;
}
if (new_size <= InlineRep::kMaxInline) {
char* dest = sub_cord.contents_.data_.as_chars();
- Cord::ChunkIterator it = chunk_begin();
- it.AdvanceBytes(pos);
- size_t remaining_size = new_size;
- while (remaining_size > it->size()) {
- cord_internal::SmallMemmove(dest, it->data(), it->size());
- remaining_size -= it->size();
- dest += it->size();
- ++it;
- }
- cord_internal::SmallMemmove(dest, it->data(), remaining_size);
+ Cord::ChunkIterator it = chunk_begin();
+ it.AdvanceBytes(pos);
+ size_t remaining_size = new_size;
+ while (remaining_size > it->size()) {
+ cord_internal::SmallMemmove(dest, it->data(), it->size());
+ remaining_size -= it->size();
+ dest += it->size();
+ ++it;
+ }
+ cord_internal::SmallMemmove(dest, it->data(), remaining_size);
sub_cord.contents_.set_inline_size(new_size);
return sub_cord;
}
if (tree->IsBtree()) {
tree = tree->btree()->SubTree(pos, new_size);
- } else {
+ } else {
tree = NewSubRange(tree, pos, new_size);
- }
+ }
sub_cord.contents_.EmplaceTree(tree, contents_.data_,
CordzUpdateTracker::kSubCord);
- return sub_cord;
-}
-
-// --------------------------------------------------------------------
-// Balancing
-
-class CordForest {
- public:
- explicit CordForest(size_t length)
- : root_length_(length), trees_(kMinLengthSize, nullptr) {}
-
- void Build(CordRep* cord_root) {
- std::vector<CordRep*> pending = {cord_root};
-
- while (!pending.empty()) {
- CordRep* node = pending.back();
- pending.pop_back();
- CheckNode(node);
+ return sub_cord;
+}
+
+// --------------------------------------------------------------------
+// Balancing
+
+class CordForest {
+ public:
+ explicit CordForest(size_t length)
+ : root_length_(length), trees_(kMinLengthSize, nullptr) {}
+
+ void Build(CordRep* cord_root) {
+ std::vector<CordRep*> pending = {cord_root};
+
+ while (!pending.empty()) {
+ CordRep* node = pending.back();
+ pending.pop_back();
+ CheckNode(node);
if (ABSL_PREDICT_FALSE(!node->IsConcat())) {
- AddNode(node);
- continue;
- }
-
- CordRepConcat* concat_node = node->concat();
- if (concat_node->depth() >= kMinLengthSize ||
- concat_node->length < min_length[concat_node->depth()]) {
- pending.push_back(concat_node->right);
- pending.push_back(concat_node->left);
-
- if (concat_node->refcount.IsOne()) {
- concat_node->left = concat_freelist_;
- concat_freelist_ = concat_node;
- } else {
+ AddNode(node);
+ continue;
+ }
+
+ CordRepConcat* concat_node = node->concat();
+ if (concat_node->depth() >= kMinLengthSize ||
+ concat_node->length < min_length[concat_node->depth()]) {
+ pending.push_back(concat_node->right);
+ pending.push_back(concat_node->left);
+
+ if (concat_node->refcount.IsOne()) {
+ concat_node->left = concat_freelist_;
+ concat_freelist_ = concat_node;
+ } else {
CordRep::Ref(concat_node->right);
CordRep::Ref(concat_node->left);
CordRep::Unref(concat_node);
- }
- } else {
- AddNode(node);
- }
- }
- }
-
- CordRep* ConcatNodes() {
- CordRep* sum = nullptr;
- for (auto* node : trees_) {
- if (node == nullptr) continue;
-
- sum = PrependNode(node, sum);
- root_length_ -= node->length;
- if (root_length_ == 0) break;
- }
- ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node");
- return VerifyTree(sum);
- }
-
- private:
- CordRep* AppendNode(CordRep* node, CordRep* sum) {
- return (sum == nullptr) ? node : MakeConcat(sum, node);
- }
-
- CordRep* PrependNode(CordRep* node, CordRep* sum) {
- return (sum == nullptr) ? node : MakeConcat(node, sum);
- }
-
- void AddNode(CordRep* node) {
- CordRep* sum = nullptr;
-
- // Collect together everything with which we will merge with node
- int i = 0;
- for (; node->length > min_length[i + 1]; ++i) {
- auto& tree_at_i = trees_[i];
-
- if (tree_at_i == nullptr) continue;
- sum = PrependNode(tree_at_i, sum);
- tree_at_i = nullptr;
- }
-
- sum = AppendNode(node, sum);
-
- // Insert sum into appropriate place in the forest
- for (; sum->length >= min_length[i]; ++i) {
- auto& tree_at_i = trees_[i];
- if (tree_at_i == nullptr) continue;
-
- sum = MakeConcat(tree_at_i, sum);
- tree_at_i = nullptr;
- }
-
- // min_length[0] == 1, which means sum->length >= min_length[0]
- assert(i > 0);
- trees_[i - 1] = sum;
- }
-
- // Make concat node trying to resue existing CordRepConcat nodes we
- // already collected in the concat_freelist_.
- CordRep* MakeConcat(CordRep* left, CordRep* right) {
- if (concat_freelist_ == nullptr) return RawConcat(left, right);
-
- CordRepConcat* rep = concat_freelist_;
- if (concat_freelist_->left == nullptr) {
- concat_freelist_ = nullptr;
- } else {
- concat_freelist_ = concat_freelist_->left->concat();
- }
- SetConcatChildren(rep, left, right);
-
- return rep;
- }
-
- static void CheckNode(CordRep* node) {
- ABSL_INTERNAL_CHECK(node->length != 0u, "");
+ }
+ } else {
+ AddNode(node);
+ }
+ }
+ }
+
+ CordRep* ConcatNodes() {
+ CordRep* sum = nullptr;
+ for (auto* node : trees_) {
+ if (node == nullptr) continue;
+
+ sum = PrependNode(node, sum);
+ root_length_ -= node->length;
+ if (root_length_ == 0) break;
+ }
+ ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node");
+ return VerifyTree(sum);
+ }
+
+ private:
+ CordRep* AppendNode(CordRep* node, CordRep* sum) {
+ return (sum == nullptr) ? node : MakeConcat(sum, node);
+ }
+
+ CordRep* PrependNode(CordRep* node, CordRep* sum) {
+ return (sum == nullptr) ? node : MakeConcat(node, sum);
+ }
+
+ void AddNode(CordRep* node) {
+ CordRep* sum = nullptr;
+
+ // Collect together everything with which we will merge with node
+ int i = 0;
+ for (; node->length > min_length[i + 1]; ++i) {
+ auto& tree_at_i = trees_[i];
+
+ if (tree_at_i == nullptr) continue;
+ sum = PrependNode(tree_at_i, sum);
+ tree_at_i = nullptr;
+ }
+
+ sum = AppendNode(node, sum);
+
+ // Insert sum into appropriate place in the forest
+ for (; sum->length >= min_length[i]; ++i) {
+ auto& tree_at_i = trees_[i];
+ if (tree_at_i == nullptr) continue;
+
+ sum = MakeConcat(tree_at_i, sum);
+ tree_at_i = nullptr;
+ }
+
+ // min_length[0] == 1, which means sum->length >= min_length[0]
+ assert(i > 0);
+ trees_[i - 1] = sum;
+ }
+
+ // Make concat node trying to resue existing CordRepConcat nodes we
+ // already collected in the concat_freelist_.
+ CordRep* MakeConcat(CordRep* left, CordRep* right) {
+ if (concat_freelist_ == nullptr) return RawConcat(left, right);
+
+ CordRepConcat* rep = concat_freelist_;
+ if (concat_freelist_->left == nullptr) {
+ concat_freelist_ = nullptr;
+ } else {
+ concat_freelist_ = concat_freelist_->left->concat();
+ }
+ SetConcatChildren(rep, left, right);
+
+ return rep;
+ }
+
+ static void CheckNode(CordRep* node) {
+ ABSL_INTERNAL_CHECK(node->length != 0u, "");
if (node->IsConcat()) {
- ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, "");
- ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, "");
- ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length +
- node->concat()->right->length),
- "");
- }
- }
-
- size_t root_length_;
-
- // use an inlined vector instead of a flat array to get bounds checking
- absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_;
-
- // List of concat nodes we can re-use for Cord balancing.
- CordRepConcat* concat_freelist_ = nullptr;
-};
-
-static CordRep* Rebalance(CordRep* node) {
- VerifyTree(node);
+ ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, "");
+ ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, "");
+ ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length +
+ node->concat()->right->length),
+ "");
+ }
+ }
+
+ size_t root_length_;
+
+ // use an inlined vector instead of a flat array to get bounds checking
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_;
+
+ // List of concat nodes we can re-use for Cord balancing.
+ CordRepConcat* concat_freelist_ = nullptr;
+};
+
+static CordRep* Rebalance(CordRep* node) {
+ VerifyTree(node);
assert(node->IsConcat());
-
- if (node->length == 0) {
- return nullptr;
- }
-
- CordForest forest(node->length);
- forest.Build(node);
- return forest.ConcatNodes();
-}
-
-// --------------------------------------------------------------------
-// Comparators
-
-namespace {
-
-int ClampResult(int memcmp_res) {
- return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
-}
-
-int CompareChunks(absl::string_view* lhs, absl::string_view* rhs,
- size_t* size_to_compare) {
- size_t compared_size = std::min(lhs->size(), rhs->size());
- assert(*size_to_compare >= compared_size);
- *size_to_compare -= compared_size;
-
- int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size);
- if (memcmp_res != 0) return memcmp_res;
-
- lhs->remove_prefix(compared_size);
- rhs->remove_prefix(compared_size);
-
- return 0;
-}
-
-// This overload set computes comparison results from memcmp result. This
-// interface is used inside GenericCompare below. Differet implementations
-// are specialized for int and bool. For int we clamp result to {-1, 0, 1}
-// set. For bool we just interested in "value == 0".
-template <typename ResultType>
-ResultType ComputeCompareResult(int memcmp_res) {
- return ClampResult(memcmp_res);
-}
-template <>
-bool ComputeCompareResult<bool>(int memcmp_res) {
- return memcmp_res == 0;
-}
-
-} // namespace
-
+
+ if (node->length == 0) {
+ return nullptr;
+ }
+
+ CordForest forest(node->length);
+ forest.Build(node);
+ return forest.ConcatNodes();
+}
+
+// --------------------------------------------------------------------
+// Comparators
+
+namespace {
+
+int ClampResult(int memcmp_res) {
+ return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
+}
+
+int CompareChunks(absl::string_view* lhs, absl::string_view* rhs,
+ size_t* size_to_compare) {
+ size_t compared_size = std::min(lhs->size(), rhs->size());
+ assert(*size_to_compare >= compared_size);
+ *size_to_compare -= compared_size;
+
+ int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size);
+ if (memcmp_res != 0) return memcmp_res;
+
+ lhs->remove_prefix(compared_size);
+ rhs->remove_prefix(compared_size);
+
+ return 0;
+}
+
+// This overload set computes comparison results from memcmp result. This
+// interface is used inside GenericCompare below. Differet implementations
+// are specialized for int and bool. For int we clamp result to {-1, 0, 1}
+// set. For bool we just interested in "value == 0".
+template <typename ResultType>
+ResultType ComputeCompareResult(int memcmp_res) {
+ return ClampResult(memcmp_res);
+}
+template <>
+bool ComputeCompareResult<bool>(int memcmp_res) {
+ return memcmp_res == 0;
+}
+
+} // namespace
+
// Helper routine. Locates the first flat or external chunk of the Cord without
// initializing the iterator, and returns a string_view referencing the data.
-inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
+inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
if (!is_tree()) {
return absl::string_view(data_.as_chars(), data_.inline_size());
- }
-
- CordRep* node = tree();
+ }
+
+ CordRep* node = tree();
if (node->IsFlat()) {
return absl::string_view(node->flat()->Data(), node->length);
- }
-
+ }
+
if (node->IsExternal()) {
- return absl::string_view(node->external()->base, node->length);
- }
-
+ return absl::string_view(node->external()->base, node->length);
+ }
+
if (node->IsBtree()) {
CordRepBtree* tree = node->btree();
int height = tree->height();
@@ -1274,264 +1274,264 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
return tree->Data(tree->begin());
}
- // Walk down the left branches until we hit a non-CONCAT node.
+ // Walk down the left branches until we hit a non-CONCAT node.
while (node->IsConcat()) {
- node = node->concat()->left;
- }
-
- // Get the child node if we encounter a SUBSTRING.
- size_t offset = 0;
- size_t length = node->length;
- assert(length != 0);
-
+ node = node->concat()->left;
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
+ assert(length != 0);
+
if (node->IsSubstring()) {
- offset = node->substring()->start;
- node = node->substring()->child;
- }
-
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
if (node->IsFlat()) {
return absl::string_view(node->flat()->Data() + offset, length);
- }
-
+ }
+
assert(node->IsExternal() && "Expect FLAT or EXTERNAL node here");
-
- return absl::string_view(node->external()->base + offset, length);
-}
-
-inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
- size_t size_to_compare) const {
- auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
- if (!chunk->empty()) return true;
- ++*it;
- if (it->bytes_remaining_ == 0) return false;
- *chunk = **it;
- return true;
- };
-
- Cord::ChunkIterator lhs_it = chunk_begin();
-
- // compared_size is inside first chunk.
- absl::string_view lhs_chunk =
- (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
- assert(compared_size <= lhs_chunk.size());
- assert(compared_size <= rhs.size());
- lhs_chunk.remove_prefix(compared_size);
- rhs.remove_prefix(compared_size);
- size_to_compare -= compared_size; // skip already compared size.
-
- while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) {
- int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare);
- if (comparison_result != 0) return comparison_result;
- if (size_to_compare == 0) return 0;
- }
-
- return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty());
-}
-
-inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
- size_t size_to_compare) const {
- auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
- if (!chunk->empty()) return true;
- ++*it;
- if (it->bytes_remaining_ == 0) return false;
- *chunk = **it;
- return true;
- };
-
- Cord::ChunkIterator lhs_it = chunk_begin();
- Cord::ChunkIterator rhs_it = rhs.chunk_begin();
-
- // compared_size is inside both first chunks.
- absl::string_view lhs_chunk =
- (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
- absl::string_view rhs_chunk =
- (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view();
- assert(compared_size <= lhs_chunk.size());
- assert(compared_size <= rhs_chunk.size());
- lhs_chunk.remove_prefix(compared_size);
- rhs_chunk.remove_prefix(compared_size);
- size_to_compare -= compared_size; // skip already compared size.
-
- while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) {
- int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare);
- if (memcmp_res != 0) return memcmp_res;
- if (size_to_compare == 0) return 0;
- }
-
- return static_cast<int>(rhs_chunk.empty()) -
- static_cast<int>(lhs_chunk.empty());
-}
-
-inline absl::string_view Cord::GetFirstChunk(const Cord& c) {
- return c.contents_.FindFlatStartPiece();
-}
-inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {
- return sv;
-}
-
-// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed
-// that 'size_to_compare' is greater that size of smallest of first chunks.
-template <typename ResultType, typename RHS>
-ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
- size_t size_to_compare) {
- absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs);
- absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs);
-
- size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());
- assert(size_to_compare >= compared_size);
- int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size);
- if (compared_size == size_to_compare || memcmp_res != 0) {
- return ComputeCompareResult<ResultType>(memcmp_res);
- }
-
- return ComputeCompareResult<ResultType>(
- lhs.CompareSlowPath(rhs, compared_size, size_to_compare));
-}
-
-bool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const {
- return GenericCompare<bool>(*this, rhs, size_to_compare);
-}
-
-bool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const {
- return GenericCompare<bool>(*this, rhs, size_to_compare);
-}
-
-template <typename RHS>
-inline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) {
- size_t lhs_size = lhs.size();
- size_t rhs_size = rhs.size();
- if (lhs_size == rhs_size) {
- return GenericCompare<int>(lhs, rhs, lhs_size);
- }
- if (lhs_size < rhs_size) {
- auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size);
- return data_comp_res == 0 ? -1 : data_comp_res;
- }
-
- auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size);
- return data_comp_res == 0 ? +1 : data_comp_res;
-}
-
-int Cord::Compare(absl::string_view rhs) const {
- return SharedCompareImpl(*this, rhs);
-}
-
-int Cord::CompareImpl(const Cord& rhs) const {
- return SharedCompareImpl(*this, rhs);
-}
-
-bool Cord::EndsWith(absl::string_view rhs) const {
- size_t my_size = size();
- size_t rhs_size = rhs.size();
-
- if (my_size < rhs_size) return false;
-
- Cord tmp(*this);
- tmp.RemovePrefix(my_size - rhs_size);
- return tmp.EqualsImpl(rhs, rhs_size);
-}
-
-bool Cord::EndsWith(const Cord& rhs) const {
- size_t my_size = size();
- size_t rhs_size = rhs.size();
-
- if (my_size < rhs_size) return false;
-
- Cord tmp(*this);
- tmp.RemovePrefix(my_size - rhs_size);
- return tmp.EqualsImpl(rhs, rhs_size);
-}
-
-// --------------------------------------------------------------------
-// Misc.
-
-Cord::operator std::string() const {
- std::string s;
- absl::CopyCordToString(*this, &s);
- return s;
-}
-
-void CopyCordToString(const Cord& src, std::string* dst) {
- if (!src.contents_.is_tree()) {
- src.contents_.CopyTo(dst);
- } else {
- absl::strings_internal::STLStringResizeUninitialized(dst, src.size());
- src.CopyToArraySlowPath(&(*dst)[0]);
- }
-}
-
-void Cord::CopyToArraySlowPath(char* dst) const {
- assert(contents_.is_tree());
- absl::string_view fragment;
- if (GetFlatAux(contents_.tree(), &fragment)) {
- memcpy(dst, fragment.data(), fragment.size());
- return;
- }
- for (absl::string_view chunk : Chunks()) {
- memcpy(dst, chunk.data(), chunk.size());
- dst += chunk.size();
- }
-}
-
+
+ return absl::string_view(node->external()->base + offset, length);
+}
+
+inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
+ size_t size_to_compare) const {
+ auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+ if (!chunk->empty()) return true;
+ ++*it;
+ if (it->bytes_remaining_ == 0) return false;
+ *chunk = **it;
+ return true;
+ };
+
+ Cord::ChunkIterator lhs_it = chunk_begin();
+
+ // compared_size is inside first chunk.
+ absl::string_view lhs_chunk =
+ (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+ assert(compared_size <= lhs_chunk.size());
+ assert(compared_size <= rhs.size());
+ lhs_chunk.remove_prefix(compared_size);
+ rhs.remove_prefix(compared_size);
+ size_to_compare -= compared_size; // skip already compared size.
+
+ while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) {
+ int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare);
+ if (comparison_result != 0) return comparison_result;
+ if (size_to_compare == 0) return 0;
+ }
+
+ return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty());
+}
+
+inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
+ size_t size_to_compare) const {
+ auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+ if (!chunk->empty()) return true;
+ ++*it;
+ if (it->bytes_remaining_ == 0) return false;
+ *chunk = **it;
+ return true;
+ };
+
+ Cord::ChunkIterator lhs_it = chunk_begin();
+ Cord::ChunkIterator rhs_it = rhs.chunk_begin();
+
+ // compared_size is inside both first chunks.
+ absl::string_view lhs_chunk =
+ (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+ absl::string_view rhs_chunk =
+ (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view();
+ assert(compared_size <= lhs_chunk.size());
+ assert(compared_size <= rhs_chunk.size());
+ lhs_chunk.remove_prefix(compared_size);
+ rhs_chunk.remove_prefix(compared_size);
+ size_to_compare -= compared_size; // skip already compared size.
+
+ while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) {
+ int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare);
+ if (memcmp_res != 0) return memcmp_res;
+ if (size_to_compare == 0) return 0;
+ }
+
+ return static_cast<int>(rhs_chunk.empty()) -
+ static_cast<int>(lhs_chunk.empty());
+}
+
+inline absl::string_view Cord::GetFirstChunk(const Cord& c) {
+ return c.contents_.FindFlatStartPiece();
+}
+inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {
+ return sv;
+}
+
+// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed
+// that 'size_to_compare' is greater that size of smallest of first chunks.
+template <typename ResultType, typename RHS>
+ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+ size_t size_to_compare) {
+ absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs);
+ absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs);
+
+ size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());
+ assert(size_to_compare >= compared_size);
+ int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size);
+ if (compared_size == size_to_compare || memcmp_res != 0) {
+ return ComputeCompareResult<ResultType>(memcmp_res);
+ }
+
+ return ComputeCompareResult<ResultType>(
+ lhs.CompareSlowPath(rhs, compared_size, size_to_compare));
+}
+
+bool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const {
+ return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+bool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const {
+ return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+template <typename RHS>
+inline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) {
+ size_t lhs_size = lhs.size();
+ size_t rhs_size = rhs.size();
+ if (lhs_size == rhs_size) {
+ return GenericCompare<int>(lhs, rhs, lhs_size);
+ }
+ if (lhs_size < rhs_size) {
+ auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size);
+ return data_comp_res == 0 ? -1 : data_comp_res;
+ }
+
+ auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size);
+ return data_comp_res == 0 ? +1 : data_comp_res;
+}
+
+int Cord::Compare(absl::string_view rhs) const {
+ return SharedCompareImpl(*this, rhs);
+}
+
+int Cord::CompareImpl(const Cord& rhs) const {
+ return SharedCompareImpl(*this, rhs);
+}
+
+bool Cord::EndsWith(absl::string_view rhs) const {
+ size_t my_size = size();
+ size_t rhs_size = rhs.size();
+
+ if (my_size < rhs_size) return false;
+
+ Cord tmp(*this);
+ tmp.RemovePrefix(my_size - rhs_size);
+ return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+bool Cord::EndsWith(const Cord& rhs) const {
+ size_t my_size = size();
+ size_t rhs_size = rhs.size();
+
+ if (my_size < rhs_size) return false;
+
+ Cord tmp(*this);
+ tmp.RemovePrefix(my_size - rhs_size);
+ return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+// --------------------------------------------------------------------
+// Misc.
+
+Cord::operator std::string() const {
+ std::string s;
+ absl::CopyCordToString(*this, &s);
+ return s;
+}
+
+void CopyCordToString(const Cord& src, std::string* dst) {
+ if (!src.contents_.is_tree()) {
+ src.contents_.CopyTo(dst);
+ } else {
+ absl::strings_internal::STLStringResizeUninitialized(dst, src.size());
+ src.CopyToArraySlowPath(&(*dst)[0]);
+ }
+}
+
+void Cord::CopyToArraySlowPath(char* dst) const {
+ assert(contents_.is_tree());
+ absl::string_view fragment;
+ if (GetFlatAux(contents_.tree(), &fragment)) {
+ memcpy(dst, fragment.data(), fragment.size());
+ return;
+ }
+ for (absl::string_view chunk : Chunks()) {
+ memcpy(dst, chunk.data(), chunk.size());
+ dst += chunk.size();
+ }
+}
+
Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
auto& stack_of_right_children = stack_of_right_children_;
if (stack_of_right_children.empty()) {
- assert(!current_chunk_.empty()); // Called on invalid iterator.
- // We have reached the end of the Cord.
- return *this;
- }
-
- // Process the next node on the stack.
+ assert(!current_chunk_.empty()); // Called on invalid iterator.
+ // We have reached the end of the Cord.
+ return *this;
+ }
+
+ // Process the next node on the stack.
CordRep* node = stack_of_right_children.back();
stack_of_right_children.pop_back();
-
- // Walk down the left branches until we hit a non-CONCAT node. Save the
- // right children to the stack for subsequent traversal.
+
+ // Walk down the left branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
while (node->IsConcat()) {
stack_of_right_children.push_back(node->concat()->right);
- node = node->concat()->left;
- }
-
- // Get the child node if we encounter a SUBSTRING.
- size_t offset = 0;
- size_t length = node->length;
+ node = node->concat()->left;
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
if (node->IsSubstring()) {
- offset = node->substring()->start;
- node = node->substring()->child;
- }
-
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
assert(node->IsExternal() || node->IsFlat());
- assert(length != 0);
- const char* data =
+ assert(length != 0);
+ const char* data =
node->IsExternal() ? node->external()->base : node->flat()->Data();
- current_chunk_ = absl::string_view(data + offset, length);
- current_leaf_ = node;
- return *this;
-}
-
-Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
- ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
- "Attempted to iterate past `end()`");
- Cord subcord;
+ current_chunk_ = absl::string_view(data + offset, length);
+ current_leaf_ = node;
+ return *this;
+}
+
+Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
+ "Attempted to iterate past `end()`");
+ Cord subcord;
auto constexpr method = CordzUpdateTracker::kCordReader;
-
- if (n <= InlineRep::kMaxInline) {
- // Range to read fits in inline data. Flatten it.
- char* data = subcord.contents_.set_data(n);
- while (n > current_chunk_.size()) {
- memcpy(data, current_chunk_.data(), current_chunk_.size());
- data += current_chunk_.size();
- n -= current_chunk_.size();
- ++*this;
- }
- memcpy(data, current_chunk_.data(), n);
- if (n < current_chunk_.size()) {
- RemoveChunkPrefix(n);
- } else if (n > 0) {
- ++*this;
- }
- return subcord;
- }
+
+ if (n <= InlineRep::kMaxInline) {
+ // Range to read fits in inline data. Flatten it.
+ char* data = subcord.contents_.set_data(n);
+ while (n > current_chunk_.size()) {
+ memcpy(data, current_chunk_.data(), current_chunk_.size());
+ data += current_chunk_.size();
+ n -= current_chunk_.size();
+ ++*this;
+ }
+ memcpy(data, current_chunk_.data(), n);
+ if (n < current_chunk_.size()) {
+ RemoveChunkPrefix(n);
+ } else if (n > 0) {
+ ++*this;
+ }
+ return subcord;
+ }
if (btree_reader_) {
size_t chunk_size = current_chunk_.size();
@@ -1552,261 +1552,261 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
}
auto& stack_of_right_children = stack_of_right_children_;
- if (n < current_chunk_.size()) {
- // Range to read is a proper subrange of the current chunk.
- assert(current_leaf_ != nullptr);
+ if (n < current_chunk_.size()) {
+ // Range to read is a proper subrange of the current chunk.
+ assert(current_leaf_ != nullptr);
CordRep* subnode = CordRep::Ref(current_leaf_);
const char* data = subnode->IsExternal() ? subnode->external()->base
: subnode->flat()->Data();
- subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
+ subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
- RemoveChunkPrefix(n);
- return subcord;
- }
-
- // Range to read begins with a proper subrange of the current chunk.
- assert(!current_chunk_.empty());
- assert(current_leaf_ != nullptr);
+ RemoveChunkPrefix(n);
+ return subcord;
+ }
+
+ // Range to read begins with a proper subrange of the current chunk.
+ assert(!current_chunk_.empty());
+ assert(current_leaf_ != nullptr);
CordRep* subnode = CordRep::Ref(current_leaf_);
- if (current_chunk_.size() < subnode->length) {
+ if (current_chunk_.size() < subnode->length) {
const char* data = subnode->IsExternal() ? subnode->external()->base
: subnode->flat()->Data();
- subnode = NewSubstring(subnode, current_chunk_.data() - data,
- current_chunk_.size());
- }
- n -= current_chunk_.size();
- bytes_remaining_ -= current_chunk_.size();
-
- // Process the next node(s) on the stack, reading whole subtrees depending on
- // their length and how many bytes we are advancing.
- CordRep* node = nullptr;
+ subnode = NewSubstring(subnode, current_chunk_.data() - data,
+ current_chunk_.size());
+ }
+ n -= current_chunk_.size();
+ bytes_remaining_ -= current_chunk_.size();
+
+ // Process the next node(s) on the stack, reading whole subtrees depending on
+ // their length and how many bytes we are advancing.
+ CordRep* node = nullptr;
while (!stack_of_right_children.empty()) {
node = stack_of_right_children.back();
stack_of_right_children.pop_back();
- if (node->length > n) break;
- // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
- // Avoiding that would need pretty complicated logic (instead of
+ if (node->length > n) break;
+ // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
+ // Avoiding that would need pretty complicated logic (instead of
// current_leaf, keep current_subtree_ which points to the highest node
- // such that the current leaf can be found on the path of left children
- // starting from current_subtree_; delay creating subnode while node is
- // below current_subtree_; find the proper node along the path of left
- // children starting from current_subtree_ if this loop exits while staying
- // below current_subtree_; etc.; alternatively, push parents instead of
- // right children on the stack).
+ // such that the current leaf can be found on the path of left children
+ // starting from current_subtree_; delay creating subnode while node is
+ // below current_subtree_; find the proper node along the path of left
+ // children starting from current_subtree_ if this loop exits while staying
+ // below current_subtree_; etc.; alternatively, push parents instead of
+ // right children on the stack).
subnode = Concat(subnode, CordRep::Ref(node));
- n -= node->length;
- bytes_remaining_ -= node->length;
- node = nullptr;
- }
-
- if (node == nullptr) {
- // We have reached the end of the Cord.
- assert(bytes_remaining_ == 0);
+ n -= node->length;
+ bytes_remaining_ -= node->length;
+ node = nullptr;
+ }
+
+ if (node == nullptr) {
+ // We have reached the end of the Cord.
+ assert(bytes_remaining_ == 0);
subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
- return subcord;
- }
-
- // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
- // right children to the stack for subsequent traversal.
+ return subcord;
+ }
+
+ // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
while (node->IsConcat()) {
- if (node->concat()->left->length > n) {
- // Push right, descend left.
+ if (node->concat()->left->length > n) {
+ // Push right, descend left.
stack_of_right_children.push_back(node->concat()->right);
- node = node->concat()->left;
- } else {
- // Read left, descend right.
+ node = node->concat()->left;
+ } else {
+ // Read left, descend right.
subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
- n -= node->concat()->left->length;
- bytes_remaining_ -= node->concat()->left->length;
- node = node->concat()->right;
- }
- }
-
- // Get the child node if we encounter a SUBSTRING.
- size_t offset = 0;
- size_t length = node->length;
+ n -= node->concat()->left->length;
+ bytes_remaining_ -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
if (node->IsSubstring()) {
- offset = node->substring()->start;
- node = node->substring()->child;
- }
-
- // Range to read ends with a proper (possibly empty) subrange of the current
- // chunk.
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
+ // Range to read ends with a proper (possibly empty) subrange of the current
+ // chunk.
assert(node->IsExternal() || node->IsFlat());
- assert(length > n);
+ assert(length > n);
if (n > 0) {
subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
}
- const char* data =
+ const char* data =
node->IsExternal() ? node->external()->base : node->flat()->Data();
- current_chunk_ = absl::string_view(data + offset + n, length - n);
- current_leaf_ = node;
- bytes_remaining_ -= n;
+ current_chunk_ = absl::string_view(data + offset + n, length - n);
+ current_leaf_ = node;
+ bytes_remaining_ -= n;
subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
- return subcord;
-}
-
-void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
- assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
- assert(n >= current_chunk_.size()); // This should only be called when
- // iterating to a new node.
-
- n -= current_chunk_.size();
- bytes_remaining_ -= current_chunk_.size();
-
+ return subcord;
+}
+
+void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
+ assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
+ assert(n >= current_chunk_.size()); // This should only be called when
+ // iterating to a new node.
+
+ n -= current_chunk_.size();
+ bytes_remaining_ -= current_chunk_.size();
+
if (stack_of_right_children_.empty()) {
// We have reached the end of the Cord.
assert(bytes_remaining_ == 0);
return;
}
- // Process the next node(s) on the stack, skipping whole subtrees depending on
- // their length and how many bytes we are advancing.
- CordRep* node = nullptr;
+ // Process the next node(s) on the stack, skipping whole subtrees depending on
+ // their length and how many bytes we are advancing.
+ CordRep* node = nullptr;
auto& stack_of_right_children = stack_of_right_children_;
while (!stack_of_right_children.empty()) {
node = stack_of_right_children.back();
stack_of_right_children.pop_back();
- if (node->length > n) break;
- n -= node->length;
- bytes_remaining_ -= node->length;
- node = nullptr;
- }
-
- if (node == nullptr) {
- // We have reached the end of the Cord.
- assert(bytes_remaining_ == 0);
- return;
- }
-
- // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
- // right children to the stack for subsequent traversal.
+ if (node->length > n) break;
+ n -= node->length;
+ bytes_remaining_ -= node->length;
+ node = nullptr;
+ }
+
+ if (node == nullptr) {
+ // We have reached the end of the Cord.
+ assert(bytes_remaining_ == 0);
+ return;
+ }
+
+ // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
while (node->IsConcat()) {
- if (node->concat()->left->length > n) {
- // Push right, descend left.
+ if (node->concat()->left->length > n) {
+ // Push right, descend left.
stack_of_right_children.push_back(node->concat()->right);
- node = node->concat()->left;
- } else {
- // Skip left, descend right.
- n -= node->concat()->left->length;
- bytes_remaining_ -= node->concat()->left->length;
- node = node->concat()->right;
- }
- }
-
- // Get the child node if we encounter a SUBSTRING.
- size_t offset = 0;
- size_t length = node->length;
+ node = node->concat()->left;
+ } else {
+ // Skip left, descend right.
+ n -= node->concat()->left->length;
+ bytes_remaining_ -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
if (node->IsSubstring()) {
- offset = node->substring()->start;
- node = node->substring()->child;
- }
-
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
assert(node->IsExternal() || node->IsFlat());
- assert(length > n);
- const char* data =
+ assert(length > n);
+ const char* data =
node->IsExternal() ? node->external()->base : node->flat()->Data();
- current_chunk_ = absl::string_view(data + offset + n, length - n);
- current_leaf_ = node;
- bytes_remaining_ -= n;
-}
-
-char Cord::operator[](size_t i) const {
- ABSL_HARDENING_ASSERT(i < size());
- size_t offset = i;
- const CordRep* rep = contents_.tree();
- if (rep == nullptr) {
- return contents_.data()[i];
- }
- while (true) {
- assert(rep != nullptr);
- assert(offset < rep->length);
+ current_chunk_ = absl::string_view(data + offset + n, length - n);
+ current_leaf_ = node;
+ bytes_remaining_ -= n;
+}
+
+char Cord::operator[](size_t i) const {
+ ABSL_HARDENING_ASSERT(i < size());
+ size_t offset = i;
+ const CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return contents_.data()[i];
+ }
+ while (true) {
+ assert(rep != nullptr);
+ assert(offset < rep->length);
if (rep->IsFlat()) {
- // Get the "i"th character directly from the flat array.
+ // Get the "i"th character directly from the flat array.
return rep->flat()->Data()[offset];
} else if (rep->IsBtree()) {
return rep->btree()->GetCharacter(offset);
} else if (rep->IsExternal()) {
- // Get the "i"th character from the external array.
- return rep->external()->base[offset];
+ // Get the "i"th character from the external array.
+ return rep->external()->base[offset];
} else if (rep->IsConcat()) {
- // Recursively branch to the side of the concatenation that the "i"th
- // character is on.
- size_t left_length = rep->concat()->left->length;
- if (offset < left_length) {
- rep = rep->concat()->left;
- } else {
- offset -= left_length;
- rep = rep->concat()->right;
- }
- } else {
- // This must be a substring a node, so bypass it to get to the child.
+ // Recursively branch to the side of the concatenation that the "i"th
+ // character is on.
+ size_t left_length = rep->concat()->left->length;
+ if (offset < left_length) {
+ rep = rep->concat()->left;
+ } else {
+ offset -= left_length;
+ rep = rep->concat()->right;
+ }
+ } else {
+ // This must be a substring a node, so bypass it to get to the child.
assert(rep->IsSubstring());
- offset += rep->substring()->start;
- rep = rep->substring()->child;
- }
- }
-}
-
-absl::string_view Cord::FlattenSlowPath() {
+ offset += rep->substring()->start;
+ rep = rep->substring()->child;
+ }
+ }
+}
+
+absl::string_view Cord::FlattenSlowPath() {
assert(contents_.is_tree());
- size_t total_size = size();
- CordRep* new_rep;
- char* new_buffer;
-
- // Try to put the contents into a new flat rep. If they won't fit in the
- // biggest possible flat node, use an external rep instead.
- if (total_size <= kMaxFlatLength) {
+ size_t total_size = size();
+ CordRep* new_rep;
+ char* new_buffer;
+
+ // Try to put the contents into a new flat rep. If they won't fit in the
+ // biggest possible flat node, use an external rep instead.
+ if (total_size <= kMaxFlatLength) {
new_rep = CordRepFlat::New(total_size);
- new_rep->length = total_size;
+ new_rep->length = total_size;
new_buffer = new_rep->flat()->Data();
- CopyToArraySlowPath(new_buffer);
- } else {
- new_buffer = std::allocator<char>().allocate(total_size);
- CopyToArraySlowPath(new_buffer);
- new_rep = absl::cord_internal::NewExternalRep(
- absl::string_view(new_buffer, total_size), [](absl::string_view s) {
- std::allocator<char>().deallocate(const_cast<char*>(s.data()),
- s.size());
- });
- }
+ CopyToArraySlowPath(new_buffer);
+ } else {
+ new_buffer = std::allocator<char>().allocate(total_size);
+ CopyToArraySlowPath(new_buffer);
+ new_rep = absl::cord_internal::NewExternalRep(
+ absl::string_view(new_buffer, total_size), [](absl::string_view s) {
+ std::allocator<char>().deallocate(const_cast<char*>(s.data()),
+ s.size());
+ });
+ }
CordzUpdateScope scope(contents_.cordz_info(), CordzUpdateTracker::kFlatten);
CordRep::Unref(contents_.as_tree());
contents_.SetTree(new_rep, scope);
- return absl::string_view(new_buffer, total_size);
-}
-
-/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
- assert(rep != nullptr);
+ return absl::string_view(new_buffer, total_size);
+}
+
+/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
+ assert(rep != nullptr);
if (rep->IsFlat()) {
*fragment = absl::string_view(rep->flat()->Data(), rep->length);
- return true;
+ return true;
} else if (rep->IsExternal()) {
- *fragment = absl::string_view(rep->external()->base, rep->length);
- return true;
+ *fragment = absl::string_view(rep->external()->base, rep->length);
+ return true;
} else if (rep->IsBtree()) {
return rep->btree()->IsFlat(fragment);
} else if (rep->IsSubstring()) {
- CordRep* child = rep->substring()->child;
+ CordRep* child = rep->substring()->child;
if (child->IsFlat()) {
*fragment = absl::string_view(
child->flat()->Data() + rep->substring()->start, rep->length);
- return true;
+ return true;
} else if (child->IsExternal()) {
- *fragment = absl::string_view(
- child->external()->base + rep->substring()->start, rep->length);
- return true;
+ *fragment = absl::string_view(
+ child->external()->base + rep->substring()->start, rep->length);
+ return true;
} else if (child->IsBtree()) {
return child->btree()->IsFlat(rep->substring()->start, rep->length,
fragment);
- }
- }
- return false;
-}
-
-/* static */ void Cord::ForEachChunkAux(
- absl::cord_internal::CordRep* rep,
- absl::FunctionRef<void(absl::string_view)> callback) {
+ }
+ }
+ return false;
+}
+
+/* static */ void Cord::ForEachChunkAux(
+ absl::cord_internal::CordRep* rep,
+ absl::FunctionRef<void(absl::string_view)> callback) {
if (rep->IsBtree()) {
ChunkIterator it(rep), end;
while (it != end) {
@@ -1816,175 +1816,175 @@ absl::string_view Cord::FlattenSlowPath() {
return;
}
- assert(rep != nullptr);
- int stack_pos = 0;
- constexpr int stack_max = 128;
- // Stack of right branches for tree traversal
- absl::cord_internal::CordRep* stack[stack_max];
- absl::cord_internal::CordRep* current_node = rep;
- while (true) {
+ assert(rep != nullptr);
+ int stack_pos = 0;
+ constexpr int stack_max = 128;
+ // Stack of right branches for tree traversal
+ absl::cord_internal::CordRep* stack[stack_max];
+ absl::cord_internal::CordRep* current_node = rep;
+ while (true) {
if (current_node->IsConcat()) {
- if (stack_pos == stack_max) {
- // There's no more room on our stack array to add another right branch,
- // and the idea is to avoid allocations, so call this function
- // recursively to navigate this subtree further. (This is not something
- // we expect to happen in practice).
- ForEachChunkAux(current_node, callback);
-
- // Pop the next right branch and iterate.
- current_node = stack[--stack_pos];
- continue;
- } else {
- // Save the right branch for later traversal and continue down the left
- // branch.
- stack[stack_pos++] = current_node->concat()->right;
- current_node = current_node->concat()->left;
- continue;
- }
- }
- // This is a leaf node, so invoke our callback.
- absl::string_view chunk;
- bool success = GetFlatAux(current_node, &chunk);
- assert(success);
- if (success) {
- callback(chunk);
- }
- if (stack_pos == 0) {
- // end of traversal
- return;
- }
- current_node = stack[--stack_pos];
- }
-}
-
+ if (stack_pos == stack_max) {
+ // There's no more room on our stack array to add another right branch,
+ // and the idea is to avoid allocations, so call this function
+ // recursively to navigate this subtree further. (This is not something
+ // we expect to happen in practice).
+ ForEachChunkAux(current_node, callback);
+
+ // Pop the next right branch and iterate.
+ current_node = stack[--stack_pos];
+ continue;
+ } else {
+ // Save the right branch for later traversal and continue down the left
+ // branch.
+ stack[stack_pos++] = current_node->concat()->right;
+ current_node = current_node->concat()->left;
+ continue;
+ }
+ }
+ // This is a leaf node, so invoke our callback.
+ absl::string_view chunk;
+ bool success = GetFlatAux(current_node, &chunk);
+ assert(success);
+ if (success) {
+ callback(chunk);
+ }
+ if (stack_pos == 0) {
+ // end of traversal
+ return;
+ }
+ current_node = stack[--stack_pos];
+ }
+}
+
static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
int indent) {
- const int kIndentStep = 1;
- absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
- absl::InlinedVector<int, kInlinedVectorSize> indents;
- for (;;) {
- *os << std::setw(3) << rep->refcount.Get();
- *os << " " << std::setw(7) << rep->length;
- *os << " [";
- if (include_data) *os << static_cast<void*>(rep);
- *os << "]";
- *os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
- *os << " " << std::setw(indent) << "";
+ const int kIndentStep = 1;
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
+ absl::InlinedVector<int, kInlinedVectorSize> indents;
+ for (;;) {
+ *os << std::setw(3) << rep->refcount.Get();
+ *os << " " << std::setw(7) << rep->length;
+ *os << " [";
+ if (include_data) *os << static_cast<void*>(rep);
+ *os << "]";
+ *os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
+ *os << " " << std::setw(indent) << "";
if (rep->IsConcat()) {
- *os << "CONCAT depth=" << Depth(rep) << "\n";
- indent += kIndentStep;
- indents.push_back(indent);
- stack.push_back(rep->concat()->right);
- rep = rep->concat()->left;
+ *os << "CONCAT depth=" << Depth(rep) << "\n";
+ indent += kIndentStep;
+ indents.push_back(indent);
+ stack.push_back(rep->concat()->right);
+ rep = rep->concat()->left;
} else if (rep->IsSubstring()) {
- *os << "SUBSTRING @ " << rep->substring()->start << "\n";
- indent += kIndentStep;
- rep = rep->substring()->child;
+ *os << "SUBSTRING @ " << rep->substring()->start << "\n";
+ indent += kIndentStep;
+ rep = rep->substring()->child;
} else { // Leaf or ring
if (rep->IsExternal()) {
- *os << "EXTERNAL [";
- if (include_data)
- *os << absl::CEscape(std::string(rep->external()->base, rep->length));
- *os << "]\n";
+ *os << "EXTERNAL [";
+ if (include_data)
+ *os << absl::CEscape(std::string(rep->external()->base, rep->length));
+ *os << "]\n";
} else if (rep->IsFlat()) {
*os << "FLAT cap=" << rep->flat()->Capacity() << " [";
- if (include_data)
+ if (include_data)
*os << absl::CEscape(std::string(rep->flat()->Data(), rep->length));
- *os << "]\n";
+ *os << "]\n";
} else {
CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os);
- }
- if (stack.empty()) break;
- rep = stack.back();
- stack.pop_back();
- indent = indents.back();
- indents.pop_back();
- }
- }
- ABSL_INTERNAL_CHECK(indents.empty(), "");
-}
-
-static std::string ReportError(CordRep* root, CordRep* node) {
- std::ostringstream buf;
- buf << "Error at node " << node << " in:";
- DumpNode(root, true, &buf);
- return buf.str();
-}
-
-static bool VerifyNode(CordRep* root, CordRep* start_node,
- bool full_validation) {
- absl::InlinedVector<CordRep*, 2> worklist;
- worklist.push_back(start_node);
- do {
- CordRep* node = worklist.back();
- worklist.pop_back();
-
- ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));
- if (node != root) {
- ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
- }
-
+ }
+ if (stack.empty()) break;
+ rep = stack.back();
+ stack.pop_back();
+ indent = indents.back();
+ indents.pop_back();
+ }
+ }
+ ABSL_INTERNAL_CHECK(indents.empty(), "");
+}
+
+static std::string ReportError(CordRep* root, CordRep* node) {
+ std::ostringstream buf;
+ buf << "Error at node " << node << " in:";
+ DumpNode(root, true, &buf);
+ return buf.str();
+}
+
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+ bool full_validation) {
+ absl::InlinedVector<CordRep*, 2> worklist;
+ worklist.push_back(start_node);
+ do {
+ CordRep* node = worklist.back();
+ worklist.pop_back();
+
+ ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));
+ if (node != root) {
+ ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
+ }
+
if (node->IsConcat()) {
- ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
- ReportError(root, node));
- ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
- ReportError(root, node));
- ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length +
- node->concat()->right->length),
- ReportError(root, node));
- if (full_validation) {
- worklist.push_back(node->concat()->right);
- worklist.push_back(node->concat()->left);
- }
+ ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length +
+ node->concat()->right->length),
+ ReportError(root, node));
+ if (full_validation) {
+ worklist.push_back(node->concat()->right);
+ worklist.push_back(node->concat()->left);
+ }
} else if (node->IsFlat()) {
ABSL_INTERNAL_CHECK(node->length <= node->flat()->Capacity(),
ReportError(root, node));
} else if (node->IsExternal()) {
- ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
- ReportError(root, node));
+ ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
+ ReportError(root, node));
} else if (node->IsSubstring()) {
- ABSL_INTERNAL_CHECK(
- node->substring()->start < node->substring()->child->length,
- ReportError(root, node));
- ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=
- node->substring()->child->length,
- ReportError(root, node));
- }
- } while (!worklist.empty());
- return true;
-}
-
-// Traverses the tree and computes the total memory allocated.
-/* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) {
- size_t total_mem_usage = 0;
-
- // Allow a quick exit for the common case that the root is a leaf.
- if (RepMemoryUsageLeaf(rep, &total_mem_usage)) {
- return total_mem_usage;
- }
-
- // Iterate over the tree. cur_node is never a leaf node and leaf nodes will
- // never be appended to tree_stack. This reduces overhead from manipulating
- // tree_stack.
- absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack;
- const CordRep* cur_node = rep;
- while (true) {
- const CordRep* next_node = nullptr;
-
+ ABSL_INTERNAL_CHECK(
+ node->substring()->start < node->substring()->child->length,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=
+ node->substring()->child->length,
+ ReportError(root, node));
+ }
+ } while (!worklist.empty());
+ return true;
+}
+
+// Traverses the tree and computes the total memory allocated.
+/* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) {
+ size_t total_mem_usage = 0;
+
+ // Allow a quick exit for the common case that the root is a leaf.
+ if (RepMemoryUsageLeaf(rep, &total_mem_usage)) {
+ return total_mem_usage;
+ }
+
+ // Iterate over the tree. cur_node is never a leaf node and leaf nodes will
+ // never be appended to tree_stack. This reduces overhead from manipulating
+ // tree_stack.
+ absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack;
+ const CordRep* cur_node = rep;
+ while (true) {
+ const CordRep* next_node = nullptr;
+
if (cur_node->IsConcat()) {
- total_mem_usage += sizeof(CordRepConcat);
- const CordRep* left = cur_node->concat()->left;
- if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
- next_node = left;
- }
-
- const CordRep* right = cur_node->concat()->right;
- if (!RepMemoryUsageLeaf(right, &total_mem_usage)) {
- if (next_node) {
- tree_stack.push_back(next_node);
- }
- next_node = right;
- }
+ total_mem_usage += sizeof(CordRepConcat);
+ const CordRep* left = cur_node->concat()->left;
+ if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
+ next_node = left;
+ }
+
+ const CordRep* right = cur_node->concat()->right;
+ if (!RepMemoryUsageLeaf(right, &total_mem_usage)) {
+ if (next_node) {
+ tree_stack.push_back(next_node);
+ }
+ next_node = right;
+ }
} else if (cur_node->IsBtree()) {
total_mem_usage += sizeof(CordRepBtree);
const CordRepBtree* node = cur_node->btree();
@@ -1997,51 +1997,51 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
tree_stack.push_back(edge);
}
}
- } else {
- // Since cur_node is not a leaf or a concat node it must be a substring.
+ } else {
+ // Since cur_node is not a leaf or a concat node it must be a substring.
assert(cur_node->IsSubstring());
- total_mem_usage += sizeof(CordRepSubstring);
- next_node = cur_node->substring()->child;
- if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
- next_node = nullptr;
- }
- }
-
- if (!next_node) {
- if (tree_stack.empty()) {
- return total_mem_usage;
- }
- next_node = tree_stack.back();
- tree_stack.pop_back();
- }
- cur_node = next_node;
- }
-}
-
-std::ostream& operator<<(std::ostream& out, const Cord& cord) {
- for (absl::string_view chunk : cord.Chunks()) {
- out.write(chunk.data(), chunk.size());
- }
- return out;
-}
-
-namespace strings_internal {
+ total_mem_usage += sizeof(CordRepSubstring);
+ next_node = cur_node->substring()->child;
+ if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
+ next_node = nullptr;
+ }
+ }
+
+ if (!next_node) {
+ if (tree_stack.empty()) {
+ return total_mem_usage;
+ }
+ next_node = tree_stack.back();
+ tree_stack.pop_back();
+ }
+ cur_node = next_node;
+ }
+}
+
+std::ostream& operator<<(std::ostream& out, const Cord& cord) {
+ for (absl::string_view chunk : cord.Chunks()) {
+ out.write(chunk.data(), chunk.size());
+ }
+ return out;
+}
+
+namespace strings_internal {
size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
-size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
+size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
return cord_internal::TagToLength(tag);
-}
-uint8_t CordTestAccess::LengthToTag(size_t s) {
- ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
+}
+uint8_t CordTestAccess::LengthToTag(size_t s) {
+ ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
-}
-size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
-size_t CordTestAccess::SizeofCordRepExternal() {
- return sizeof(CordRepExternal);
-}
-size_t CordTestAccess::SizeofCordRepSubstring() {
- return sizeof(CordRepSubstring);
-}
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace absl
+}
+size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
+size_t CordTestAccess::SizeofCordRepExternal() {
+ return sizeof(CordRepExternal);
+}
+size_t CordTestAccess::SizeofCordRepSubstring() {
+ return sizeof(CordRepSubstring);
+}
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.h b/contrib/restricted/abseil-cpp/absl/strings/cord.h
index f0a1991471..d5753e5839 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord.h
@@ -1,84 +1,84 @@
-// Copyright 2020 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.
-//
-// -----------------------------------------------------------------------------
-// File: cord.h
-// -----------------------------------------------------------------------------
-//
-// This file defines the `absl::Cord` data structure and operations on that data
-// structure. A Cord is a string-like sequence of characters optimized for
-// specific use cases. Unlike a `std::string`, which stores an array of
-// contiguous characters, Cord data is stored in a structure consisting of
-// separate, reference-counted "chunks." (Currently, this implementation is a
-// tree structure, though that implementation may change.)
-//
-// Because a Cord consists of these chunks, data can be added to or removed from
-// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
+// Copyright 2020 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.
+//
+// -----------------------------------------------------------------------------
+// File: cord.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the `absl::Cord` data structure and operations on that data
+// structure. A Cord is a string-like sequence of characters optimized for
+// specific use cases. Unlike a `std::string`, which stores an array of
+// contiguous characters, Cord data is stored in a structure consisting of
+// separate, reference-counted "chunks." (Currently, this implementation is a
+// tree structure, though that implementation may change.)
+//
+// Because a Cord consists of these chunks, data can be added to or removed from
+// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
// `std::string`, a Cord can therefore accommodate data that changes over its
-// lifetime, though it's not quite "mutable"; it can change only in the
-// attachment, detachment, or rearrangement of chunks of its constituent data.
-//
-// A Cord provides some benefit over `std::string` under the following (albeit
-// narrow) circumstances:
-//
-// * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
-// provides efficient insertions and deletions at the start and end of the
-// character sequences, avoiding copies in those cases. Static data should
-// generally be stored as strings.
-// * External memory consisting of string-like data can be directly added to
-// a Cord without requiring copies or allocations.
-// * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
-// implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
-// operation.
-//
-// As a consequence to the above, Cord data is generally large. Small data
-// should generally use strings, as construction of a Cord requires some
-// overhead. Small Cords (<= 15 bytes) are represented inline, but most small
-// Cords are expected to grow over their lifetimes.
-//
-// Note that because a Cord is made up of separate chunked data, random access
-// to character data within a Cord is slower than within a `std::string`.
-//
-// Thread Safety
-//
-// Cord has the same thread-safety properties as many other types like
-// std::string, std::vector<>, int, etc -- it is thread-compatible. In
-// particular, if threads do not call non-const methods, then it is safe to call
-// const methods without synchronization. Copying a Cord produces a new instance
-// that can be used concurrently with the original in arbitrary ways.
-
-#ifndef ABSL_STRINGS_CORD_H_
-#define ABSL_STRINGS_CORD_H_
-
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <iosfwd>
-#include <iterator>
-#include <string>
-#include <type_traits>
-
+// lifetime, though it's not quite "mutable"; it can change only in the
+// attachment, detachment, or rearrangement of chunks of its constituent data.
+//
+// A Cord provides some benefit over `std::string` under the following (albeit
+// narrow) circumstances:
+//
+// * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
+// provides efficient insertions and deletions at the start and end of the
+// character sequences, avoiding copies in those cases. Static data should
+// generally be stored as strings.
+// * External memory consisting of string-like data can be directly added to
+// a Cord without requiring copies or allocations.
+// * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
+// implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
+// operation.
+//
+// As a consequence to the above, Cord data is generally large. Small data
+// should generally use strings, as construction of a Cord requires some
+// overhead. Small Cords (<= 15 bytes) are represented inline, but most small
+// Cords are expected to grow over their lifetimes.
+//
+// Note that because a Cord is made up of separate chunked data, random access
+// to character data within a Cord is slower than within a `std::string`.
+//
+// Thread Safety
+//
+// Cord has the same thread-safety properties as many other types like
+// std::string, std::vector<>, int, etc -- it is thread-compatible. In
+// particular, if threads do not call non-const methods, then it is safe to call
+// const methods without synchronization. Copying a Cord produces a new instance
+// that can be used concurrently with the original in arbitrary ways.
+
+#ifndef ABSL_STRINGS_CORD_H_
+#define ABSL_STRINGS_CORD_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <string>
+#include <type_traits>
+
#include "absl/base/config.h"
-#include "absl/base/internal/endian.h"
-#include "absl/base/internal/per_thread_tls.h"
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
-#include "absl/container/inlined_vector.h"
-#include "absl/functional/function_ref.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/internal/cord_internal.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_btree_reader.h"
#include "absl/strings/internal/cord_rep_ring.h"
@@ -87,287 +87,287 @@
#include "absl/strings/internal/cordz_statistics.h"
#include "absl/strings/internal/cordz_update_scope.h"
#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/string_constant.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-class Cord;
-class CordTestPeer;
-template <typename Releaser>
-Cord MakeCordFromExternal(absl::string_view, Releaser&&);
-void CopyCordToString(const Cord& src, std::string* dst);
-
-// Cord
-//
-// A Cord is a sequence of characters, designed to be more efficient than a
-// `std::string` in certain circumstances: namely, large string data that needs
-// to change over its lifetime or shared, especially when such data is shared
-// across API boundaries.
-//
-// A Cord stores its character data in a structure that allows efficient prepend
-// and append operations. This makes a Cord useful for large string data sent
-// over in a wire format that may need to be prepended or appended at some point
-// during the data exchange (e.g. HTTP, protocol buffers). For example, a
-// Cord is useful for storing an HTTP request, and prepending an HTTP header to
-// such a request.
-//
-// Cords should not be used for storing general string data, however. They
-// require overhead to construct and are slower than strings for random access.
-//
-// The Cord API provides the following common API operations:
-//
-// * Create or assign Cords out of existing string data, memory, or other Cords
-// * Append and prepend data to an existing Cord
-// * Create new Sub-Cords from existing Cord data
-// * Swap Cord data and compare Cord equality
-// * Write out Cord data by constructing a `std::string`
-//
-// Additionally, the API provides iterator utilities to iterate through Cord
-// data via chunks or character bytes.
-//
-class Cord {
- private:
- template <typename T>
- using EnableIfString =
- absl::enable_if_t<std::is_same<T, std::string>::value, int>;
-
- public:
- // Cord::Cord() Constructors.
-
- // Creates an empty Cord.
- constexpr Cord() noexcept;
-
- // Creates a Cord from an existing Cord. Cord is copyable and efficiently
- // movable. The moved-from state is valid but unspecified.
- Cord(const Cord& src);
- Cord(Cord&& src) noexcept;
- Cord& operator=(const Cord& x);
- Cord& operator=(Cord&& x) noexcept;
-
- // Creates a Cord from a `src` string. This constructor is marked explicit to
- // prevent implicit Cord constructions from arguments convertible to an
- // `absl::string_view`.
- explicit Cord(absl::string_view src);
- Cord& operator=(absl::string_view src);
-
- // Creates a Cord from a `std::string&&` rvalue. These constructors are
- // templated to avoid ambiguities for types that are convertible to both
- // `absl::string_view` and `std::string`, such as `const char*`.
- template <typename T, EnableIfString<T> = 0>
- explicit Cord(T&& src);
- template <typename T, EnableIfString<T> = 0>
- Cord& operator=(T&& src);
-
- // Cord::~Cord()
- //
- // Destructs the Cord.
- ~Cord() {
- if (contents_.is_tree()) DestroyCordSlow();
- }
-
- // MakeCordFromExternal()
- //
- // Creates a Cord that takes ownership of external string memory. The
- // contents of `data` are not copied to the Cord; instead, the external
- // memory is added to the Cord and reference-counted. This data may not be
- // changed for the life of the Cord, though it may be prepended or appended
- // to.
- //
- // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
- // the reference count for `data` reaches zero. As noted above, this data must
- // remain live until the releaser is invoked. The callable releaser also must:
- //
- // * be move constructible
- // * support `void operator()(absl::string_view) const` or `void operator()`
- //
- // Example:
- //
- // Cord MakeCord(BlockPool* pool) {
- // Block* block = pool->NewBlock();
- // FillBlock(block);
- // return absl::MakeCordFromExternal(
- // block->ToStringView(),
- // [pool, block](absl::string_view v) {
- // pool->FreeBlock(block, v);
- // });
- // }
- //
- // WARNING: Because a Cord can be reference-counted, it's likely a bug if your
- // releaser doesn't do anything. For example, consider the following:
- //
- // void Foo(const char* buffer, int len) {
- // auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
- // [](absl::string_view) {});
- //
- // // BUG: If Bar() copies its cord for any reason, including keeping a
- // // substring of it, the lifetime of buffer might be extended beyond
- // // when Foo() returns.
- // Bar(c);
- // }
- template <typename Releaser>
- friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
-
- // Cord::Clear()
- //
- // Releases the Cord data. Any nodes that share data with other Cords, if
- // applicable, will have their reference counts reduced by 1.
- void Clear();
-
- // Cord::Append()
- //
- // Appends data to the Cord, which may come from another Cord or other string
- // data.
- void Append(const Cord& src);
- void Append(Cord&& src);
- void Append(absl::string_view src);
- template <typename T, EnableIfString<T> = 0>
- void Append(T&& src);
-
- // Cord::Prepend()
- //
- // Prepends data to the Cord, which may come from another Cord or other string
- // data.
- void Prepend(const Cord& src);
- void Prepend(absl::string_view src);
- template <typename T, EnableIfString<T> = 0>
- void Prepend(T&& src);
-
- // Cord::RemovePrefix()
- //
- // Removes the first `n` bytes of a Cord.
- void RemovePrefix(size_t n);
- void RemoveSuffix(size_t n);
-
- // Cord::Subcord()
- //
- // Returns a new Cord representing the subrange [pos, pos + new_size) of
- // *this. If pos >= size(), the result is empty(). If
- // (pos + new_size) >= size(), the result is the subrange [pos, size()).
- Cord Subcord(size_t pos, size_t new_size) const;
-
- // Cord::swap()
- //
- // Swaps the contents of the Cord with `other`.
- void swap(Cord& other) noexcept;
-
- // swap()
- //
- // Swaps the contents of two Cords.
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+class Cord;
+class CordTestPeer;
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view, Releaser&&);
+void CopyCordToString(const Cord& src, std::string* dst);
+
+// Cord
+//
+// A Cord is a sequence of characters, designed to be more efficient than a
+// `std::string` in certain circumstances: namely, large string data that needs
+// to change over its lifetime or shared, especially when such data is shared
+// across API boundaries.
+//
+// A Cord stores its character data in a structure that allows efficient prepend
+// and append operations. This makes a Cord useful for large string data sent
+// over in a wire format that may need to be prepended or appended at some point
+// during the data exchange (e.g. HTTP, protocol buffers). For example, a
+// Cord is useful for storing an HTTP request, and prepending an HTTP header to
+// such a request.
+//
+// Cords should not be used for storing general string data, however. They
+// require overhead to construct and are slower than strings for random access.
+//
+// The Cord API provides the following common API operations:
+//
+// * Create or assign Cords out of existing string data, memory, or other Cords
+// * Append and prepend data to an existing Cord
+// * Create new Sub-Cords from existing Cord data
+// * Swap Cord data and compare Cord equality
+// * Write out Cord data by constructing a `std::string`
+//
+// Additionally, the API provides iterator utilities to iterate through Cord
+// data via chunks or character bytes.
+//
+class Cord {
+ private:
+ template <typename T>
+ using EnableIfString =
+ absl::enable_if_t<std::is_same<T, std::string>::value, int>;
+
+ public:
+ // Cord::Cord() Constructors.
+
+ // Creates an empty Cord.
+ constexpr Cord() noexcept;
+
+ // Creates a Cord from an existing Cord. Cord is copyable and efficiently
+ // movable. The moved-from state is valid but unspecified.
+ Cord(const Cord& src);
+ Cord(Cord&& src) noexcept;
+ Cord& operator=(const Cord& x);
+ Cord& operator=(Cord&& x) noexcept;
+
+ // Creates a Cord from a `src` string. This constructor is marked explicit to
+ // prevent implicit Cord constructions from arguments convertible to an
+ // `absl::string_view`.
+ explicit Cord(absl::string_view src);
+ Cord& operator=(absl::string_view src);
+
+ // Creates a Cord from a `std::string&&` rvalue. These constructors are
+ // templated to avoid ambiguities for types that are convertible to both
+ // `absl::string_view` and `std::string`, such as `const char*`.
+ template <typename T, EnableIfString<T> = 0>
+ explicit Cord(T&& src);
+ template <typename T, EnableIfString<T> = 0>
+ Cord& operator=(T&& src);
+
+ // Cord::~Cord()
+ //
+ // Destructs the Cord.
+ ~Cord() {
+ if (contents_.is_tree()) DestroyCordSlow();
+ }
+
+ // MakeCordFromExternal()
+ //
+ // Creates a Cord that takes ownership of external string memory. The
+ // contents of `data` are not copied to the Cord; instead, the external
+ // memory is added to the Cord and reference-counted. This data may not be
+ // changed for the life of the Cord, though it may be prepended or appended
+ // to.
+ //
+ // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
+ // the reference count for `data` reaches zero. As noted above, this data must
+ // remain live until the releaser is invoked. The callable releaser also must:
+ //
+ // * be move constructible
+ // * support `void operator()(absl::string_view) const` or `void operator()`
+ //
+ // Example:
+ //
+ // Cord MakeCord(BlockPool* pool) {
+ // Block* block = pool->NewBlock();
+ // FillBlock(block);
+ // return absl::MakeCordFromExternal(
+ // block->ToStringView(),
+ // [pool, block](absl::string_view v) {
+ // pool->FreeBlock(block, v);
+ // });
+ // }
+ //
+ // WARNING: Because a Cord can be reference-counted, it's likely a bug if your
+ // releaser doesn't do anything. For example, consider the following:
+ //
+ // void Foo(const char* buffer, int len) {
+ // auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
+ // [](absl::string_view) {});
+ //
+ // // BUG: If Bar() copies its cord for any reason, including keeping a
+ // // substring of it, the lifetime of buffer might be extended beyond
+ // // when Foo() returns.
+ // Bar(c);
+ // }
+ template <typename Releaser>
+ friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
+
+ // Cord::Clear()
+ //
+ // Releases the Cord data. Any nodes that share data with other Cords, if
+ // applicable, will have their reference counts reduced by 1.
+ void Clear();
+
+ // Cord::Append()
+ //
+ // Appends data to the Cord, which may come from another Cord or other string
+ // data.
+ void Append(const Cord& src);
+ void Append(Cord&& src);
+ void Append(absl::string_view src);
+ template <typename T, EnableIfString<T> = 0>
+ void Append(T&& src);
+
+ // Cord::Prepend()
+ //
+ // Prepends data to the Cord, which may come from another Cord or other string
+ // data.
+ void Prepend(const Cord& src);
+ void Prepend(absl::string_view src);
+ template <typename T, EnableIfString<T> = 0>
+ void Prepend(T&& src);
+
+ // Cord::RemovePrefix()
+ //
+ // Removes the first `n` bytes of a Cord.
+ void RemovePrefix(size_t n);
+ void RemoveSuffix(size_t n);
+
+ // Cord::Subcord()
+ //
+ // Returns a new Cord representing the subrange [pos, pos + new_size) of
+ // *this. If pos >= size(), the result is empty(). If
+ // (pos + new_size) >= size(), the result is the subrange [pos, size()).
+ Cord Subcord(size_t pos, size_t new_size) const;
+
+ // Cord::swap()
+ //
+ // Swaps the contents of the Cord with `other`.
+ void swap(Cord& other) noexcept;
+
+ // swap()
+ //
+ // Swaps the contents of two Cords.
friend void swap(Cord& x, Cord& y) noexcept { x.swap(y); }
-
- // Cord::size()
- //
- // Returns the size of the Cord.
- size_t size() const;
-
- // Cord::empty()
- //
- // Determines whether the given Cord is empty, returning `true` is so.
- bool empty() const;
-
- // Cord::EstimatedMemoryUsage()
- //
- // Returns the *approximate* number of bytes held in full or in part by this
- // Cord (which may not remain the same between invocations). Note that Cords
- // that share memory could each be "charged" independently for the same shared
- // memory.
- size_t EstimatedMemoryUsage() const;
-
- // Cord::Compare()
- //
- // Compares 'this' Cord with rhs. This function and its relatives treat Cords
- // as sequences of unsigned bytes. The comparison is a straightforward
- // lexicographic comparison. `Cord::Compare()` returns values as follows:
- //
- // -1 'this' Cord is smaller
- // 0 two Cords are equal
- // 1 'this' Cord is larger
- int Compare(absl::string_view rhs) const;
- int Compare(const Cord& rhs) const;
-
- // Cord::StartsWith()
- //
- // Determines whether the Cord starts with the passed string data `rhs`.
- bool StartsWith(const Cord& rhs) const;
- bool StartsWith(absl::string_view rhs) const;
-
+
+ // Cord::size()
+ //
+ // Returns the size of the Cord.
+ size_t size() const;
+
+ // Cord::empty()
+ //
+ // Determines whether the given Cord is empty, returning `true` is so.
+ bool empty() const;
+
+ // Cord::EstimatedMemoryUsage()
+ //
+ // Returns the *approximate* number of bytes held in full or in part by this
+ // Cord (which may not remain the same between invocations). Note that Cords
+ // that share memory could each be "charged" independently for the same shared
+ // memory.
+ size_t EstimatedMemoryUsage() const;
+
+ // Cord::Compare()
+ //
+ // Compares 'this' Cord with rhs. This function and its relatives treat Cords
+ // as sequences of unsigned bytes. The comparison is a straightforward
+ // lexicographic comparison. `Cord::Compare()` returns values as follows:
+ //
+ // -1 'this' Cord is smaller
+ // 0 two Cords are equal
+ // 1 'this' Cord is larger
+ int Compare(absl::string_view rhs) const;
+ int Compare(const Cord& rhs) const;
+
+ // Cord::StartsWith()
+ //
+ // Determines whether the Cord starts with the passed string data `rhs`.
+ bool StartsWith(const Cord& rhs) const;
+ bool StartsWith(absl::string_view rhs) const;
+
// Cord::EndsWith()
- //
- // Determines whether the Cord ends with the passed string data `rhs`.
- bool EndsWith(absl::string_view rhs) const;
- bool EndsWith(const Cord& rhs) const;
-
- // Cord::operator std::string()
- //
- // Converts a Cord into a `std::string()`. This operator is marked explicit to
- // prevent unintended Cord usage in functions that take a string.
- explicit operator std::string() const;
-
- // CopyCordToString()
- //
- // Copies the contents of a `src` Cord into a `*dst` string.
- //
- // This function optimizes the case of reusing the destination string since it
- // can reuse previously allocated capacity. However, this function does not
- // guarantee that pointers previously returned by `dst->data()` remain valid
- // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
- // object, prefer to simply use the conversion operator to `std::string`.
- friend void CopyCordToString(const Cord& src, std::string* dst);
-
- class CharIterator;
-
- //----------------------------------------------------------------------------
- // Cord::ChunkIterator
- //----------------------------------------------------------------------------
- //
- // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
- // Cord. Such iteration allows you to perform non-const operatons on the data
- // of a Cord without modifying it.
- //
- // Generally, you do not instantiate a `Cord::ChunkIterator` directly;
- // instead, you create one implicitly through use of the `Cord::Chunks()`
- // member function.
- //
- // The `Cord::ChunkIterator` has the following properties:
- //
- // * The iterator is invalidated after any non-const operation on the
- // Cord object over which it iterates.
- // * The `string_view` returned by dereferencing a valid, non-`end()`
- // iterator is guaranteed to be non-empty.
- // * Two `ChunkIterator` objects can be compared equal if and only if they
- // remain valid and iterate over the same Cord.
- // * The iterator in this case is a proxy iterator; the `string_view`
- // returned by the iterator does not live inside the Cord, and its
- // lifetime is limited to the lifetime of the iterator itself. To help
- // prevent lifetime issues, `ChunkIterator::reference` is not a true
- // reference type and is equivalent to `value_type`.
- // * The iterator keeps state that can grow for Cords that contain many
- // nodes and are imbalanced due to sharing. Prefer to pass this type by
- // const reference instead of by value.
- class ChunkIterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = absl::string_view;
- using difference_type = ptrdiff_t;
- using pointer = const value_type*;
- using reference = value_type;
-
- ChunkIterator() = default;
-
- ChunkIterator& operator++();
- ChunkIterator operator++(int);
- bool operator==(const ChunkIterator& other) const;
- bool operator!=(const ChunkIterator& other) const;
- reference operator*() const;
- pointer operator->() const;
-
- friend class Cord;
- friend class CharIterator;
-
- private:
+ //
+ // Determines whether the Cord ends with the passed string data `rhs`.
+ bool EndsWith(absl::string_view rhs) const;
+ bool EndsWith(const Cord& rhs) const;
+
+ // Cord::operator std::string()
+ //
+ // Converts a Cord into a `std::string()`. This operator is marked explicit to
+ // prevent unintended Cord usage in functions that take a string.
+ explicit operator std::string() const;
+
+ // CopyCordToString()
+ //
+ // Copies the contents of a `src` Cord into a `*dst` string.
+ //
+ // This function optimizes the case of reusing the destination string since it
+ // can reuse previously allocated capacity. However, this function does not
+ // guarantee that pointers previously returned by `dst->data()` remain valid
+ // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
+ // object, prefer to simply use the conversion operator to `std::string`.
+ friend void CopyCordToString(const Cord& src, std::string* dst);
+
+ class CharIterator;
+
+ //----------------------------------------------------------------------------
+ // Cord::ChunkIterator
+ //----------------------------------------------------------------------------
+ //
+ // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
+ // Cord. Such iteration allows you to perform non-const operatons on the data
+ // of a Cord without modifying it.
+ //
+ // Generally, you do not instantiate a `Cord::ChunkIterator` directly;
+ // instead, you create one implicitly through use of the `Cord::Chunks()`
+ // member function.
+ //
+ // The `Cord::ChunkIterator` has the following properties:
+ //
+ // * The iterator is invalidated after any non-const operation on the
+ // Cord object over which it iterates.
+ // * The `string_view` returned by dereferencing a valid, non-`end()`
+ // iterator is guaranteed to be non-empty.
+ // * Two `ChunkIterator` objects can be compared equal if and only if they
+ // remain valid and iterate over the same Cord.
+ // * The iterator in this case is a proxy iterator; the `string_view`
+ // returned by the iterator does not live inside the Cord, and its
+ // lifetime is limited to the lifetime of the iterator itself. To help
+ // prevent lifetime issues, `ChunkIterator::reference` is not a true
+ // reference type and is equivalent to `value_type`.
+ // * The iterator keeps state that can grow for Cords that contain many
+ // nodes and are imbalanced due to sharing. Prefer to pass this type by
+ // const reference instead of by value.
+ class ChunkIterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = absl::string_view;
+ using difference_type = ptrdiff_t;
+ using pointer = const value_type*;
+ using reference = value_type;
+
+ ChunkIterator() = default;
+
+ ChunkIterator& operator++();
+ ChunkIterator operator++(int);
+ bool operator==(const ChunkIterator& other) const;
+ bool operator!=(const ChunkIterator& other) const;
+ reference operator*() const;
+ pointer operator->() const;
+
+ friend class Cord;
+ friend class CharIterator;
+
+ private:
using CordRep = absl::cord_internal::CordRep;
using CordRepBtree = absl::cord_internal::CordRepBtree;
using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
@@ -381,17 +381,17 @@ class Cord {
// Constructs a `begin()` iterator from `tree`. `tree` must not be null.
explicit ChunkIterator(cord_internal::CordRep* tree);
- // Constructs a `begin()` iterator from `cord`.
- explicit ChunkIterator(const Cord* cord);
-
+ // Constructs a `begin()` iterator from `cord`.
+ explicit ChunkIterator(const Cord* cord);
+
// Initializes this instance from a tree. Invoked by constructors.
void InitTree(cord_internal::CordRep* tree);
- // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
- // `current_chunk_.size()`.
- void RemoveChunkPrefix(size_t n);
- Cord AdvanceAndReadBytes(size_t n);
- void AdvanceBytes(size_t n);
+ // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
+ // `current_chunk_.size()`.
+ void RemoveChunkPrefix(size_t n);
+ Cord AdvanceAndReadBytes(size_t n);
+ void AdvanceBytes(size_t n);
// Stack specific operator++
ChunkIterator& AdvanceStack();
@@ -400,66 +400,66 @@ class Cord {
ChunkIterator& AdvanceBtree();
void AdvanceBytesBtree(size_t n);
- // Iterates `n` bytes, where `n` is expected to be greater than or equal to
- // `current_chunk_.size()`.
- void AdvanceBytesSlowPath(size_t n);
-
- // A view into bytes of the current `CordRep`. It may only be a view to a
- // suffix of bytes if this is being used by `CharIterator`.
- absl::string_view current_chunk_;
- // The current leaf, or `nullptr` if the iterator points to short data.
- // If the current chunk is a substring node, current_leaf_ points to the
- // underlying flat or external node.
- absl::cord_internal::CordRep* current_leaf_ = nullptr;
- // The number of bytes left in the `Cord` over which we are iterating.
- size_t bytes_remaining_ = 0;
+ // Iterates `n` bytes, where `n` is expected to be greater than or equal to
+ // `current_chunk_.size()`.
+ void AdvanceBytesSlowPath(size_t n);
+
+ // A view into bytes of the current `CordRep`. It may only be a view to a
+ // suffix of bytes if this is being used by `CharIterator`.
+ absl::string_view current_chunk_;
+ // The current leaf, or `nullptr` if the iterator points to short data.
+ // If the current chunk is a substring node, current_leaf_ points to the
+ // underlying flat or external node.
+ absl::cord_internal::CordRep* current_leaf_ = nullptr;
+ // The number of bytes left in the `Cord` over which we are iterating.
+ size_t bytes_remaining_ = 0;
// Cord reader for cord btrees. Empty if not traversing a btree.
CordRepBtreeReader btree_reader_;
// See 'Stack' alias definition.
Stack stack_of_right_children_;
- };
-
- // Cord::ChunkIterator::chunk_begin()
- //
- // Returns an iterator to the first chunk of the `Cord`.
- //
- // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
- // iterating over the chunks of a Cord. This method may be useful for getting
- // a `ChunkIterator` where range-based for-loops are not useful.
- //
- // Example:
- //
- // absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
- // absl::string_view s) {
- // return std::find(c.chunk_begin(), c.chunk_end(), s);
- // }
- ChunkIterator chunk_begin() const;
-
- // Cord::ChunkItertator::chunk_end()
- //
- // Returns an iterator one increment past the last chunk of the `Cord`.
- //
- // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
- // iterating over the chunks of a Cord. This method may be useful for getting
- // a `ChunkIterator` where range-based for-loops may not be available.
- ChunkIterator chunk_end() const;
-
- //----------------------------------------------------------------------------
- // Cord::ChunkIterator::ChunkRange
- //----------------------------------------------------------------------------
- //
- // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
- // producing an iterator which can be used within a range-based for loop.
- // Construction of a `ChunkRange` will return an iterator pointing to the
- // first chunk of the Cord. Generally, do not construct a `ChunkRange`
- // directly; instead, prefer to use the `Cord::Chunks()` method.
- //
- // Implementation note: `ChunkRange` is simply a convenience wrapper over
- // `Cord::chunk_begin()` and `Cord::chunk_end()`.
- class ChunkRange {
- public:
+ };
+
+ // Cord::ChunkIterator::chunk_begin()
+ //
+ // Returns an iterator to the first chunk of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `ChunkIterator` where range-based for-loops are not useful.
+ //
+ // Example:
+ //
+ // absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
+ // absl::string_view s) {
+ // return std::find(c.chunk_begin(), c.chunk_end(), s);
+ // }
+ ChunkIterator chunk_begin() const;
+
+ // Cord::ChunkItertator::chunk_end()
+ //
+ // Returns an iterator one increment past the last chunk of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `ChunkIterator` where range-based for-loops may not be available.
+ ChunkIterator chunk_end() const;
+
+ //----------------------------------------------------------------------------
+ // Cord::ChunkIterator::ChunkRange
+ //----------------------------------------------------------------------------
+ //
+ // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
+ // producing an iterator which can be used within a range-based for loop.
+ // Construction of a `ChunkRange` will return an iterator pointing to the
+ // first chunk of the Cord. Generally, do not construct a `ChunkRange`
+ // directly; instead, prefer to use the `Cord::Chunks()` method.
+ //
+ // Implementation note: `ChunkRange` is simply a convenience wrapper over
+ // `Cord::chunk_begin()` and `Cord::chunk_end()`.
+ class ChunkRange {
+ public:
// Fulfill minimum c++ container requirements [container.requirements]
// Theses (partial) container type definitions allow ChunkRange to be used
// in various utilities expecting a subset of [container.requirements].
@@ -470,137 +470,137 @@ class Cord {
using iterator = ChunkIterator;
using const_iterator = ChunkIterator;
- explicit ChunkRange(const Cord* cord) : cord_(cord) {}
-
- ChunkIterator begin() const;
- ChunkIterator end() const;
-
- private:
- const Cord* cord_;
- };
-
- // Cord::Chunks()
- //
- // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks
- // of a `Cord` with a range-based for-loop. For most iteration tasks on a
- // Cord, use `Cord::Chunks()` to retrieve this iterator.
- //
- // Example:
- //
- // void ProcessChunks(const Cord& cord) {
- // for (absl::string_view chunk : cord.Chunks()) { ... }
- // }
- //
- // Note that the ordinary caveats of temporary lifetime extension apply:
- //
- // void Process() {
- // for (absl::string_view chunk : CordFactory().Chunks()) {
- // // The temporary Cord returned by CordFactory has been destroyed!
- // }
- // }
- ChunkRange Chunks() const;
-
- //----------------------------------------------------------------------------
- // Cord::CharIterator
- //----------------------------------------------------------------------------
- //
- // A `Cord::CharIterator` allows iteration over the constituent characters of
- // a `Cord`.
- //
- // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
- // you create one implicitly through use of the `Cord::Chars()` member
- // function.
- //
- // A `Cord::CharIterator` has the following properties:
- //
- // * The iterator is invalidated after any non-const operation on the
- // Cord object over which it iterates.
- // * Two `CharIterator` objects can be compared equal if and only if they
- // remain valid and iterate over the same Cord.
- // * The iterator keeps state that can grow for Cords that contain many
- // nodes and are imbalanced due to sharing. Prefer to pass this type by
- // const reference instead of by value.
- // * This type cannot act as a forward iterator because a `Cord` can reuse
- // sections of memory. This fact violates the requirement for forward
- // iterators to compare equal if dereferencing them returns the same
- // object.
- class CharIterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = char;
- using difference_type = ptrdiff_t;
- using pointer = const char*;
- using reference = const char&;
-
- CharIterator() = default;
-
- CharIterator& operator++();
- CharIterator operator++(int);
- bool operator==(const CharIterator& other) const;
- bool operator!=(const CharIterator& other) const;
- reference operator*() const;
- pointer operator->() const;
-
- friend Cord;
-
- private:
- explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {}
-
- ChunkIterator chunk_iterator_;
- };
-
- // Cord::CharIterator::AdvanceAndRead()
- //
- // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
- // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
- // number of bytes within the Cord; otherwise, behavior is undefined. It is
- // valid to pass `char_end()` and `0`.
- static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes);
-
- // Cord::CharIterator::Advance()
- //
- // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
- // or equal to the number of bytes remaining within the Cord; otherwise,
- // behavior is undefined. It is valid to pass `char_end()` and `0`.
- static void Advance(CharIterator* it, size_t n_bytes);
-
- // Cord::CharIterator::ChunkRemaining()
- //
- // Returns the longest contiguous view starting at the iterator's position.
- //
- // `it` must be dereferenceable.
- static absl::string_view ChunkRemaining(const CharIterator& it);
-
- // Cord::CharIterator::char_begin()
- //
- // Returns an iterator to the first character of the `Cord`.
- //
- // Generally, prefer using `Cord::Chars()` within a range-based for loop for
- // iterating over the chunks of a Cord. This method may be useful for getting
- // a `CharIterator` where range-based for-loops may not be available.
- CharIterator char_begin() const;
-
- // Cord::CharIterator::char_end()
- //
- // Returns an iterator to one past the last character of the `Cord`.
- //
- // Generally, prefer using `Cord::Chars()` within a range-based for loop for
- // iterating over the chunks of a Cord. This method may be useful for getting
- // a `CharIterator` where range-based for-loops are not useful.
- CharIterator char_end() const;
-
- // Cord::CharIterator::CharRange
- //
- // `CharRange` is a helper class for iterating over the characters of a
- // producing an iterator which can be used within a range-based for loop.
- // Construction of a `CharRange` will return an iterator pointing to the first
- // character of the Cord. Generally, do not construct a `CharRange` directly;
- // instead, prefer to use the `Cord::Chars()` method show below.
- //
- // Implementation note: `CharRange` is simply a convenience wrapper over
- // `Cord::char_begin()` and `Cord::char_end()`.
- class CharRange {
- public:
+ explicit ChunkRange(const Cord* cord) : cord_(cord) {}
+
+ ChunkIterator begin() const;
+ ChunkIterator end() const;
+
+ private:
+ const Cord* cord_;
+ };
+
+ // Cord::Chunks()
+ //
+ // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks
+ // of a `Cord` with a range-based for-loop. For most iteration tasks on a
+ // Cord, use `Cord::Chunks()` to retrieve this iterator.
+ //
+ // Example:
+ //
+ // void ProcessChunks(const Cord& cord) {
+ // for (absl::string_view chunk : cord.Chunks()) { ... }
+ // }
+ //
+ // Note that the ordinary caveats of temporary lifetime extension apply:
+ //
+ // void Process() {
+ // for (absl::string_view chunk : CordFactory().Chunks()) {
+ // // The temporary Cord returned by CordFactory has been destroyed!
+ // }
+ // }
+ ChunkRange Chunks() const;
+
+ //----------------------------------------------------------------------------
+ // Cord::CharIterator
+ //----------------------------------------------------------------------------
+ //
+ // A `Cord::CharIterator` allows iteration over the constituent characters of
+ // a `Cord`.
+ //
+ // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
+ // you create one implicitly through use of the `Cord::Chars()` member
+ // function.
+ //
+ // A `Cord::CharIterator` has the following properties:
+ //
+ // * The iterator is invalidated after any non-const operation on the
+ // Cord object over which it iterates.
+ // * Two `CharIterator` objects can be compared equal if and only if they
+ // remain valid and iterate over the same Cord.
+ // * The iterator keeps state that can grow for Cords that contain many
+ // nodes and are imbalanced due to sharing. Prefer to pass this type by
+ // const reference instead of by value.
+ // * This type cannot act as a forward iterator because a `Cord` can reuse
+ // sections of memory. This fact violates the requirement for forward
+ // iterators to compare equal if dereferencing them returns the same
+ // object.
+ class CharIterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ CharIterator() = default;
+
+ CharIterator& operator++();
+ CharIterator operator++(int);
+ bool operator==(const CharIterator& other) const;
+ bool operator!=(const CharIterator& other) const;
+ reference operator*() const;
+ pointer operator->() const;
+
+ friend Cord;
+
+ private:
+ explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {}
+
+ ChunkIterator chunk_iterator_;
+ };
+
+ // Cord::CharIterator::AdvanceAndRead()
+ //
+ // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
+ // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
+ // number of bytes within the Cord; otherwise, behavior is undefined. It is
+ // valid to pass `char_end()` and `0`.
+ static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes);
+
+ // Cord::CharIterator::Advance()
+ //
+ // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
+ // or equal to the number of bytes remaining within the Cord; otherwise,
+ // behavior is undefined. It is valid to pass `char_end()` and `0`.
+ static void Advance(CharIterator* it, size_t n_bytes);
+
+ // Cord::CharIterator::ChunkRemaining()
+ //
+ // Returns the longest contiguous view starting at the iterator's position.
+ //
+ // `it` must be dereferenceable.
+ static absl::string_view ChunkRemaining(const CharIterator& it);
+
+ // Cord::CharIterator::char_begin()
+ //
+ // Returns an iterator to the first character of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `CharIterator` where range-based for-loops may not be available.
+ CharIterator char_begin() const;
+
+ // Cord::CharIterator::char_end()
+ //
+ // Returns an iterator to one past the last character of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `CharIterator` where range-based for-loops are not useful.
+ CharIterator char_end() const;
+
+ // Cord::CharIterator::CharRange
+ //
+ // `CharRange` is a helper class for iterating over the characters of a
+ // producing an iterator which can be used within a range-based for loop.
+ // Construction of a `CharRange` will return an iterator pointing to the first
+ // character of the Cord. Generally, do not construct a `CharRange` directly;
+ // instead, prefer to use the `Cord::Chars()` method show below.
+ //
+ // Implementation note: `CharRange` is simply a convenience wrapper over
+ // `Cord::char_begin()` and `Cord::char_end()`.
+ class CharRange {
+ public:
// Fulfill minimum c++ container requirements [container.requirements]
// Theses (partial) container type definitions allow CharRange to be used
// in various utilities expecting a subset of [container.requirements].
@@ -611,75 +611,75 @@ class Cord {
using iterator = CharIterator;
using const_iterator = CharIterator;
- explicit CharRange(const Cord* cord) : cord_(cord) {}
-
- CharIterator begin() const;
- CharIterator end() const;
-
- private:
- const Cord* cord_;
- };
-
- // Cord::CharIterator::Chars()
- //
- // Returns a `Cord::CharIterator` for iterating over the characters of a
- // `Cord` with a range-based for-loop. For most character-based iteration
- // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator.
- //
- // Example:
- //
- // void ProcessCord(const Cord& cord) {
- // for (char c : cord.Chars()) { ... }
- // }
- //
- // Note that the ordinary caveats of temporary lifetime extension apply:
- //
- // void Process() {
- // for (char c : CordFactory().Chars()) {
- // // The temporary Cord returned by CordFactory has been destroyed!
- // }
- // }
- CharRange Chars() const;
-
- // Cord::operator[]
- //
- // Gets the "i"th character of the Cord and returns it, provided that
- // 0 <= i < Cord.size().
- //
- // NOTE: This routine is reasonably efficient. It is roughly
- // logarithmic based on the number of chunks that make up the cord. Still,
- // if you need to iterate over the contents of a cord, you should
- // use a CharIterator/ChunkIterator rather than call operator[] or Get()
- // repeatedly in a loop.
- char operator[](size_t i) const;
-
- // Cord::TryFlat()
- //
- // If this cord's representation is a single flat array, returns a
- // string_view referencing that array. Otherwise returns nullopt.
- absl::optional<absl::string_view> TryFlat() const;
-
- // Cord::Flatten()
- //
- // Flattens the cord into a single array and returns a view of the data.
- //
- // If the cord was already flat, the contents are not modified.
- absl::string_view Flatten();
-
- // Supports absl::Cord as a sink object for absl::Format().
- friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) {
- cord->Append(part);
- }
-
- template <typename H>
- friend H AbslHashValue(H hash_state, const absl::Cord& c) {
- absl::optional<absl::string_view> maybe_flat = c.TryFlat();
- if (maybe_flat.has_value()) {
- return H::combine(std::move(hash_state), *maybe_flat);
- }
- return c.HashFragmented(std::move(hash_state));
- }
-
+ explicit CharRange(const Cord* cord) : cord_(cord) {}
+
+ CharIterator begin() const;
+ CharIterator end() const;
+
+ private:
+ const Cord* cord_;
+ };
+
+ // Cord::CharIterator::Chars()
+ //
+ // Returns a `Cord::CharIterator` for iterating over the characters of a
+ // `Cord` with a range-based for-loop. For most character-based iteration
+ // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator.
+ //
+ // Example:
+ //
+ // void ProcessCord(const Cord& cord) {
+ // for (char c : cord.Chars()) { ... }
+ // }
+ //
+ // Note that the ordinary caveats of temporary lifetime extension apply:
+ //
+ // void Process() {
+ // for (char c : CordFactory().Chars()) {
+ // // The temporary Cord returned by CordFactory has been destroyed!
+ // }
+ // }
+ CharRange Chars() const;
+
+ // Cord::operator[]
+ //
+ // Gets the "i"th character of the Cord and returns it, provided that
+ // 0 <= i < Cord.size().
+ //
+ // NOTE: This routine is reasonably efficient. It is roughly
+ // logarithmic based on the number of chunks that make up the cord. Still,
+ // if you need to iterate over the contents of a cord, you should
+ // use a CharIterator/ChunkIterator rather than call operator[] or Get()
+ // repeatedly in a loop.
+ char operator[](size_t i) const;
+
+ // Cord::TryFlat()
+ //
+ // If this cord's representation is a single flat array, returns a
+ // string_view referencing that array. Otherwise returns nullopt.
+ absl::optional<absl::string_view> TryFlat() const;
+
+ // Cord::Flatten()
+ //
+ // Flattens the cord into a single array and returns a view of the data.
+ //
+ // If the cord was already flat, the contents are not modified.
+ absl::string_view Flatten();
+
+ // Supports absl::Cord as a sink object for absl::Format().
+ friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) {
+ cord->Append(part);
+ }
+
+ template <typename H>
+ friend H AbslHashValue(H hash_state, const absl::Cord& c) {
+ absl::optional<absl::string_view> maybe_flat = c.TryFlat();
+ if (maybe_flat.has_value()) {
+ return H::combine(std::move(hash_state), *maybe_flat);
+ }
+ return c.HashFragmented(std::move(hash_state));
+ }
+
// Create a Cord with the contents of StringConstant<T>::value.
// No allocations will be done and no data will be copied.
// This is an INTERNAL API and subject to change or removal. This API can only
@@ -688,7 +688,7 @@ class Cord {
template <typename T>
explicit constexpr Cord(strings_internal::StringConstant<T>);
- private:
+ private:
using CordRep = absl::cord_internal::CordRep;
using CordRepFlat = absl::cord_internal::CordRepFlat;
using CordzInfo = cord_internal::CordzInfo;
@@ -701,56 +701,56 @@ class Cord {
// public API call causing the cord to be created.
explicit Cord(absl::string_view src, MethodIdentifier method);
- friend class CordTestPeer;
- friend bool operator==(const Cord& lhs, const Cord& rhs);
- friend bool operator==(const Cord& lhs, absl::string_view rhs);
-
+ friend class CordTestPeer;
+ friend bool operator==(const Cord& lhs, const Cord& rhs);
+ friend bool operator==(const Cord& lhs, absl::string_view rhs);
+
friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord);
- // Calls the provided function once for each cord chunk, in order. Unlike
- // Chunks(), this API will not allocate memory.
- void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
-
- // Allocates new contiguous storage for the contents of the cord. This is
- // called by Flatten() when the cord was not already flat.
- absl::string_view FlattenSlowPath();
-
- // Actual cord contents are hidden inside the following simple
- // class so that we can isolate the bulk of cord.cc from changes
- // to the representation.
- //
- // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
- class InlineRep {
- public:
- static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
- static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
-
- constexpr InlineRep() : data_() {}
+ // Calls the provided function once for each cord chunk, in order. Unlike
+ // Chunks(), this API will not allocate memory.
+ void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
+
+ // Allocates new contiguous storage for the contents of the cord. This is
+ // called by Flatten() when the cord was not already flat.
+ absl::string_view FlattenSlowPath();
+
+ // Actual cord contents are hidden inside the following simple
+ // class so that we can isolate the bulk of cord.cc from changes
+ // to the representation.
+ //
+ // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
+ class InlineRep {
+ public:
+ static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
+ static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
+
+ constexpr InlineRep() : data_() {}
explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {}
- InlineRep(const InlineRep& src);
- InlineRep(InlineRep&& src);
- InlineRep& operator=(const InlineRep& src);
- InlineRep& operator=(InlineRep&& src) noexcept;
-
+ InlineRep(const InlineRep& src);
+ InlineRep(InlineRep&& src);
+ InlineRep& operator=(const InlineRep& src);
+ InlineRep& operator=(InlineRep&& src) noexcept;
+
explicit constexpr InlineRep(cord_internal::InlineData data);
- void Swap(InlineRep* rhs);
- bool empty() const;
- size_t size() const;
- const char* data() const; // Returns nullptr if holding pointer
- void set_data(const char* data, size_t n,
- bool nullify_tail); // Discards pointer, if any
+ void Swap(InlineRep* rhs);
+ bool empty() const;
+ size_t size() const;
+ const char* data() const; // Returns nullptr if holding pointer
+ void set_data(const char* data, size_t n,
+ bool nullify_tail); // Discards pointer, if any
char* set_data(size_t n); // Write data to the result
- // Returns nullptr if holding bytes
- absl::cord_internal::CordRep* tree() const;
+ // Returns nullptr if holding bytes
+ absl::cord_internal::CordRep* tree() const;
absl::cord_internal::CordRep* as_tree() const;
- // Returns non-null iff was holding a pointer
- absl::cord_internal::CordRep* clear();
- // Converts to pointer if necessary.
+ // Returns non-null iff was holding a pointer
+ absl::cord_internal::CordRep* clear();
+ // Converts to pointer if necessary.
void reduce_size(size_t n); // REQUIRES: holding data
- void remove_prefix(size_t n); // REQUIRES: holding data
+ void remove_prefix(size_t n); // REQUIRES: holding data
void AppendArray(absl::string_view src, MethodIdentifier method);
- absl::string_view FindFlatStartPiece() const;
+ absl::string_view FindFlatStartPiece() const;
// Creates a CordRepFlat instance from the current inlined data with `extra'
// bytes of desired additional capacity.
@@ -794,40 +794,40 @@ class Cord {
template <bool has_length>
void GetAppendRegion(char** region, size_t* size, size_t length);
- bool IsSame(const InlineRep& other) const {
- return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
- }
- int BitwiseCompare(const InlineRep& other) const {
- uint64_t x, y;
- // Use memcpy to avoid aliasing issues.
- memcpy(&x, &data_, sizeof(x));
- memcpy(&y, &other.data_, sizeof(y));
- if (x == y) {
- memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
- memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
- if (x == y) return 0;
- }
- return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
- ? -1
- : 1;
- }
- void CopyTo(std::string* dst) const {
- // memcpy is much faster when operating on a known size. On most supported
- // platforms, the small string optimization is large enough that resizing
- // to 15 bytes does not cause a memory allocation.
- absl::strings_internal::STLStringResizeUninitialized(dst,
- sizeof(data_) - 1);
- memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
- // erase is faster than resize because the logic for memory allocation is
- // not needed.
+ bool IsSame(const InlineRep& other) const {
+ return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
+ }
+ int BitwiseCompare(const InlineRep& other) const {
+ uint64_t x, y;
+ // Use memcpy to avoid aliasing issues.
+ memcpy(&x, &data_, sizeof(x));
+ memcpy(&y, &other.data_, sizeof(y));
+ if (x == y) {
+ memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
+ memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
+ if (x == y) return 0;
+ }
+ return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
+ ? -1
+ : 1;
+ }
+ void CopyTo(std::string* dst) const {
+ // memcpy is much faster when operating on a known size. On most supported
+ // platforms, the small string optimization is large enough that resizing
+ // to 15 bytes does not cause a memory allocation.
+ absl::strings_internal::STLStringResizeUninitialized(dst,
+ sizeof(data_) - 1);
+ memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
+ // erase is faster than resize because the logic for memory allocation is
+ // not needed.
dst->erase(inline_size());
- }
-
- // Copies the inline contents into `dst`. Assumes the cord is not empty.
- void CopyToArray(char* dst) const;
-
+ }
+
+ // Copies the inline contents into `dst`. Assumes the cord is not empty.
+ void CopyToArray(char* dst) const;
+
bool is_tree() const { return data_.is_tree(); }
-
+
// Returns true if the Cord is being profiled by cordz.
bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); }
@@ -845,62 +845,62 @@ class Cord {
// Resets the current cordz_info to null / empty.
void clear_cordz_info() { data_.clear_cordz_info(); }
- private:
- friend class Cord;
-
- void AssignSlow(const InlineRep& src);
+ private:
+ friend class Cord;
+
+ void AssignSlow(const InlineRep& src);
// Unrefs the tree and stops profiling.
void UnrefTree();
-
- void ResetToEmpty() { data_ = {}; }
-
+
+ void ResetToEmpty() { data_ = {}; }
+
void set_inline_size(size_t size) { data_.set_inline_size(size); }
size_t inline_size() const { return data_.inline_size(); }
-
- cord_internal::InlineData data_;
- };
- InlineRep contents_;
-
- // Helper for MemoryUsage().
- static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
-
- // Helper for GetFlat() and TryFlat().
- static bool GetFlatAux(absl::cord_internal::CordRep* rep,
- absl::string_view* fragment);
-
- // Helper for ForEachChunk().
- static void ForEachChunkAux(
- absl::cord_internal::CordRep* rep,
- absl::FunctionRef<void(absl::string_view)> callback);
-
- // The destructor for non-empty Cords.
- void DestroyCordSlow();
-
- // Out-of-line implementation of slower parts of logic.
- void CopyToArraySlowPath(char* dst) const;
- int CompareSlowPath(absl::string_view rhs, size_t compared_size,
- size_t size_to_compare) const;
- int CompareSlowPath(const Cord& rhs, size_t compared_size,
- size_t size_to_compare) const;
- bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
- bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
- int CompareImpl(const Cord& rhs) const;
-
- template <typename ResultType, typename RHS>
- friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
- size_t size_to_compare);
- static absl::string_view GetFirstChunk(const Cord& c);
- static absl::string_view GetFirstChunk(absl::string_view sv);
-
- // Returns a new reference to contents_.tree(), or steals an existing
- // reference if called on an rvalue.
- absl::cord_internal::CordRep* TakeRep() const&;
- absl::cord_internal::CordRep* TakeRep() &&;
-
- // Helper for Append().
- template <typename C>
- void AppendImpl(C&& src);
-
+
+ cord_internal::InlineData data_;
+ };
+ InlineRep contents_;
+
+ // Helper for MemoryUsage().
+ static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
+
+ // Helper for GetFlat() and TryFlat().
+ static bool GetFlatAux(absl::cord_internal::CordRep* rep,
+ absl::string_view* fragment);
+
+ // Helper for ForEachChunk().
+ static void ForEachChunkAux(
+ absl::cord_internal::CordRep* rep,
+ absl::FunctionRef<void(absl::string_view)> callback);
+
+ // The destructor for non-empty Cords.
+ void DestroyCordSlow();
+
+ // Out-of-line implementation of slower parts of logic.
+ void CopyToArraySlowPath(char* dst) const;
+ int CompareSlowPath(absl::string_view rhs, size_t compared_size,
+ size_t size_to_compare) const;
+ int CompareSlowPath(const Cord& rhs, size_t compared_size,
+ size_t size_to_compare) const;
+ bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
+ bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
+ int CompareImpl(const Cord& rhs) const;
+
+ template <typename ResultType, typename RHS>
+ friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+ size_t size_to_compare);
+ static absl::string_view GetFirstChunk(const Cord& c);
+ static absl::string_view GetFirstChunk(absl::string_view sv);
+
+ // Returns a new reference to contents_.tree(), or steals an existing
+ // reference if called on an rvalue.
+ absl::cord_internal::CordRep* TakeRep() const&;
+ absl::cord_internal::CordRep* TakeRep() &&;
+
+ // Helper for Append().
+ template <typename C>
+ void AppendImpl(C&& src);
+
// Prepends the provided data to this instance. `method` contains the public
// API method for this action which is tracked for Cordz sampling purposes.
void PrependArray(absl::string_view src, MethodIdentifier method);
@@ -909,116 +909,116 @@ class Cord {
// Requires src.length() > kMaxBytesToCopy.
Cord& AssignLargeString(std::string&& src);
- // Helper for AbslHashValue().
- template <typename H>
- H HashFragmented(H hash_state) const {
- typename H::AbslInternalPiecewiseCombiner combiner;
- ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
- hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
- chunk.size());
- });
- return H::combine(combiner.finalize(std::move(hash_state)), size());
- }
-};
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// allow a Cord to be logged
-extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
-
-// ------------------------------------------------------------------
-// Internal details follow. Clients should ignore.
-
-namespace cord_internal {
-
-// Fast implementation of memmove for up to 15 bytes. This implementation is
-// safe for overlapping regions. If nullify_tail is true, the destination is
-// padded with '\0' up to 16 bytes.
-inline void SmallMemmove(char* dst, const char* src, size_t n,
- bool nullify_tail = false) {
- if (n >= 8) {
- assert(n <= 16);
- uint64_t buf1;
- uint64_t buf2;
- memcpy(&buf1, src, 8);
- memcpy(&buf2, src + n - 8, 8);
- if (nullify_tail) {
- memset(dst + 8, 0, 8);
- }
- memcpy(dst, &buf1, 8);
- memcpy(dst + n - 8, &buf2, 8);
- } else if (n >= 4) {
- uint32_t buf1;
- uint32_t buf2;
- memcpy(&buf1, src, 4);
- memcpy(&buf2, src + n - 4, 4);
- if (nullify_tail) {
- memset(dst + 4, 0, 4);
- memset(dst + 8, 0, 8);
- }
- memcpy(dst, &buf1, 4);
- memcpy(dst + n - 4, &buf2, 4);
- } else {
- if (n != 0) {
- dst[0] = src[0];
- dst[n / 2] = src[n / 2];
- dst[n - 1] = src[n - 1];
- }
- if (nullify_tail) {
- memset(dst + 8, 0, 8);
- memset(dst + n, 0, 8);
- }
- }
-}
-
-// Does non-template-specific `CordRepExternal` initialization.
-// Expects `data` to be non-empty.
-void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
-
-// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
-// to it, or `nullptr` if `data` was empty.
-template <typename Releaser>
-// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
-CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
- using ReleaserType = absl::decay_t<Releaser>;
- if (data.empty()) {
- // Never create empty external nodes.
- InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
- data);
- return nullptr;
- }
-
- CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
- std::forward<Releaser>(releaser), 0);
- InitializeCordRepExternal(data, rep);
- return rep;
-}
-
-// Overload for function reference types that dispatches using a function
-// pointer because there are no `alignof()` or `sizeof()` a function reference.
-// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
-inline CordRep* NewExternalRep(absl::string_view data,
- void (&releaser)(absl::string_view)) {
- return NewExternalRep(data, &releaser);
-}
-
-} // namespace cord_internal
-
-template <typename Releaser>
-Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
- Cord cord;
+ // Helper for AbslHashValue().
+ template <typename H>
+ H HashFragmented(H hash_state) const {
+ typename H::AbslInternalPiecewiseCombiner combiner;
+ ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
+ hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
+ chunk.size());
+ });
+ return H::combine(combiner.finalize(std::move(hash_state)), size());
+ }
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// allow a Cord to be logged
+extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
+
+// ------------------------------------------------------------------
+// Internal details follow. Clients should ignore.
+
+namespace cord_internal {
+
+// Fast implementation of memmove for up to 15 bytes. This implementation is
+// safe for overlapping regions. If nullify_tail is true, the destination is
+// padded with '\0' up to 16 bytes.
+inline void SmallMemmove(char* dst, const char* src, size_t n,
+ bool nullify_tail = false) {
+ if (n >= 8) {
+ assert(n <= 16);
+ uint64_t buf1;
+ uint64_t buf2;
+ memcpy(&buf1, src, 8);
+ memcpy(&buf2, src + n - 8, 8);
+ if (nullify_tail) {
+ memset(dst + 8, 0, 8);
+ }
+ memcpy(dst, &buf1, 8);
+ memcpy(dst + n - 8, &buf2, 8);
+ } else if (n >= 4) {
+ uint32_t buf1;
+ uint32_t buf2;
+ memcpy(&buf1, src, 4);
+ memcpy(&buf2, src + n - 4, 4);
+ if (nullify_tail) {
+ memset(dst + 4, 0, 4);
+ memset(dst + 8, 0, 8);
+ }
+ memcpy(dst, &buf1, 4);
+ memcpy(dst + n - 4, &buf2, 4);
+ } else {
+ if (n != 0) {
+ dst[0] = src[0];
+ dst[n / 2] = src[n / 2];
+ dst[n - 1] = src[n - 1];
+ }
+ if (nullify_tail) {
+ memset(dst + 8, 0, 8);
+ memset(dst + n, 0, 8);
+ }
+ }
+}
+
+// Does non-template-specific `CordRepExternal` initialization.
+// Expects `data` to be non-empty.
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
+
+// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
+// to it, or `nullptr` if `data` was empty.
+template <typename Releaser>
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
+ using ReleaserType = absl::decay_t<Releaser>;
+ if (data.empty()) {
+ // Never create empty external nodes.
+ InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
+ data);
+ return nullptr;
+ }
+
+ CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
+ std::forward<Releaser>(releaser), 0);
+ InitializeCordRepExternal(data, rep);
+ return rep;
+}
+
+// Overload for function reference types that dispatches using a function
+// pointer because there are no `alignof()` or `sizeof()` a function reference.
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+inline CordRep* NewExternalRep(absl::string_view data,
+ void (&releaser)(absl::string_view)) {
+ return NewExternalRep(data, &releaser);
+}
+
+} // namespace cord_internal
+
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
+ Cord cord;
if (auto* rep = ::absl::cord_internal::NewExternalRep(
data, std::forward<Releaser>(releaser))) {
cord.contents_.EmplaceTree(rep,
Cord::MethodIdentifier::kMakeCordFromExternal);
}
- return cord;
-}
-
+ return cord;
+}
+
constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
: data_(data) {}
@@ -1030,64 +1030,64 @@ inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
} else {
data_ = src.data_;
}
-}
-
+}
+
inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {
- src.ResetToEmpty();
-}
-
-inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
- if (this == &src) {
- return *this;
- }
- if (!is_tree() && !src.is_tree()) {
- data_ = src.data_;
- return *this;
- }
- AssignSlow(src);
- return *this;
-}
-
-inline Cord::InlineRep& Cord::InlineRep::operator=(
- Cord::InlineRep&& src) noexcept {
- if (is_tree()) {
+ src.ResetToEmpty();
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
+ if (this == &src) {
+ return *this;
+ }
+ if (!is_tree() && !src.is_tree()) {
+ data_ = src.data_;
+ return *this;
+ }
+ AssignSlow(src);
+ return *this;
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(
+ Cord::InlineRep&& src) noexcept {
+ if (is_tree()) {
UnrefTree();
- }
- data_ = src.data_;
- src.ResetToEmpty();
- return *this;
-}
-
-inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
- if (rhs == this) {
- return;
- }
- std::swap(data_, rhs->data_);
-}
-
-inline const char* Cord::InlineRep::data() const {
+ }
+ data_ = src.data_;
+ src.ResetToEmpty();
+ return *this;
+}
+
+inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
+ if (rhs == this) {
+ return;
+ }
+ std::swap(data_, rhs->data_);
+}
+
+inline const char* Cord::InlineRep::data() const {
return is_tree() ? nullptr : data_.as_chars();
-}
-
+}
+
inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
assert(data_.is_tree());
return data_.as_tree();
}
-inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
- if (is_tree()) {
+inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
+ if (is_tree()) {
return as_tree();
- } else {
- return nullptr;
- }
-}
-
+ } else {
+ return nullptr;
+ }
+}
+
inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
-
-inline size_t Cord::InlineRep::size() const {
+
+inline size_t Cord::InlineRep::size() const {
return is_tree() ? as_tree()->length : inline_size();
-}
-
+}
+
inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
size_t extra) {
static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
@@ -1124,12 +1124,12 @@ inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep,
assert(data_.is_tree());
if (rep) {
data_.set_tree(rep);
- } else {
+ } else {
data_ = {};
- }
+ }
scope.SetCordRep(rep);
-}
-
+}
+
inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep,
const CordzUpdateScope& scope,
MethodIdentifier method) {
@@ -1137,27 +1137,27 @@ inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep,
SetTree(rep, scope);
} else {
EmplaceTree(rep, method);
- }
-}
-
-inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
+ }
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
if (is_tree()) {
CordzInfo::MaybeUntrackCord(cordz_info());
}
- absl::cord_internal::CordRep* result = tree();
- ResetToEmpty();
- return result;
-}
-
-inline void Cord::InlineRep::CopyToArray(char* dst) const {
- assert(!is_tree());
+ absl::cord_internal::CordRep* result = tree();
+ ResetToEmpty();
+ return result;
+}
+
+inline void Cord::InlineRep::CopyToArray(char* dst) const {
+ assert(!is_tree());
size_t n = inline_size();
- assert(n != 0);
+ assert(n != 0);
cord_internal::SmallMemmove(dst, data_.as_chars(), n);
-}
-
-constexpr inline Cord::Cord() noexcept {}
-
+}
+
+constexpr inline Cord::Cord() noexcept {}
+
inline Cord::Cord(absl::string_view src)
: Cord(src, CordzUpdateTracker::kConstructorString) {}
@@ -1171,11 +1171,11 @@ constexpr Cord::Cord(strings_internal::StringConstant<T>)
&cord_internal::ConstInitExternalStorage<
strings_internal::StringConstant<T>>::value)) {}
-inline Cord& Cord::operator=(const Cord& x) {
- contents_ = x.contents_;
- return *this;
-}
-
+inline Cord& Cord::operator=(const Cord& x) {
+ contents_ = x.contents_;
+ return *this;
+}
+
template <typename T, Cord::EnableIfString<T>>
Cord& Cord::operator=(T&& src) {
if (src.size() <= cord_internal::kMaxBytesToCopy) {
@@ -1187,92 +1187,92 @@ Cord& Cord::operator=(T&& src) {
inline Cord::Cord(const Cord& src) : contents_(src.contents_) {}
-inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
-
-inline void Cord::swap(Cord& other) noexcept {
- contents_.Swap(&other.contents_);
-}
-
-inline Cord& Cord::operator=(Cord&& x) noexcept {
- contents_ = std::move(x.contents_);
- return *this;
-}
-
-extern template Cord::Cord(std::string&& src);
-
-inline size_t Cord::size() const {
- // Length is 1st field in str.rep_
- return contents_.size();
-}
-
-inline bool Cord::empty() const { return contents_.empty(); }
-
-inline size_t Cord::EstimatedMemoryUsage() const {
- size_t result = sizeof(Cord);
- if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
- result += MemoryUsageAux(rep);
- }
- return result;
-}
-
-inline absl::optional<absl::string_view> Cord::TryFlat() const {
- absl::cord_internal::CordRep* rep = contents_.tree();
- if (rep == nullptr) {
- return absl::string_view(contents_.data(), contents_.size());
- }
- absl::string_view fragment;
- if (GetFlatAux(rep, &fragment)) {
- return fragment;
- }
- return absl::nullopt;
-}
-
-inline absl::string_view Cord::Flatten() {
- absl::cord_internal::CordRep* rep = contents_.tree();
- if (rep == nullptr) {
- return absl::string_view(contents_.data(), contents_.size());
- } else {
- absl::string_view already_flat_contents;
- if (GetFlatAux(rep, &already_flat_contents)) {
- return already_flat_contents;
- }
- }
- return FlattenSlowPath();
-}
-
-inline void Cord::Append(absl::string_view src) {
+inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
+
+inline void Cord::swap(Cord& other) noexcept {
+ contents_.Swap(&other.contents_);
+}
+
+inline Cord& Cord::operator=(Cord&& x) noexcept {
+ contents_ = std::move(x.contents_);
+ return *this;
+}
+
+extern template Cord::Cord(std::string&& src);
+
+inline size_t Cord::size() const {
+ // Length is 1st field in str.rep_
+ return contents_.size();
+}
+
+inline bool Cord::empty() const { return contents_.empty(); }
+
+inline size_t Cord::EstimatedMemoryUsage() const {
+ size_t result = sizeof(Cord);
+ if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
+ result += MemoryUsageAux(rep);
+ }
+ return result;
+}
+
+inline absl::optional<absl::string_view> Cord::TryFlat() const {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return absl::string_view(contents_.data(), contents_.size());
+ }
+ absl::string_view fragment;
+ if (GetFlatAux(rep, &fragment)) {
+ return fragment;
+ }
+ return absl::nullopt;
+}
+
+inline absl::string_view Cord::Flatten() {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return absl::string_view(contents_.data(), contents_.size());
+ } else {
+ absl::string_view already_flat_contents;
+ if (GetFlatAux(rep, &already_flat_contents)) {
+ return already_flat_contents;
+ }
+ }
+ return FlattenSlowPath();
+}
+
+inline void Cord::Append(absl::string_view src) {
contents_.AppendArray(src, CordzUpdateTracker::kAppendString);
-}
-
+}
+
inline void Cord::Prepend(absl::string_view src) {
PrependArray(src, CordzUpdateTracker::kPrependString);
}
-extern template void Cord::Append(std::string&& src);
-extern template void Cord::Prepend(std::string&& src);
-
-inline int Cord::Compare(const Cord& rhs) const {
- if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
- return contents_.BitwiseCompare(rhs.contents_);
- }
-
- return CompareImpl(rhs);
-}
-
-// Does 'this' cord start/end with rhs
-inline bool Cord::StartsWith(const Cord& rhs) const {
- if (contents_.IsSame(rhs.contents_)) return true;
- size_t rhs_size = rhs.size();
- if (size() < rhs_size) return false;
- return EqualsImpl(rhs, rhs_size);
-}
-
-inline bool Cord::StartsWith(absl::string_view rhs) const {
- size_t rhs_size = rhs.size();
- if (size() < rhs_size) return false;
- return EqualsImpl(rhs, rhs_size);
-}
-
+extern template void Cord::Append(std::string&& src);
+extern template void Cord::Prepend(std::string&& src);
+
+inline int Cord::Compare(const Cord& rhs) const {
+ if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
+ return contents_.BitwiseCompare(rhs.contents_);
+ }
+
+ return CompareImpl(rhs);
+}
+
+// Does 'this' cord start/end with rhs
+inline bool Cord::StartsWith(const Cord& rhs) const {
+ if (contents_.IsSame(rhs.contents_)) return true;
+ size_t rhs_size = rhs.size();
+ if (size() < rhs_size) return false;
+ return EqualsImpl(rhs, rhs_size);
+}
+
+inline bool Cord::StartsWith(absl::string_view rhs) const {
+ size_t rhs_size = rhs.size();
+ if (size() < rhs_size) return false;
+ return EqualsImpl(rhs, rhs_size);
+}
+
inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
if (tree->tag == cord_internal::BTREE) {
current_chunk_ = btree_reader_.Init(tree->btree());
@@ -1288,16 +1288,16 @@ inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree)
InitTree(tree);
}
-inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
- : bytes_remaining_(cord->size()) {
- if (cord->contents_.is_tree()) {
+inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
+ : bytes_remaining_(cord->size()) {
+ if (cord->contents_.is_tree()) {
InitTree(cord->contents_.as_tree());
- } else {
+ } else {
current_chunk_ =
absl::string_view(cord->contents_.data(), bytes_remaining_);
- }
-}
-
+ }
+}
+
inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {
current_chunk_ = btree_reader_.Next();
return *this;
@@ -1331,191 +1331,191 @@ inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
return *this;
}
-inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
- ChunkIterator tmp(*this);
- operator++();
- return tmp;
-}
-
-inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
- return bytes_remaining_ == other.bytes_remaining_;
-}
-
-inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
- return !(*this == other);
-}
-
-inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
- return current_chunk_;
-}
-
-inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
- return &current_chunk_;
-}
-
-inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
- assert(n < current_chunk_.size());
- current_chunk_.remove_prefix(n);
- bytes_remaining_ -= n;
-}
-
-inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
+inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
+ ChunkIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
+ return bytes_remaining_ == other.bytes_remaining_;
+}
+
+inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
+ return !(*this == other);
+}
+
+inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ return current_chunk_;
+}
+
+inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ return &current_chunk_;
+}
+
+inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
+ assert(n < current_chunk_.size());
+ current_chunk_.remove_prefix(n);
+ bytes_remaining_ -= n;
+}
+
+inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
assert(bytes_remaining_ >= n);
- if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
- RemoveChunkPrefix(n);
- } else if (n != 0) {
+ if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
+ RemoveChunkPrefix(n);
+ } else if (n != 0) {
btree_reader_ ? AdvanceBytesBtree(n) : AdvanceBytesSlowPath(n);
- }
-}
-
-inline Cord::ChunkIterator Cord::chunk_begin() const {
- return ChunkIterator(this);
-}
-
-inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
-
-inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
- return cord_->chunk_begin();
-}
-
-inline Cord::ChunkIterator Cord::ChunkRange::end() const {
- return cord_->chunk_end();
-}
-
-inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
-
-inline Cord::CharIterator& Cord::CharIterator::operator++() {
- if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
- chunk_iterator_.RemoveChunkPrefix(1);
- } else {
- ++chunk_iterator_;
- }
- return *this;
-}
-
-inline Cord::CharIterator Cord::CharIterator::operator++(int) {
- CharIterator tmp(*this);
- operator++();
- return tmp;
-}
-
-inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
- return chunk_iterator_ == other.chunk_iterator_;
-}
-
-inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
- return !(*this == other);
-}
-
-inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
- return *chunk_iterator_->data();
-}
-
-inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
- return chunk_iterator_->data();
-}
-
-inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) {
- assert(it != nullptr);
- return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
-}
-
-inline void Cord::Advance(CharIterator* it, size_t n_bytes) {
- assert(it != nullptr);
- it->chunk_iterator_.AdvanceBytes(n_bytes);
-}
-
-inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
- return *it.chunk_iterator_;
-}
-
-inline Cord::CharIterator Cord::char_begin() const {
- return CharIterator(this);
-}
-
-inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
-
-inline Cord::CharIterator Cord::CharRange::begin() const {
- return cord_->char_begin();
-}
-
-inline Cord::CharIterator Cord::CharRange::end() const {
- return cord_->char_end();
-}
-
-inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
-
-inline void Cord::ForEachChunk(
- absl::FunctionRef<void(absl::string_view)> callback) const {
- absl::cord_internal::CordRep* rep = contents_.tree();
- if (rep == nullptr) {
- callback(absl::string_view(contents_.data(), contents_.size()));
- } else {
- return ForEachChunkAux(rep, callback);
- }
-}
-
-// Nonmember Cord-to-Cord relational operarators.
-inline bool operator==(const Cord& lhs, const Cord& rhs) {
- if (lhs.contents_.IsSame(rhs.contents_)) return true;
- size_t rhs_size = rhs.size();
- if (lhs.size() != rhs_size) return false;
- return lhs.EqualsImpl(rhs, rhs_size);
-}
-
-inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
+ }
+}
+
+inline Cord::ChunkIterator Cord::chunk_begin() const {
+ return ChunkIterator(this);
+}
+
+inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
+
+inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
+ return cord_->chunk_begin();
+}
+
+inline Cord::ChunkIterator Cord::ChunkRange::end() const {
+ return cord_->chunk_end();
+}
+
+inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
+
+inline Cord::CharIterator& Cord::CharIterator::operator++() {
+ if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
+ chunk_iterator_.RemoveChunkPrefix(1);
+ } else {
+ ++chunk_iterator_;
+ }
+ return *this;
+}
+
+inline Cord::CharIterator Cord::CharIterator::operator++(int) {
+ CharIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
+ return chunk_iterator_ == other.chunk_iterator_;
+}
+
+inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
+ return !(*this == other);
+}
+
+inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
+ return *chunk_iterator_->data();
+}
+
+inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
+ return chunk_iterator_->data();
+}
+
+inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) {
+ assert(it != nullptr);
+ return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
+}
+
+inline void Cord::Advance(CharIterator* it, size_t n_bytes) {
+ assert(it != nullptr);
+ it->chunk_iterator_.AdvanceBytes(n_bytes);
+}
+
+inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
+ return *it.chunk_iterator_;
+}
+
+inline Cord::CharIterator Cord::char_begin() const {
+ return CharIterator(this);
+}
+
+inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
+
+inline Cord::CharIterator Cord::CharRange::begin() const {
+ return cord_->char_begin();
+}
+
+inline Cord::CharIterator Cord::CharRange::end() const {
+ return cord_->char_end();
+}
+
+inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
+
+inline void Cord::ForEachChunk(
+ absl::FunctionRef<void(absl::string_view)> callback) const {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ callback(absl::string_view(contents_.data(), contents_.size()));
+ } else {
+ return ForEachChunkAux(rep, callback);
+ }
+}
+
+// Nonmember Cord-to-Cord relational operarators.
+inline bool operator==(const Cord& lhs, const Cord& rhs) {
+ if (lhs.contents_.IsSame(rhs.contents_)) return true;
+ size_t rhs_size = rhs.size();
+ if (lhs.size() != rhs_size) return false;
+ return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
inline bool operator<(const Cord& x, const Cord& y) { return x.Compare(y) < 0; }
inline bool operator>(const Cord& x, const Cord& y) { return x.Compare(y) > 0; }
-inline bool operator<=(const Cord& x, const Cord& y) {
- return x.Compare(y) <= 0;
-}
-inline bool operator>=(const Cord& x, const Cord& y) {
- return x.Compare(y) >= 0;
-}
-
-// Nonmember Cord-to-absl::string_view relational operators.
-//
-// Due to implicit conversions, these also enable comparisons of Cord with
-// with std::string, ::string, and const char*.
-inline bool operator==(const Cord& lhs, absl::string_view rhs) {
- size_t lhs_size = lhs.size();
- size_t rhs_size = rhs.size();
- if (lhs_size != rhs_size) return false;
- return lhs.EqualsImpl(rhs, rhs_size);
-}
-
-inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
-inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
-inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
-inline bool operator<(const Cord& x, absl::string_view y) {
- return x.Compare(y) < 0;
-}
-inline bool operator<(absl::string_view x, const Cord& y) {
- return y.Compare(x) > 0;
-}
-inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
-inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
-inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
-inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
-inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
-inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
-
-// Some internals exposed to test code.
-namespace strings_internal {
-class CordTestAccess {
- public:
- static size_t FlatOverhead();
- static size_t MaxFlatLength();
- static size_t SizeofCordRepConcat();
- static size_t SizeofCordRepExternal();
- static size_t SizeofCordRepSubstring();
- static size_t FlatTagToLength(uint8_t tag);
- static uint8_t LengthToTag(size_t s);
-};
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORD_H_
+inline bool operator<=(const Cord& x, const Cord& y) {
+ return x.Compare(y) <= 0;
+}
+inline bool operator>=(const Cord& x, const Cord& y) {
+ return x.Compare(y) >= 0;
+}
+
+// Nonmember Cord-to-absl::string_view relational operators.
+//
+// Due to implicit conversions, these also enable comparisons of Cord with
+// with std::string, ::string, and const char*.
+inline bool operator==(const Cord& lhs, absl::string_view rhs) {
+ size_t lhs_size = lhs.size();
+ size_t rhs_size = rhs.size();
+ if (lhs_size != rhs_size) return false;
+ return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
+inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
+inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
+inline bool operator<(const Cord& x, absl::string_view y) {
+ return x.Compare(y) < 0;
+}
+inline bool operator<(absl::string_view x, const Cord& y) {
+ return y.Compare(x) > 0;
+}
+inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
+inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
+inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
+inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
+inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
+inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
+
+// Some internals exposed to test code.
+namespace strings_internal {
+class CordTestAccess {
+ public:
+ static size_t FlatOverhead();
+ static size_t MaxFlatLength();
+ static size_t SizeofCordRepConcat();
+ static size_t SizeofCordRepExternal();
+ static size_t SizeofCordRepSubstring();
+ static size_t FlatTagToLength(uint8_t tag);
+ static uint8_t LengthToTag(size_t s);
+};
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_CORD_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h b/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h
index 31a1dc8980..e8832f72c1 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h
@@ -1,34 +1,34 @@
-//
-// 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.
-//
-
-#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_
-#define ABSL_STRINGS_CORD_TEST_HELPERS_H_
-
+//
+// 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.
+//
+
+#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_
+#define ABSL_STRINGS_CORD_TEST_HELPERS_H_
+
#include <cstdint>
#include <iostream>
#include <string>
#include "absl/base/config.h"
-#include "absl/strings/cord.h"
+#include "absl/strings/cord.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
// Cord sizes relevant for testing
enum class TestCordSize {
// An empty value
@@ -84,39 +84,39 @@ inline std::ostream& operator<<(std::ostream& stream, TestCordSize size) {
return stream << ToString(size);
}
-// Creates a multi-segment Cord from an iterable container of strings. The
-// resulting Cord is guaranteed to have one segment for every string in the
-// container. This allows code to be unit tested with multi-segment Cord
-// inputs.
-//
-// Example:
-//
-// absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
-// EXPECT_FALSE(c.GetFlat(&unused));
-//
-// The mechanism by which this Cord is created is an implementation detail. Any
-// implementation that produces a multi-segment Cord may produce a flat Cord in
-// the future as new optimizations are added to the Cord class.
-// MakeFragmentedCord will, however, always be updated to return a multi-segment
-// Cord.
-template <typename Container>
-Cord MakeFragmentedCord(const Container& c) {
- Cord result;
- for (const auto& s : c) {
- auto* external = new std::string(s);
- Cord tmp = absl::MakeCordFromExternal(
- *external, [external](absl::string_view) { delete external; });
- tmp.Prepend(result);
- result = tmp;
- }
- return result;
-}
-
-inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {
- return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);
-}
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORD_TEST_HELPERS_H_
+// Creates a multi-segment Cord from an iterable container of strings. The
+// resulting Cord is guaranteed to have one segment for every string in the
+// container. This allows code to be unit tested with multi-segment Cord
+// inputs.
+//
+// Example:
+//
+// absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
+// EXPECT_FALSE(c.GetFlat(&unused));
+//
+// The mechanism by which this Cord is created is an implementation detail. Any
+// implementation that produces a multi-segment Cord may produce a flat Cord in
+// the future as new optimizations are added to the Cord class.
+// MakeFragmentedCord will, however, always be updated to return a multi-segment
+// Cord.
+template <typename Container>
+Cord MakeFragmentedCord(const Container& c) {
+ Cord result;
+ for (const auto& s : c) {
+ auto* external = new std::string(s);
+ Cord tmp = absl::MakeCordFromExternal(
+ *external, [external](absl::string_view) { delete external; });
+ tmp.Prepend(result);
+ result = tmp;
+ }
+ return result;
+}
+
+inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {
+ return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_CORD_TEST_HELPERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
index 18b20b83fd..0c4a52f877 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
@@ -26,7 +26,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/strings/internal/char_map.h"
-#include "absl/strings/internal/escaping.h"
+#include "absl/strings/internal/escaping.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/utf8.h"
#include "absl/strings/str_cat.h"
@@ -34,7 +34,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace {
// These are used for the leave_nulls_escaped argument to CUnescapeInternal().
@@ -450,7 +450,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
// The GET_INPUT macro gets the next input character, skipping
// over any whitespace, and stopping when we reach the end of the
- // string or when we read any non-data character. The arguments are
+ // string or when we read any non-data character. The arguments are
// an arbitrary identifier (used as a label for goto) and the number
// of data bytes that must remain in the input to avoid aborting the
// loop.
@@ -473,18 +473,18 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
if (dest) {
// This loop consumes 4 input bytes and produces 3 output bytes
// per iteration. We can't know at the start that there is enough
- // data left in the string for a full iteration, so the loop may
+ // data left in the string for a full iteration, so the loop may
// break out in the middle; if so 'state' will be set to the
// number of input bytes read.
while (szsrc >= 4) {
// We'll start by optimistically assuming that the next four
- // bytes of the string (src[0..3]) are four good data bytes
+ // bytes of the string (src[0..3]) are four good data bytes
// (that is, no nulls, whitespace, padding chars, or illegal
// chars). We need to test src[0..2] for nulls individually
// before constructing temp to preserve the property that we
- // never read past a null in the string (no matter how long
- // szsrc claims the string is).
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
if (!src[0] || !src[1] || !src[2] ||
((temp = ((unsigned(unbase64[src[0]]) << 18) |
@@ -509,7 +509,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
temp = (temp << 6) | decode;
} else {
// We really did have four good data bytes, so advance four
- // characters in the string.
+ // characters in the string.
szsrc -= 4;
src += 4;
@@ -644,7 +644,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
state);
}
- // The remainder of the string should be all whitespace, mixed with
+ // The remainder of the string should be all whitespace, mixed with
// exactly 0 equals signs, or exactly 'expected_equals' equals
// signs. (Always accepting 0 equals signs is an Abseil extension
// not covered in the RFC, as is accepting dot as the pad character.)
@@ -771,7 +771,7 @@ constexpr char kWebSafeBase64Chars[] =
template <typename String>
bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
const signed char* unbase64) {
- // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
// 4 characters. any leftover chars are added directly for good measure.
// This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
const size_t dest_len = 3 * (slen / 4) + (slen % 4);
@@ -779,7 +779,7 @@ bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
strings_internal::STLStringResizeUninitialized(dest, dest_len);
// We are getting the destination buffer by getting the beginning of the
- // string and converting it into a char *.
+ // string and converting it into a char *.
size_t len;
const bool ok =
Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
@@ -796,7 +796,7 @@ bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
}
/* clang-format off */
-constexpr char kHexValueLenient[256] = {
+constexpr char kHexValueLenient[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -812,9 +812,9 @@ constexpr char kHexValueLenient[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
-
+
/* clang-format on */
// This is a templated function so that T can be either a char*
@@ -823,8 +823,8 @@ constexpr char kHexValueLenient[256] = {
template <typename T>
void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
for (int i = 0; i < num; i++) {
- to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
- (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
+ to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
+ (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
}
}
@@ -902,30 +902,30 @@ bool WebSafeBase64Unescape(absl::string_view src, std::string* dest) {
}
void Base64Escape(absl::string_view src, std::string* dest) {
- strings_internal::Base64EscapeInternal(
- reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
- true, strings_internal::kBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+ true, strings_internal::kBase64Chars);
}
void WebSafeBase64Escape(absl::string_view src, std::string* dest) {
- strings_internal::Base64EscapeInternal(
- reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
- false, kWebSafeBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+ false, kWebSafeBase64Chars);
}
std::string Base64Escape(absl::string_view src) {
std::string dest;
- strings_internal::Base64EscapeInternal(
- reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
- true, strings_internal::kBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+ true, strings_internal::kBase64Chars);
return dest;
}
std::string WebSafeBase64Escape(absl::string_view src) {
std::string dest;
- strings_internal::Base64EscapeInternal(
- reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
- false, kWebSafeBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+ false, kWebSafeBase64Chars);
return dest;
}
@@ -945,5 +945,5 @@ std::string BytesToHexString(absl::string_view from) {
return result;
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.h b/contrib/restricted/abseil-cpp/absl/strings/escaping.h
index f5ca26c5da..e2a6b106ae 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/escaping.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.h
@@ -33,7 +33,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// CUnescape()
//
@@ -158,7 +158,7 @@ std::string HexStringToBytes(absl::string_view from);
// `2*from.size()`.
std::string BytesToHexString(absl::string_view from);
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_ESCAPING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal/ya.make b/contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal/ya.make
index 2c62f6421a..38fe96f8ef 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal/ya.make
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal/ya.make
@@ -8,13 +8,13 @@ OWNER(g:cpp-contrib)
LICENSE(Apache-2.0)
-PEERDIR(
+PEERDIR(
contrib/restricted/abseil-cpp/absl/base
- contrib/restricted/abseil-cpp/absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp/absl/base/internal/raw_logging
contrib/restricted/abseil-cpp/absl/base/internal/spinlock_wait
- contrib/restricted/abseil-cpp/absl/base/log_severity
-)
-
+ contrib/restricted/abseil-cpp/absl/base/log_severity
+)
+
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp
)
@@ -23,14 +23,14 @@ NO_COMPILER_WARNINGS()
NO_UTIL()
-CFLAGS(
- -DNOMINMAX
-)
-
+CFLAGS(
+ -DNOMINMAX
+)
+
SRCDIR(contrib/restricted/abseil-cpp/absl/strings/internal)
SRCS(
- escaping.cc
+ escaping.cc
ostringstream.cc
utf8.cc
)
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h b/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
index 61484de0b7..9fb6fca1ad 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
@@ -28,7 +28,7 @@
#include "absl/base/port.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
class Charmap {
@@ -72,7 +72,7 @@ class Charmap {
CharMaskForWord(x, 2), CharMaskForWord(x, 3));
}
- // Containing all the chars in the C-string 's'.
+ // Containing all the chars in the C-string 's'.
// Note that this is expensively recursive because of the C++11 constexpr
// formulation. Use only in constexpr initializers.
static constexpr Charmap FromString(const char* s) {
@@ -150,7 +150,7 @@ constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); }
constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
index ebf8c0791a..ab4de5da19 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
@@ -19,7 +19,7 @@
#include <string>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
namespace {
@@ -158,12 +158,12 @@ const uint32_t* LargePowerOfFiveData(int i) {
int LargePowerOfFiveSize(int i) { return 2 * i; }
} // namespace
-ABSL_DLL const uint32_t kFiveToNth[14] = {
+ABSL_DLL const uint32_t kFiveToNth[14] = {
1, 5, 25, 125, 625, 3125, 15625,
78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
};
-ABSL_DLL const uint32_t kTenToNth[10] = {
+ABSL_DLL const uint32_t kTenToNth[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
};
@@ -208,7 +208,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
++dropped_digits;
}
if (begin < end && *std::prev(end) == '.') {
- // If the string ends in '.', either before or after dropping zeroes, then
+ // If the string ends in '.', either before or after dropping zeroes, then
// drop the decimal point and look for more digits to drop.
dropped_digits = 0;
--end;
@@ -355,5 +355,5 @@ template class BigUnsigned<4>;
template class BigUnsigned<84>;
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h
index 8f702976a8..bb5350f4c8 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h
@@ -20,13 +20,13 @@
#include <iostream>
#include <string>
-#include "absl/base/config.h"
+#include "absl/base/config.h"
#include "absl/strings/ascii.h"
#include "absl/strings/internal/charconv_parse.h"
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// The largest power that 5 that can be raised to, and still fit in a uint32_t.
@@ -34,9 +34,9 @@ constexpr int kMaxSmallPowerOfFive = 13;
// The largest power that 10 that can be raised to, and still fit in a uint32_t.
constexpr int kMaxSmallPowerOfTen = 9;
-ABSL_DLL extern const uint32_t
- kFiveToNth[kMaxSmallPowerOfFive + 1];
-ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
+ABSL_DLL extern const uint32_t
+ kFiveToNth[kMaxSmallPowerOfFive + 1];
+ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
// Large, fixed-width unsigned integer.
//
@@ -66,7 +66,7 @@ class BigUnsigned {
static_cast<uint32_t>(v >> 32)} {}
// Constructs a BigUnsigned from the given string_view containing a decimal
- // value. If the input string is not a decimal integer, constructs a 0
+ // value. If the input string is not a decimal integer, constructs a 0
// instead.
explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
// Check for valid input, returning a 0 otherwise. This is reasonable
@@ -210,7 +210,7 @@ class BigUnsigned {
return words_[index];
}
- // Returns this integer as a decimal string. This is not used in the decimal-
+ // Returns this integer as a decimal string. This is not used in the decimal-
// to-binary conversion; it is intended to aid in testing.
std::string ToString() const;
@@ -417,7 +417,7 @@ extern template class BigUnsigned<4>;
extern template class BigUnsigned<84>;
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
index d29acaf462..31df50d2a5 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
@@ -22,7 +22,7 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace {
// ParseFloat<10> will read the first 19 significant digits of the mantissa.
@@ -302,7 +302,7 @@ bool ParseInfinityOrNan(const char* begin, const char* end,
switch (*begin) {
case 'i':
case 'I': {
- // An infinity string consists of the characters "inf" or "infinity",
+ // An infinity string consists of the characters "inf" or "infinity",
// case insensitive.
if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
return false;
@@ -326,7 +326,7 @@ bool ParseInfinityOrNan(const char* begin, const char* end,
}
out->type = strings_internal::FloatType::kNan;
out->end = begin + 3;
- // NaN is allowed to be followed by a parenthesized string, consisting of
+ // NaN is allowed to be followed by a parenthesized string, consisting of
// only the characters [a-zA-Z0-9_]. Match that if it's present.
begin += 3;
if (begin < end && *begin == '(') {
@@ -500,5 +500,5 @@ template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
chars_format format_flags);
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.h b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.h
index 505998b539..12d828f4c8 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.h
@@ -17,11 +17,11 @@
#include <cstdint>
-#include "absl/base/config.h"
+#include "absl/base/config.h"
#include "absl/strings/charconv.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// Enum indicating whether a parsed float is a number or special value.
@@ -94,6 +94,6 @@ extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
absl::chars_format format_flags);
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
index bfe5564e46..1656482024 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
@@ -1,38 +1,38 @@
// Copyright 2021 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.
-
-#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
-#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
-
-#include <atomic>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <type_traits>
-
+//
+// 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.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
-#include "absl/base/internal/invoke.h"
+#include "absl/base/internal/invoke.h"
#include "absl/base/optimization.h"
-#include "absl/container/internal/compressed_tuple.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
class CordzInfo;
// Default feature enable states for cord ring buffers
@@ -83,48 +83,48 @@ enum Constants {
// Compact class for tracking the reference count and state flags for CordRep
// instances. Data is stored in an atomic int32_t for compactness and speed.
class RefcountAndFlags {
- public:
+ public:
constexpr RefcountAndFlags() : count_{kRefIncrement} {}
struct Immortal {};
explicit constexpr RefcountAndFlags(Immortal) : count_(kImmortalFlag) {}
struct WithCrc {};
explicit constexpr RefcountAndFlags(WithCrc)
: count_(kCrcFlag | kRefIncrement) {}
-
+
// Increments the reference count. Imposes no memory ordering.
inline void Increment() {
count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
}
-
- // Asserts that the current refcount is greater than 0. If the refcount is
+
+ // Asserts that the current refcount is greater than 0. If the refcount is
// greater than 1, decrements the reference count.
- //
- // Returns false if there are no references outstanding; true otherwise.
- // Inserts barriers to ensure that state written before this method returns
- // false will be visible to a thread that just observed this method returning
+ //
+ // Returns false if there are no references outstanding; true otherwise.
+ // Inserts barriers to ensure that state written before this method returns
+ // false will be visible to a thread that just observed this method returning
// false. Always returns false when the immortal bit is set.
- inline bool Decrement() {
+ inline bool Decrement() {
int32_t refcount = count_.load(std::memory_order_acquire) & kRefcountMask;
assert(refcount > 0 || refcount & kImmortalFlag);
return refcount != kRefIncrement &&
(count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) &
kRefcountMask) != kRefIncrement;
- }
-
- // Same as Decrement but expect that refcount is greater than 1.
- inline bool DecrementExpectHighRefcount() {
+ }
+
+ // Same as Decrement but expect that refcount is greater than 1.
+ inline bool DecrementExpectHighRefcount() {
int32_t refcount =
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) &
kRefcountMask;
assert(refcount > 0 || refcount & kImmortalFlag);
return refcount != kRefIncrement;
- }
-
- // Returns the current reference count using acquire semantics.
+ }
+
+ // Returns the current reference count using acquire semantics.
inline int32_t Get() const {
return count_.load(std::memory_order_acquire) >> kNumFlags;
}
-
+
// Returns true if the referenced object carries a CRC value.
bool HasCrc() const {
return (count_.load(std::memory_order_relaxed) & kCrcFlag) != 0;
@@ -155,12 +155,12 @@ class RefcountAndFlags {
return (count_.load(std::memory_order_acquire) & kRefcountMask) ==
kRefIncrement;
}
-
+
bool IsImmortal() const {
return (count_.load(std::memory_order_relaxed) & kImmortalFlag) != 0;
}
- private:
+ private:
// We reserve the bottom bits for flags.
// kImmortalBit indicates that this entity should never be collected; it is
// used for the StringConstant constructor to avoid collecting immutable
@@ -180,30 +180,30 @@ class RefcountAndFlags {
kRefcountMask = ~kCrcFlag,
};
- std::atomic<int32_t> count_;
-};
-
-// The overhead of a vtable is too much for Cord, so we roll our own subclasses
-// using only a single byte to differentiate classes from each other - the "tag"
-// byte. Define the subclasses first so we can provide downcasting helper
-// functions in the base class.
-
-struct CordRepConcat;
+ std::atomic<int32_t> count_;
+};
+
+// The overhead of a vtable is too much for Cord, so we roll our own subclasses
+// using only a single byte to differentiate classes from each other - the "tag"
+// byte. Define the subclasses first so we can provide downcasting helper
+// functions in the base class.
+
+struct CordRepConcat;
struct CordRepExternal;
struct CordRepFlat;
-struct CordRepSubstring;
+struct CordRepSubstring;
class CordRepRing;
class CordRepBtree;
-
-// Various representations that we allow
-enum CordRepKind {
+
+// Various representations that we allow
+enum CordRepKind {
CONCAT = 0,
SUBSTRING = 1,
BTREE = 2,
RING = 3,
EXTERNAL = 4,
-
- // We have different tags for different sized flat arrays,
+
+ // We have different tags for different sized flat arrays,
// starting with FLAT, and limited to MAX_FLAT_TAG. The 225 value is based on
// the current 'size to tag' encoding of 8 / 32 bytes. If a new tag is needed
// in the future, then 'FLAT' and 'MAX_FLAT_TAG' should be adjusted as well
@@ -211,8 +211,8 @@ enum CordRepKind {
// allocation size. (32 bytes as of now).
FLAT = 5,
MAX_FLAT_TAG = 225
-};
-
+};
+
// There are various locations where we want to check if some rep is a 'plain'
// data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we
// can perform this check in a single branch as 'tag >= EXTERNAL'
@@ -224,19 +224,19 @@ static_assert(RING == BTREE + 1, "BTREE and RING not consecutive");
static_assert(EXTERNAL == RING + 1, "BTREE and EXTERNAL not consecutive");
static_assert(FLAT == EXTERNAL + 1, "EXTERNAL and FLAT not consecutive");
-struct CordRep {
+struct CordRep {
CordRep() = default;
constexpr CordRep(RefcountAndFlags::Immortal immortal, size_t l)
: length(l), refcount(immortal), tag(EXTERNAL), storage{} {}
- // The following three fields have to be less than 32 bytes since
- // that is the smallest supported flat node size.
- size_t length;
+ // The following three fields have to be less than 32 bytes since
+ // that is the smallest supported flat node size.
+ size_t length;
RefcountAndFlags refcount;
- // If tag < FLAT, it represents CordRepKind and indicates the type of node.
- // Otherwise, the node type is CordRepFlat and the tag is the encoded size.
- uint8_t tag;
-
+ // If tag < FLAT, it represents CordRepKind and indicates the type of node.
+ // Otherwise, the node type is CordRepFlat and the tag is the encoded size.
+ uint8_t tag;
+
// `storage` provides two main purposes:
// - the starting point for FlatCordRep.Data() [flexible-array-member]
// - 3 bytes of additional storage for use by derived classes.
@@ -257,12 +257,12 @@ struct CordRep {
inline CordRepRing* ring();
inline const CordRepRing* ring() const;
- inline CordRepConcat* concat();
- inline const CordRepConcat* concat() const;
- inline CordRepSubstring* substring();
- inline const CordRepSubstring* substring() const;
- inline CordRepExternal* external();
- inline const CordRepExternal* external() const;
+ inline CordRepConcat* concat();
+ inline const CordRepConcat* concat() const;
+ inline CordRepSubstring* substring();
+ inline const CordRepSubstring* substring() const;
+ inline CordRepExternal* external();
+ inline const CordRepExternal* external() const;
inline CordRepFlat* flat();
inline const CordRepFlat* flat() const;
inline CordRepBtree* btree();
@@ -281,82 +281,82 @@ struct CordRep {
// Decrements the reference count of `rep`. Destroys rep if count reaches
// zero. Requires `rep` to be a non-null pointer value.
static inline void Unref(CordRep* rep);
-};
-
-struct CordRepConcat : public CordRep {
- CordRep* left;
- CordRep* right;
-
+};
+
+struct CordRepConcat : public CordRep {
+ CordRep* left;
+ CordRep* right;
+
uint8_t depth() const { return storage[0]; }
void set_depth(uint8_t depth) { storage[0] = depth; }
-};
-
-struct CordRepSubstring : public CordRep {
- size_t start; // Starting offset of substring in child
- CordRep* child;
-};
-
-// Type for function pointer that will invoke the releaser function and also
-// delete the `CordRepExternalImpl` corresponding to the passed in
-// `CordRepExternal`.
-using ExternalReleaserInvoker = void (*)(CordRepExternal*);
-
-// External CordReps are allocated together with a type erased releaser. The
-// releaser is stored in the memory directly following the CordRepExternal.
-struct CordRepExternal : public CordRep {
+};
+
+struct CordRepSubstring : public CordRep {
+ size_t start; // Starting offset of substring in child
+ CordRep* child;
+};
+
+// Type for function pointer that will invoke the releaser function and also
+// delete the `CordRepExternalImpl` corresponding to the passed in
+// `CordRepExternal`.
+using ExternalReleaserInvoker = void (*)(CordRepExternal*);
+
+// External CordReps are allocated together with a type erased releaser. The
+// releaser is stored in the memory directly following the CordRepExternal.
+struct CordRepExternal : public CordRep {
CordRepExternal() = default;
explicit constexpr CordRepExternal(absl::string_view str)
: CordRep(RefcountAndFlags::Immortal{}, str.size()),
base(str.data()),
releaser_invoker(nullptr) {}
- const char* base;
- // Pointer to function that knows how to call and destroy the releaser.
- ExternalReleaserInvoker releaser_invoker;
+ const char* base;
+ // Pointer to function that knows how to call and destroy the releaser.
+ ExternalReleaserInvoker releaser_invoker;
// Deletes (releases) the external rep.
// Requires rep != nullptr and rep->IsExternal()
static void Delete(CordRep* rep);
-};
-
-struct Rank1 {};
-struct Rank0 : Rank1 {};
-
-template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
- Releaser, absl::string_view>>
-void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
- ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
-}
-
-template <typename Releaser,
- typename = ::absl::base_internal::invoke_result_t<Releaser>>
-void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
- ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
-}
-
-// We use CompressedTuple so that we can benefit from EBCO.
-template <typename Releaser>
-struct CordRepExternalImpl
- : public CordRepExternal,
- public ::absl::container_internal::CompressedTuple<Releaser> {
- // The extra int arg is so that we can avoid interfering with copy/move
- // constructors while still benefitting from perfect forwarding.
- template <typename T>
- CordRepExternalImpl(T&& releaser, int)
- : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
- this->releaser_invoker = &Release;
- }
-
- ~CordRepExternalImpl() {
- InvokeReleaser(Rank0{}, std::move(this->template get<0>()),
- absl::string_view(base, length));
- }
-
- static void Release(CordRepExternal* rep) {
- delete static_cast<CordRepExternalImpl*>(rep);
- }
-};
-
+};
+
+struct Rank1 {};
+struct Rank0 : Rank1 {};
+
+template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
+ Releaser, absl::string_view>>
+void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+}
+
+template <typename Releaser,
+ typename = ::absl::base_internal::invoke_result_t<Releaser>>
+void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
+}
+
+// We use CompressedTuple so that we can benefit from EBCO.
+template <typename Releaser>
+struct CordRepExternalImpl
+ : public CordRepExternal,
+ public ::absl::container_internal::CompressedTuple<Releaser> {
+ // The extra int arg is so that we can avoid interfering with copy/move
+ // constructors while still benefitting from perfect forwarding.
+ template <typename T>
+ CordRepExternalImpl(T&& releaser, int)
+ : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
+ this->releaser_invoker = &Release;
+ }
+
+ ~CordRepExternalImpl() {
+ InvokeReleaser(Rank0{}, std::move(this->template get<0>()),
+ absl::string_view(base, length));
+ }
+
+ static void Release(CordRepExternal* rep) {
+ delete static_cast<CordRepExternalImpl*>(rep);
+ }
+};
+
inline void CordRepExternal::Delete(CordRep* rep) {
assert(rep != nullptr && rep->IsExternal());
auto* rep_external = static_cast<CordRepExternal*>(rep);
@@ -372,10 +372,10 @@ struct ConstInitExternalStorage {
template <typename Str>
CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
-enum {
- kMaxInline = 15,
-};
-
+enum {
+ kMaxInline = 15,
+};
+
constexpr char GetOrNull(absl::string_view data, size_t pos) {
return pos < data.size() ? data[pos] : '\0';
}
@@ -564,10 +564,10 @@ class InlineData {
char as_chars_[kMaxInline + 1];
AsTree as_tree_;
};
-};
-
-static_assert(sizeof(InlineData) == kMaxInline + 1, "");
-
+};
+
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+
inline CordRepConcat* CordRep::concat() {
assert(IsConcat());
return static_cast<CordRepConcat*>(this);
@@ -613,8 +613,8 @@ inline void CordRep::Unref(CordRep* rep) {
}
}
-} // namespace cord_internal
+} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions/ya.make b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions/ya.make
index 6dc8a23cc5..69f582d096 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions/ya.make
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions/ya.make
@@ -22,10 +22,10 @@ NO_COMPILER_WARNINGS()
NO_UTIL()
-CFLAGS(
- -DNOMINMAX
-)
-
+CFLAGS(
+ -DNOMINMAX
+)
+
SRCDIR(contrib/restricted/abseil-cpp/absl/strings/internal)
SRCS(
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
index c5271286ad..73de85e483 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
@@ -1,180 +1,180 @@
-// Copyright 2020 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/internal/escaping.h"
-
-#include "absl/base/internal/endian.h"
-#include "absl/base/internal/raw_logging.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-const char kBase64Chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
- // Base64 encodes three bytes of input at a time. If the input is not
- // divisible by three, we pad as appropriate.
- //
- // (from https://tools.ietf.org/html/rfc3548)
- // Special processing is performed if fewer than 24 bits are available
- // at the end of the data being encoded. A full encoding quantum is
- // always completed at the end of a quantity. When fewer than 24 input
- // bits are available in an input group, zero bits are added (on the
- // right) to form an integral number of 6-bit groups. Padding at the
- // end of the data is performed using the '=' character. Since all base
- // 64 input is an integral number of octets, only the following cases
- // can arise:
-
- // Base64 encodes each three bytes of input into four bytes of output.
- size_t len = (input_len / 3) * 4;
-
- if (input_len % 3 == 0) {
- // (from https://tools.ietf.org/html/rfc3548)
- // (1) the final quantum of encoding input is an integral multiple of 24
- // bits; here, the final unit of encoded output will be an integral
- // multiple of 4 characters with no "=" padding,
- } else if (input_len % 3 == 1) {
- // (from https://tools.ietf.org/html/rfc3548)
- // (2) the final quantum of encoding input is exactly 8 bits; here, the
- // final unit of encoded output will be two characters followed by two
- // "=" padding characters, or
- len += 2;
- if (do_padding) {
- len += 2;
- }
- } else { // (input_len % 3 == 2)
- // (from https://tools.ietf.org/html/rfc3548)
- // (3) the final quantum of encoding input is exactly 16 bits; here, the
- // final unit of encoded output will be three characters followed by one
- // "=" padding character.
- len += 3;
- if (do_padding) {
- len += 1;
- }
- }
-
- assert(len >= input_len); // make sure we didn't overflow
- return len;
-}
-
-size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
- size_t szdest, const char* base64,
- bool do_padding) {
- static const char kPad64 = '=';
-
- if (szsrc * 4 > szdest * 3) return 0;
-
- char* cur_dest = dest;
- const unsigned char* cur_src = src;
-
- char* const limit_dest = dest + szdest;
- const unsigned char* const limit_src = src + szsrc;
-
- // Three bytes of data encodes to four characters of cyphertext.
- // So we can pump through three-byte chunks atomically.
- if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3.
- while (cur_src < limit_src - 3) { // While we have >= 32 bits.
- uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
-
- cur_dest[0] = base64[in >> 18];
- in &= 0x3FFFF;
- cur_dest[1] = base64[in >> 12];
- in &= 0xFFF;
- cur_dest[2] = base64[in >> 6];
- in &= 0x3F;
- cur_dest[3] = base64[in];
-
- cur_dest += 4;
- cur_src += 3;
- }
- }
- // To save time, we didn't update szdest or szsrc in the loop. So do it now.
- szdest = limit_dest - cur_dest;
- szsrc = limit_src - cur_src;
-
- /* now deal with the tail (<=3 bytes) */
- switch (szsrc) {
- case 0:
- // Nothing left; nothing more to do.
- break;
- case 1: {
- // One byte left: this encodes to two characters, and (optionally)
- // two pad characters to round out the four-character cypherblock.
- if (szdest < 2) return 0;
- uint32_t in = cur_src[0];
- cur_dest[0] = base64[in >> 2];
- in &= 0x3;
- cur_dest[1] = base64[in << 4];
- cur_dest += 2;
- szdest -= 2;
- if (do_padding) {
- if (szdest < 2) return 0;
- cur_dest[0] = kPad64;
- cur_dest[1] = kPad64;
- cur_dest += 2;
- szdest -= 2;
- }
- break;
- }
- case 2: {
- // Two bytes left: this encodes to three characters, and (optionally)
- // one pad character to round out the four-character cypherblock.
- if (szdest < 3) return 0;
- uint32_t in = absl::big_endian::Load16(cur_src);
- cur_dest[0] = base64[in >> 10];
- in &= 0x3FF;
- cur_dest[1] = base64[in >> 4];
- in &= 0x00F;
- cur_dest[2] = base64[in << 2];
- cur_dest += 3;
- szdest -= 3;
- if (do_padding) {
- if (szdest < 1) return 0;
- cur_dest[0] = kPad64;
- cur_dest += 1;
- szdest -= 1;
- }
- break;
- }
- case 3: {
- // Three bytes left: same as in the big loop above. We can't do this in
- // the loop because the loop above always reads 4 bytes, and the fourth
- // byte is past the end of the input.
- if (szdest < 4) return 0;
- uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
- cur_dest[0] = base64[in >> 18];
- in &= 0x3FFFF;
- cur_dest[1] = base64[in >> 12];
- in &= 0xFFF;
- cur_dest[2] = base64[in >> 6];
- in &= 0x3F;
- cur_dest[3] = base64[in];
- cur_dest += 4;
- szdest -= 4;
- break;
- }
- default:
- // Should not be reached: blocks of 4 bytes are handled
- // in the while loop before this switch statement.
- ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
- break;
- }
- return (cur_dest - dest);
-}
-
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace absl
+// Copyright 2020 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/internal/escaping.h"
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+const char kBase64Chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
+ // Base64 encodes three bytes of input at a time. If the input is not
+ // divisible by three, we pad as appropriate.
+ //
+ // (from https://tools.ietf.org/html/rfc3548)
+ // Special processing is performed if fewer than 24 bits are available
+ // at the end of the data being encoded. A full encoding quantum is
+ // always completed at the end of a quantity. When fewer than 24 input
+ // bits are available in an input group, zero bits are added (on the
+ // right) to form an integral number of 6-bit groups. Padding at the
+ // end of the data is performed using the '=' character. Since all base
+ // 64 input is an integral number of octets, only the following cases
+ // can arise:
+
+ // Base64 encodes each three bytes of input into four bytes of output.
+ size_t len = (input_len / 3) * 4;
+
+ if (input_len % 3 == 0) {
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (1) the final quantum of encoding input is an integral multiple of 24
+ // bits; here, the final unit of encoded output will be an integral
+ // multiple of 4 characters with no "=" padding,
+ } else if (input_len % 3 == 1) {
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (2) the final quantum of encoding input is exactly 8 bits; here, the
+ // final unit of encoded output will be two characters followed by two
+ // "=" padding characters, or
+ len += 2;
+ if (do_padding) {
+ len += 2;
+ }
+ } else { // (input_len % 3 == 2)
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (3) the final quantum of encoding input is exactly 16 bits; here, the
+ // final unit of encoded output will be three characters followed by one
+ // "=" padding character.
+ len += 3;
+ if (do_padding) {
+ len += 1;
+ }
+ }
+
+ assert(len >= input_len); // make sure we didn't overflow
+ return len;
+}
+
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+ size_t szdest, const char* base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc * 4 > szdest * 3) return 0;
+
+ char* cur_dest = dest;
+ const unsigned char* cur_src = src;
+
+ char* const limit_dest = dest + szdest;
+ const unsigned char* const limit_src = src + szsrc;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3.
+ while (cur_src < limit_src - 3) { // While we have >= 32 bits.
+ uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
+
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+
+ cur_dest += 4;
+ cur_src += 3;
+ }
+ }
+ // To save time, we didn't update szdest or szsrc in the loop. So do it now.
+ szdest = limit_dest - cur_dest;
+ szsrc = limit_src - cur_src;
+
+ /* now deal with the tail (<=3 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1: {
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if (szdest < 2) return 0;
+ uint32_t in = cur_src[0];
+ cur_dest[0] = base64[in >> 2];
+ in &= 0x3;
+ cur_dest[1] = base64[in << 4];
+ cur_dest += 2;
+ szdest -= 2;
+ if (do_padding) {
+ if (szdest < 2) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ szdest -= 2;
+ }
+ break;
+ }
+ case 2: {
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if (szdest < 3) return 0;
+ uint32_t in = absl::big_endian::Load16(cur_src);
+ cur_dest[0] = base64[in >> 10];
+ in &= 0x3FF;
+ cur_dest[1] = base64[in >> 4];
+ in &= 0x00F;
+ cur_dest[2] = base64[in << 2];
+ cur_dest += 3;
+ szdest -= 3;
+ if (do_padding) {
+ if (szdest < 1) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ szdest -= 1;
+ }
+ break;
+ }
+ case 3: {
+ // Three bytes left: same as in the big loop above. We can't do this in
+ // the loop because the loop above always reads 4 bytes, and the fourth
+ // byte is past the end of the input.
+ if (szdest < 4) return 0;
+ uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+ cur_dest += 4;
+ szdest -= 4;
+ break;
+ }
+ default:
+ // Should not be reached: blocks of 4 bytes are handled
+ // in the while loop before this switch statement.
+ ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
index 6a9ce602d9..dc20940e75 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
@@ -1,58 +1,58 @@
-// Copyright 2020 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.
-
-#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_H_
-#define ABSL_STRINGS_INTERNAL_ESCAPING_H_
-
-#include <cassert>
-
-#include "absl/strings/internal/resize_uninitialized.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-ABSL_CONST_INIT extern const char kBase64Chars[];
-
-// Calculates how long a string will be when it is base64 encoded given its
-// length and whether or not the result should be padded.
-size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);
-
-// Base64-encodes `src` using the alphabet provided in `base64` and writes the
-// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
-// until its length is a multiple of 3. Returns the length of `dest`.
-size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
- size_t szdest, const char* base64, bool do_padding);
-
-// Base64-encodes `src` using the alphabet provided in `base64` and writes the
-// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
-// until its length is a multiple of 3.
-template <typename String>
-void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
- bool do_padding, const char* base64_chars) {
- const size_t calc_escaped_size =
- CalculateBase64EscapedLenInternal(szsrc, do_padding);
- STLStringResizeUninitialized(dest, calc_escaped_size);
-
- const size_t escaped_len = Base64EscapeInternal(
- src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
- assert(calc_escaped_size == escaped_len);
- dest->erase(escaped_len);
-}
-
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_ESCAPING_H_
+// Copyright 2020 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.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_H_
+
+#include <cassert>
+
+#include "absl/strings/internal/resize_uninitialized.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+ABSL_CONST_INIT extern const char kBase64Chars[];
+
+// Calculates how long a string will be when it is base64 encoded given its
+// length and whether or not the result should be padded.
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3. Returns the length of `dest`.
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+ size_t szdest, const char* base64, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3.
+template <typename String>
+void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
+ bool do_padding, const char* base64_chars) {
+ const size_t calc_escaped_size =
+ CalculateBase64EscapedLenInternal(szsrc, do_padding);
+ STLStringResizeUninitialized(dest, calc_escaped_size);
+
+ const size_t escaped_len = Base64EscapeInternal(
+ src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
+ assert(calc_escaped_size == escaped_len);
+ dest->erase(escaped_len);
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_ESCAPING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h
index 7b18017a08..0e6fc75de7 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h
@@ -22,7 +22,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
struct base64_testcase {
@@ -127,7 +127,7 @@ inline const std::array<base64_testcase, 5>& base64_strings() {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
index 2519c6881e..22a33cc584 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
@@ -17,7 +17,7 @@
#include <cstdlib>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
int memcasecmp(const char* s1, const char* s2, size_t len) {
@@ -108,5 +108,5 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.h b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.h
index 9ad0535808..f0217db9f1 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.h
@@ -69,7 +69,7 @@
#include "absl/strings/ascii.h" // for absl::ascii_tolower
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
inline char* memcat(char* dest, size_t destlen, const char* src,
@@ -142,7 +142,7 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
size_t neelen);
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h b/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h
index eaa88a8897..709cc6b209 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h
@@ -23,10 +23,10 @@
#include <limits>
#include <string>
-#include "absl/base/config.h"
-
+#include "absl/base/config.h"
+
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
template <typename IntType>
@@ -170,7 +170,7 @@ inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
{"0x1234", true, 16, 0x1234},
- // Base-10 string version.
+ // Base-10 string version.
{"1234", true, 0, 1234},
{nullptr, false, 0, 0},
}};
@@ -178,7 +178,7 @@ inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
index 05324c780c..290b3b1776 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -15,7 +15,7 @@
#include "absl/strings/internal/ostringstream.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
OStringStream::Buf::int_type OStringStream::overflow(int c) {
@@ -32,5 +32,5 @@ std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
index d25d60473f..a219a0be4c 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
@@ -23,7 +23,7 @@
#include "absl/base/port.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// The same as std::ostringstream but appends to a user-specified std::string,
@@ -83,7 +83,7 @@ class OStringStream : private std::basic_streambuf<char>, public std::ostream {
};
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h b/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h
index c37c2c3ffe..5e124e4cac 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h
@@ -22,10 +22,10 @@
#include <vector>
-#include "absl/base/config.h"
-
+#include "absl/base/config.h"
+
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// Computes the precise value of 10^exp. (I.e. the nearest representable
@@ -34,7 +34,7 @@ namespace strings_internal {
double Pow10(int exp);
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/resize_uninitialized.h b/contrib/restricted/abseil-cpp/absl/strings/internal/resize_uninitialized.h
index 49859dcc7d..023a61c69b 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/resize_uninitialized.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/resize_uninitialized.h
@@ -26,7 +26,7 @@
#include "absl/meta/type_traits.h" // for void_t
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// In this type trait, we look for a __resize_default_init member function, and
@@ -113,7 +113,7 @@ void STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/stl_type_traits.h b/contrib/restricted/abseil-cpp/absl/strings/internal/stl_type_traits.h
index 6035ca45cb..20b0bee39e 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/stl_type_traits.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/stl_type_traits.h
@@ -40,7 +40,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
template <typename C, template <typename...> class T>
@@ -243,6 +243,6 @@ struct IsStrictlyBaseOfAndConvertibleToSTLContainer
IsConvertibleToSTLContainer<C>> {};
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
index e28a29b171..bf57d5fdc7 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -1,18 +1,18 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
+//
// POSIX spec:
// http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
//
@@ -26,10 +26,10 @@
#include "absl/base/port.h"
#include "absl/strings/internal/str_format/float_conversion.h"
-#include "absl/strings/numbers.h"
+#include "absl/strings/numbers.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -61,179 +61,179 @@ struct IsSigned<absl::int128> : std::true_type {};
template <>
struct IsSigned<absl::uint128> : std::false_type {};
-// Integral digit printer.
-// Call one of the PrintAs* routines after construction once.
-// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
-class IntDigits {
+// Integral digit printer.
+// Call one of the PrintAs* routines after construction once.
+// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
+class IntDigits {
public:
- // Print the unsigned integer as octal.
- // Supports unsigned integral types and uint128.
+ // Print the unsigned integer as octal.
+ // Supports unsigned integral types and uint128.
template <typename T>
- void PrintAsOct(T v) {
- static_assert(!IsSigned<T>::value, "");
- char *p = storage_ + sizeof(storage_);
- do {
- *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
- v >>= 3;
- } while (v);
- start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
- }
-
- // Print the signed or unsigned integer as decimal.
- // Supports all integral types.
- template <typename T>
- void PrintAsDec(T v) {
- static_assert(std::is_integral<T>::value, "");
- start_ = storage_;
- size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
- }
-
- void PrintAsDec(int128 v) {
- auto u = static_cast<uint128>(v);
- bool add_neg = false;
- if (v < 0) {
- add_neg = true;
- u = uint128{} - u;
+ void PrintAsOct(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+ do {
+ *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
+ v >>= 3;
+ } while (v);
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
+ }
+
+ // Print the signed or unsigned integer as decimal.
+ // Supports all integral types.
+ template <typename T>
+ void PrintAsDec(T v) {
+ static_assert(std::is_integral<T>::value, "");
+ start_ = storage_;
+ size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
+ }
+
+ void PrintAsDec(int128 v) {
+ auto u = static_cast<uint128>(v);
+ bool add_neg = false;
+ if (v < 0) {
+ add_neg = true;
+ u = uint128{} - u;
}
- PrintAsDec(u, add_neg);
+ PrintAsDec(u, add_neg);
}
- void PrintAsDec(uint128 v, bool add_neg = false) {
- // This function can be sped up if needed. We can call FastIntToBuffer
- // twice, or fix FastIntToBuffer to support uint128.
- char *p = storage_ + sizeof(storage_);
- do {
- p -= 2;
- numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
- v /= 100;
- } while (v);
- if (p[0] == '0') {
- // We printed one too many hexits.
- ++p;
- }
- if (add_neg) {
- *--p = '-';
- }
- size_ = storage_ + sizeof(storage_) - p;
- start_ = p;
+ void PrintAsDec(uint128 v, bool add_neg = false) {
+ // This function can be sped up if needed. We can call FastIntToBuffer
+ // twice, or fix FastIntToBuffer to support uint128.
+ char *p = storage_ + sizeof(storage_);
+ do {
+ p -= 2;
+ numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
+ v /= 100;
+ } while (v);
+ if (p[0] == '0') {
+ // We printed one too many hexits.
+ ++p;
+ }
+ if (add_neg) {
+ *--p = '-';
+ }
+ size_ = storage_ + sizeof(storage_) - p;
+ start_ = p;
}
- // Print the unsigned integer as hex using lowercase.
- // Supports unsigned integral types and uint128.
+ // Print the unsigned integer as hex using lowercase.
+ // Supports unsigned integral types and uint128.
template <typename T>
- void PrintAsHexLower(T v) {
- static_assert(!IsSigned<T>::value, "");
- char *p = storage_ + sizeof(storage_);
-
- do {
- p -= 2;
- constexpr const char* table = numbers_internal::kHexTable;
- std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
- if (sizeof(T) == 1) break;
- v >>= 8;
- } while (v);
- if (p[0] == '0') {
- // We printed one too many digits.
- ++p;
+ void PrintAsHexLower(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+
+ do {
+ p -= 2;
+ constexpr const char* table = numbers_internal::kHexTable;
+ std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
+ if (sizeof(T) == 1) break;
+ v >>= 8;
+ } while (v);
+ if (p[0] == '0') {
+ // We printed one too many digits.
+ ++p;
}
- start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
- }
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
+ }
- // Print the unsigned integer as hex using uppercase.
- // Supports unsigned integral types and uint128.
+ // Print the unsigned integer as hex using uppercase.
+ // Supports unsigned integral types and uint128.
template <typename T>
- void PrintAsHexUpper(T v) {
- static_assert(!IsSigned<T>::value, "");
- char *p = storage_ + sizeof(storage_);
-
- // kHexTable is only lowercase, so do it manually for uppercase.
- do {
- *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
- v >>= 4;
- } while (v);
- start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ void PrintAsHexUpper(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+
+ // kHexTable is only lowercase, so do it manually for uppercase.
+ do {
+ *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
+ v >>= 4;
+ } while (v);
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
}
- // The printed value including the '-' sign if available.
- // For inputs of value `0`, this will return "0"
- string_view with_neg_and_zero() const { return {start_, size_}; }
-
- // The printed value not including the '-' sign.
- // For inputs of value `0`, this will return "".
- string_view without_neg_or_zero() const {
- static_assert('-' < '0', "The check below verifies both.");
- size_t advance = start_[0] <= '0' ? 1 : 0;
- return {start_ + advance, size_ - advance};
+ // The printed value including the '-' sign if available.
+ // For inputs of value `0`, this will return "0"
+ string_view with_neg_and_zero() const { return {start_, size_}; }
+
+ // The printed value not including the '-' sign.
+ // For inputs of value `0`, this will return "".
+ string_view without_neg_or_zero() const {
+ static_assert('-' < '0', "The check below verifies both.");
+ size_t advance = start_[0] <= '0' ? 1 : 0;
+ return {start_ + advance, size_ - advance};
}
- bool is_negative() const { return start_[0] == '-'; }
+ bool is_negative() const { return start_[0] == '-'; }
- private:
- const char *start_;
- size_t size_;
- // Max size: 128 bit value as octal -> 43 digits, plus sign char
- char storage_[128 / 3 + 1 + 1];
+ private:
+ const char *start_;
+ size_t size_;
+ // Max size: 128 bit value as octal -> 43 digits, plus sign char
+ char storage_[128 / 3 + 1 + 1];
};
// Note: 'o' conversions do not have a base indicator, it's just that
// the '#' flag is specified to modify the precision for 'o' conversions.
-string_view BaseIndicator(const IntDigits &as_digits,
- const FormatConversionSpecImpl conv) {
- // always show 0x for %p.
- bool alt = conv.has_alt_flag() ||
- conv.conversion_char() == FormatConversionCharInternal::p;
- bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
- conv.conversion_char() == FormatConversionCharInternal::X ||
- conv.conversion_char() == FormatConversionCharInternal::p);
+string_view BaseIndicator(const IntDigits &as_digits,
+ const FormatConversionSpecImpl conv) {
+ // always show 0x for %p.
+ bool alt = conv.has_alt_flag() ||
+ conv.conversion_char() == FormatConversionCharInternal::p;
+ bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
+ conv.conversion_char() == FormatConversionCharInternal::X ||
+ conv.conversion_char() == FormatConversionCharInternal::p);
// From the POSIX description of '#' flag:
// "For x or X conversion specifiers, a non-zero result shall have
// 0x (or 0X) prefixed to it."
- if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
- return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
- : "0x";
+ if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
+ return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
+ : "0x";
}
return {};
}
-string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
- if (conv.conversion_char() == FormatConversionCharInternal::d ||
- conv.conversion_char() == FormatConversionCharInternal::i) {
+string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
+ if (conv.conversion_char() == FormatConversionCharInternal::d ||
+ conv.conversion_char() == FormatConversionCharInternal::i) {
if (neg) return "-";
- if (conv.has_show_pos_flag()) return "+";
- if (conv.has_sign_col_flag()) return " ";
+ if (conv.has_show_pos_flag()) return "+";
+ if (conv.has_sign_col_flag()) return " ";
}
return {};
}
-bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
+bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
ReducePadding(1, &fill);
- if (!conv.has_left_flag()) sink->Append(fill, ' ');
+ if (!conv.has_left_flag()) sink->Append(fill, ' ');
sink->Append(1, v);
- if (conv.has_left_flag()) sink->Append(fill, ' ');
+ if (conv.has_left_flag()) sink->Append(fill, ' ');
return true;
}
-bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
// Print as a sequence of Substrings:
// [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
- string_view formatted = as_digits.without_neg_or_zero();
+ string_view formatted = as_digits.without_neg_or_zero();
ReducePadding(formatted, &fill);
- string_view sign = SignColumn(as_digits.is_negative(), conv);
+ string_view sign = SignColumn(as_digits.is_negative(), conv);
ReducePadding(sign, &fill);
- string_view base_indicator = BaseIndicator(as_digits, conv);
+ string_view base_indicator = BaseIndicator(as_digits, conv);
ReducePadding(base_indicator, &fill);
int precision = conv.precision();
@@ -241,8 +241,8 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
if (!precision_specified)
precision = 1;
- if (conv.has_alt_flag() &&
- conv.conversion_char() == FormatConversionCharInternal::o) {
+ if (conv.has_alt_flag() &&
+ conv.conversion_char() == FormatConversionCharInternal::o) {
// From POSIX description of the '#' (alt) flag:
// "For o conversion, it increases the precision (if necessary) to
// force the first digit of the result to be zero."
@@ -255,13 +255,13 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
size_t num_zeroes = Excess(formatted.size(), precision);
ReducePadding(num_zeroes, &fill);
- size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
- size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
+ size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
+ size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
// From POSIX description of the '0' (zero) flag:
// "For d, i, o, u, x, and X conversion specifiers, if a precision
// is specified, the '0' flag is ignored."
- if (!precision_specified && conv.has_zero_flag()) {
+ if (!precision_specified && conv.has_zero_flag()) {
num_zeroes += num_left_spaces;
num_left_spaces = 0;
}
@@ -276,97 +276,97 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
}
template <typename T>
-bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- using U = typename MakeUnsigned<T>::type;
- IntDigits as_digits;
-
- // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
- // it to complain about a switch/case type mismatch, even though both are
- // FormatConverionChar. Likely this is because at this point
- // FormatConversionChar is declared, but not defined.
- switch (static_cast<uint8_t>(conv.conversion_char())) {
- case static_cast<uint8_t>(FormatConversionCharInternal::c):
- return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
-
- case static_cast<uint8_t>(FormatConversionCharInternal::o):
- as_digits.PrintAsOct(static_cast<U>(v));
- break;
-
- case static_cast<uint8_t>(FormatConversionCharInternal::x):
- as_digits.PrintAsHexLower(static_cast<U>(v));
- break;
- case static_cast<uint8_t>(FormatConversionCharInternal::X):
- as_digits.PrintAsHexUpper(static_cast<U>(v));
- break;
-
- case static_cast<uint8_t>(FormatConversionCharInternal::u):
- as_digits.PrintAsDec(static_cast<U>(v));
- break;
-
- case static_cast<uint8_t>(FormatConversionCharInternal::d):
- case static_cast<uint8_t>(FormatConversionCharInternal::i):
- as_digits.PrintAsDec(v);
- break;
-
- case static_cast<uint8_t>(FormatConversionCharInternal::a):
- case static_cast<uint8_t>(FormatConversionCharInternal::e):
- case static_cast<uint8_t>(FormatConversionCharInternal::f):
- case static_cast<uint8_t>(FormatConversionCharInternal::g):
- case static_cast<uint8_t>(FormatConversionCharInternal::A):
- case static_cast<uint8_t>(FormatConversionCharInternal::E):
- case static_cast<uint8_t>(FormatConversionCharInternal::F):
- case static_cast<uint8_t>(FormatConversionCharInternal::G):
- return ConvertFloatImpl(static_cast<double>(v), conv, sink);
-
- default:
- ABSL_INTERNAL_ASSUME(false);
+bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ using U = typename MakeUnsigned<T>::type;
+ IntDigits as_digits;
+
+ // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
+ // it to complain about a switch/case type mismatch, even though both are
+ // FormatConverionChar. Likely this is because at this point
+ // FormatConversionChar is declared, but not defined.
+ switch (static_cast<uint8_t>(conv.conversion_char())) {
+ case static_cast<uint8_t>(FormatConversionCharInternal::c):
+ return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::o):
+ as_digits.PrintAsOct(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::x):
+ as_digits.PrintAsHexLower(static_cast<U>(v));
+ break;
+ case static_cast<uint8_t>(FormatConversionCharInternal::X):
+ as_digits.PrintAsHexUpper(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::u):
+ as_digits.PrintAsDec(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::d):
+ case static_cast<uint8_t>(FormatConversionCharInternal::i):
+ as_digits.PrintAsDec(v);
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::a):
+ case static_cast<uint8_t>(FormatConversionCharInternal::e):
+ case static_cast<uint8_t>(FormatConversionCharInternal::f):
+ case static_cast<uint8_t>(FormatConversionCharInternal::g):
+ case static_cast<uint8_t>(FormatConversionCharInternal::A):
+ case static_cast<uint8_t>(FormatConversionCharInternal::E):
+ case static_cast<uint8_t>(FormatConversionCharInternal::F):
+ case static_cast<uint8_t>(FormatConversionCharInternal::G):
+ return ConvertFloatImpl(static_cast<double>(v), conv, sink);
+
+ default:
+ ABSL_INTERNAL_ASSUME(false);
}
- if (conv.is_basic()) {
- sink->Append(as_digits.with_neg_and_zero());
- return true;
+ if (conv.is_basic()) {
+ sink->Append(as_digits.with_neg_and_zero());
+ return true;
}
- return ConvertIntImplInnerSlow(as_digits, conv, sink);
+ return ConvertIntImplInnerSlow(as_digits, conv, sink);
}
template <typename T>
-bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return FormatConversionCharIsFloat(conv.conversion_char()) &&
- ConvertFloatImpl(v, conv, sink);
+bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ return FormatConversionCharIsFloat(conv.conversion_char()) &&
+ ConvertFloatImpl(v, conv, sink);
}
-inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
+inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
- if (conv.is_basic()) {
+ if (conv.is_basic()) {
sink->Append(v);
return true;
}
return sink->PutPaddedString(v, conv.width(), conv.precision(),
- conv.has_left_flag());
+ conv.has_left_flag());
}
} // namespace
// ==================== Strings ====================
-StringConvertResult FormatConvertImpl(const std::string &v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(const std::string &v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-StringConvertResult FormatConvertImpl(string_view v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(string_view v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
-FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- if (conv.conversion_char() == FormatConversionCharInternal::p)
+ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ if (conv.conversion_char() == FormatConversionCharInternal::p)
return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
size_t len;
if (v == nullptr) {
@@ -374,106 +374,106 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
} else if (conv.precision() < 0) {
len = std::strlen(v);
} else {
- // If precision is set, we look for the NUL-terminator on the valid range.
+ // If precision is set, we look for the NUL-terminator on the valid range.
len = std::find(v, v + conv.precision(), '\0') - v;
}
return {ConvertStringArg(string_view(v, len), conv, sink)};
}
// ==================== Raw pointers ====================
-ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
- VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+ VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
if (!v.value) {
sink->Append("(nil)");
return {true};
}
- IntDigits as_digits;
- as_digits.PrintAsHexLower(v.value);
- return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
+ IntDigits as_digits;
+ as_digits.PrintAsHexLower(v.value);
+ return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
}
// ==================== Floats ====================
-FloatingConvertResult FormatConvertImpl(float v,
- const FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(float v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
-FloatingConvertResult FormatConvertImpl(double v,
- const FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(double v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
FloatingConvertResult FormatConvertImpl(long double v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
// ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(char v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(signed char v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned char v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
// ==================== Ints ====================
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(int v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(unsigned v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(absl::int128 v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(absl::uint128 v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
@@ -484,5 +484,5 @@ ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
index 3c91be701f..fbfa00ee47 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
@@ -1,17 +1,17 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
@@ -33,58 +33,58 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
-class Cord;
+class Cord;
class FormatCountCapture;
class FormatSink;
-template <absl::FormatConversionCharSet C>
-struct FormatConvertResult;
-class FormatConversionSpec;
-
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
+class FormatConversionSpec;
+
namespace str_format_internal {
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
template <typename T>
-struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
- std::declval<const T&>(),
- std::declval<const FormatConversionSpec&>(),
- std::declval<FormatSink*>()))>>
- : std::true_type {};
-
-void AbslFormatConvert(); // Stops the lexical name lookup
-template <typename T>
-auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink)
- -> decltype(AbslFormatConvert(v,
- std::declval<const FormatConversionSpec&>(),
- std::declval<FormatSink*>())) {
- using FormatConversionSpecT =
- absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
- using FormatSinkT =
- absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
- auto fcs = conv.Wrap<FormatConversionSpecT>();
- auto fs = sink->Wrap<FormatSinkT>();
- return AbslFormatConvert(v, fcs, &fs);
-}
+struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
+ std::declval<const T&>(),
+ std::declval<const FormatConversionSpec&>(),
+ std::declval<FormatSink*>()))>>
+ : std::true_type {};
+void AbslFormatConvert(); // Stops the lexical name lookup
template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink)
+ -> decltype(AbslFormatConvert(v,
+ std::declval<const FormatConversionSpec&>(),
+ std::declval<FormatSink*>())) {
+ using FormatConversionSpecT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+ using FormatSinkT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+ auto fcs = conv.Wrap<FormatConversionSpecT>();
+ auto fs = sink->Wrap<FormatSinkT>();
+ return AbslFormatConvert(v, fcs, &fs);
+}
+
+template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
-// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
-// as an extension mechanism. These FormatConvertImpl functions are the default
-// implementations.
-// The ADL search is augmented via the 'Sink*' parameter, which also
-// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
-// functions in the namespaces associated with 'v'.
-
+// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
+// as an extension mechanism. These FormatConvertImpl functions are the default
+// implementations.
+// The ADL search is augmented via the 'Sink*' parameter, which also
+// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
+// functions in the namespaces associated with 'v'.
+
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
@@ -95,33 +95,33 @@ struct VoidPtr {
uintptr_t value;
};
-template <FormatConversionCharSet C>
-struct ArgConvertResult {
- bool value;
-};
-
-template <FormatConversionCharSet C>
-constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
- return C;
-}
-
-template <FormatConversionCharSet C>
-constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
- return C;
-}
-
-using StringConvertResult =
- ArgConvertResult<FormatConversionCharSetInternal::s>;
-ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
- VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
-
+template <FormatConversionCharSet C>
+struct ArgConvertResult {
+ bool value;
+};
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
+ return C;
+}
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
+ return C;
+}
+
+using StringConvertResult =
+ ArgConvertResult<FormatConversionCharSetInternal::s>;
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+ VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
+
// Strings.
-StringConvertResult FormatConvertImpl(const std::string& v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-StringConvertResult FormatConvertImpl(string_view v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+StringConvertResult FormatConvertImpl(const std::string& v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+StringConvertResult FormatConvertImpl(string_view v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW)
inline StringConvertResult FormatConvertImpl(std::string_view v,
FormatConversionSpecImpl conv,
@@ -130,17 +130,17 @@ inline StringConvertResult FormatConvertImpl(std::string_view v,
}
#endif // ABSL_HAVE_STD_STRING_VIEW && !ABSL_USES_STD_STRING_VIEW
-ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
-FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-
-template <class AbslCord, typename std::enable_if<std::is_same<
- AbslCord, absl::Cord>::value>::type* = nullptr>
-StringConvertResult FormatConvertImpl(const AbslCord& value,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
- bool is_left = conv.has_left_flag();
+ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+
+template <class AbslCord, typename std::enable_if<std::is_same<
+ AbslCord, absl::Cord>::value>::type* = nullptr>
+StringConvertResult FormatConvertImpl(const AbslCord& value,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
+ bool is_left = conv.has_left_flag();
size_t space_remaining = 0;
int width = conv.width();
@@ -156,80 +156,80 @@ StringConvertResult FormatConvertImpl(const AbslCord& value,
if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
- for (string_view piece : value.Chunks()) {
- if (piece.size() > to_write) {
- piece.remove_suffix(piece.size() - to_write);
- to_write = 0;
- } else {
- to_write -= piece.size();
- }
+ for (string_view piece : value.Chunks()) {
+ if (piece.size() > to_write) {
+ piece.remove_suffix(piece.size() - to_write);
+ to_write = 0;
+ } else {
+ to_write -= piece.size();
+ }
sink->Append(piece);
- if (to_write == 0) {
- break;
- }
+ if (to_write == 0) {
+ break;
+ }
}
if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
return {true};
}
-using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::c,
- FormatConversionCharSetInternal::kNumeric,
- FormatConversionCharSetInternal::kStar)>;
-using FloatingConvertResult =
- ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
+using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::c,
+ FormatConversionCharSetInternal::kNumeric,
+ FormatConversionCharSetInternal::kStar)>;
+using FloatingConvertResult =
+ ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
// Floats.
-FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(long double v,
- FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(long double v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Chars.
-IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(signed char v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(signed char v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned char v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned char v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- FormatConversionSpecImpl conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(uint128 v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(uint128 v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
-IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
@@ -240,12 +240,12 @@ template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
!HasUserDefinedConvert<T>::value,
IntegralConvertResult>::type
-FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
+FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
template <typename T>
-StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* out) {
+StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* out) {
std::ostringstream oss;
oss << v.v_;
if (!oss) return {false};
@@ -256,24 +256,24 @@ StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
// until after FormatCountCapture is fully defined.
struct FormatCountCaptureHelper {
template <class T = int>
- static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
- const FormatCountCapture& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
+ static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
+ const FormatCountCapture& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
- if (conv.conversion_char() !=
- str_format_internal::FormatConversionCharInternal::n) {
+ if (conv.conversion_char() !=
+ str_format_internal::FormatConversionCharInternal::n) {
return {false};
- }
+ }
*v2.p_ = static_cast<int>(sink->size());
return {true};
}
};
template <class T = int>
-ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
- const FormatCountCapture& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
+ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
+ const FormatCountCapture& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
}
@@ -282,13 +282,13 @@ ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
struct FormatArgImplFriend {
template <typename Arg>
static bool ToInt(Arg arg, int* out) {
- // A value initialized FormatConversionSpecImpl has a `none` conv, which
- // tells the dispatcher to run the `int` conversion.
+ // A value initialized FormatConversionSpecImpl has a `none` conv, which
+ // tells the dispatcher to run the `int` conversion.
return arg.dispatcher_(arg.data_, {}, out);
}
template <typename Arg>
- static bool Convert(Arg arg, FormatConversionSpecImpl conv,
+ static bool Convert(Arg arg, FormatConversionSpecImpl conv,
FormatSinkImpl* out) {
return arg.dispatcher_(arg.data_, conv, out);
}
@@ -299,15 +299,15 @@ struct FormatArgImplFriend {
}
};
-template <typename Arg>
-constexpr FormatConversionCharSet ArgumentToConv() {
- return absl::str_format_internal::ExtractCharSet(
- decltype(str_format_internal::FormatConvertImpl(
- std::declval<const Arg&>(),
- std::declval<const FormatConversionSpecImpl&>(),
- std::declval<FormatSinkImpl*>())){});
-}
-
+template <typename Arg>
+constexpr FormatConversionCharSet ArgumentToConv() {
+ return absl::str_format_internal::ExtractCharSet(
+ decltype(str_format_internal::FormatConvertImpl(
+ std::declval<const Arg&>(),
+ std::declval<const FormatConversionSpecImpl&>(),
+ std::declval<FormatSinkImpl*>())){});
+}
+
// A type-erased handle to a format argument.
class FormatArgImpl {
private:
@@ -321,7 +321,7 @@ class FormatArgImpl {
char buf[kInlinedSpace];
};
- using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
+ using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
template <typename T>
struct store_by_value
@@ -463,20 +463,20 @@ class FormatArgImpl {
}
template <typename T>
- static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
+ static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
// A `none` conv indicates that we want the `int` conversion.
- if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
- FormatConversionCharInternal::kNone)) {
+ if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
+ FormatConversionCharInternal::kNone)) {
return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
std::is_enum<T>());
}
- if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
- spec.conversion_char()))) {
- return false;
- }
+ if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
+ spec.conversion_char()))) {
+ return false;
+ }
return str_format_internal::FormatConvertImpl(
- Manager<T>::Value(arg), spec,
- static_cast<FormatSinkImpl*>(out))
+ Manager<T>::Value(arg), spec,
+ static_cast<FormatSinkImpl*>(out))
.value;
}
@@ -484,9 +484,9 @@ class FormatArgImpl {
Dispatcher dispatcher_;
};
-#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
- E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
- void*)
+#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
+ E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
+ void*)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
@@ -520,7 +520,7 @@ ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
index c988ba8fd2..34742bff72 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
@@ -1,17 +1,17 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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/internal/str_format/bind.h"
#include <cerrno>
@@ -20,7 +20,7 @@
#include <string>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -80,21 +80,21 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
return false;
}
- FormatConversionSpecImplFriend::SetWidth(width, bound);
- FormatConversionSpecImplFriend::SetPrecision(precision, bound);
-
- if (force_left) {
+ FormatConversionSpecImplFriend::SetWidth(width, bound);
+ FormatConversionSpecImplFriend::SetPrecision(precision, bound);
+
+ if (force_left) {
FormatConversionSpecImplFriend::SetFlags(unbound->flags | Flags::kLeft,
bound);
- } else {
- FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
- }
+ } else {
+ FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+ }
} else {
- FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
- FormatConversionSpecImplFriend::SetWidth(-1, bound);
- FormatConversionSpecImplFriend::SetPrecision(-1, bound);
+ FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+ FormatConversionSpecImplFriend::SetWidth(-1, bound);
+ FormatConversionSpecImplFriend::SetPrecision(-1, bound);
}
- FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
+ FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
bound->set_arg(arg);
return true;
}
@@ -156,11 +156,11 @@ class SummarizingConverter {
UntypedFormatSpecImpl spec("%d");
std::ostringstream ss;
- ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
- << FormatConversionSpecImplFriend::FlagsToString(bound);
+ ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
+ << FormatConversionSpecImplFriend::FlagsToString(bound);
if (bound.width() >= 0) ss << bound.width();
if (bound.precision() >= 0) ss << "." << bound.precision();
- ss << bound.conversion_char() << "}";
+ ss << bound.conversion_char() << "}";
Append(ss.str());
return true;
}
@@ -254,5 +254,5 @@ int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
index b26cff6648..3d88a6f830 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
@@ -1,17 +1,17 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
@@ -27,13 +27,13 @@
#include "absl/types/span.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
class UntypedFormatSpec;
namespace str_format_internal {
-class BoundConversion : public FormatConversionSpecImpl {
+class BoundConversion : public FormatConversionSpecImpl {
public:
const FormatArgImpl* arg() const { return arg_; }
void set_arg(const FormatArgImpl* a) { arg_ = a; }
@@ -74,7 +74,7 @@ class UntypedFormatSpecImpl {
size_t size_;
};
-template <typename T, FormatConversionCharSet...>
+template <typename T, FormatConversionCharSet...>
struct MakeDependent {
using type = T;
};
@@ -82,19 +82,19 @@ struct MakeDependent {
// Implicitly convertible from `const char*`, `string_view`, and the
// `ExtendedParsedFormat` type. This abstraction allows all format functions to
// operate on any without providing too many overloads.
-template <FormatConversionCharSet... Args>
+template <FormatConversionCharSet... Args>
class FormatSpecTemplate
: public MakeDependent<UntypedFormatSpec, Args...>::type {
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
public:
-#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- // Honeypot overload for when the string is not constexpr.
+ // Honeypot overload for when the string is not constexpr.
// We use the 'unavailable' attribute to give a better compiler error than
// just 'method is deleted'.
FormatSpecTemplate(...) // NOLINT
- __attribute__((unavailable("Format string is not constexpr.")));
+ __attribute__((unavailable("Format string is not constexpr.")));
// Honeypot overload for when the format is constexpr and invalid.
// We use the 'unavailable' attribute to give a better compiler error than
@@ -119,11 +119,11 @@ class FormatSpecTemplate
// Good format overload.
FormatSpecTemplate(const char* s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
FormatSpecTemplate(string_view s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -204,14 +204,14 @@ class StreamedWrapper {
private:
template <typename S>
- friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
- const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* out);
+ friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
+ const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* out);
const T& v_;
};
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
index 2a2601eccf..bfff09965f 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
@@ -1,34 +1,34 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
-#include "absl/base/attributes.h"
+#include "absl/base/attributes.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/extension.h"
// Compile time check support for entry points.
#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
+#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
-#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
+#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
constexpr bool AllOf() { return true; }
@@ -38,7 +38,7 @@ constexpr bool AllOf(bool b, T... t) {
return b && AllOf(t...);
}
-#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
constexpr bool ContainsChar(const char* chars, char c) {
return *chars == c || (*chars && ContainsChar(chars + 1, c));
@@ -46,14 +46,14 @@ constexpr bool ContainsChar(const char* chars, char c) {
// A constexpr compatible list of Convs.
struct ConvList {
- const FormatConversionCharSet* array;
+ const FormatConversionCharSet* array;
int count;
// We do the bound check here to avoid having to do it on the callers.
- // Returning an empty FormatConversionCharSet has the same effect as
- // short circuiting because it will never match any conversion.
- constexpr FormatConversionCharSet operator[](int i) const {
- return i < count ? array[i] : FormatConversionCharSet{};
+ // Returning an empty FormatConversionCharSet has the same effect as
+ // short circuiting because it will never match any conversion.
+ constexpr FormatConversionCharSet operator[](int i) const {
+ return i < count ? array[i] : FormatConversionCharSet{};
}
constexpr ConvList without_front() const {
@@ -64,7 +64,7 @@ struct ConvList {
template <size_t count>
struct ConvListT {
// Make sure the array has size > 0.
- FormatConversionCharSet list[count ? count : 1];
+ FormatConversionCharSet list[count ? count : 1];
};
constexpr char GetChar(string_view str, size_t index) {
@@ -317,7 +317,7 @@ class FormatParser {
ConvList args_;
};
-template <FormatConversionCharSet... C>
+template <FormatConversionCharSet... C>
constexpr bool ValidFormatImpl(string_view format) {
return FormatParser(format,
{ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
@@ -327,7 +327,7 @@ constexpr bool ValidFormatImpl(string_view format) {
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
index 484f6ebfc1..afc0a0bb56 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
@@ -20,7 +20,7 @@
#include <string>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
std::string FlagsToString(Flags v) {
@@ -33,43 +33,43 @@ std::string FlagsToString(Flags v) {
return s;
}
-#define ABSL_INTERNAL_X_VAL(id) \
- constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
-ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
-#undef ABSL_INTERNAL_X_VAL
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
+#define ABSL_INTERNAL_X_VAL(id) \
+ constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
-#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
- constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
-ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
-#undef ABSL_INTERNAL_CHAR_SET_CASE
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
-
-bool FormatSinkImpl::PutPaddedString(string_view value, int width,
- int precision, bool left) {
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
+
+bool FormatSinkImpl::PutPaddedString(string_view value, int width,
+ int precision, bool left) {
size_t space_remaining = 0;
- if (width >= 0) space_remaining = width;
- size_t n = value.size();
- if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
- string_view shown(value.data(), n);
+ if (width >= 0) space_remaining = width;
+ size_t n = value.size();
+ if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
+ string_view shown(value.data(), n);
space_remaining = Excess(shown.size(), space_remaining);
- if (!left) Append(space_remaining, ' ');
+ if (!left) Append(space_remaining, ' ');
Append(shown);
- if (left) Append(space_remaining, ' ');
+ if (left) Append(space_remaining, ' ');
return true;
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
index 55cbb56d0a..760cda3778 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
@@ -17,23 +17,23 @@
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#include <limits.h>
-
+
#include <cstddef>
#include <cstring>
#include <ostream>
-#include "absl/base/config.h"
+#include "absl/base/config.h"
#include "absl/base/port.h"
-#include "absl/meta/type_traits.h"
+#include "absl/meta/type_traits.h"
#include "absl/strings/internal/str_format/output.h"
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-enum class FormatConversionChar : uint8_t;
-enum class FormatConversionCharSet : uint64_t;
+ABSL_NAMESPACE_BEGIN
+enum class FormatConversionChar : uint8_t;
+enum class FormatConversionCharSet : uint64_t;
+
namespace str_format_internal {
class FormatRawSinkImpl {
@@ -107,7 +107,7 @@ class FormatSinkImpl {
size_t size() const { return size_; }
// Put 'v' to 'sink' with specified width, precision, and left flag.
- bool PutPaddedString(string_view v, int width, int precision, bool left);
+ bool PutPaddedString(string_view v, int width, int precision, bool left);
template <typename T>
T Wrap() {
@@ -156,9 +156,9 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
}
// clang-format off
-#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
+#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
/* text */ \
- X_VAL(c) X_SEP X_VAL(s) X_SEP \
+ X_VAL(c) X_SEP X_VAL(s) X_SEP \
/* ints */ \
X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
@@ -169,108 +169,108 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
X_VAL(n) X_SEP X_VAL(p)
// clang-format on
-// This type should not be referenced, it exists only to provide labels
-// internally that match the values declared in FormatConversionChar in
-// str_format.h. This is meant to allow internal libraries to use the same
-// declared interface type as the public interface
-// (absl::StrFormatConversionChar) while keeping the definition in a public
-// header.
-// Internal libraries should use the form
-// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
-// comparisons. Use in switch statements is not recommended due to a bug in how
-// gcc 4.9 -Wswitch handles declared but undefined enums.
-struct FormatConversionCharInternal {
- FormatConversionCharInternal() = delete;
-
- private:
- // clang-format off
- enum class Enum : uint8_t {
- c, s, // text
+// This type should not be referenced, it exists only to provide labels
+// internally that match the values declared in FormatConversionChar in
+// str_format.h. This is meant to allow internal libraries to use the same
+// declared interface type as the public interface
+// (absl::StrFormatConversionChar) while keeping the definition in a public
+// header.
+// Internal libraries should use the form
+// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
+// comparisons. Use in switch statements is not recommended due to a bug in how
+// gcc 4.9 -Wswitch handles declared but undefined enums.
+struct FormatConversionCharInternal {
+ FormatConversionCharInternal() = delete;
+
+ private:
+ // clang-format off
+ enum class Enum : uint8_t {
+ c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
n, p, // misc
- kNone
+ kNone
};
- // clang-format on
+ // clang-format on
public:
-#define ABSL_INTERNAL_X_VAL(id) \
- static constexpr FormatConversionChar id = \
- static_cast<FormatConversionChar>(Enum::id);
- ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
-#undef ABSL_INTERNAL_X_VAL
- static constexpr FormatConversionChar kNone =
- static_cast<FormatConversionChar>(Enum::kNone);
-};
-// clang-format on
-
-inline FormatConversionChar FormatConversionCharFromChar(char c) {
- switch (c) {
-#define ABSL_INTERNAL_X_VAL(id) \
- case #id[0]: \
- return FormatConversionCharInternal::id;
- ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
-#undef ABSL_INTERNAL_X_VAL
+#define ABSL_INTERNAL_X_VAL(id) \
+ static constexpr FormatConversionChar id = \
+ static_cast<FormatConversionChar>(Enum::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+ static constexpr FormatConversionChar kNone =
+ static_cast<FormatConversionChar>(Enum::kNone);
+};
+// clang-format on
+
+inline FormatConversionChar FormatConversionCharFromChar(char c) {
+ switch (c) {
+#define ABSL_INTERNAL_X_VAL(id) \
+ case #id[0]: \
+ return FormatConversionCharInternal::id;
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
}
- return FormatConversionCharInternal::kNone;
-}
-
-inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
- if (c == FormatConversionCharInternal::X ||
- c == FormatConversionCharInternal::F ||
- c == FormatConversionCharInternal::E ||
- c == FormatConversionCharInternal::G ||
- c == FormatConversionCharInternal::A) {
- return true;
- } else {
- return false;
+ return FormatConversionCharInternal::kNone;
+}
+
+inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::X ||
+ c == FormatConversionCharInternal::F ||
+ c == FormatConversionCharInternal::E ||
+ c == FormatConversionCharInternal::G ||
+ c == FormatConversionCharInternal::A) {
+ return true;
+ } else {
+ return false;
}
-}
-
-inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
- if (c == FormatConversionCharInternal::a ||
- c == FormatConversionCharInternal::e ||
- c == FormatConversionCharInternal::f ||
- c == FormatConversionCharInternal::g ||
- c == FormatConversionCharInternal::A ||
- c == FormatConversionCharInternal::E ||
- c == FormatConversionCharInternal::F ||
- c == FormatConversionCharInternal::G) {
- return true;
- } else {
- return false;
+}
+
+inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::a ||
+ c == FormatConversionCharInternal::e ||
+ c == FormatConversionCharInternal::f ||
+ c == FormatConversionCharInternal::g ||
+ c == FormatConversionCharInternal::A ||
+ c == FormatConversionCharInternal::E ||
+ c == FormatConversionCharInternal::F ||
+ c == FormatConversionCharInternal::G) {
+ return true;
+ } else {
+ return false;
}
-}
-
-inline char FormatConversionCharToChar(FormatConversionChar c) {
- if (c == FormatConversionCharInternal::kNone) {
- return '\0';
-
-#define ABSL_INTERNAL_X_VAL(e) \
- } else if (c == FormatConversionCharInternal::e) { \
- return #e[0];
-#define ABSL_INTERNAL_X_SEP
- ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
- ABSL_INTERNAL_X_SEP)
- } else {
- return '\0';
+}
+
+inline char FormatConversionCharToChar(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::kNone) {
+ return '\0';
+
+#define ABSL_INTERNAL_X_VAL(e) \
+ } else if (c == FormatConversionCharInternal::e) { \
+ return #e[0];
+#define ABSL_INTERNAL_X_SEP
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
+ ABSL_INTERNAL_X_SEP)
+ } else {
+ return '\0';
}
-#undef ABSL_INTERNAL_X_VAL
-#undef ABSL_INTERNAL_X_SEP
-}
+#undef ABSL_INTERNAL_X_VAL
+#undef ABSL_INTERNAL_X_SEP
+}
-// The associated char.
-inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
- char c = FormatConversionCharToChar(v);
- if (!c) c = '?';
- return os << c;
-}
+// The associated char.
+inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
+ char c = FormatConversionCharToChar(v);
+ if (!c) c = '?';
+ return os << c;
+}
-struct FormatConversionSpecImplFriend;
+struct FormatConversionSpecImplFriend;
-class FormatConversionSpecImpl {
- public:
- // Width and precison are not specified, no flags are set.
+class FormatConversionSpecImpl {
+ public:
+ // Width and precison are not specified, no flags are set.
bool is_basic() const { return flags_ == Flags::kBasic; }
bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
bool has_show_pos_flag() const {
@@ -282,10 +282,10 @@ class FormatConversionSpecImpl {
bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
- FormatConversionChar conversion_char() const {
+ FormatConversionChar conversion_char() const {
// Keep this field first in the struct . It generates better code when
// accessing it when ConversionSpec is passed by value in registers.
- static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
+ static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
return conv_;
}
@@ -296,96 +296,96 @@ class FormatConversionSpecImpl {
// negative value.
int precision() const { return precision_; }
- template <typename T>
- T Wrap() {
- return T(*this);
- }
+ template <typename T>
+ T Wrap() {
+ return T(*this);
+ }
private:
- friend struct str_format_internal::FormatConversionSpecImplFriend;
- FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
+ friend struct str_format_internal::FormatConversionSpecImplFriend;
+ FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
Flags flags_;
int width_;
int precision_;
};
-struct FormatConversionSpecImplFriend final {
- static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
- conv->flags_ = f;
- }
- static void SetConversionChar(FormatConversionChar c,
- FormatConversionSpecImpl* conv) {
- conv->conv_ = c;
- }
- static void SetWidth(int w, FormatConversionSpecImpl* conv) {
- conv->width_ = w;
- }
- static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
- conv->precision_ = p;
- }
- static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
+struct FormatConversionSpecImplFriend final {
+ static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
+ conv->flags_ = f;
+ }
+ static void SetConversionChar(FormatConversionChar c,
+ FormatConversionSpecImpl* conv) {
+ conv->conv_ = c;
+ }
+ static void SetWidth(int w, FormatConversionSpecImpl* conv) {
+ conv->width_ = w;
+ }
+ static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
+ conv->precision_ = p;
+ }
+ static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
return str_format_internal::FlagsToString(spec.flags_);
- }
-};
-
-// Type safe OR operator.
-// We need this for two reasons:
-// 1. operator| on enums makes them decay to integers and the result is an
-// integer. We need the result to stay as an enum.
-// 2. We use "enum class" which would not work even if we accepted the decay.
-constexpr FormatConversionCharSet FormatConversionCharSetUnion(
- FormatConversionCharSet a) {
- return a;
-}
-
-template <typename... CharSet>
-constexpr FormatConversionCharSet FormatConversionCharSetUnion(
- FormatConversionCharSet a, CharSet... rest) {
- return static_cast<FormatConversionCharSet>(
- static_cast<uint64_t>(a) |
- static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
-}
-
-constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
- return uint64_t{1} << (1 + static_cast<uint8_t>(c));
-}
-
-constexpr uint64_t FormatConversionCharToConvInt(char conv) {
+ }
+};
+
+// Type safe OR operator.
+// We need this for two reasons:
+// 1. operator| on enums makes them decay to integers and the result is an
+// integer. We need the result to stay as an enum.
+// 2. We use "enum class" which would not work even if we accepted the decay.
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+ FormatConversionCharSet a) {
+ return a;
+}
+
+template <typename... CharSet>
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+ FormatConversionCharSet a, CharSet... rest) {
+ return static_cast<FormatConversionCharSet>(
+ static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
+ return uint64_t{1} << (1 + static_cast<uint8_t>(c));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(char conv) {
return
-#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
- conv == #c[0] \
- ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
- :
- ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
-#undef ABSL_INTERNAL_CHAR_SET_CASE
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ conv == #c[0] \
+ ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
+ :
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
conv == '*'
? 1
: 0;
}
-constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
- return static_cast<FormatConversionCharSet>(
- FormatConversionCharToConvInt(conv));
-}
-
-struct FormatConversionCharSetInternal {
-#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
- static constexpr FormatConversionCharSet c = \
- FormatConversionCharToConvValue(#c[0]);
- ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
-#undef ABSL_INTERNAL_CHAR_SET_CASE
-
+constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
+ return static_cast<FormatConversionCharSet>(
+ FormatConversionCharToConvInt(conv));
+}
+
+struct FormatConversionCharSetInternal {
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ static constexpr FormatConversionCharSet c = \
+ FormatConversionCharToConvValue(#c[0]);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
+
// Used for width/precision '*' specification.
- static constexpr FormatConversionCharSet kStar =
- FormatConversionCharToConvValue('*');
-
- static constexpr FormatConversionCharSet kIntegral =
- FormatConversionCharSetUnion(d, i, u, o, x, X);
- static constexpr FormatConversionCharSet kFloating =
- FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
- static constexpr FormatConversionCharSet kNumeric =
- FormatConversionCharSetUnion(kIntegral, kFloating);
- static constexpr FormatConversionCharSet kPointer = p;
+ static constexpr FormatConversionCharSet kStar =
+ FormatConversionCharToConvValue('*');
+
+ static constexpr FormatConversionCharSet kIntegral =
+ FormatConversionCharSetUnion(d, i, u, o, x, X);
+ static constexpr FormatConversionCharSet kFloating =
+ FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
+ static constexpr FormatConversionCharSet kNumeric =
+ FormatConversionCharSetUnion(kIntegral, kFloating);
+ static constexpr FormatConversionCharSet kPointer = p;
};
// Type safe OR operator.
@@ -393,44 +393,44 @@ struct FormatConversionCharSetInternal {
// 1. operator| on enums makes them decay to integers and the result is an
// integer. We need the result to stay as an enum.
// 2. We use "enum class" which would not work even if we accepted the decay.
-constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
- FormatConversionCharSet b) {
- return FormatConversionCharSetUnion(a, b);
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+ FormatConversionCharSet b) {
+ return FormatConversionCharSetUnion(a, b);
}
-// Overloaded conversion functions to support absl::ParsedFormat.
+// Overloaded conversion functions to support absl::ParsedFormat.
// Get a conversion with a single character in it.
-constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
- return static_cast<FormatConversionCharSet>(
- FormatConversionCharToConvValue(c));
+constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
+ return static_cast<FormatConversionCharSet>(
+ FormatConversionCharToConvValue(c));
}
-// Get a conversion with a single character in it.
-constexpr FormatConversionCharSet ToFormatConversionCharSet(
- FormatConversionCharSet c) {
- return c;
-}
-
-template <typename T>
-void ToFormatConversionCharSet(T) = delete;
-
+// Get a conversion with a single character in it.
+constexpr FormatConversionCharSet ToFormatConversionCharSet(
+ FormatConversionCharSet c) {
+ return c;
+}
+
+template <typename T>
+void ToFormatConversionCharSet(T) = delete;
+
// Checks whether `c` exists in `set`.
-constexpr bool Contains(FormatConversionCharSet set, char c) {
- return (static_cast<uint64_t>(set) &
- static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
+constexpr bool Contains(FormatConversionCharSet set, char c) {
+ return (static_cast<uint64_t>(set) &
+ static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
-constexpr bool Contains(FormatConversionCharSet set,
- FormatConversionCharSet c) {
+constexpr bool Contains(FormatConversionCharSet set,
+ FormatConversionCharSet c) {
return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
static_cast<uint64_t>(c);
}
-// Checks whether all the characters in `c` are contained in `set`
-constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
- return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
-}
+// Checks whether all the characters in `c` are contained in `set`
+constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
+ return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
+}
// Return capacity - used, clipped to a minimum of 0.
inline size_t Excess(size_t used, size_t capacity) {
@@ -439,7 +439,7 @@ inline size_t Excess(size_t used, size_t capacity) {
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
index b1c4068475..1d151dd9bf 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -1,944 +1,944 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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/internal/str_format/float_conversion.h"
#include <string.h>
-
+
#include <algorithm>
#include <cassert>
#include <cmath>
-#include <limits>
+#include <limits>
#include <string>
-#include "absl/base/attributes.h"
+#include "absl/base/attributes.h"
#include "absl/base/config.h"
-#include "absl/base/optimization.h"
-#include "absl/functional/function_ref.h"
-#include "absl/meta/type_traits.h"
+#include "absl/base/optimization.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
#include "absl/numeric/bits.h"
-#include "absl/numeric/int128.h"
+#include "absl/numeric/int128.h"
#include "absl/numeric/internal/representation.h"
-#include "absl/strings/numbers.h"
-#include "absl/types/optional.h"
-#include "absl/types/span.h"
+#include "absl/strings/numbers.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
using ::absl::numeric_internal::IsDoubleDouble;
-// The code below wants to avoid heap allocations.
-// To do so it needs to allocate memory on the stack.
-// `StackArray` will allocate memory on the stack in the form of a uint32_t
-// array and call the provided callback with said memory.
-// It will allocate memory in increments of 512 bytes. We could allocate the
-// largest needed unconditionally, but that is more than we need in most of
-// cases. This way we use less stack in the common cases.
-class StackArray {
- using Func = absl::FunctionRef<void(absl::Span<uint32_t>)>;
- static constexpr size_t kStep = 512 / sizeof(uint32_t);
- // 5 steps is 2560 bytes, which is enough to hold a long double with the
- // largest/smallest exponents.
- // The operations below will static_assert their particular maximum.
- static constexpr size_t kNumSteps = 5;
-
- // We do not want this function to be inlined.
- // Otherwise the caller will allocate the stack space unnecessarily for all
- // the variants even though it only calls one.
- template <size_t steps>
- ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) {
- uint32_t values[steps * kStep]{};
- f(absl::MakeSpan(values));
- }
-
- public:
- static constexpr size_t kMaxCapacity = kStep * kNumSteps;
-
- static void RunWithCapacity(size_t capacity, Func f) {
- assert(capacity <= kMaxCapacity);
- const size_t step = (capacity + kStep - 1) / kStep;
- assert(step <= kNumSteps);
- switch (step) {
- case 1:
- return RunWithCapacityImpl<1>(f);
- case 2:
- return RunWithCapacityImpl<2>(f);
- case 3:
- return RunWithCapacityImpl<3>(f);
- case 4:
- return RunWithCapacityImpl<4>(f);
- case 5:
- return RunWithCapacityImpl<5>(f);
- }
-
- assert(false && "Invalid capacity");
- }
-};
-
-// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
-// the carry.
-template <typename Int>
-inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
- using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
- BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
- *v = static_cast<Int>(tmp);
- return static_cast<Int>(tmp >> (sizeof(Int) * 8));
-}
-
-// Calculates `(2^64 * carry + *v) / 10`.
-// Stores the quotient in `*v` and returns the remainder.
-// Requires: `0 <= carry <= 9`
-inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
- constexpr uint64_t divisor = 10;
- // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
- constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
- constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
-
- const uint64_t mod = *v % divisor;
- const uint64_t next_carry = chunk_remainder * carry + mod;
- *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
- return next_carry % divisor;
-}
-
+// The code below wants to avoid heap allocations.
+// To do so it needs to allocate memory on the stack.
+// `StackArray` will allocate memory on the stack in the form of a uint32_t
+// array and call the provided callback with said memory.
+// It will allocate memory in increments of 512 bytes. We could allocate the
+// largest needed unconditionally, but that is more than we need in most of
+// cases. This way we use less stack in the common cases.
+class StackArray {
+ using Func = absl::FunctionRef<void(absl::Span<uint32_t>)>;
+ static constexpr size_t kStep = 512 / sizeof(uint32_t);
+ // 5 steps is 2560 bytes, which is enough to hold a long double with the
+ // largest/smallest exponents.
+ // The operations below will static_assert their particular maximum.
+ static constexpr size_t kNumSteps = 5;
+
+ // We do not want this function to be inlined.
+ // Otherwise the caller will allocate the stack space unnecessarily for all
+ // the variants even though it only calls one.
+ template <size_t steps>
+ ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) {
+ uint32_t values[steps * kStep]{};
+ f(absl::MakeSpan(values));
+ }
+
+ public:
+ static constexpr size_t kMaxCapacity = kStep * kNumSteps;
+
+ static void RunWithCapacity(size_t capacity, Func f) {
+ assert(capacity <= kMaxCapacity);
+ const size_t step = (capacity + kStep - 1) / kStep;
+ assert(step <= kNumSteps);
+ switch (step) {
+ case 1:
+ return RunWithCapacityImpl<1>(f);
+ case 2:
+ return RunWithCapacityImpl<2>(f);
+ case 3:
+ return RunWithCapacityImpl<3>(f);
+ case 4:
+ return RunWithCapacityImpl<4>(f);
+ case 5:
+ return RunWithCapacityImpl<5>(f);
+ }
+
+ assert(false && "Invalid capacity");
+ }
+};
+
+// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
+// the carry.
+template <typename Int>
+inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
+ using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
+ BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
+ *v = static_cast<Int>(tmp);
+ return static_cast<Int>(tmp >> (sizeof(Int) * 8));
+}
+
+// Calculates `(2^64 * carry + *v) / 10`.
+// Stores the quotient in `*v` and returns the remainder.
+// Requires: `0 <= carry <= 9`
+inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
+ constexpr uint64_t divisor = 10;
+ // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
+ constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
+ constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
+
+ const uint64_t mod = *v % divisor;
+ const uint64_t next_carry = chunk_remainder * carry + mod;
+ *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
+ return next_carry % divisor;
+}
+
using MaxFloatType =
typename std::conditional<IsDoubleDouble(), double, long double>::type;
-// Generates the decimal representation for an integer of the form `v * 2^exp`,
-// where `v` and `exp` are both positive integers.
-// It generates the digits from the left (ie the most significant digit first)
-// to allow for direct printing into the sink.
-//
+// Generates the decimal representation for an integer of the form `v * 2^exp`,
+// where `v` and `exp` are both positive integers.
+// It generates the digits from the left (ie the most significant digit first)
+// to allow for direct printing into the sink.
+//
// Requires `0 <= exp` and `exp <= numeric_limits<MaxFloatType>::max_exponent`.
-class BinaryToDecimal {
- static constexpr int ChunksNeeded(int exp) {
- // We will left shift a uint128 by `exp` bits, so we need `128+exp` total
- // bits. Round up to 32.
- // See constructor for details about adding `10%` to the value.
- return (128 + exp + 31) / 32 * 11 / 10;
- }
-
- public:
- // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`.
- // This function will allocate enough stack space to perform the conversion.
- static void RunConversion(uint128 v, int exp,
- absl::FunctionRef<void(BinaryToDecimal)> f) {
- assert(exp > 0);
+class BinaryToDecimal {
+ static constexpr int ChunksNeeded(int exp) {
+ // We will left shift a uint128 by `exp` bits, so we need `128+exp` total
+ // bits. Round up to 32.
+ // See constructor for details about adding `10%` to the value.
+ return (128 + exp + 31) / 32 * 11 / 10;
+ }
+
+ public:
+ // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`.
+ // This function will allocate enough stack space to perform the conversion.
+ static void RunConversion(uint128 v, int exp,
+ absl::FunctionRef<void(BinaryToDecimal)> f) {
+ assert(exp > 0);
assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
- static_assert(
+ static_assert(
static_cast<int>(StackArray::kMaxCapacity) >=
ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
- "");
-
- StackArray::RunWithCapacity(
- ChunksNeeded(exp),
- [=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
- }
-
- int TotalDigits() const {
- return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
- CurrentDigits().size());
- }
-
- // See the current block of digits.
- absl::string_view CurrentDigits() const {
- return absl::string_view(digits_ + kDigitsPerChunk - size_, size_);
- }
-
- // Advance the current view of digits.
- // Returns `false` when no more digits are available.
- bool AdvanceDigits() {
- if (decimal_start_ >= decimal_end_) return false;
-
- uint32_t w = data_[decimal_start_++];
- for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) {
- digits_[kDigitsPerChunk - ++size_] = w % 10 + '0';
- }
- return true;
- }
-
- private:
- BinaryToDecimal(absl::Span<uint32_t> data, uint128 v, int exp) : data_(data) {
- // We need to print the digits directly into the sink object without
- // buffering them all first. To do this we need two things:
- // - to know the total number of digits to do padding when necessary
- // - to generate the decimal digits from the left.
- //
- // In order to do this, we do a two pass conversion.
- // On the first pass we convert the binary representation of the value into
- // a decimal representation in which each uint32_t chunk holds up to 9
- // decimal digits. In the second pass we take each decimal-holding-uint32_t
- // value and generate the ascii decimal digits into `digits_`.
- //
- // The binary and decimal representations actually share the same memory
- // region. As we go converting the chunks from binary to decimal we free
- // them up and reuse them for the decimal representation. One caveat is that
- // the decimal representation is around 7% less efficient in space than the
- // binary one. We allocate an extra 10% memory to account for this. See
- // ChunksNeeded for this calculation.
- int chunk_index = exp / 32;
- decimal_start_ = decimal_end_ = ChunksNeeded(exp);
- const int offset = exp % 32;
- // Left shift v by exp bits.
- data_[chunk_index] = static_cast<uint32_t>(v << offset);
- for (v >>= (32 - offset); v; v >>= 32)
- data_[++chunk_index] = static_cast<uint32_t>(v);
-
- while (chunk_index >= 0) {
- // While we have more than one chunk available, go in steps of 1e9.
- // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
- // the variable updated.
- uint32_t carry = 0;
- for (int i = chunk_index; i >= 0; --i) {
- uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
- data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
- carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
- }
-
- // If the highest chunk is now empty, remove it from view.
- if (data_[chunk_index] == 0) --chunk_index;
-
- --decimal_start_;
- assert(decimal_start_ != chunk_index);
- data_[decimal_start_] = carry;
- }
-
- // Fill the first set of digits. The first chunk might not be complete, so
- // handle differently.
- for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) {
- digits_[kDigitsPerChunk - ++size_] = first % 10 + '0';
- }
- }
-
- private:
- static constexpr int kDigitsPerChunk = 9;
-
- int decimal_start_;
- int decimal_end_;
-
- char digits_[kDigitsPerChunk];
- int size_ = 0;
-
- absl::Span<uint32_t> data_;
-};
-
-// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits.
-// Requires `-exp < 0` and
+ "");
+
+ StackArray::RunWithCapacity(
+ ChunksNeeded(exp),
+ [=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
+ }
+
+ int TotalDigits() const {
+ return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
+ CurrentDigits().size());
+ }
+
+ // See the current block of digits.
+ absl::string_view CurrentDigits() const {
+ return absl::string_view(digits_ + kDigitsPerChunk - size_, size_);
+ }
+
+ // Advance the current view of digits.
+ // Returns `false` when no more digits are available.
+ bool AdvanceDigits() {
+ if (decimal_start_ >= decimal_end_) return false;
+
+ uint32_t w = data_[decimal_start_++];
+ for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) {
+ digits_[kDigitsPerChunk - ++size_] = w % 10 + '0';
+ }
+ return true;
+ }
+
+ private:
+ BinaryToDecimal(absl::Span<uint32_t> data, uint128 v, int exp) : data_(data) {
+ // We need to print the digits directly into the sink object without
+ // buffering them all first. To do this we need two things:
+ // - to know the total number of digits to do padding when necessary
+ // - to generate the decimal digits from the left.
+ //
+ // In order to do this, we do a two pass conversion.
+ // On the first pass we convert the binary representation of the value into
+ // a decimal representation in which each uint32_t chunk holds up to 9
+ // decimal digits. In the second pass we take each decimal-holding-uint32_t
+ // value and generate the ascii decimal digits into `digits_`.
+ //
+ // The binary and decimal representations actually share the same memory
+ // region. As we go converting the chunks from binary to decimal we free
+ // them up and reuse them for the decimal representation. One caveat is that
+ // the decimal representation is around 7% less efficient in space than the
+ // binary one. We allocate an extra 10% memory to account for this. See
+ // ChunksNeeded for this calculation.
+ int chunk_index = exp / 32;
+ decimal_start_ = decimal_end_ = ChunksNeeded(exp);
+ const int offset = exp % 32;
+ // Left shift v by exp bits.
+ data_[chunk_index] = static_cast<uint32_t>(v << offset);
+ for (v >>= (32 - offset); v; v >>= 32)
+ data_[++chunk_index] = static_cast<uint32_t>(v);
+
+ while (chunk_index >= 0) {
+ // While we have more than one chunk available, go in steps of 1e9.
+ // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
+ // the variable updated.
+ uint32_t carry = 0;
+ for (int i = chunk_index; i >= 0; --i) {
+ uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
+ data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
+ carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
+ }
+
+ // If the highest chunk is now empty, remove it from view.
+ if (data_[chunk_index] == 0) --chunk_index;
+
+ --decimal_start_;
+ assert(decimal_start_ != chunk_index);
+ data_[decimal_start_] = carry;
+ }
+
+ // Fill the first set of digits. The first chunk might not be complete, so
+ // handle differently.
+ for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) {
+ digits_[kDigitsPerChunk - ++size_] = first % 10 + '0';
+ }
+ }
+
+ private:
+ static constexpr int kDigitsPerChunk = 9;
+
+ int decimal_start_;
+ int decimal_end_;
+
+ char digits_[kDigitsPerChunk];
+ int size_ = 0;
+
+ absl::Span<uint32_t> data_;
+};
+
+// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits.
+// Requires `-exp < 0` and
// `-exp >= limits<MaxFloatType>::min_exponent - limits<MaxFloatType>::digits`.
-class FractionalDigitGenerator {
- public:
- // Run the conversion for `v * 2^exp` and call `f(generator)`.
- // This function will allocate enough stack space to perform the conversion.
- static void RunConversion(
- uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
+class FractionalDigitGenerator {
+ public:
+ // Run the conversion for `v * 2^exp` and call `f(generator)`.
+ // This function will allocate enough stack space to perform the conversion.
+ static void RunConversion(
+ uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
using Limits = std::numeric_limits<MaxFloatType>;
- assert(-exp < 0);
- assert(-exp >= Limits::min_exponent - 128);
- static_assert(StackArray::kMaxCapacity >=
- (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
- "");
- StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
- [=](absl::Span<uint32_t> input) {
- f(FractionalDigitGenerator(input, v, exp));
- });
- }
-
- // Returns true if there are any more non-zero digits left.
- bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
-
- // Returns true if the remainder digits are greater than 5000...
- bool IsGreaterThanHalf() const {
- return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
- }
- // Returns true if the remainder digits are exactly 5000...
- bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
-
- struct Digits {
- int digit_before_nine;
- int num_nines;
- };
-
- // Get the next set of digits.
- // They are composed by a non-9 digit followed by a runs of zero or more 9s.
- Digits GetDigits() {
- Digits digits{next_digit_, 0};
-
- next_digit_ = GetOneDigit();
- while (next_digit_ == 9) {
- ++digits.num_nines;
- next_digit_ = GetOneDigit();
- }
-
- return digits;
- }
-
- private:
- // Return the next digit.
- int GetOneDigit() {
- if (chunk_index_ < 0) return 0;
-
- uint32_t carry = 0;
- for (int i = chunk_index_; i >= 0; --i) {
- carry = MultiplyBy10WithCarry(&data_[i], carry);
- }
- // If the lowest chunk is now empty, remove it from view.
- if (data_[chunk_index_] == 0) --chunk_index_;
- return carry;
- }
-
- FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
- : chunk_index_(exp / 32), data_(data) {
- const int offset = exp % 32;
- // Right shift `v` by `exp` bits.
- data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
- v >>= offset;
- // Make sure we don't overflow the data. We already calculated that
- // non-zero bits fit, so we might not have space for leading zero bits.
- for (int pos = chunk_index_; v; v >>= 32)
- data_[--pos] = static_cast<uint32_t>(v);
-
- // Fill next_digit_, as GetDigits expects it to be populated always.
- next_digit_ = GetOneDigit();
- }
-
- int next_digit_;
- int chunk_index_;
- absl::Span<uint32_t> data_;
-};
-
-// Count the number of leading zero bits.
+ assert(-exp < 0);
+ assert(-exp >= Limits::min_exponent - 128);
+ static_assert(StackArray::kMaxCapacity >=
+ (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
+ "");
+ StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
+ [=](absl::Span<uint32_t> input) {
+ f(FractionalDigitGenerator(input, v, exp));
+ });
+ }
+
+ // Returns true if there are any more non-zero digits left.
+ bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
+
+ // Returns true if the remainder digits are greater than 5000...
+ bool IsGreaterThanHalf() const {
+ return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
+ }
+ // Returns true if the remainder digits are exactly 5000...
+ bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
+
+ struct Digits {
+ int digit_before_nine;
+ int num_nines;
+ };
+
+ // Get the next set of digits.
+ // They are composed by a non-9 digit followed by a runs of zero or more 9s.
+ Digits GetDigits() {
+ Digits digits{next_digit_, 0};
+
+ next_digit_ = GetOneDigit();
+ while (next_digit_ == 9) {
+ ++digits.num_nines;
+ next_digit_ = GetOneDigit();
+ }
+
+ return digits;
+ }
+
+ private:
+ // Return the next digit.
+ int GetOneDigit() {
+ if (chunk_index_ < 0) return 0;
+
+ uint32_t carry = 0;
+ for (int i = chunk_index_; i >= 0; --i) {
+ carry = MultiplyBy10WithCarry(&data_[i], carry);
+ }
+ // If the lowest chunk is now empty, remove it from view.
+ if (data_[chunk_index_] == 0) --chunk_index_;
+ return carry;
+ }
+
+ FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
+ : chunk_index_(exp / 32), data_(data) {
+ const int offset = exp % 32;
+ // Right shift `v` by `exp` bits.
+ data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
+ v >>= offset;
+ // Make sure we don't overflow the data. We already calculated that
+ // non-zero bits fit, so we might not have space for leading zero bits.
+ for (int pos = chunk_index_; v; v >>= 32)
+ data_[--pos] = static_cast<uint32_t>(v);
+
+ // Fill next_digit_, as GetDigits expects it to be populated always.
+ next_digit_ = GetOneDigit();
+ }
+
+ int next_digit_;
+ int chunk_index_;
+ absl::Span<uint32_t> data_;
+};
+
+// Count the number of leading zero bits.
int LeadingZeros(uint64_t v) { return countl_zero(v); }
-int LeadingZeros(uint128 v) {
- auto high = static_cast<uint64_t>(v >> 64);
- auto low = static_cast<uint64_t>(v);
+int LeadingZeros(uint128 v) {
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
return high != 0 ? countl_zero(high) : 64 + countl_zero(low);
-}
-
-// Round up the text digits starting at `p`.
-// The buffer must have an extra digit that is known to not need rounding.
-// This is done below by having an extra '0' digit on the left.
-void RoundUp(char *p) {
- while (*p == '9' || *p == '.') {
- if (*p == '9') *p = '0';
- --p;
- }
- ++*p;
-}
-
-// Check the previous digit and round up or down to follow the round-to-even
-// policy.
-void RoundToEven(char *p) {
- if (*p == '.') --p;
- if (*p % 2 == 1) RoundUp(p);
-}
-
-// Simple integral decimal digit printing for values that fit in 64-bits.
-// Returns the pointer to the last written digit.
-char *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) {
- do {
- *--p = DivideBy10WithCarry(&v, 0) + '0';
- } while (v != 0);
- return p;
-}
-
-// Simple integral decimal digit printing for values that fit in 128-bits.
-// Returns the pointer to the last written digit.
-char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
- auto high = static_cast<uint64_t>(v >> 64);
- auto low = static_cast<uint64_t>(v);
-
- while (high != 0) {
- uint64_t carry = DivideBy10WithCarry(&high, 0);
- carry = DivideBy10WithCarry(&low, carry);
- *--p = carry + '0';
- }
- return PrintIntegralDigitsFromRightFast(low, p);
-}
-
-// Simple fractional decimal digit printing for values that fir in 64-bits after
-// shifting.
-// Performs rounding if necessary to fit within `precision`.
-// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
- int precision) {
- char *p = start;
- v <<= (64 - exp);
- while (precision > 0) {
- if (!v) return p;
- *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
- --precision;
- }
-
- // We need to round.
- if (v < 0x8000000000000000) {
- // We round down, so nothing to do.
- } else if (v > 0x8000000000000000) {
- // We round up.
- RoundUp(p - 1);
- } else {
- RoundToEven(p - 1);
- }
-
- assert(precision == 0);
- // Precision can only be zero here.
- return p;
-}
-
-// Simple fractional decimal digit printing for values that fir in 128-bits
-// after shifting.
-// Performs rounding if necessary to fit within `precision`.
-// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
- int precision) {
- char *p = start;
- v <<= (128 - exp);
- auto high = static_cast<uint64_t>(v >> 64);
- auto low = static_cast<uint64_t>(v);
-
- // While we have digits to print and `low` is not empty, do the long
- // multiplication.
- while (precision > 0 && low != 0) {
- uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
- carry = MultiplyBy10WithCarry(&high, carry);
-
- *p++ = carry + '0';
- --precision;
- }
-
- // Now `low` is empty, so use a faster approach for the rest of the digits.
- // This block is pretty much the same as the main loop for the 64-bit case
- // above.
- while (precision > 0) {
- if (!high) return p;
- *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
- --precision;
- }
-
- // We need to round.
- if (high < 0x8000000000000000) {
- // We round down, so nothing to do.
- } else if (high > 0x8000000000000000 || low != 0) {
- // We round up.
- RoundUp(p - 1);
- } else {
- RoundToEven(p - 1);
- }
-
- assert(precision == 0);
- // Precision can only be zero here.
- return p;
-}
-
-struct FormatState {
- char sign_char;
- int precision;
- const FormatConversionSpecImpl &conv;
- FormatSinkImpl *sink;
-
- // In `alt` mode (flag #) we keep the `.` even if there are no fractional
- // digits. In non-alt mode, we strip it.
- bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); }
-};
-
-struct Padding {
- int left_spaces;
- int zeros;
- int right_spaces;
-};
-
-Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
- if (state.conv.width() < 0 ||
- static_cast<size_t>(state.conv.width()) <= total_size) {
- return {0, 0, 0};
- }
- int missing_chars = state.conv.width() - total_size;
- if (state.conv.has_left_flag()) {
- return {0, 0, missing_chars};
- } else if (state.conv.has_zero_flag()) {
- return {0, missing_chars, 0};
- } else {
- return {missing_chars, 0, 0};
- }
-}
-
-void FinalPrint(const FormatState &state, absl::string_view data,
- int padding_offset, int trailing_zeros,
- absl::string_view data_postfix) {
- if (state.conv.width() < 0) {
- // No width specified. Fast-path.
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
- state.sink->Append(data);
- state.sink->Append(trailing_zeros, '0');
- state.sink->Append(data_postfix);
- return;
- }
-
- auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
- data.size() + data_postfix.size() +
- static_cast<size_t>(trailing_zeros),
- state);
-
- state.sink->Append(padding.left_spaces, ' ');
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
- // Padding in general needs to be inserted somewhere in the middle of `data`.
- state.sink->Append(data.substr(0, padding_offset));
- state.sink->Append(padding.zeros, '0');
- state.sink->Append(data.substr(padding_offset));
- state.sink->Append(trailing_zeros, '0');
- state.sink->Append(data_postfix);
- state.sink->Append(padding.right_spaces, ' ');
-}
-
-// Fastpath %f formatter for when the shifted value fits in a simple integral
-// type.
-// Prints `v*2^exp` with the options from `state`.
-template <typename Int>
-void FormatFFast(Int v, int exp, const FormatState &state) {
- constexpr int input_bits = sizeof(Int) * 8;
-
- static constexpr size_t integral_size =
- /* in case we need to round up an extra digit */ 1 +
- /* decimal digits for uint128 */ 40 + 1;
- char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128];
- buffer[integral_size] = '.';
- char *const integral_digits_end = buffer + integral_size;
- char *integral_digits_start;
- char *const fractional_digits_start = buffer + integral_size + 1;
- char *fractional_digits_end = fractional_digits_start;
-
- if (exp >= 0) {
- const int total_bits = input_bits - LeadingZeros(v) + exp;
- integral_digits_start =
- total_bits <= 64
- ? PrintIntegralDigitsFromRightFast(static_cast<uint64_t>(v) << exp,
- integral_digits_end)
- : PrintIntegralDigitsFromRightFast(static_cast<uint128>(v) << exp,
- integral_digits_end);
- } else {
- exp = -exp;
-
- integral_digits_start = PrintIntegralDigitsFromRightFast(
- exp < input_bits ? v >> exp : 0, integral_digits_end);
- // PrintFractionalDigits may pull a carried 1 all the way up through the
- // integral portion.
- integral_digits_start[-1] = '0';
-
- fractional_digits_end =
- exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp,
- state.precision)
- : PrintFractionalDigitsFast(static_cast<uint128>(v),
- fractional_digits_start, exp,
- state.precision);
- // There was a carry, so include the first digit too.
- if (integral_digits_start[-1] != '0') --integral_digits_start;
- }
-
- size_t size = fractional_digits_end - integral_digits_start;
-
- // In `alt` mode (flag #) we keep the `.` even if there are no fractional
- // digits. In non-alt mode, we strip it.
- if (!state.ShouldPrintDot()) --size;
- FinalPrint(state, absl::string_view(integral_digits_start, size),
- /*padding_offset=*/0,
- static_cast<int>(state.precision - (fractional_digits_end -
- fractional_digits_start)),
- /*data_postfix=*/"");
-}
-
-// Slow %f formatter for when the shifted value does not fit in a uint128, and
-// `exp > 0`.
-// Prints `v*2^exp` with the options from `state`.
-// This one is guaranteed to not have fractional digits, so we don't have to
-// worry about anything after the `.`.
-void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
- BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
- const size_t total_digits =
- btd.TotalDigits() +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
-
- const auto padding = ExtraWidthToPadding(
- total_digits + (state.sign_char != '\0' ? 1 : 0), state);
-
- state.sink->Append(padding.left_spaces, ' ');
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
- state.sink->Append(padding.zeros, '0');
-
- do {
- state.sink->Append(btd.CurrentDigits());
- } while (btd.AdvanceDigits());
-
- if (state.ShouldPrintDot()) state.sink->Append(1, '.');
- state.sink->Append(state.precision, '0');
- state.sink->Append(padding.right_spaces, ' ');
- });
-}
-
-// Slow %f formatter for when the shifted value does not fit in a uint128, and
-// `exp < 0`.
-// Prints `v*2^exp` with the options from `state`.
-// This one is guaranteed to be < 1.0, so we don't have to worry about integral
-// digits.
-void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
- const size_t total_digits =
- /* 0 */ 1 +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
- auto padding =
- ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
- padding.zeros += 1;
- state.sink->Append(padding.left_spaces, ' ');
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
- state.sink->Append(padding.zeros, '0');
-
- if (state.ShouldPrintDot()) state.sink->Append(1, '.');
-
- // Print digits
- int digits_to_go = state.precision;
-
- FractionalDigitGenerator::RunConversion(
- v, exp, [&](FractionalDigitGenerator digit_gen) {
- // There are no digits to print here.
- if (state.precision == 0) return;
-
- // We go one digit at a time, while keeping track of runs of nines.
- // The runs of nines are used to perform rounding when necessary.
-
- while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {
- auto digits = digit_gen.GetDigits();
-
- // Now we have a digit and a run of nines.
- // See if we can print them all.
- if (digits.num_nines + 1 < digits_to_go) {
- // We don't have to round yet, so print them.
- state.sink->Append(1, digits.digit_before_nine + '0');
- state.sink->Append(digits.num_nines, '9');
- digits_to_go -= digits.num_nines + 1;
-
- } else {
- // We can't print all the nines, see where we have to truncate.
-
- bool round_up = false;
- if (digits.num_nines + 1 > digits_to_go) {
- // We round up at a nine. No need to print them.
- round_up = true;
- } else {
- // We can fit all the nines, but truncate just after it.
- if (digit_gen.IsGreaterThanHalf()) {
- round_up = true;
- } else if (digit_gen.IsExactlyHalf()) {
- // Round to even
- round_up =
- digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;
- }
- }
-
- if (round_up) {
- state.sink->Append(1, digits.digit_before_nine + '1');
- --digits_to_go;
- // The rest will be zeros.
- } else {
- state.sink->Append(1, digits.digit_before_nine + '0');
- state.sink->Append(digits_to_go - 1, '9');
- digits_to_go = 0;
- }
- return;
- }
- }
- });
-
- state.sink->Append(digits_to_go, '0');
- state.sink->Append(padding.right_spaces, ' ');
-}
-
-template <typename Int>
-void FormatF(Int mantissa, int exp, const FormatState &state) {
- if (exp >= 0) {
- const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
-
- // Fallback to the slow stack-based approach if we can't do it in a 64 or
- // 128 bit state.
- if (ABSL_PREDICT_FALSE(total_bits > 128)) {
- return FormatFPositiveExpSlow(mantissa, exp, state);
- }
- } else {
- // Fallback to the slow stack-based approach if we can't do it in a 64 or
- // 128 bit state.
- if (ABSL_PREDICT_FALSE(exp < -128)) {
- return FormatFNegativeExpSlow(mantissa, -exp, state);
- }
- }
- return FormatFFast(mantissa, exp, state);
-}
-
-// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
-// bits 4-7.
-template <typename Int>
-uint8_t GetNibble(Int n, int nibble_index) {
- constexpr Int mask_low_nibble = Int{0xf};
- int shift = nibble_index * 4;
- n &= mask_low_nibble << shift;
- return static_cast<uint8_t>((n >> shift) & 0xf);
-}
-
-// Add one to the given nibble, applying carry to higher nibbles. Returns true
-// if overflow, false otherwise.
-template <typename Int>
-bool IncrementNibble(int nibble_index, Int *n) {
- constexpr int kShift = sizeof(Int) * 8 - 1;
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
- Int before = *n >> kShift;
- // Here we essentially want to take the number 1 and move it into the requsted
- // nibble, then add it to *n to effectively increment the nibble. However,
- // ASan will complain if we try to shift the 1 beyond the limits of the Int,
- // i.e., if the nibble_index is out of range. So therefore we check for this
- // and if we are out of range we just add 0 which leaves *n unchanged, which
- // seems like the reasonable thing to do in that case.
- *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
- Int after = *n >> kShift;
- return (before && !after) || (nibble_index >= kNumNibbles);
-}
-
-// Return a mask with 1's in the given nibble and all lower nibbles.
-template <typename Int>
-Int MaskUpToNibbleInclusive(int nibble_index) {
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
- static const Int ones = ~Int{0};
- return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
-}
-
-// Return a mask with 1's below the given nibble.
-template <typename Int>
-Int MaskUpToNibbleExclusive(int nibble_index) {
- return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
-}
-
-template <typename Int>
-Int MoveToNibble(uint8_t nibble, int nibble_index) {
- return Int{nibble} << (4 * nibble_index);
-}
-
-// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
-//
-// In the hex representation we keep a single hex digit to the left of the dot.
-// However, the question as to how many bits of the mantissa should be put into
-// that hex digit in theory is arbitrary, but in practice it is optimal to
-// choose based on the size of the mantissa. E.g., for a `double`, there are 53
-// mantissa bits, so that means that we should put 1 bit to the left of the dot,
-// thereby leaving 52 bits to the right, which is evenly divisible by four and
-// thus all fractional digits represent actual precision. For a `long double`,
-// on the other hand, there are 64 bits of mantissa, thus we can use all four
-// bits for the initial hex digit and still have a number left over (60) that is
-// a multiple of four. Once again, the goal is to have all fractional digits
-// represent real precision.
-template <typename Float>
-constexpr int HexFloatLeadingDigitSizeInBits() {
- return std::numeric_limits<Float>::digits % 4 > 0
- ? std::numeric_limits<Float>::digits % 4
- : 4;
-}
-
-// This function captures the rounding behavior of glibc for hex float
-// representations. E.g. when rounding 0x1.ab800000 to a precision of .2
-// ("%.2a") glibc will round up because it rounds toward the even number (since
-// 0xb is an odd number, it will round up to 0xc). However, when rounding at a
-// point that is not followed by 800000..., it disregards the parity and rounds
-// up if > 8 and rounds down if < 8.
-template <typename Int>
-bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
- uint8_t leading) {
- // If the last nibble (hex digit) to be displayed is the lowest on in the
- // mantissa then that means that we don't have any further nibbles to inform
- // rounding, so don't round.
- if (final_nibble_displayed <= 0) {
- return false;
- }
- int rounding_nibble_idx = final_nibble_displayed - 1;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
- assert(final_nibble_displayed <= kTotalNibbles);
- Int mantissa_up_to_rounding_nibble_inclusive =
- mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
- Int eight = MoveToNibble<Int>(8, rounding_nibble_idx);
- if (mantissa_up_to_rounding_nibble_inclusive != eight) {
- return mantissa_up_to_rounding_nibble_inclusive > eight;
- }
- // Nibble in question == 8.
- uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles)
- ? leading
- : GetNibble(mantissa, final_nibble_displayed);
- return round_if_odd % 2 == 1;
-}
-
-// Stores values associated with a Float type needed by the FormatA
-// implementation in order to avoid templatizing that function by the Float
-// type.
-struct HexFloatTypeParams {
- template <typename Float>
- explicit HexFloatTypeParams(Float)
- : min_exponent(std::numeric_limits<Float>::min_exponent - 1),
- leading_digit_size_bits(HexFloatLeadingDigitSizeInBits<Float>()) {
- assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4);
- }
-
- int min_exponent;
- int leading_digit_size_bits;
-};
-
-// Hex Float Rounding. First check if we need to round; if so, then we do that
-// by manipulating (incrementing) the mantissa, that way we can later print the
-// mantissa digits by iterating through them in the same way regardless of
-// whether a rounding happened.
-template <typename Int>
-void FormatARound(bool precision_specified, const FormatState &state,
- uint8_t *leading, Int *mantissa, int *exp) {
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
- // Index of the last nibble that we could display given precision.
- int final_nibble_displayed =
- precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
- if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
- // Need to round up.
- bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
- *leading += (overflow ? 1 : 0);
- if (ABSL_PREDICT_FALSE(*leading > 15)) {
- // We have overflowed the leading digit. This would mean that we would
- // need two hex digits to the left of the dot, which is not allowed. So
- // adjust the mantissa and exponent so that the result is always 1.0eXXX.
- *leading = 1;
- *mantissa = 0;
- *exp += 4;
- }
- }
- // Now that we have handled a possible round-up we can go ahead and zero out
- // all the nibbles of the mantissa that we won't need.
- if (precision_specified) {
- *mantissa &= ~MaskUpToNibbleExclusive<Int>(final_nibble_displayed);
- }
-}
-
-template <typename Int>
-void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
- Int *mantissa, int *exp) {
- constexpr int kIntBits = sizeof(Int) * 8;
- static const Int kHighIntBit = Int{1} << (kIntBits - 1);
- const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
- // Normalize mantissa so that highest bit set is in MSB position, unless we
- // get interrupted by the exponent threshold.
- while (*mantissa && !(*mantissa & kHighIntBit)) {
- if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) {
- *mantissa >>= (float_traits.min_exponent - *exp);
- *exp = float_traits.min_exponent;
- return;
- }
- *mantissa <<= 1;
- --*exp;
- }
- // Extract bits for leading digit then shift them away leaving the
- // fractional part.
- *leading =
- static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
- *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
- *mantissa <<= kLeadDigitBitsCount;
-}
-
-template <typename Int>
-void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
- bool uppercase, const FormatState &state) {
- // Int properties.
- constexpr int kIntBits = sizeof(Int) * 8;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
- // Did the user specify a precision explicitly?
- const bool precision_specified = state.conv.precision() >= 0;
-
- // ========== Normalize/Denormalize ==========
- exp += kIntBits; // make all digits fractional digits.
- // This holds the (up to four) bits of leading digit, i.e., the '1' in the
- // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal.
- uint8_t leading = 0;
- FormatANormalize(float_traits, &leading, &mantissa, &exp);
-
- // =============== Rounding ==================
- // Check if we need to round; if so, then we do that by manipulating
- // (incrementing) the mantissa before beginning to print characters.
- FormatARound(precision_specified, state, &leading, &mantissa, &exp);
-
- // ============= Format Result ===============
- // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the
- // size with long double which is the largest of the floats.
- constexpr size_t kBufSizeForHexFloatRepr =
+}
+
+// Round up the text digits starting at `p`.
+// The buffer must have an extra digit that is known to not need rounding.
+// This is done below by having an extra '0' digit on the left.
+void RoundUp(char *p) {
+ while (*p == '9' || *p == '.') {
+ if (*p == '9') *p = '0';
+ --p;
+ }
+ ++*p;
+}
+
+// Check the previous digit and round up or down to follow the round-to-even
+// policy.
+void RoundToEven(char *p) {
+ if (*p == '.') --p;
+ if (*p % 2 == 1) RoundUp(p);
+}
+
+// Simple integral decimal digit printing for values that fit in 64-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) {
+ do {
+ *--p = DivideBy10WithCarry(&v, 0) + '0';
+ } while (v != 0);
+ return p;
+}
+
+// Simple integral decimal digit printing for values that fit in 128-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
+
+ while (high != 0) {
+ uint64_t carry = DivideBy10WithCarry(&high, 0);
+ carry = DivideBy10WithCarry(&low, carry);
+ *--p = carry + '0';
+ }
+ return PrintIntegralDigitsFromRightFast(low, p);
+}
+
+// Simple fractional decimal digit printing for values that fir in 64-bits after
+// shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
+ int precision) {
+ char *p = start;
+ v <<= (64 - exp);
+ while (precision > 0) {
+ if (!v) return p;
+ *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
+ --precision;
+ }
+
+ // We need to round.
+ if (v < 0x8000000000000000) {
+ // We round down, so nothing to do.
+ } else if (v > 0x8000000000000000) {
+ // We round up.
+ RoundUp(p - 1);
+ } else {
+ RoundToEven(p - 1);
+ }
+
+ assert(precision == 0);
+ // Precision can only be zero here.
+ return p;
+}
+
+// Simple fractional decimal digit printing for values that fir in 128-bits
+// after shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
+ int precision) {
+ char *p = start;
+ v <<= (128 - exp);
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
+
+ // While we have digits to print and `low` is not empty, do the long
+ // multiplication.
+ while (precision > 0 && low != 0) {
+ uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
+ carry = MultiplyBy10WithCarry(&high, carry);
+
+ *p++ = carry + '0';
+ --precision;
+ }
+
+ // Now `low` is empty, so use a faster approach for the rest of the digits.
+ // This block is pretty much the same as the main loop for the 64-bit case
+ // above.
+ while (precision > 0) {
+ if (!high) return p;
+ *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
+ --precision;
+ }
+
+ // We need to round.
+ if (high < 0x8000000000000000) {
+ // We round down, so nothing to do.
+ } else if (high > 0x8000000000000000 || low != 0) {
+ // We round up.
+ RoundUp(p - 1);
+ } else {
+ RoundToEven(p - 1);
+ }
+
+ assert(precision == 0);
+ // Precision can only be zero here.
+ return p;
+}
+
+struct FormatState {
+ char sign_char;
+ int precision;
+ const FormatConversionSpecImpl &conv;
+ FormatSinkImpl *sink;
+
+ // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+ // digits. In non-alt mode, we strip it.
+ bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); }
+};
+
+struct Padding {
+ int left_spaces;
+ int zeros;
+ int right_spaces;
+};
+
+Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
+ if (state.conv.width() < 0 ||
+ static_cast<size_t>(state.conv.width()) <= total_size) {
+ return {0, 0, 0};
+ }
+ int missing_chars = state.conv.width() - total_size;
+ if (state.conv.has_left_flag()) {
+ return {0, 0, missing_chars};
+ } else if (state.conv.has_zero_flag()) {
+ return {0, missing_chars, 0};
+ } else {
+ return {missing_chars, 0, 0};
+ }
+}
+
+void FinalPrint(const FormatState &state, absl::string_view data,
+ int padding_offset, int trailing_zeros,
+ absl::string_view data_postfix) {
+ if (state.conv.width() < 0) {
+ // No width specified. Fast-path.
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(data);
+ state.sink->Append(trailing_zeros, '0');
+ state.sink->Append(data_postfix);
+ return;
+ }
+
+ auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
+ data.size() + data_postfix.size() +
+ static_cast<size_t>(trailing_zeros),
+ state);
+
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ // Padding in general needs to be inserted somewhere in the middle of `data`.
+ state.sink->Append(data.substr(0, padding_offset));
+ state.sink->Append(padding.zeros, '0');
+ state.sink->Append(data.substr(padding_offset));
+ state.sink->Append(trailing_zeros, '0');
+ state.sink->Append(data_postfix);
+ state.sink->Append(padding.right_spaces, ' ');
+}
+
+// Fastpath %f formatter for when the shifted value fits in a simple integral
+// type.
+// Prints `v*2^exp` with the options from `state`.
+template <typename Int>
+void FormatFFast(Int v, int exp, const FormatState &state) {
+ constexpr int input_bits = sizeof(Int) * 8;
+
+ static constexpr size_t integral_size =
+ /* in case we need to round up an extra digit */ 1 +
+ /* decimal digits for uint128 */ 40 + 1;
+ char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128];
+ buffer[integral_size] = '.';
+ char *const integral_digits_end = buffer + integral_size;
+ char *integral_digits_start;
+ char *const fractional_digits_start = buffer + integral_size + 1;
+ char *fractional_digits_end = fractional_digits_start;
+
+ if (exp >= 0) {
+ const int total_bits = input_bits - LeadingZeros(v) + exp;
+ integral_digits_start =
+ total_bits <= 64
+ ? PrintIntegralDigitsFromRightFast(static_cast<uint64_t>(v) << exp,
+ integral_digits_end)
+ : PrintIntegralDigitsFromRightFast(static_cast<uint128>(v) << exp,
+ integral_digits_end);
+ } else {
+ exp = -exp;
+
+ integral_digits_start = PrintIntegralDigitsFromRightFast(
+ exp < input_bits ? v >> exp : 0, integral_digits_end);
+ // PrintFractionalDigits may pull a carried 1 all the way up through the
+ // integral portion.
+ integral_digits_start[-1] = '0';
+
+ fractional_digits_end =
+ exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp,
+ state.precision)
+ : PrintFractionalDigitsFast(static_cast<uint128>(v),
+ fractional_digits_start, exp,
+ state.precision);
+ // There was a carry, so include the first digit too.
+ if (integral_digits_start[-1] != '0') --integral_digits_start;
+ }
+
+ size_t size = fractional_digits_end - integral_digits_start;
+
+ // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+ // digits. In non-alt mode, we strip it.
+ if (!state.ShouldPrintDot()) --size;
+ FinalPrint(state, absl::string_view(integral_digits_start, size),
+ /*padding_offset=*/0,
+ static_cast<int>(state.precision - (fractional_digits_end -
+ fractional_digits_start)),
+ /*data_postfix=*/"");
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp > 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to not have fractional digits, so we don't have to
+// worry about anything after the `.`.
+void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
+ BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
+ const size_t total_digits =
+ btd.TotalDigits() +
+ (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+
+ const auto padding = ExtraWidthToPadding(
+ total_digits + (state.sign_char != '\0' ? 1 : 0), state);
+
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(padding.zeros, '0');
+
+ do {
+ state.sink->Append(btd.CurrentDigits());
+ } while (btd.AdvanceDigits());
+
+ if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+ state.sink->Append(state.precision, '0');
+ state.sink->Append(padding.right_spaces, ' ');
+ });
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp < 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to be < 1.0, so we don't have to worry about integral
+// digits.
+void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
+ const size_t total_digits =
+ /* 0 */ 1 +
+ (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ auto padding =
+ ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
+ padding.zeros += 1;
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(padding.zeros, '0');
+
+ if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+
+ // Print digits
+ int digits_to_go = state.precision;
+
+ FractionalDigitGenerator::RunConversion(
+ v, exp, [&](FractionalDigitGenerator digit_gen) {
+ // There are no digits to print here.
+ if (state.precision == 0) return;
+
+ // We go one digit at a time, while keeping track of runs of nines.
+ // The runs of nines are used to perform rounding when necessary.
+
+ while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {
+ auto digits = digit_gen.GetDigits();
+
+ // Now we have a digit and a run of nines.
+ // See if we can print them all.
+ if (digits.num_nines + 1 < digits_to_go) {
+ // We don't have to round yet, so print them.
+ state.sink->Append(1, digits.digit_before_nine + '0');
+ state.sink->Append(digits.num_nines, '9');
+ digits_to_go -= digits.num_nines + 1;
+
+ } else {
+ // We can't print all the nines, see where we have to truncate.
+
+ bool round_up = false;
+ if (digits.num_nines + 1 > digits_to_go) {
+ // We round up at a nine. No need to print them.
+ round_up = true;
+ } else {
+ // We can fit all the nines, but truncate just after it.
+ if (digit_gen.IsGreaterThanHalf()) {
+ round_up = true;
+ } else if (digit_gen.IsExactlyHalf()) {
+ // Round to even
+ round_up =
+ digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;
+ }
+ }
+
+ if (round_up) {
+ state.sink->Append(1, digits.digit_before_nine + '1');
+ --digits_to_go;
+ // The rest will be zeros.
+ } else {
+ state.sink->Append(1, digits.digit_before_nine + '0');
+ state.sink->Append(digits_to_go - 1, '9');
+ digits_to_go = 0;
+ }
+ return;
+ }
+ }
+ });
+
+ state.sink->Append(digits_to_go, '0');
+ state.sink->Append(padding.right_spaces, ' ');
+}
+
+template <typename Int>
+void FormatF(Int mantissa, int exp, const FormatState &state) {
+ if (exp >= 0) {
+ const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
+
+ // Fallback to the slow stack-based approach if we can't do it in a 64 or
+ // 128 bit state.
+ if (ABSL_PREDICT_FALSE(total_bits > 128)) {
+ return FormatFPositiveExpSlow(mantissa, exp, state);
+ }
+ } else {
+ // Fallback to the slow stack-based approach if we can't do it in a 64 or
+ // 128 bit state.
+ if (ABSL_PREDICT_FALSE(exp < -128)) {
+ return FormatFNegativeExpSlow(mantissa, -exp, state);
+ }
+ }
+ return FormatFFast(mantissa, exp, state);
+}
+
+// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
+// bits 4-7.
+template <typename Int>
+uint8_t GetNibble(Int n, int nibble_index) {
+ constexpr Int mask_low_nibble = Int{0xf};
+ int shift = nibble_index * 4;
+ n &= mask_low_nibble << shift;
+ return static_cast<uint8_t>((n >> shift) & 0xf);
+}
+
+// Add one to the given nibble, applying carry to higher nibbles. Returns true
+// if overflow, false otherwise.
+template <typename Int>
+bool IncrementNibble(int nibble_index, Int *n) {
+ constexpr int kShift = sizeof(Int) * 8 - 1;
+ constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+ Int before = *n >> kShift;
+ // Here we essentially want to take the number 1 and move it into the requsted
+ // nibble, then add it to *n to effectively increment the nibble. However,
+ // ASan will complain if we try to shift the 1 beyond the limits of the Int,
+ // i.e., if the nibble_index is out of range. So therefore we check for this
+ // and if we are out of range we just add 0 which leaves *n unchanged, which
+ // seems like the reasonable thing to do in that case.
+ *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
+ Int after = *n >> kShift;
+ return (before && !after) || (nibble_index >= kNumNibbles);
+}
+
+// Return a mask with 1's in the given nibble and all lower nibbles.
+template <typename Int>
+Int MaskUpToNibbleInclusive(int nibble_index) {
+ constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+ static const Int ones = ~Int{0};
+ return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
+}
+
+// Return a mask with 1's below the given nibble.
+template <typename Int>
+Int MaskUpToNibbleExclusive(int nibble_index) {
+ return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
+}
+
+template <typename Int>
+Int MoveToNibble(uint8_t nibble, int nibble_index) {
+ return Int{nibble} << (4 * nibble_index);
+}
+
+// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
+//
+// In the hex representation we keep a single hex digit to the left of the dot.
+// However, the question as to how many bits of the mantissa should be put into
+// that hex digit in theory is arbitrary, but in practice it is optimal to
+// choose based on the size of the mantissa. E.g., for a `double`, there are 53
+// mantissa bits, so that means that we should put 1 bit to the left of the dot,
+// thereby leaving 52 bits to the right, which is evenly divisible by four and
+// thus all fractional digits represent actual precision. For a `long double`,
+// on the other hand, there are 64 bits of mantissa, thus we can use all four
+// bits for the initial hex digit and still have a number left over (60) that is
+// a multiple of four. Once again, the goal is to have all fractional digits
+// represent real precision.
+template <typename Float>
+constexpr int HexFloatLeadingDigitSizeInBits() {
+ return std::numeric_limits<Float>::digits % 4 > 0
+ ? std::numeric_limits<Float>::digits % 4
+ : 4;
+}
+
+// This function captures the rounding behavior of glibc for hex float
+// representations. E.g. when rounding 0x1.ab800000 to a precision of .2
+// ("%.2a") glibc will round up because it rounds toward the even number (since
+// 0xb is an odd number, it will round up to 0xc). However, when rounding at a
+// point that is not followed by 800000..., it disregards the parity and rounds
+// up if > 8 and rounds down if < 8.
+template <typename Int>
+bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
+ uint8_t leading) {
+ // If the last nibble (hex digit) to be displayed is the lowest on in the
+ // mantissa then that means that we don't have any further nibbles to inform
+ // rounding, so don't round.
+ if (final_nibble_displayed <= 0) {
+ return false;
+ }
+ int rounding_nibble_idx = final_nibble_displayed - 1;
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ assert(final_nibble_displayed <= kTotalNibbles);
+ Int mantissa_up_to_rounding_nibble_inclusive =
+ mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
+ Int eight = MoveToNibble<Int>(8, rounding_nibble_idx);
+ if (mantissa_up_to_rounding_nibble_inclusive != eight) {
+ return mantissa_up_to_rounding_nibble_inclusive > eight;
+ }
+ // Nibble in question == 8.
+ uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles)
+ ? leading
+ : GetNibble(mantissa, final_nibble_displayed);
+ return round_if_odd % 2 == 1;
+}
+
+// Stores values associated with a Float type needed by the FormatA
+// implementation in order to avoid templatizing that function by the Float
+// type.
+struct HexFloatTypeParams {
+ template <typename Float>
+ explicit HexFloatTypeParams(Float)
+ : min_exponent(std::numeric_limits<Float>::min_exponent - 1),
+ leading_digit_size_bits(HexFloatLeadingDigitSizeInBits<Float>()) {
+ assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4);
+ }
+
+ int min_exponent;
+ int leading_digit_size_bits;
+};
+
+// Hex Float Rounding. First check if we need to round; if so, then we do that
+// by manipulating (incrementing) the mantissa, that way we can later print the
+// mantissa digits by iterating through them in the same way regardless of
+// whether a rounding happened.
+template <typename Int>
+void FormatARound(bool precision_specified, const FormatState &state,
+ uint8_t *leading, Int *mantissa, int *exp) {
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ // Index of the last nibble that we could display given precision.
+ int final_nibble_displayed =
+ precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
+ if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
+ // Need to round up.
+ bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
+ *leading += (overflow ? 1 : 0);
+ if (ABSL_PREDICT_FALSE(*leading > 15)) {
+ // We have overflowed the leading digit. This would mean that we would
+ // need two hex digits to the left of the dot, which is not allowed. So
+ // adjust the mantissa and exponent so that the result is always 1.0eXXX.
+ *leading = 1;
+ *mantissa = 0;
+ *exp += 4;
+ }
+ }
+ // Now that we have handled a possible round-up we can go ahead and zero out
+ // all the nibbles of the mantissa that we won't need.
+ if (precision_specified) {
+ *mantissa &= ~MaskUpToNibbleExclusive<Int>(final_nibble_displayed);
+ }
+}
+
+template <typename Int>
+void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
+ Int *mantissa, int *exp) {
+ constexpr int kIntBits = sizeof(Int) * 8;
+ static const Int kHighIntBit = Int{1} << (kIntBits - 1);
+ const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
+ // Normalize mantissa so that highest bit set is in MSB position, unless we
+ // get interrupted by the exponent threshold.
+ while (*mantissa && !(*mantissa & kHighIntBit)) {
+ if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) {
+ *mantissa >>= (float_traits.min_exponent - *exp);
+ *exp = float_traits.min_exponent;
+ return;
+ }
+ *mantissa <<= 1;
+ --*exp;
+ }
+ // Extract bits for leading digit then shift them away leaving the
+ // fractional part.
+ *leading =
+ static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
+ *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
+ *mantissa <<= kLeadDigitBitsCount;
+}
+
+template <typename Int>
+void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
+ bool uppercase, const FormatState &state) {
+ // Int properties.
+ constexpr int kIntBits = sizeof(Int) * 8;
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ // Did the user specify a precision explicitly?
+ const bool precision_specified = state.conv.precision() >= 0;
+
+ // ========== Normalize/Denormalize ==========
+ exp += kIntBits; // make all digits fractional digits.
+ // This holds the (up to four) bits of leading digit, i.e., the '1' in the
+ // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal.
+ uint8_t leading = 0;
+ FormatANormalize(float_traits, &leading, &mantissa, &exp);
+
+ // =============== Rounding ==================
+ // Check if we need to round; if so, then we do that by manipulating
+ // (incrementing) the mantissa before beginning to print characters.
+ FormatARound(precision_specified, state, &leading, &mantissa, &exp);
+
+ // ============= Format Result ===============
+ // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the
+ // size with long double which is the largest of the floats.
+ constexpr size_t kBufSizeForHexFloatRepr =
2 // 0x
+ std::numeric_limits<MaxFloatType>::digits / 4 // number of hex digits
+ 1 // round up
+ 1; // "." (dot)
- char digits_buffer[kBufSizeForHexFloatRepr];
- char *digits_iter = digits_buffer;
- const char *const digits =
- static_cast<const char *>("0123456789ABCDEF0123456789abcdef") +
- (uppercase ? 0 : 16);
-
- // =============== Hex Prefix ================
- *digits_iter++ = '0';
- *digits_iter++ = uppercase ? 'X' : 'x';
-
- // ========== Non-Fractional Digit ===========
- *digits_iter++ = digits[leading];
-
- // ================== Dot ====================
- // There are three reasons we might need a dot. Keep in mind that, at this
- // point, the mantissa holds only the fractional part.
- if ((precision_specified && state.precision > 0) ||
- (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) {
- *digits_iter++ = '.';
- }
-
- // ============ Fractional Digits ============
- int digits_emitted = 0;
- while (mantissa > 0) {
- *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
- mantissa <<= 4;
- ++digits_emitted;
- }
- int trailing_zeros =
- precision_specified ? state.precision - digits_emitted : 0;
- assert(trailing_zeros >= 0);
- auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
-
- // =============== Exponent ==================
- constexpr size_t kBufSizeForExpDecRepr =
- numbers_internal::kFastToBufferSize // requred for FastIntToBuffer
- + 1 // 'p' or 'P'
- + 1; // '+' or '-'
- char exp_buffer[kBufSizeForExpDecRepr];
- exp_buffer[0] = uppercase ? 'P' : 'p';
- exp_buffer[1] = exp >= 0 ? '+' : '-';
- numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
-
- // ============ Assemble Result ==============
- FinalPrint(state, //
- digits_result, // 0xN.NNN...
- 2, // offset in `data` to start padding if needed.
- trailing_zeros, // num remaining mantissa padding zeros
- exp_buffer); // exponent
-}
-
-char *CopyStringTo(absl::string_view v, char *out) {
+ char digits_buffer[kBufSizeForHexFloatRepr];
+ char *digits_iter = digits_buffer;
+ const char *const digits =
+ static_cast<const char *>("0123456789ABCDEF0123456789abcdef") +
+ (uppercase ? 0 : 16);
+
+ // =============== Hex Prefix ================
+ *digits_iter++ = '0';
+ *digits_iter++ = uppercase ? 'X' : 'x';
+
+ // ========== Non-Fractional Digit ===========
+ *digits_iter++ = digits[leading];
+
+ // ================== Dot ====================
+ // There are three reasons we might need a dot. Keep in mind that, at this
+ // point, the mantissa holds only the fractional part.
+ if ((precision_specified && state.precision > 0) ||
+ (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) {
+ *digits_iter++ = '.';
+ }
+
+ // ============ Fractional Digits ============
+ int digits_emitted = 0;
+ while (mantissa > 0) {
+ *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
+ mantissa <<= 4;
+ ++digits_emitted;
+ }
+ int trailing_zeros =
+ precision_specified ? state.precision - digits_emitted : 0;
+ assert(trailing_zeros >= 0);
+ auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
+
+ // =============== Exponent ==================
+ constexpr size_t kBufSizeForExpDecRepr =
+ numbers_internal::kFastToBufferSize // requred for FastIntToBuffer
+ + 1 // 'p' or 'P'
+ + 1; // '+' or '-'
+ char exp_buffer[kBufSizeForExpDecRepr];
+ exp_buffer[0] = uppercase ? 'P' : 'p';
+ exp_buffer[1] = exp >= 0 ? '+' : '-';
+ numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
+
+ // ============ Assemble Result ==============
+ FinalPrint(state, //
+ digits_result, // 0xN.NNN...
+ 2, // offset in `data` to start padding if needed.
+ trailing_zeros, // num remaining mantissa padding zeros
+ exp_buffer); // exponent
+}
+
+char *CopyStringTo(absl::string_view v, char *out) {
std::memcpy(out, v.data(), v.size());
return out + v.size();
}
template <typename Float>
-bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
+bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
int w = conv.width() >= 0 ? conv.width() : 0;
int p = conv.precision() >= 0 ? conv.precision() : -1;
@@ -946,22 +946,22 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
{
char *fp = fmt;
*fp++ = '%';
- fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
+ fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
fp = CopyStringTo("*.*", fp);
if (std::is_same<long double, Float>()) {
*fp++ = 'L';
}
- *fp++ = FormatConversionCharToChar(conv.conversion_char());
+ *fp++ = FormatConversionCharToChar(conv.conversion_char());
*fp = 0;
assert(fp < fmt + sizeof(fmt));
}
std::string space(512, '\0');
- absl::string_view result;
+ absl::string_view result;
while (true) {
int n = snprintf(&space[0], space.size(), fmt, w, p, v);
if (n < 0) return false;
if (static_cast<size_t>(n) < space.size()) {
- result = absl::string_view(space.data(), n);
+ result = absl::string_view(space.data(), n);
break;
}
space.resize(n + 1);
@@ -1014,24 +1014,24 @@ enum class FormatStyle { Fixed, Precision };
// Otherwise, return false.
template <typename Float>
bool ConvertNonNumericFloats(char sign_char, Float v,
- const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+ const FormatConversionSpecImpl &conv,
+ FormatSinkImpl *sink) {
char text[4], *ptr = text;
- if (sign_char != '\0') *ptr++ = sign_char;
+ if (sign_char != '\0') *ptr++ = sign_char;
if (std::isnan(v)) {
- ptr = std::copy_n(
- FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
- ptr);
+ ptr = std::copy_n(
+ FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
+ ptr);
} else if (std::isinf(v)) {
- ptr = std::copy_n(
- FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
- ptr);
+ ptr = std::copy_n(
+ FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
+ ptr);
} else {
return false;
}
return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
- conv.has_left_flag());
+ conv.has_left_flag());
}
// Round up the last digit of the value.
@@ -1091,12 +1091,12 @@ constexpr bool CanFitMantissa() {
template <typename Float>
struct Decomposed {
- using MantissaType =
- absl::conditional_t<std::is_same<long double, Float>::value, uint128,
- uint64_t>;
- static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
- "");
- MantissaType mantissa;
+ using MantissaType =
+ absl::conditional_t<std::is_same<long double, Float>::value, uint128,
+ uint64_t>;
+ static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
+ "");
+ MantissaType mantissa;
int exponent;
};
@@ -1107,8 +1107,8 @@ Decomposed<Float> Decompose(Float v) {
Float m = std::frexp(v, &exp);
m = std::ldexp(m, std::numeric_limits<Float>::digits);
exp -= std::numeric_limits<Float>::digits;
-
- return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
+
+ return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
}
// Print 'digits' as decimal.
@@ -1277,32 +1277,32 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
return false;
}
-void WriteBufferToSink(char sign_char, absl::string_view str,
- const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+void WriteBufferToSink(char sign_char, absl::string_view str,
+ const FormatConversionSpecImpl &conv,
+ FormatSinkImpl *sink) {
int left_spaces = 0, zeros = 0, right_spaces = 0;
int missing_chars =
conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
static_cast<int>(sign_char != 0),
0)
: 0;
- if (conv.has_left_flag()) {
+ if (conv.has_left_flag()) {
right_spaces = missing_chars;
- } else if (conv.has_zero_flag()) {
+ } else if (conv.has_zero_flag()) {
zeros = missing_chars;
} else {
left_spaces = missing_chars;
}
sink->Append(left_spaces, ' ');
- if (sign_char != '\0') sink->Append(1, sign_char);
+ if (sign_char != '\0') sink->Append(1, sign_char);
sink->Append(zeros, '0');
sink->Append(str);
sink->Append(right_spaces, ' ');
}
template <typename Float>
-bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
+bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
// Print the sign or the sign column.
Float abs_v = v;
@@ -1310,9 +1310,9 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
if (std::signbit(abs_v)) {
sign_char = '-';
abs_v = -abs_v;
- } else if (conv.has_show_pos_flag()) {
+ } else if (conv.has_show_pos_flag()) {
sign_char = '+';
- } else if (conv.has_sign_col_flag()) {
+ } else if (conv.has_sign_col_flag()) {
sign_char = ' ';
}
@@ -1329,95 +1329,95 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
Buffer buffer;
- FormatConversionChar c = conv.conversion_char();
-
- if (c == FormatConversionCharInternal::f ||
- c == FormatConversionCharInternal::F) {
- FormatF(decomposed.mantissa, decomposed.exponent,
- {sign_char, precision, conv, sink});
- return true;
- } else if (c == FormatConversionCharInternal::e ||
- c == FormatConversionCharInternal::E) {
- if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
- &exp)) {
- return FallbackToSnprintf(v, conv, sink);
- }
- if (!conv.has_alt_flag() && buffer.back() == '.') buffer.pop_back();
- PrintExponent(
- exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
- &buffer);
- } else if (c == FormatConversionCharInternal::g ||
- c == FormatConversionCharInternal::G) {
- precision = std::max(0, precision - 1);
- if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
- &exp)) {
- return FallbackToSnprintf(v, conv, sink);
- }
- if (precision + 1 > exp && exp >= -4) {
- if (exp < 0) {
- // Have 1.23456, needs 0.00123456
- // Move the first digit
- buffer.begin[1] = *buffer.begin;
- // Add some zeros
- for (; exp < -1; ++exp) *buffer.begin-- = '0';
- *buffer.begin-- = '.';
- *buffer.begin = '0';
- } else if (exp > 0) {
- // Have 1.23456, needs 1234.56
- // Move the '.' exp positions to the right.
- std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);
+ FormatConversionChar c = conv.conversion_char();
+
+ if (c == FormatConversionCharInternal::f ||
+ c == FormatConversionCharInternal::F) {
+ FormatF(decomposed.mantissa, decomposed.exponent,
+ {sign_char, precision, conv, sink});
+ return true;
+ } else if (c == FormatConversionCharInternal::e ||
+ c == FormatConversionCharInternal::E) {
+ if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+ &exp)) {
+ return FallbackToSnprintf(v, conv, sink);
+ }
+ if (!conv.has_alt_flag() && buffer.back() == '.') buffer.pop_back();
+ PrintExponent(
+ exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+ &buffer);
+ } else if (c == FormatConversionCharInternal::g ||
+ c == FormatConversionCharInternal::G) {
+ precision = std::max(0, precision - 1);
+ if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+ &exp)) {
+ return FallbackToSnprintf(v, conv, sink);
+ }
+ if (precision + 1 > exp && exp >= -4) {
+ if (exp < 0) {
+ // Have 1.23456, needs 0.00123456
+ // Move the first digit
+ buffer.begin[1] = *buffer.begin;
+ // Add some zeros
+ for (; exp < -1; ++exp) *buffer.begin-- = '0';
+ *buffer.begin-- = '.';
+ *buffer.begin = '0';
+ } else if (exp > 0) {
+ // Have 1.23456, needs 1234.56
+ // Move the '.' exp positions to the right.
+ std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);
}
- exp = 0;
- }
- if (!conv.has_alt_flag()) {
- while (buffer.back() == '0') buffer.pop_back();
- if (buffer.back() == '.') buffer.pop_back();
- }
- if (exp) {
- PrintExponent(
- exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
- &buffer);
- }
- } else if (c == FormatConversionCharInternal::a ||
- c == FormatConversionCharInternal::A) {
- bool uppercase = (c == FormatConversionCharInternal::A);
- FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,
- decomposed.exponent, uppercase, {sign_char, precision, conv, sink});
- return true;
- } else {
- return false;
+ exp = 0;
+ }
+ if (!conv.has_alt_flag()) {
+ while (buffer.back() == '0') buffer.pop_back();
+ if (buffer.back() == '.') buffer.pop_back();
+ }
+ if (exp) {
+ PrintExponent(
+ exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+ &buffer);
+ }
+ } else if (c == FormatConversionCharInternal::a ||
+ c == FormatConversionCharInternal::A) {
+ bool uppercase = (c == FormatConversionCharInternal::A);
+ FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,
+ decomposed.exponent, uppercase, {sign_char, precision, conv, sink});
+ return true;
+ } else {
+ return false;
}
WriteBufferToSink(sign_char,
- absl::string_view(buffer.begin, buffer.end - buffer.begin),
- conv, sink);
+ absl::string_view(buffer.begin, buffer.end - buffer.begin),
+ conv, sink);
return true;
}
} // namespace
-bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
if (IsDoubleDouble()) {
// This is the `double-double` representation of `long double`. We do not
// handle it natively. Fallback to snprintf.
- return FallbackToSnprintf(v, conv, sink);
- }
-
+ return FallbackToSnprintf(v, conv, sink);
+ }
+
return FloatToSink(v, conv, sink);
}
-bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- return FloatToSink(static_cast<double>(v), conv, sink);
+ return FloatToSink(static_cast<double>(v), conv, sink);
}
-bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
return FloatToSink(v, conv, sink);
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
index 71100e7142..5d44c4b5e9 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
@@ -1,37 +1,37 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
index c4b2470613..f96aa1ecaa 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
@@ -18,7 +18,7 @@
#include <cstring>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -68,5 +68,5 @@ void FILERawSink::Write(string_view v) {
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.h
index 8030dae00f..3eb18ccd47 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.h
@@ -29,7 +29,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
// RawSink implementation that writes into a char* buffer.
@@ -82,15 +82,15 @@ inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
sink->Write(v);
}
-// This is a SFINAE to get a better compiler error message when the type
-// is not supported.
+// This is a SFINAE to get a better compiler error message when the type
+// is not supported.
template <typename T>
-auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
- AbslFormatFlush(out, s);
+auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
+ AbslFormatFlush(out, s);
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
index 2c9c07dacc..b7ace91c1b 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
@@ -1,17 +1,17 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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/internal/str_format/parser.h"
#include <assert.h>
@@ -28,12 +28,12 @@
#include <unordered_set>
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-using CC = FormatConversionCharInternal;
-using LM = LengthMod;
-
+using CC = FormatConversionCharInternal;
+using LM = LengthMod;
+
// Abbreviations to fit in the table below.
constexpr auto f_sign = Flags::kSignCol;
constexpr auto f_alt = Flags::kAlt;
@@ -209,11 +209,11 @@ const char *ConsumeConversion(const char *pos, const char *const end,
using str_format_internal::LengthMod;
LengthMod length_mod = tag.as_length();
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (c == 'h' && length_mod == LengthMod::h) {
- conv->length_mod = LengthMod::hh;
+ if (c == 'h' && length_mod == LengthMod::h) {
+ conv->length_mod = LengthMod::hh;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else if (c == 'l' && length_mod == LengthMod::l) {
- conv->length_mod = LengthMod::ll;
+ } else if (c == 'l' && length_mod == LengthMod::l) {
+ conv->length_mod = LengthMod::ll;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->length_mod = length_mod;
@@ -232,32 +232,32 @@ const char *ConsumeConversion(const char *pos, const char *const end,
} // namespace
-std::string LengthModToString(LengthMod v) {
- switch (v) {
- case LengthMod::h:
- return "h";
- case LengthMod::hh:
- return "hh";
- case LengthMod::l:
- return "l";
- case LengthMod::ll:
- return "ll";
- case LengthMod::L:
- return "L";
- case LengthMod::j:
- return "j";
- case LengthMod::z:
- return "z";
- case LengthMod::t:
- return "t";
- case LengthMod::q:
- return "q";
- case LengthMod::none:
- return "";
- }
- return "";
-}
-
+std::string LengthModToString(LengthMod v) {
+ switch (v) {
+ case LengthMod::h:
+ return "h";
+ case LengthMod::hh:
+ return "hh";
+ case LengthMod::l:
+ return "l";
+ case LengthMod::ll:
+ return "ll";
+ case LengthMod::L:
+ return "L";
+ case LengthMod::j:
+ return "j";
+ case LengthMod::z:
+ return "z";
+ case LengthMod::t:
+ return "t";
+ case LengthMod::q:
+ return "q";
+ case LengthMod::none:
+ return "";
+ }
+ return "";
+}
+
const char *ConsumeUnboundConversion(const char *p, const char *end,
UnboundConversion *conv, int *next_arg) {
if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
@@ -299,17 +299,17 @@ struct ParsedFormatBase::ParsedFormatConsumer {
char* data_pos;
};
-ParsedFormatBase::ParsedFormatBase(
- string_view format, bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs)
+ParsedFormatBase::ParsedFormatBase(
+ string_view format, bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs)
: data_(format.empty() ? nullptr : new char[format.size()]) {
has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||
!MatchesConversions(allow_ignored, convs);
}
bool ParsedFormatBase::MatchesConversions(
- bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs) const {
+ bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs) const {
std::unordered_set<int> used;
auto add_if_valid_conv = [&](int pos, char c) {
if (static_cast<size_t>(pos) > convs.size() ||
@@ -327,13 +327,13 @@ bool ParsedFormatBase::MatchesConversions(
if (conv.width.is_from_arg() &&
!add_if_valid_conv(conv.width.get_from_arg(), '*'))
return false;
- if (!add_if_valid_conv(conv.arg_position,
- FormatConversionCharToChar(conv.conv)))
- return false;
+ if (!add_if_valid_conv(conv.arg_position,
+ FormatConversionCharToChar(conv.conv)))
+ return false;
}
return used.size() == convs.size() || allow_ignored;
}
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
index ad8646edff..c0db5b4335 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
@@ -1,17 +1,17 @@
-// Copyright 2020 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.
-
+// Copyright 2020 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.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
@@ -20,25 +20,25 @@
#include <stdlib.h>
#include <cassert>
-#include <cstdint>
+#include <cstdint>
#include <initializer_list>
#include <iosfwd>
#include <iterator>
#include <memory>
-#include <string>
+#include <string>
#include <vector>
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
-
-std::string LengthModToString(LengthMod v);
-
+enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
+
+std::string LengthModToString(LengthMod v);
+
// The analyzed properties of a single specified conversion.
struct UnboundConversion {
UnboundConversion() {}
@@ -77,8 +77,8 @@ struct UnboundConversion {
InputValue precision;
Flags flags = Flags::kBasic;
- LengthMod length_mod = LengthMod::none;
- FormatConversionChar conv = FormatConversionCharInternal::kNone;
+ LengthMod length_mod = LengthMod::none;
+ FormatConversionChar conv = FormatConversionCharInternal::kNone;
};
// Consume conversion spec prefix (not including '%') of [p, end) if valid.
@@ -91,12 +91,12 @@ const char* ConsumeUnboundConversion(const char* p, const char* end,
// Helper tag class for the table below.
// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
-// conversions.
+// conversions.
class ConvTag {
public:
- constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
+ constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
: tag_(static_cast<uint8_t>(conversion_char)) {}
- constexpr ConvTag(LengthMod length_mod) // NOLINT
+ constexpr ConvTag(LengthMod length_mod) // NOLINT
: tag_(0x80 | static_cast<uint8_t>(length_mod)) {}
constexpr ConvTag(Flags flags) // NOLINT
: tag_(0xc0 | static_cast<uint8_t>(flags)) {}
@@ -106,11 +106,11 @@ class ConvTag {
bool is_length() const { return (tag_ & 0xC0) == 0x80; }
bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
- FormatConversionChar as_conv() const {
+ FormatConversionChar as_conv() const {
assert(is_conv());
assert(!is_length());
assert(!is_flags());
- return static_cast<FormatConversionChar>(tag_);
+ return static_cast<FormatConversionChar>(tag_);
}
LengthMod as_length() const {
assert(!is_conv());
@@ -165,7 +165,7 @@ bool ParseFormatString(string_view src, Consumer consumer) {
auto tag = GetTagForChar(percent[1]);
if (tag.is_conv()) {
if (ABSL_PREDICT_FALSE(next_arg < 0)) {
- // This indicates an error in the format string.
+ // This indicates an error in the format string.
// The only way to get `next_arg < 0` here is to have a positional
// argument first which sets next_arg to -1 and then a non-positional
// argument.
@@ -208,9 +208,9 @@ constexpr bool EnsureConstexpr(string_view s) {
class ParsedFormatBase {
public:
- explicit ParsedFormatBase(
- string_view format, bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs);
+ explicit ParsedFormatBase(
+ string_view format, bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs);
ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
@@ -257,9 +257,9 @@ class ParsedFormatBase {
private:
// Returns whether the conversions match and if !allow_ignored it verifies
// that all conversions are used by the format.
- bool MatchesConversions(
- bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs) const;
+ bool MatchesConversions(
+ bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs) const;
struct ParsedFormatConsumer;
@@ -304,14 +304,14 @@ class ParsedFormatBase {
// This is the only API that allows the user to pass a runtime specified format
// string. These factory functions will return NULL if the format does not match
// the conversions requested by the user.
-template <FormatConversionCharSet... C>
+template <FormatConversionCharSet... C>
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
public:
explicit ExtendedParsedFormat(string_view format)
-#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
__attribute__((
enable_if(str_format_internal::EnsureConstexpr(format),
- "Format string is not constexpr."),
+ "Format string is not constexpr."),
enable_if(str_format_internal::ValidFormatImpl<C...>(format),
"Format specified does not match the template arguments.")))
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -351,7 +351,7 @@ class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
: ParsedFormatBase(s, allow_ignored, {C...}) {}
};
} // namespace str_format_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_join_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_join_internal.h
index 31dbf672f0..86219f2016 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_join_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_join_internal.h
@@ -43,7 +43,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
//
@@ -308,7 +308,7 @@ std::string JoinRange(const Range& range, absl::string_view separator) {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
index e766421617..a7229b6873 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
@@ -47,7 +47,7 @@
#endif // _GLIBCXX_DEBUG
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// This class is implicitly constructible from everything that absl::string_view
@@ -318,7 +318,7 @@ class Splitter {
Container operator()(const Splitter& splitter) const {
Container c;
auto it = std::inserter(c, c.end());
- for (const auto& sp : splitter) {
+ for (const auto& sp : splitter) {
*it++ = ValueType(sp);
}
return c;
@@ -424,7 +424,7 @@ class Splitter {
};
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
index 8fd8edc1ec..66a2ca9496 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
@@ -17,7 +17,7 @@
#include "absl/strings/internal/utf8.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
@@ -49,5 +49,5 @@ size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
}
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.h b/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.h
index 32fb1093be..38ce7b97d8 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.h
@@ -20,10 +20,10 @@
#include <cstddef>
#include <cstdint>
-#include "absl/base/config.h"
-
+#include "absl/base/config.h"
+
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes
@@ -44,7 +44,7 @@ enum { kMaxEncodedUTF8Size = 4 };
size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
} // namespace strings_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/match.cc b/contrib/restricted/abseil-cpp/absl/strings/match.cc
index 2d67250970..c77d0ad322 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/match.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/match.cc
@@ -17,7 +17,7 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
bool EqualsIgnoreCase(absl::string_view piece1,
absl::string_view piece2) noexcept {
@@ -39,5 +39,5 @@ bool EndsWithIgnoreCase(absl::string_view text,
EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/match.h b/contrib/restricted/abseil-cpp/absl/strings/match.h
index 038cbb3fa8..d83d31ea1d 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/match.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/match.h
@@ -20,7 +20,7 @@
// This file contains simple utilities for performing string matching checks.
// All of these function parameters are specified as `absl::string_view`,
// meaning that these functions can accept `std::string`, `absl::string_view` or
-// NUL-terminated C-style strings.
+// NUL-terminated C-style strings.
//
// Examples:
// std::string s = "foo";
@@ -38,7 +38,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// StrContains()
//
@@ -94,7 +94,7 @@ bool StartsWithIgnoreCase(absl::string_view text,
bool EndsWithIgnoreCase(absl::string_view text,
absl::string_view suffix) noexcept;
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_MATCH_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
index cbd84c918b..43550e3c4b 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
@@ -30,7 +30,7 @@
#include <memory>
#include <utility>
-#include "absl/base/attributes.h"
+#include "absl/base/attributes.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/numeric/bits.h"
#include "absl/strings/ascii.h"
@@ -41,7 +41,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
bool SimpleAtof(absl::string_view str, float* out) {
*out = 0.0;
@@ -730,8 +730,8 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
// commonly used bases.
template <typename IntType>
struct LookupTables {
- ABSL_CONST_INIT static const IntType kVmaxOverBase[];
- ABSL_CONST_INIT static const IntType kVminOverBase[];
+ ABSL_CONST_INIT static const IntType kVmaxOverBase[];
+ ABSL_CONST_INIT static const IntType kVminOverBase[];
};
// An array initializer macro for X/base where base in [0, 36].
@@ -755,49 +755,49 @@ struct LookupTables {
// }
// See https://godbolt.org/z/aneYsb
//
-// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
-// array to avoid a static initializer.
+// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
+// array to avoid a static initializer.
template<>
-const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
- 0,
- 0,
- MakeUint128(9223372036854775807u, 18446744073709551615u),
- MakeUint128(6148914691236517205u, 6148914691236517205u),
- MakeUint128(4611686018427387903u, 18446744073709551615u),
- MakeUint128(3689348814741910323u, 3689348814741910323u),
- MakeUint128(3074457345618258602u, 12297829382473034410u),
- MakeUint128(2635249153387078802u, 5270498306774157604u),
- MakeUint128(2305843009213693951u, 18446744073709551615u),
- MakeUint128(2049638230412172401u, 14347467612885206812u),
- MakeUint128(1844674407370955161u, 11068046444225730969u),
- MakeUint128(1676976733973595601u, 8384883669867978007u),
- MakeUint128(1537228672809129301u, 6148914691236517205u),
- MakeUint128(1418980313362273201u, 4256940940086819603u),
- MakeUint128(1317624576693539401u, 2635249153387078802u),
- MakeUint128(1229782938247303441u, 1229782938247303441u),
- MakeUint128(1152921504606846975u, 18446744073709551615u),
- MakeUint128(1085102592571150095u, 1085102592571150095u),
- MakeUint128(1024819115206086200u, 16397105843297379214u),
- MakeUint128(970881267037344821u, 16504981539634861972u),
- MakeUint128(922337203685477580u, 14757395258967641292u),
- MakeUint128(878416384462359600u, 14054662151397753612u),
- MakeUint128(838488366986797800u, 13415813871788764811u),
- MakeUint128(802032351030850070u, 4812194106185100421u),
- MakeUint128(768614336404564650u, 12297829382473034410u),
- MakeUint128(737869762948382064u, 11805916207174113034u),
- MakeUint128(709490156681136600u, 11351842506898185609u),
- MakeUint128(683212743470724133u, 17080318586768103348u),
- MakeUint128(658812288346769700u, 10540996613548315209u),
- MakeUint128(636094623231363848u, 15266270957552732371u),
- MakeUint128(614891469123651720u, 9838263505978427528u),
- MakeUint128(595056260442243600u, 9520900167075897608u),
- MakeUint128(576460752303423487u, 18446744073709551615u),
- MakeUint128(558992244657865200u, 8943875914525843207u),
- MakeUint128(542551296285575047u, 9765923333140350855u),
- MakeUint128(527049830677415760u, 8432797290838652167u),
- MakeUint128(512409557603043100u, 8198552921648689607u),
-};
-
+const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
+ 0,
+ 0,
+ MakeUint128(9223372036854775807u, 18446744073709551615u),
+ MakeUint128(6148914691236517205u, 6148914691236517205u),
+ MakeUint128(4611686018427387903u, 18446744073709551615u),
+ MakeUint128(3689348814741910323u, 3689348814741910323u),
+ MakeUint128(3074457345618258602u, 12297829382473034410u),
+ MakeUint128(2635249153387078802u, 5270498306774157604u),
+ MakeUint128(2305843009213693951u, 18446744073709551615u),
+ MakeUint128(2049638230412172401u, 14347467612885206812u),
+ MakeUint128(1844674407370955161u, 11068046444225730969u),
+ MakeUint128(1676976733973595601u, 8384883669867978007u),
+ MakeUint128(1537228672809129301u, 6148914691236517205u),
+ MakeUint128(1418980313362273201u, 4256940940086819603u),
+ MakeUint128(1317624576693539401u, 2635249153387078802u),
+ MakeUint128(1229782938247303441u, 1229782938247303441u),
+ MakeUint128(1152921504606846975u, 18446744073709551615u),
+ MakeUint128(1085102592571150095u, 1085102592571150095u),
+ MakeUint128(1024819115206086200u, 16397105843297379214u),
+ MakeUint128(970881267037344821u, 16504981539634861972u),
+ MakeUint128(922337203685477580u, 14757395258967641292u),
+ MakeUint128(878416384462359600u, 14054662151397753612u),
+ MakeUint128(838488366986797800u, 13415813871788764811u),
+ MakeUint128(802032351030850070u, 4812194106185100421u),
+ MakeUint128(768614336404564650u, 12297829382473034410u),
+ MakeUint128(737869762948382064u, 11805916207174113034u),
+ MakeUint128(709490156681136600u, 11351842506898185609u),
+ MakeUint128(683212743470724133u, 17080318586768103348u),
+ MakeUint128(658812288346769700u, 10540996613548315209u),
+ MakeUint128(636094623231363848u, 15266270957552732371u),
+ MakeUint128(614891469123651720u, 9838263505978427528u),
+ MakeUint128(595056260442243600u, 9520900167075897608u),
+ MakeUint128(576460752303423487u, 18446744073709551615u),
+ MakeUint128(558992244657865200u, 8943875914525843207u),
+ MakeUint128(542551296285575047u, 9765923333140350855u),
+ MakeUint128(527049830677415760u, 8432797290838652167u),
+ MakeUint128(512409557603043100u, 8198552921648689607u),
+};
+
// This kVmaxOverBase generated with
// for (int base = 2; base < 37; ++base) {
// absl::int128 max = std::numeric_limits<absl::int128>::max();
@@ -922,8 +922,8 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
assert(base >= 0);
assert(vmax >= static_cast<IntType>(base));
const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
- assert(base < 2 ||
- std::numeric_limits<IntType>::max() / base == vmax_over_base);
+ assert(base < 2 ||
+ std::numeric_limits<IntType>::max() / base == vmax_over_base);
const char* start = text.data();
const char* end = start + text.size();
// loop over digits
@@ -957,8 +957,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base,
assert(vmin < 0);
assert(vmin <= 0 - base);
IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
- assert(base < 2 ||
- std::numeric_limits<IntType>::min() / base == vmin_over_base);
+ assert(base < 2 ||
+ std::numeric_limits<IntType>::min() / base == vmin_over_base);
// 2003 c++ standard [expr.mul]
// "... the sign of the remainder is implementation-defined."
// Although (vmin/base)*base + vmin%base is always vmin.
@@ -1024,10 +1024,10 @@ inline bool safe_uint_internal(absl::string_view text, IntType* value_p,
namespace numbers_internal {
// Digit conversion.
-ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
- "0123456789abcdef";
+ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
+ "0123456789abcdef";
-ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
+ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
@@ -1045,7 +1045,7 @@ ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
+ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
{'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
{'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
@@ -1089,5 +1089,5 @@ bool safe_strtou128_base(absl::string_view text, uint128* value, int base) {
}
} // namespace numbers_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.h b/contrib/restricted/abseil-cpp/absl/strings/numbers.h
index 899e623c8c..6cdaa73db0 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/numbers.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.h
@@ -39,7 +39,7 @@
#include <string>
#include <type_traits>
-#include "absl/base/config.h"
+#include "absl/base/config.h"
#ifdef __SSE4_2__
// TODO(jorg): Remove this when we figure out the right way
// to swap bytes on SSE 4.2 that works with the compilers
@@ -55,24 +55,24 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// SimpleAtoi()
//
-// Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into an integer value, returning `true` if successful. The string
-// must reflect a base-10 integer whose value falls within the range of the
-// integer type (optionally preceded by a `+` or `-`). If any errors are
-// encountered, this function returns `false`, leaving `out` in an unspecified
-// state.
+// Converts the given string (optionally followed or preceded by ASCII
+// whitespace) into an integer value, returning `true` if successful. The string
+// must reflect a base-10 integer whose value falls within the range of the
+// integer type (optionally preceded by a `+` or `-`). If any errors are
+// encountered, this function returns `false`, leaving `out` in an unspecified
+// state.
template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
// SimpleAtof()
//
// Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a float, which may be rounded on overflow or underflow,
-// returning `true` if successful.
+// whitespace) into a float, which may be rounded on overflow or underflow,
+// returning `true` if successful.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
// allowed formats for `str`, except SimpleAtof() is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function
@@ -82,8 +82,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
// SimpleAtod()
//
// Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a double, which may be rounded on overflow or underflow,
-// returning `true` if successful.
+// whitespace) into a double, which may be rounded on overflow or underflow,
+// returning `true` if successful.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
// allowed formats for `str`, except SimpleAtod is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function
@@ -119,21 +119,21 @@ ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
absl::uint128* out);
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
// End of public API. Implementation details follow.
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace numbers_internal {
// Digit conversion.
-ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
-ABSL_DLL extern const char
- kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
-ABSL_DLL extern const char
- two_ASCII_digits[100][2]; // 00, 01, 02, 03...
+ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
+ABSL_DLL extern const char
+ kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
+ABSL_DLL extern const char
+ two_ASCII_digits[100][2]; // 00, 01, 02, 03...
// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
// range 0 <= i < 100, and buf must have space for two characters. Example:
@@ -298,7 +298,7 @@ ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
return numbers_internal::safe_strtou128_base(str, out, 16);
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_NUMBERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
index f4a77493a4..5bd867d918 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
@@ -25,7 +25,7 @@
#include "absl/strings/numbers.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
AlphaNum::AlphaNum(Hex hex) {
static_assert(numbers_internal::kFastToBufferSize >= 32,
@@ -141,12 +141,12 @@ namespace strings_internal {
std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
std::string result;
size_t total_size = 0;
- for (const absl::string_view& piece : pieces) total_size += piece.size();
+ for (const absl::string_view& piece : pieces) total_size += piece.size();
strings_internal::STLStringResizeUninitialized(&result, total_size);
char* const begin = &result[0];
char* out = begin;
- for (const absl::string_view& piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
@@ -170,7 +170,7 @@ void AppendPieces(std::string* dest,
std::initializer_list<absl::string_view> pieces) {
size_t old_size = dest->size();
size_t total_size = old_size;
- for (const absl::string_view& piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
ASSERT_NO_OVERLAP(*dest, piece);
total_size += piece.size();
}
@@ -178,7 +178,7 @@ void AppendPieces(std::string* dest,
char* const begin = &(*dest)[0];
char* out = begin + old_size;
- for (const absl::string_view& piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
@@ -242,5 +242,5 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
assert(out == begin + dest->size());
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
index a8a85c7322..3253bb0077 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
@@ -64,7 +64,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// AlphaNumBuffer allows a way to pass a string to StrCat without having to do
@@ -253,7 +253,7 @@ class AlphaNum {
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
: piece_(str) {}
- // Use string literals ":" instead of character literals ':'.
+ // Use string literals ":" instead of character literals ':'.
AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
AlphaNum(const AlphaNum&) = delete;
@@ -402,7 +402,7 @@ SixDigits(double d) {
return result;
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_CAT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_format.h b/contrib/restricted/abseil-cpp/absl/strings/str_format.h
index 4b05c70c23..d7a2a90d9f 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_format.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_format.h
@@ -19,7 +19,7 @@
//
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
-// header. Like the `printf` family, `str_format` uses a "format string" to
+// header. Like the `printf` family, `str_format` uses a "format string" to
// perform argument substitutions based on types. See the `FormatSpec` section
// below for format string documentation.
//
@@ -57,7 +57,7 @@
// arbitrary sink types:
//
// * A generic `Format()` function to write outputs to arbitrary sink types,
-// which must implement a `FormatRawSink` interface.
+// which must implement a `FormatRawSink` interface.
//
// * A `FormatUntyped()` function that is similar to `Format()` except it is
// loosely typed. `FormatUntyped()` is not a template and does not perform
@@ -65,7 +65,7 @@
// boolean from a runtime check.
//
// In addition, the `str_format` library provides extension points for
-// augmenting formatting to new types. See "StrFormat Extensions" below.
+// augmenting formatting to new types. See "StrFormat Extensions" below.
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
@@ -80,7 +80,7 @@
#include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// UntypedFormatSpec
//
@@ -253,8 +253,8 @@ class FormatCountCapture {
// argument, etc.
template <typename... Args>
-using FormatSpec = str_format_internal::FormatSpecTemplate<
- str_format_internal::ArgumentToConv<Args>()...>;
+using FormatSpec = str_format_internal::FormatSpecTemplate<
+ str_format_internal::ArgumentToConv<Args>()...>;
// ParsedFormat
//
@@ -281,36 +281,36 @@ using FormatSpec = str_format_internal::FormatSpecTemplate<
// } else {
// ... error case ...
// }
-
-#if defined(__cpp_nontype_template_parameter_auto)
-// If C++17 is available, an 'extended' format is also allowed that can specify
-// multiple conversion characters per format argument, using a combination of
-// `absl::FormatConversionCharSet` enum values (logically a set union)
-// via the `|` operator. (Single character-based arguments are still accepted,
-// but cannot be combined). Some common conversions also have predefined enum
-// values, such as `absl::FormatConversionCharSet::kIntegral`.
-//
-// Example:
-// // Extended format supports multiple conversion characters per argument,
-// // specified via a combination of `FormatConversionCharSet` enums.
-// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
-// absl::FormatConversionCharSet::x>;
-// MyFormat GetFormat(bool use_hex) {
-// if (use_hex) return MyFormat("foo %x bar");
-// return MyFormat("foo %d bar");
-// }
-// // `format` can be used with any value that supports 'd' and 'x',
-// // like `int`.
-// auto format = GetFormat(use_hex);
-// value = StringF(format, i);
-template <auto... Conv>
-using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
- absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
-#else
+
+#if defined(__cpp_nontype_template_parameter_auto)
+// If C++17 is available, an 'extended' format is also allowed that can specify
+// multiple conversion characters per format argument, using a combination of
+// `absl::FormatConversionCharSet` enum values (logically a set union)
+// via the `|` operator. (Single character-based arguments are still accepted,
+// but cannot be combined). Some common conversions also have predefined enum
+// values, such as `absl::FormatConversionCharSet::kIntegral`.
+//
+// Example:
+// // Extended format supports multiple conversion characters per argument,
+// // specified via a combination of `FormatConversionCharSet` enums.
+// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
+// absl::FormatConversionCharSet::x>;
+// MyFormat GetFormat(bool use_hex) {
+// if (use_hex) return MyFormat("foo %x bar");
+// return MyFormat("foo %d bar");
+// }
+// // `format` can be used with any value that supports 'd' and 'x',
+// // like `int`.
+// auto format = GetFormat(use_hex);
+// value = StringF(format, i);
+template <auto... Conv>
+using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
+ absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#else
template <char... Conv>
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
- absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
-#endif // defined(__cpp_nontype_template_parameter_auto)
+ absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#endif // defined(__cpp_nontype_template_parameter_auto)
// StrFormat()
//
@@ -427,7 +427,7 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
//
// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
-// bytes of the formatted output to `output`, including a NUL-terminator, and
+// bytes of the formatted output to `output`, including a NUL-terminator, and
// returns the number of bytes that would have been written if truncation did
// not occur. In the event of an error, a negative value is returned and `errno`
// is set.
@@ -457,16 +457,16 @@ int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
//
// FormatRawSink is a type erased wrapper around arbitrary sink objects
// specifically used as an argument to `Format()`.
-//
-// All the object has to do define an overload of `AbslFormatFlush()` for the
-// sink, usually by adding a ADL-based free function in the same namespace as
-// the sink:
-//
-// void AbslFormatFlush(MySink* dest, absl::string_view part);
-//
-// where `dest` is the pointer passed to `absl::Format()`. The function should
-// append `part` to `dest`.
-//
+//
+// All the object has to do define an overload of `AbslFormatFlush()` for the
+// sink, usually by adding a ADL-based free function in the same namespace as
+// the sink:
+//
+// void AbslFormatFlush(MySink* dest, absl::string_view part);
+//
+// where `dest` is the pointer passed to `absl::Format()`. The function should
+// append `part` to `dest`.
+//
// FormatRawSink does not own the passed sink object. The passed object must
// outlive the FormatRawSink.
class FormatRawSink {
@@ -490,13 +490,13 @@ class FormatRawSink {
// `absl::FormatRawSink` interface), using a format string and zero or more
// additional arguments.
//
-// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
-// destination objects. If a `std::string` is used the formatted string is
-// appended to it.
+// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
+// destination objects. If a `std::string` is used the formatted string is
+// appended to it.
//
-// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
-// custom sinks. The format string, like format strings for `StrFormat()`, is
-// checked at compile-time.
+// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
+// custom sinks. The format string, like format strings for `StrFormat()`, is
+// checked at compile-time.
//
// On failure, this function returns `false` and the state of the sink is
// unspecified.
@@ -566,247 +566,247 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
}
-//------------------------------------------------------------------------------
-// StrFormat Extensions
-//------------------------------------------------------------------------------
-//
-// AbslFormatConvert()
-//
-// The StrFormat library provides a customization API for formatting
-// user-defined types using absl::StrFormat(). The API relies on detecting an
-// overload in the user-defined type's namespace of a free (non-member)
-// `AbslFormatConvert()` function, usually as a friend definition with the
-// following signature:
-//
-// absl::FormatConvertResult<...> AbslFormatConvert(
-// const X& value,
-// const absl::FormatConversionSpec& spec,
-// absl::FormatSink *sink);
-//
-// An `AbslFormatConvert()` overload for a type should only be declared in the
-// same file and namespace as said type.
-//
-// The abstractions within this definition include:
-//
-// * An `absl::FormatConversionSpec` to specify the fields to pull from a
-// user-defined type's format string
-// * An `absl::FormatSink` to hold the converted string data during the
-// conversion process.
-// * An `absl::FormatConvertResult` to hold the status of the returned
-// formatting operation
-//
-// The return type encodes all the conversion characters that your
-// AbslFormatConvert() routine accepts. The return value should be {true}.
-// A return value of {false} will result in `StrFormat()` returning
-// an empty string. This result will be propagated to the result of
-// `FormatUntyped`.
-//
-// Example:
-//
-// struct Point {
-// // To add formatting support to `Point`, we simply need to add a free
-// // (non-member) function `AbslFormatConvert()`. This method interprets
-// // `spec` to print in the request format. The allowed conversion characters
-// // can be restricted via the type of the result, in this example
-// // string and integral formatting are allowed (but not, for instance
-// // floating point characters like "%f"). You can add such a free function
-// // using a friend declaration within the body of the class:
-// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
-// absl::FormatConversionCharSet::kIntegral>
-// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
-// absl::FormatSink* s) {
-// if (spec.conversion_char() == absl::FormatConversionChar::s) {
-// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
-// } else {
-// s->Append(absl::StrCat(p.x, ",", p.y));
-// }
-// return {true};
-// }
-//
-// int x;
-// int y;
-// };
-
-// clang-format off
-
-// FormatConversionChar
-//
-// Specifies the formatting character provided in the format string
-// passed to `StrFormat()`.
-enum class FormatConversionChar : uint8_t {
- c, s, // text
- d, i, o, u, x, X, // int
- f, F, e, E, g, G, a, A, // float
- n, p // misc
-};
-// clang-format on
-
-// FormatConversionSpec
-//
-// Specifies modifications to the conversion of the format string, through use
-// of one or more format flags in the source format string.
-class FormatConversionSpec {
- public:
- // FormatConversionSpec::is_basic()
- //
- // Indicates that width and precision are not specified, and no additional
- // flags are set for this conversion character in the format string.
- bool is_basic() const { return impl_.is_basic(); }
-
- // FormatConversionSpec::has_left_flag()
- //
- // Indicates whether the result should be left justified for this conversion
- // character in the format string. This flag is set through use of a '-'
- // character in the format string. E.g. "%-s"
- bool has_left_flag() const { return impl_.has_left_flag(); }
-
- // FormatConversionSpec::has_show_pos_flag()
- //
- // Indicates whether a sign column is prepended to the result for this
- // conversion character in the format string, even if the result is positive.
- // This flag is set through use of a '+' character in the format string.
- // E.g. "%+d"
- bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
-
- // FormatConversionSpec::has_sign_col_flag()
- //
- // Indicates whether a mandatory sign column is added to the result for this
- // conversion character. This flag is set through use of a space character
- // (' ') in the format string. E.g. "% i"
- bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
-
- // FormatConversionSpec::has_alt_flag()
- //
- // Indicates whether an "alternate" format is applied to the result for this
- // conversion character. Alternative forms depend on the type of conversion
- // character, and unallowed alternatives are undefined. This flag is set
- // through use of a '#' character in the format string. E.g. "%#h"
- bool has_alt_flag() const { return impl_.has_alt_flag(); }
-
- // FormatConversionSpec::has_zero_flag()
- //
- // Indicates whether zeroes should be prepended to the result for this
- // conversion character instead of spaces. This flag is set through use of the
- // '0' character in the format string. E.g. "%0f"
- bool has_zero_flag() const { return impl_.has_zero_flag(); }
-
- // FormatConversionSpec::conversion_char()
- //
- // Returns the underlying conversion character.
- FormatConversionChar conversion_char() const {
- return impl_.conversion_char();
- }
-
- // FormatConversionSpec::width()
- //
- // Returns the specified width (indicated through use of a non-zero integer
- // value or '*' character) of the conversion character. If width is
- // unspecified, it returns a negative value.
- int width() const { return impl_.width(); }
-
- // FormatConversionSpec::precision()
- //
- // Returns the specified precision (through use of the '.' character followed
- // by a non-zero integer value or '*' character) of the conversion character.
- // If precision is unspecified, it returns a negative value.
- int precision() const { return impl_.precision(); }
-
- private:
- explicit FormatConversionSpec(
- str_format_internal::FormatConversionSpecImpl impl)
- : impl_(impl) {}
-
- friend str_format_internal::FormatConversionSpecImpl;
-
- absl::str_format_internal::FormatConversionSpecImpl impl_;
-};
-
-// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
-// conversion chars in custom format converters.
-constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
- FormatConversionCharSet b) {
- return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
- static_cast<uint64_t>(b));
-}
-
-// FormatConversionCharSet
-//
-// Specifies the _accepted_ conversion types as a template parameter to
-// FormatConvertResult for custom implementations of `AbslFormatConvert`.
-// Note the helper predefined alias definitions (kIntegral, etc.) below.
-enum class FormatConversionCharSet : uint64_t {
- // text
- c = str_format_internal::FormatConversionCharToConvInt('c'),
- s = str_format_internal::FormatConversionCharToConvInt('s'),
- // integer
- d = str_format_internal::FormatConversionCharToConvInt('d'),
- i = str_format_internal::FormatConversionCharToConvInt('i'),
- o = str_format_internal::FormatConversionCharToConvInt('o'),
- u = str_format_internal::FormatConversionCharToConvInt('u'),
- x = str_format_internal::FormatConversionCharToConvInt('x'),
- X = str_format_internal::FormatConversionCharToConvInt('X'),
- // Float
- f = str_format_internal::FormatConversionCharToConvInt('f'),
- F = str_format_internal::FormatConversionCharToConvInt('F'),
- e = str_format_internal::FormatConversionCharToConvInt('e'),
- E = str_format_internal::FormatConversionCharToConvInt('E'),
- g = str_format_internal::FormatConversionCharToConvInt('g'),
- G = str_format_internal::FormatConversionCharToConvInt('G'),
- a = str_format_internal::FormatConversionCharToConvInt('a'),
- A = str_format_internal::FormatConversionCharToConvInt('A'),
- // misc
- n = str_format_internal::FormatConversionCharToConvInt('n'),
- p = str_format_internal::FormatConversionCharToConvInt('p'),
-
- // Used for width/precision '*' specification.
- kStar = static_cast<uint64_t>(
- absl::str_format_internal::FormatConversionCharSetInternal::kStar),
- // Some predefined values:
- kIntegral = d | i | u | o | x | X,
- kFloating = a | e | f | g | A | E | F | G,
- kNumeric = kIntegral | kFloating,
- kString = s,
- kPointer = p,
-};
-
-// FormatSink
-//
-// An abstraction to which conversions write their string data.
-//
-class FormatSink {
- public:
- // Appends `count` copies of `ch`.
- void Append(size_t count, char ch) { sink_->Append(count, ch); }
-
- void Append(string_view v) { sink_->Append(v); }
-
- // Appends the first `precision` bytes of `v`. If this is less than
- // `width`, spaces will be appended first (if `left` is false), or
- // after (if `left` is true) to ensure the total amount appended is
- // at least `width`.
- bool PutPaddedString(string_view v, int width, int precision, bool left) {
- return sink_->PutPaddedString(v, width, precision, left);
- }
-
- private:
- friend str_format_internal::FormatSinkImpl;
- explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
- str_format_internal::FormatSinkImpl* sink_;
-};
-
-// FormatConvertResult
-//
-// Indicates whether a call to AbslFormatConvert() was successful.
-// This return type informs the StrFormat extension framework (through
-// ADL but using the return type) of what conversion characters are supported.
-// It is strongly discouraged to return {false}, as this will result in an
-// empty string in StrFormat.
-template <FormatConversionCharSet C>
-struct FormatConvertResult {
- bool value;
-};
-
-ABSL_NAMESPACE_END
+//------------------------------------------------------------------------------
+// StrFormat Extensions
+//------------------------------------------------------------------------------
+//
+// AbslFormatConvert()
+//
+// The StrFormat library provides a customization API for formatting
+// user-defined types using absl::StrFormat(). The API relies on detecting an
+// overload in the user-defined type's namespace of a free (non-member)
+// `AbslFormatConvert()` function, usually as a friend definition with the
+// following signature:
+//
+// absl::FormatConvertResult<...> AbslFormatConvert(
+// const X& value,
+// const absl::FormatConversionSpec& spec,
+// absl::FormatSink *sink);
+//
+// An `AbslFormatConvert()` overload for a type should only be declared in the
+// same file and namespace as said type.
+//
+// The abstractions within this definition include:
+//
+// * An `absl::FormatConversionSpec` to specify the fields to pull from a
+// user-defined type's format string
+// * An `absl::FormatSink` to hold the converted string data during the
+// conversion process.
+// * An `absl::FormatConvertResult` to hold the status of the returned
+// formatting operation
+//
+// The return type encodes all the conversion characters that your
+// AbslFormatConvert() routine accepts. The return value should be {true}.
+// A return value of {false} will result in `StrFormat()` returning
+// an empty string. This result will be propagated to the result of
+// `FormatUntyped`.
+//
+// Example:
+//
+// struct Point {
+// // To add formatting support to `Point`, we simply need to add a free
+// // (non-member) function `AbslFormatConvert()`. This method interprets
+// // `spec` to print in the request format. The allowed conversion characters
+// // can be restricted via the type of the result, in this example
+// // string and integral formatting are allowed (but not, for instance
+// // floating point characters like "%f"). You can add such a free function
+// // using a friend declaration within the body of the class:
+// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+// absl::FormatConversionCharSet::kIntegral>
+// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+// absl::FormatSink* s) {
+// if (spec.conversion_char() == absl::FormatConversionChar::s) {
+// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+// } else {
+// s->Append(absl::StrCat(p.x, ",", p.y));
+// }
+// return {true};
+// }
+//
+// int x;
+// int y;
+// };
+
+// clang-format off
+
+// FormatConversionChar
+//
+// Specifies the formatting character provided in the format string
+// passed to `StrFormat()`.
+enum class FormatConversionChar : uint8_t {
+ c, s, // text
+ d, i, o, u, x, X, // int
+ f, F, e, E, g, G, a, A, // float
+ n, p // misc
+};
+// clang-format on
+
+// FormatConversionSpec
+//
+// Specifies modifications to the conversion of the format string, through use
+// of one or more format flags in the source format string.
+class FormatConversionSpec {
+ public:
+ // FormatConversionSpec::is_basic()
+ //
+ // Indicates that width and precision are not specified, and no additional
+ // flags are set for this conversion character in the format string.
+ bool is_basic() const { return impl_.is_basic(); }
+
+ // FormatConversionSpec::has_left_flag()
+ //
+ // Indicates whether the result should be left justified for this conversion
+ // character in the format string. This flag is set through use of a '-'
+ // character in the format string. E.g. "%-s"
+ bool has_left_flag() const { return impl_.has_left_flag(); }
+
+ // FormatConversionSpec::has_show_pos_flag()
+ //
+ // Indicates whether a sign column is prepended to the result for this
+ // conversion character in the format string, even if the result is positive.
+ // This flag is set through use of a '+' character in the format string.
+ // E.g. "%+d"
+ bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
+
+ // FormatConversionSpec::has_sign_col_flag()
+ //
+ // Indicates whether a mandatory sign column is added to the result for this
+ // conversion character. This flag is set through use of a space character
+ // (' ') in the format string. E.g. "% i"
+ bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
+
+ // FormatConversionSpec::has_alt_flag()
+ //
+ // Indicates whether an "alternate" format is applied to the result for this
+ // conversion character. Alternative forms depend on the type of conversion
+ // character, and unallowed alternatives are undefined. This flag is set
+ // through use of a '#' character in the format string. E.g. "%#h"
+ bool has_alt_flag() const { return impl_.has_alt_flag(); }
+
+ // FormatConversionSpec::has_zero_flag()
+ //
+ // Indicates whether zeroes should be prepended to the result for this
+ // conversion character instead of spaces. This flag is set through use of the
+ // '0' character in the format string. E.g. "%0f"
+ bool has_zero_flag() const { return impl_.has_zero_flag(); }
+
+ // FormatConversionSpec::conversion_char()
+ //
+ // Returns the underlying conversion character.
+ FormatConversionChar conversion_char() const {
+ return impl_.conversion_char();
+ }
+
+ // FormatConversionSpec::width()
+ //
+ // Returns the specified width (indicated through use of a non-zero integer
+ // value or '*' character) of the conversion character. If width is
+ // unspecified, it returns a negative value.
+ int width() const { return impl_.width(); }
+
+ // FormatConversionSpec::precision()
+ //
+ // Returns the specified precision (through use of the '.' character followed
+ // by a non-zero integer value or '*' character) of the conversion character.
+ // If precision is unspecified, it returns a negative value.
+ int precision() const { return impl_.precision(); }
+
+ private:
+ explicit FormatConversionSpec(
+ str_format_internal::FormatConversionSpecImpl impl)
+ : impl_(impl) {}
+
+ friend str_format_internal::FormatConversionSpecImpl;
+
+ absl::str_format_internal::FormatConversionSpecImpl impl_;
+};
+
+// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
+// conversion chars in custom format converters.
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+ FormatConversionCharSet b) {
+ return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(b));
+}
+
+// FormatConversionCharSet
+//
+// Specifies the _accepted_ conversion types as a template parameter to
+// FormatConvertResult for custom implementations of `AbslFormatConvert`.
+// Note the helper predefined alias definitions (kIntegral, etc.) below.
+enum class FormatConversionCharSet : uint64_t {
+ // text
+ c = str_format_internal::FormatConversionCharToConvInt('c'),
+ s = str_format_internal::FormatConversionCharToConvInt('s'),
+ // integer
+ d = str_format_internal::FormatConversionCharToConvInt('d'),
+ i = str_format_internal::FormatConversionCharToConvInt('i'),
+ o = str_format_internal::FormatConversionCharToConvInt('o'),
+ u = str_format_internal::FormatConversionCharToConvInt('u'),
+ x = str_format_internal::FormatConversionCharToConvInt('x'),
+ X = str_format_internal::FormatConversionCharToConvInt('X'),
+ // Float
+ f = str_format_internal::FormatConversionCharToConvInt('f'),
+ F = str_format_internal::FormatConversionCharToConvInt('F'),
+ e = str_format_internal::FormatConversionCharToConvInt('e'),
+ E = str_format_internal::FormatConversionCharToConvInt('E'),
+ g = str_format_internal::FormatConversionCharToConvInt('g'),
+ G = str_format_internal::FormatConversionCharToConvInt('G'),
+ a = str_format_internal::FormatConversionCharToConvInt('a'),
+ A = str_format_internal::FormatConversionCharToConvInt('A'),
+ // misc
+ n = str_format_internal::FormatConversionCharToConvInt('n'),
+ p = str_format_internal::FormatConversionCharToConvInt('p'),
+
+ // Used for width/precision '*' specification.
+ kStar = static_cast<uint64_t>(
+ absl::str_format_internal::FormatConversionCharSetInternal::kStar),
+ // Some predefined values:
+ kIntegral = d | i | u | o | x | X,
+ kFloating = a | e | f | g | A | E | F | G,
+ kNumeric = kIntegral | kFloating,
+ kString = s,
+ kPointer = p,
+};
+
+// FormatSink
+//
+// An abstraction to which conversions write their string data.
+//
+class FormatSink {
+ public:
+ // Appends `count` copies of `ch`.
+ void Append(size_t count, char ch) { sink_->Append(count, ch); }
+
+ void Append(string_view v) { sink_->Append(v); }
+
+ // Appends the first `precision` bytes of `v`. If this is less than
+ // `width`, spaces will be appended first (if `left` is false), or
+ // after (if `left` is true) to ensure the total amount appended is
+ // at least `width`.
+ bool PutPaddedString(string_view v, int width, int precision, bool left) {
+ return sink_->PutPaddedString(v, width, precision, left);
+ }
+
+ private:
+ friend str_format_internal::FormatSinkImpl;
+ explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
+ str_format_internal::FormatSinkImpl* sink_;
+};
+
+// FormatConvertResult
+//
+// Indicates whether a call to AbslFormatConvert() was successful.
+// This return type informs the StrFormat extension framework (through
+// ADL but using the return type) of what conversion characters are supported.
+// It is strongly discouraged to return {false}, as this will result in an
+// empty string in StrFormat.
+template <FormatConversionCharSet C>
+struct FormatConvertResult {
+ bool value;
+};
+
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_join.h b/contrib/restricted/abseil-cpp/absl/strings/str_join.h
index 33534536cf..5f388b5000 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_join.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_join.h
@@ -60,7 +60,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// Concept: Formatter
@@ -287,7 +287,7 @@ std::string StrJoin(const std::tuple<T...>& value,
return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_JOIN_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc b/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc
index 2bd5fa9821..73c72a46a1 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc
@@ -17,7 +17,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
using FixedMapping =
@@ -78,5 +78,5 @@ int StrReplaceAll(strings_internal::FixedMapping replacements,
return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_replace.h b/contrib/restricted/abseil-cpp/absl/strings/str_replace.h
index 273c707735..00dd1b85cf 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_replace.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_replace.h
@@ -46,7 +46,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// StrReplaceAll()
//
@@ -213,7 +213,7 @@ int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) {
return substitutions;
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_REPLACE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_split.cc b/contrib/restricted/abseil-cpp/absl/strings/str_split.cc
index e08c26b6bb..e421049bc2 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_split.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_split.cc
@@ -27,7 +27,7 @@
#include "absl/strings/ascii.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -42,7 +42,7 @@ absl::string_view GenericFind(absl::string_view text,
absl::string_view delimiter, size_t pos,
FindPolicy find_policy) {
if (delimiter.empty() && text.length() > 0) {
- // Special case for empty string delimiters: always return a zero-length
+ // Special case for empty string delimiters: always return a zero-length
// absl::string_view referring to the item at position 1 past pos.
return absl::string_view(text.data() + pos + 1, 0);
}
@@ -127,7 +127,7 @@ absl::string_view ByLength::Find(absl::string_view text,
size_t pos) const {
pos = std::min(pos, text.size()); // truncate `pos`
absl::string_view substr = text.substr(pos);
- // If the string is shorter than the chunk size we say we
+ // If the string is shorter than the chunk size we say we
// "can't find the delimiter" so this will be the last chunk.
if (substr.length() <= static_cast<size_t>(length_))
return absl::string_view(text.data() + text.size(), 0);
@@ -135,5 +135,5 @@ absl::string_view ByLength::Find(absl::string_view text,
return absl::string_view(substr.data() + length_, 0);
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_split.h b/contrib/restricted/abseil-cpp/absl/strings/str_split.h
index bfbca422a8..092edff75f 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_split.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_split.h
@@ -44,13 +44,13 @@
#include <vector>
#include "absl/base/internal/raw_logging.h"
-#include "absl/base/macros.h"
+#include "absl/base/macros.h"
#include "absl/strings/internal/str_split_internal.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Delimiters
@@ -542,7 +542,7 @@ StrSplit(StringType&& text, Delimiter d, Predicate p) {
std::move(text), DelimiterType(d), std::move(p));
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_SPLIT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
index d596e08cde..2e62545317 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
@@ -24,7 +24,7 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace {
void WritePadding(std::ostream& o, size_t pad) {
@@ -224,7 +224,7 @@ constexpr string_view::size_type string_view::npos;
ABSL_STRING_VIEW_SELECTANY
constexpr string_view::size_type string_view::kMaxSize;
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.h b/contrib/restricted/abseil-cpp/absl/strings/string_view.h
index 65e74ccb1d..bc2b853a07 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/string_view.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.h
@@ -28,29 +28,29 @@
#define ABSL_STRINGS_STRING_VIEW_H_
#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-#include <iosfwd>
-#include <iterator>
-#include <limits>
-#include <string>
-
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <limits>
+#include <string>
+
#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/optimization.h"
-#include "absl/base/port.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.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
+ABSL_NAMESPACE_BEGIN
+using string_view = std::string_view;
+ABSL_NAMESPACE_END
} // namespace absl
#else // ABSL_USES_STD_STRING_VIEW
@@ -71,7 +71,7 @@ ABSL_NAMESPACE_END
#endif
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// absl::string_view
//
@@ -120,22 +120,22 @@ ABSL_NAMESPACE_BEGIN
// 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
+// 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;
// absl::string_view sv(nullptr, 0);
//
// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
@@ -197,7 +197,7 @@ class string_view {
// code bloat.
: string_view(str.data(), str.size(), SkipCheckLengthTag{}) {}
- // Implicit constructor of a `string_view` from NUL-terminated `str`. When
+ // 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.
@@ -296,9 +296,9 @@ class string_view {
//
// 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 {
- return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
- }
+ constexpr const_reference operator[](size_type i) const {
+ return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+ }
// string_view::at()
//
@@ -316,24 +316,24 @@ class string_view {
// string_view::front()
//
// Returns the first element of a `string_view`.
- constexpr const_reference front() const {
- return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
- }
+ constexpr const_reference front() const {
+ return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+ }
// string_view::back()
//
// Returns the last element of a `string_view`.
- constexpr const_reference back() const {
- return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
- }
+ constexpr const_reference back() const {
+ return ABSL_HARDENING_ASSERT(!empty()), 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.
+ // 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
@@ -341,9 +341,9 @@ class string_view {
// string_view::remove_prefix()
//
// Removes the first `n` characters from the `string_view`. Note that the
- // underlying string is not changed, only the view.
+ // underlying string is not changed, only the view.
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
+ ABSL_HARDENING_ASSERT(n <= length_);
ptr_ += n;
length_ -= n;
}
@@ -351,9 +351,9 @@ class string_view {
// string_view::remove_suffix()
//
// Removes the last `n` characters from the `string_view`. Note that the
- // underlying string is not changed, only the view.
+ // underlying string is not changed, only the view.
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_suffix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
+ ABSL_HARDENING_ASSERT(n <= length_);
length_ -= n;
}
@@ -396,13 +396,13 @@ class string_view {
// 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.
+ // Use absl::ClippedSubstr if you need a truncating substr operation.
constexpr string_view substr(size_type pos = 0, size_type n = npos) const {
- return ABSL_PREDICT_FALSE(pos > length_)
- ? (base_internal::ThrowStdOutOfRange(
- "absl::string_view::substr"),
- string_view())
- : string_view(ptr_ + pos, Min(n, length_ - pos));
+ return ABSL_PREDICT_FALSE(pos > length_)
+ ? (base_internal::ThrowStdOutOfRange(
+ "absl::string_view::substr"),
+ string_view())
+ : string_view(ptr_ + pos, Min(n, length_ - pos));
}
// string_view::compare()
@@ -412,11 +412,11 @@ class string_view {
// 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_,
- Min(length_, x.length_) == 0
- ? 0
- : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
- ptr_, x.ptr_, Min(length_, x.length_)));
+ return CompareImpl(length_, x.length_,
+ Min(length_, x.length_) == 0
+ ? 0
+ : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
+ ptr_, x.ptr_, Min(length_, x.length_)));
}
// Overload of `string_view::compare()` for comparing a substring of the
@@ -437,13 +437,13 @@ class string_view {
constexpr int compare(const char* s) const { return compare(string_view(s)); }
// Overload of `string_view::compare()` for comparing a substring of the
- // `string_view` and a different string C-style string `s`.
+ // `string_view` and a different string C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s) const {
return substr(pos1, count1).compare(string_view(s));
}
// Overload of `string_view::compare()` for comparing a substring of the
- // `string_view` and a substring of a different C-style string `s`.
+ // `string_view` and a substring of a different C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s,
size_type count2) const {
return substr(pos1, count1).compare(string_view(s, count2));
@@ -608,7 +608,7 @@ class string_view {
(std::numeric_limits<difference_type>::max)();
static constexpr size_type CheckLengthInternal(size_type len) {
- return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
+ return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
}
static constexpr size_type StrlenInternal(const char* str) {
@@ -629,15 +629,15 @@ class string_view {
#endif
}
- static constexpr size_t Min(size_type length_a, size_type length_b) {
- return length_a < length_b ? length_a : length_b;
- }
-
+ static constexpr size_t Min(size_type length_a, size_type length_b) {
+ return length_a < length_b ? length_a : length_b;
+ }
+
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);
+ : (compare_result < 0 ? -1 : 1);
}
const char* ptr_;
@@ -676,7 +676,7 @@ constexpr bool operator>=(string_view x, string_view y) noexcept {
// IO Insertion Operator
std::ostream& operator<<(std::ostream& o, string_view piece);
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
@@ -685,7 +685,7 @@ ABSL_NAMESPACE_END
#endif // ABSL_USES_STD_STRING_VIEW
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// ClippedSubstr()
//
@@ -702,11 +702,11 @@ inline string_view ClippedSubstr(string_view s, size_t pos,
// Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
// This function should be used where an `absl::string_view` can be created from
// a possibly-null pointer.
-constexpr string_view NullSafeStringView(const char* p) {
+constexpr string_view NullSafeStringView(const char* p) {
return p ? string_view(p) : string_view();
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STRING_VIEW_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/strip.h b/contrib/restricted/abseil-cpp/absl/strings/strip.h
index 111872ca54..5dfa716942 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/strip.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/strip.h
@@ -30,7 +30,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
// ConsumePrefix()
//
@@ -85,7 +85,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix(
return str;
}
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STRIP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
index 8980b198c2..bc625d4082 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
@@ -23,7 +23,7 @@
#include "absl/strings/string_view.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace substitute_internal {
void SubstituteAndAppendArray(std::string* output, absl::string_view format,
@@ -36,7 +36,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (i + 1 >= format.size()) {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid absl::Substitute() format string: \"%s\".",
+ "Invalid absl::Substitute() format string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -46,8 +46,8 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
#ifndef NDEBUG
ABSL_RAW_LOG(
FATAL,
- "Invalid absl::Substitute() format string: asked for \"$"
- "%d\", but only %d args were given. Full format string was: "
+ "Invalid absl::Substitute() format string: asked for \"$"
+ "%d\", but only %d args were given. Full format string was: "
"\"%s\".",
index, static_cast<int>(num_args), absl::CEscape(format).c_str());
#endif
@@ -61,7 +61,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
} else {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid absl::Substitute() format string: \"%s\".",
+ "Invalid absl::Substitute() format string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -73,7 +73,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (size == 0) return;
- // Build the string.
+ // Build the string.
size_t original_size = output->size();
strings_internal::STLStringResizeUninitializedAmortized(output,
original_size + size);
@@ -168,5 +168,5 @@ Arg::Arg(Dec dec) {
}
} // namespace substitute_internal
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.h b/contrib/restricted/abseil-cpp/absl/strings/substitute.h
index 151c56f543..c928c0979e 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/substitute.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.h
@@ -50,7 +50,7 @@
//
// Supported types:
// * absl::string_view, std::string, const char* (null is equivalent to "")
-// * int32_t, int64_t, uint32_t, uint64_t
+// * int32_t, int64_t, uint32_t, uint64_t
// * float, double
// * bool (Printed as "true" or "false")
// * pointer types other than char* (Printed as "0x<lower case hex string>",
@@ -86,7 +86,7 @@
#include "absl/strings/strip.h"
namespace absl {
-ABSL_NAMESPACE_BEGIN
+ABSL_NAMESPACE_BEGIN
namespace substitute_internal {
// Arg
@@ -99,7 +99,7 @@ namespace substitute_internal {
// This class has implicit constructors.
class Arg {
public:
- // Overloads for string-y things
+ // Overloads for string-y things
//
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(const char* value) // NOLINT(runtime/explicit)
@@ -120,9 +120,9 @@ class Arg {
// representation. However, we can't really know, so we make the caller decide
// what to do.
Arg(char value) // NOLINT(runtime/explicit)
- : piece_(scratch_, 1) {
- scratch_[0] = value;
- }
+ : piece_(scratch_, 1) {
+ scratch_[0] = value;
+ }
Arg(short value) // NOLINT(*)
: piece_(scratch_,
numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
@@ -192,12 +192,12 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
#if defined(ABSL_BAD_CALL_IF)
constexpr int CalculateOneBit(const char* format) {
- // Returns:
- // * 2^N for '$N' when N is in [0-9]
- // * 0 for correct '$' escaping: '$$'.
- // * -1 otherwise.
- return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
- : (1 << (*format - '0'));
+ // Returns:
+ // * 2^N for '$N' when N is in [0-9]
+ // * 0 for correct '$' escaping: '$$'.
+ // * -1 otherwise.
+ return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
+ : (1 << (*format - '0'));
}
constexpr const char* SkipNumber(const char* format) {
@@ -205,11 +205,11 @@ constexpr const char* SkipNumber(const char* format) {
}
constexpr int PlaceholderBitmask(const char* format) {
- return !*format
- ? 0
- : *format != '$' ? PlaceholderBitmask(format + 1)
- : (CalculateOneBit(format + 1) |
- PlaceholderBitmask(SkipNumber(format + 1)));
+ return !*format
+ ? 0
+ : *format != '$' ? PlaceholderBitmask(format + 1)
+ : (CalculateOneBit(format + 1) |
+ PlaceholderBitmask(SkipNumber(format + 1)));
}
#endif // ABSL_BAD_CALL_IF
@@ -715,7 +715,7 @@ std::string Substitute(
"contains an unescaped $ character (use $$ instead)");
#endif // ABSL_BAD_CALL_IF
-ABSL_NAMESPACE_END
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_SUBSTITUTE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/ya.make b/contrib/restricted/abseil-cpp/absl/strings/ya.make
index bc11193f12..52364d460e 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/ya.make
+++ b/contrib/restricted/abseil-cpp/absl/strings/ya.make
@@ -8,16 +8,16 @@ LICENSE(Apache-2.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-PEERDIR(
+PEERDIR(
contrib/restricted/abseil-cpp/absl/base
- contrib/restricted/abseil-cpp/absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp/absl/base/internal/raw_logging
contrib/restricted/abseil-cpp/absl/base/internal/spinlock_wait
contrib/restricted/abseil-cpp/absl/base/internal/throw_delegate
- contrib/restricted/abseil-cpp/absl/base/log_severity
+ contrib/restricted/abseil-cpp/absl/base/log_severity
contrib/restricted/abseil-cpp/absl/numeric
contrib/restricted/abseil-cpp/absl/strings/internal/absl_strings_internal
-)
-
+)
+
ADDINCL(
GLOBAL contrib/restricted/abseil-cpp
)
@@ -26,14 +26,14 @@ NO_COMPILER_WARNINGS()
NO_UTIL()
-CFLAGS(
- -DNOMINMAX
-)
-
+CFLAGS(
+ -DNOMINMAX
+)
+
SRCS(
ascii.cc
charconv.cc
- escaping.cc
+ escaping.cc
internal/charconv_bigint.cc
internal/charconv_parse.cc
internal/memutil.cc