aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp-tstring/y_absl/strings
diff options
context:
space:
mode:
authorheretic <heretic@yandex-team.ru>2022-02-10 16:45:43 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:43 +0300
commit397cbe258b9e064f49c4ca575279f02f39fef76e (patch)
treea0b0eb3cca6a14e4e8ea715393637672fa651284 /contrib/restricted/abseil-cpp-tstring/y_absl/strings
parent43f5a35593ebc9f6bcea619bb170394ea7ae468e (diff)
downloadydb-397cbe258b9e064f49c4ca575279f02f39fef76e.tar.gz
Restoring authorship annotation for <heretic@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/abseil-cpp-tstring/y_absl/strings')
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/.yandex_meta/licenses.list.txt84
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc14
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.cc442
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.h1014
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord/ya.make84
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc26
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal/ya.make68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make12
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h4
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc16
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.cc166
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.h766
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_flat.h278
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.cc1432
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.h1130
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring_reader.h228
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make12
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_handle/ya.make68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_info/ya.make68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/.yandex_meta/licenses.list.txt40
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc472
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h310
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc32
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h58
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h42
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc62
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h296
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc2036
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h34
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h8
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc40
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h54
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make12
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h28
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/string_constant.h128
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc12
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h32
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc264
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h20
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc8
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h578
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc4
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h78
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h46
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc10
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h20
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make12
52 files changed, 5329 insertions, 5329 deletions
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/.yandex_meta/licenses.list.txt
index 9d8552c68c..bd499f8070 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/.yandex_meta/licenses.list.txt
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/.yandex_meta/licenses.list.txt
@@ -1,46 +1,46 @@
-====================Apache-2.0====================
-// 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.
-
-
-====================Apache-2.0====================
-// 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====================
-// Copyright 2017 The Abseil Authors.
-
-
-====================COPYRIGHT====================
-// Copyright 2018 The Abseil Authors.
-
-
-====================COPYRIGHT====================
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
// Copyright 2019 The Abseil Authors.
====================COPYRIGHT====================
-// Copyright 2020 The Abseil Authors.
-
-
-====================COPYRIGHT====================
-// Copyright 2021 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
index 9515ca24dd..865ed0dfeb 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/charconv.cc
@@ -20,7 +20,7 @@
#include <cstring>
#include "y_absl/base/casts.h"
-#include "y_absl/numeric/bits.h"
+#include "y_absl/numeric/bits.h"
#include "y_absl/numeric/int128.h"
#include "y_absl/strings/internal/charconv_bigint.h"
#include "y_absl/strings/internal/charconv_parse.h"
@@ -242,11 +242,11 @@ struct CalculatedFloat {
// Returns the bit width of the given uint128. (Equivalently, returns 128
// minus the number of leading zero bits.)
-unsigned BitWidth(uint128 value) {
+unsigned BitWidth(uint128 value) {
if (Uint128High64(value) == 0) {
- return static_cast<unsigned>(bit_width(Uint128Low64(value)));
+ return static_cast<unsigned>(bit_width(Uint128Low64(value)));
}
- return 128 - countl_zero(Uint128High64(value));
+ return 128 - countl_zero(Uint128High64(value));
}
// Calculates how far to the right a mantissa needs to be shifted to create a
@@ -519,7 +519,7 @@ CalculatedFloat CalculateFromParsedHexadecimal(
const strings_internal::ParsedFloat& parsed_hex) {
uint64_t mantissa = parsed_hex.mantissa;
int exponent = parsed_hex.exponent;
- auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
+ auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
bool result_exact;
exponent += shift;
@@ -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 {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.cc
index 0de4ea1b3c..c37f2c3400 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.cc
@@ -15,12 +15,12 @@
#include "y_absl/strings/cord.h"
#include <algorithm>
-#include <atomic>
+#include <atomic>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
-#include <iostream>
+#include <iostream>
#include <limits>
#include <ostream>
#include <sstream>
@@ -30,14 +30,14 @@
#include "y_absl/base/casts.h"
#include "y_absl/base/internal/raw_logging.h"
-#include "y_absl/base/macros.h"
+#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
#include "y_absl/container/fixed_array.h"
#include "y_absl/container/inlined_vector.h"
#include "y_absl/strings/escaping.h"
#include "y_absl/strings/internal/cord_internal.h"
#include "y_absl/strings/internal/cord_rep_btree.h"
-#include "y_absl/strings/internal/cord_rep_flat.h"
+#include "y_absl/strings/internal/cord_rep_flat.h"
#include "y_absl/strings/internal/cordz_statistics.h"
#include "y_absl/strings/internal/cordz_update_scope.h"
#include "y_absl/strings/internal/cordz_update_tracker.h"
@@ -54,15 +54,15 @@ using ::y_absl::cord_internal::CordRep;
using ::y_absl::cord_internal::CordRepBtree;
using ::y_absl::cord_internal::CordRepConcat;
using ::y_absl::cord_internal::CordRepExternal;
-using ::y_absl::cord_internal::CordRepFlat;
+using ::y_absl::cord_internal::CordRepFlat;
using ::y_absl::cord_internal::CordRepSubstring;
using ::y_absl::cord_internal::CordzUpdateTracker;
using ::y_absl::cord_internal::InlineData;
using ::y_absl::cord_internal::kMaxFlatLength;
-using ::y_absl::cord_internal::kMinFlatLength;
+using ::y_absl::cord_internal::kMinFlatLength;
-using ::y_absl::cord_internal::kInlinedVectorSize;
-using ::y_absl::cord_internal::kMaxBytesToCopy;
+using ::y_absl::cord_internal::kInlinedVectorSize;
+using ::y_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);
@@ -77,18 +77,18 @@ static_assert(Fibonacci(63) == 6557470319842,
// 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),
+ 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
};
@@ -96,8 +96,8 @@ static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
static inline bool btree_enabled() {
return cord_internal::cord_btree_enabled.load(
- std::memory_order_relaxed);
-}
+ std::memory_order_relaxed);
+}
static inline bool IsRootBalanced(CordRep* node) {
if (!node->IsConcat()) {
@@ -114,8 +114,8 @@ static inline bool IsRootBalanced(CordRep* node) {
}
static CordRep* Rebalance(CordRep* node);
-static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
- int indent = 0);
+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);
@@ -158,14 +158,14 @@ static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
// 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);
+ if (left == nullptr) return right;
+ if (right == nullptr) return left;
+ if (left->length == 0) {
+ CordRep::Unref(left);
return right;
}
- if (right->length == 0) {
- CordRep::Unref(right);
+ if (right->length == 0) {
+ CordRep::Unref(right);
return left;
}
@@ -204,23 +204,23 @@ static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
return reps[0];
}
-static CordRepFlat* CreateFlat(const char* data, size_t length,
+static CordRepFlat* CreateFlat(const char* data, size_t length,
size_t alloc_hint) {
- CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
- flat->length = length;
- memcpy(flat->Data(), data, length);
- return flat;
-}
-
+ CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
+ flat->length = length;
+ memcpy(flat->Data(), data, length);
+ return flat;
+}
+
// Creates a new flat or Btree out of the specified array.
-// The returned node has a refcount of 1.
+// The returned node has a refcount of 1.
static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) {
- if (length <= kMaxFlatLength) {
- return CreateFlat(data, length, alloc_hint);
+ if (length <= kMaxFlatLength) {
+ return CreateFlat(data, length, alloc_hint);
}
- CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
- data += kMaxFlatLength;
- length -= kMaxFlatLength;
+ CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
+ data += kMaxFlatLength;
+ length -= kMaxFlatLength;
auto* root = CordRepBtree::Create(flat);
return CordRepBtree::Append(root, {data, length}, alloc_hint);
}
@@ -231,14 +231,14 @@ static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) {
if (length == 0) return nullptr;
if (btree_enabled()) {
return NewBtree(data, length, alloc_hint);
- }
+ }
y_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);
+ CordRepFlat* rep = CordRepFlat::New(len + alloc_hint);
rep->length = len;
- memcpy(rep->Data(), data, len);
+ memcpy(rep->Data(), data, len);
reps[n++] = VerifyTree(rep);
data += len;
length -= len;
@@ -248,12 +248,12 @@ static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) {
namespace cord_internal {
-void InitializeCordRepExternal(y_absl::string_view data, CordRepExternal* rep) {
+void InitializeCordRepExternal(y_absl::string_view data, CordRepExternal* rep) {
assert(!data.empty());
rep->length = data.size();
rep->tag = EXTERNAL;
rep->base = data.data();
- VerifyTree(rep);
+ VerifyTree(rep);
}
} // namespace cord_internal
@@ -261,7 +261,7 @@ void InitializeCordRepExternal(y_absl::string_view data, CordRepExternal* rep) {
static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
// Never create empty substring nodes
if (length == 0) {
- CordRep::Unref(child);
+ CordRep::Unref(child);
return nullptr;
} else {
CordRepSubstring* rep = new CordRepSubstring();
@@ -306,35 +306,35 @@ static CordRep* CordRepFromString(TString&& src) {
// --------------------------------------------------------------------
// Cord::InlineRep functions
-constexpr unsigned char Cord::InlineRep::kMaxInline;
+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);
+ 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();
- set_inline_size(n);
- return data_.as_chars();
+ ResetToEmpty();
+ set_inline_size(n);
+ return data_.as_chars();
}
inline void Cord::InlineRep::reduce_size(size_t n) {
- size_t tag = inline_size();
+ size_t tag = inline_size();
assert(tag <= kMaxInline);
assert(tag >= n);
tag -= n;
- memset(data_.as_chars() + tag, 0, n);
- set_inline_size(static_cast<char>(tag));
+ memset(data_.as_chars() + tag, 0, n);
+ set_inline_size(static_cast<char>(tag));
}
inline void Cord::InlineRep::remove_prefix(size_t n) {
- cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,
- inline_size() - n);
+ cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,
+ inline_size() - n);
reduce_size(n);
}
@@ -342,8 +342,8 @@ inline void Cord::InlineRep::remove_prefix(size_t n) {
// Directly returns `rep` if `rep` is already a CordRepBtree.
static CordRepBtree* ForceBtree(CordRep* rep) {
return rep->IsBtree() ? rep->btree() : CordRepBtree::Create(rep);
-}
-
+}
+
void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
MethodIdentifier method) {
assert(!is_tree());
@@ -405,7 +405,7 @@ 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 {
@@ -421,13 +421,13 @@ 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()) {
- *region = span.data();
- *size = span.size();
- return true;
- }
- }
-
+ if (!span.empty()) {
+ *region = span.data();
+ *size = span.size();
+ return true;
+ }
+ }
+
// Search down the right-hand path for a non-full FLAT node.
CordRep* dst = root;
while (dst->IsConcat() && dst->refcount.IsMutable()) {
@@ -441,7 +441,7 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
}
const size_t in_use = dst->length;
- const size_t capacity = dst->flat()->Capacity();
+ const size_t capacity = dst->flat()->Capacity();
if (in_use == capacity) {
*region = nullptr;
*size = 0;
@@ -456,7 +456,7 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
}
dst->length += size_increase;
- *region = dst->flat()->Data() + in_use;
+ *region = dst->flat()->Data() + in_use;
*size = size_increase;
return true;
}
@@ -474,8 +474,8 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
*region = data_.as_chars() + sz;
*size = has_length ? length : available;
set_inline_size(has_length ? sz + length : kMaxInline);
- return;
- }
+ return;
+ }
}
size_t extra = has_length ? length : (std::max)(sz, kMinFlatLength);
@@ -489,14 +489,14 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
// Allocate new node.
CordRepFlat* new_node = CordRepFlat::New(extra);
new_node->length = std::min(new_node->Capacity(), length);
- *region = new_node->Data();
+ *region = new_node->Data();
*size = new_node->length;
-
+
if (btree_enabled()) {
rep = CordRepBtree::Append(ForceBtree(rep), new_node);
} else {
rep = Concat(rep, new_node);
- }
+ }
CommitTree(root, rep, scope, method);
}
@@ -522,7 +522,7 @@ static bool RepMemoryUsageDataEdge(const CordRep* rep,
sizeof(cord_internal::CordRepExternalImpl<intptr_t>) +
rep->length;
return true;
- }
+ }
return false;
}
@@ -530,7 +530,7 @@ static bool RepMemoryUsageDataEdge(const CordRep* rep,
// will return true.
static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
if (rep->IsFlat()) {
- *total_mem_usage += rep->flat()->AllocatedSize();
+ *total_mem_usage += rep->flat()->AllocatedSize();
return true;
}
if (rep->IsExternal()) {
@@ -570,7 +570,7 @@ void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
void Cord::InlineRep::UnrefTree() {
if (is_tree()) {
CordzInfo::MaybeUntrackCord(data_.cordz_info());
- CordRep::Unref(tree());
+ CordRep::Unref(tree());
}
}
@@ -588,18 +588,18 @@ Cord::Cord(y_absl::string_view src, MethodIdentifier 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(TString&& src);
-
+ }
+}
+
+template Cord::Cord(TString&& 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() {
@@ -612,9 +612,9 @@ void Cord::DestroyCordSlow() {
// Mutators
void Cord::Clear() {
- if (CordRep* tree = contents_.clear()) {
- CordRep::Unref(tree);
- }
+ if (CordRep* tree = contents_.clear()) {
+ CordRep::Unref(tree);
+ }
}
Cord& Cord::AssignLargeString(TString&& src) {
@@ -658,12 +658,12 @@ Cord& Cord::operator=(y_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;
-}
-
+ }
+ 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(y_absl::string_view src,
@@ -680,15 +680,15 @@ void Cord::InlineRep::AppendArray(y_absl::string_view src,
memcpy(region, src.data(), appended);
}
} else {
- // Try to fit in the inline buffer if possible.
- size_t inline_length = inline_size();
+ // Try to fit in the inline buffer if possible.
+ size_t inline_length = inline_size();
if (src.size() <= kMaxInline - inline_length) {
- // Append new data to embedded array
+ // Append new data to embedded array
memcpy(data_.as_chars() + inline_length, src.data(), src.size());
set_inline_size(inline_length + src.size());
- return;
- }
-
+ return;
+ }
+
// Allocate flat to be a perfect fit on first append exceeding inlined size.
// Subsequent growth will use amortized growth until we reach maximum flat
// size.
@@ -725,12 +725,12 @@ void Cord::InlineRep::AppendArray(y_absl::string_view src,
length = std::max<size_t>(rep->length / 10, src.size());
}
rep = Concat(rep, NewTree(src.data(), src.size(), length - src.size()));
- }
+ }
CommitTree(root, rep, scope, method);
}
inline CordRep* Cord::TakeRep() const& {
- return CordRep::Ref(contents_.tree());
+ return CordRep::Ref(contents_.tree());
}
inline CordRep* Cord::TakeRep() && {
@@ -781,7 +781,7 @@ inline void Cord::AppendImpl(C&& src) {
return;
}
- // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
+ // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
CordRep* rep = std::forward<C>(src).TakeRep();
contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
}
@@ -794,22 +794,22 @@ 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(y_absl::string_view(src));
- } else {
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(y_absl::string_view(src));
+ } else {
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.AppendTree(rep, CordzUpdateTracker::kAppendString);
- }
-}
-
-template void Cord::Append(TString&& src);
-
+ }
+}
+
+template void Cord::Append(TString&& src);
+
void Cord::Prepend(const Cord& src) {
CordRep* src_tree = src.contents_.tree();
if (src_tree != nullptr) {
- CordRep::Ref(src_tree);
+ CordRep::Ref(src_tree);
contents_.PrependTree(src_tree, CordzUpdateTracker::kPrependCord);
return;
}
@@ -821,37 +821,37 @@ void Cord::Prepend(const Cord& src) {
void Cord::PrependArray(y_absl::string_view src, MethodIdentifier method) {
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) {
- // Use embedded storage.
- char data[InlineRep::kMaxInline + 1] = {0};
- memcpy(data, src.data(), src.size());
- memcpy(data + src.size(), contents_.data(), cur_size);
- memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
- contents_.set_inline_size(cur_size + src.size());
- return;
- }
- }
+ if (!contents_.is_tree()) {
+ size_t cur_size = contents_.inline_size();
+ if (cur_size + src.size() <= InlineRep::kMaxInline) {
+ // Use embedded storage.
+ char data[InlineRep::kMaxInline + 1] = {0};
+ memcpy(data, src.data(), src.size());
+ memcpy(data + src.size(), contents_.data(), cur_size);
+ memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
+ 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(y_absl::string_view(src));
+}
+
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(y_absl::string_view(src));
} else {
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);
}
}
-template void Cord::Prepend(TString&& src);
-
+template void Cord::Prepend(TString&& src);
+
static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
if (n >= node->length) return nullptr;
- if (n == 0) return CordRep::Ref(node);
+ if (n == 0) return CordRep::Ref(node);
y_absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
while (node->IsConcat()) {
@@ -869,7 +869,7 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
assert(n <= node->length);
if (n == 0) {
- CordRep::Ref(node);
+ CordRep::Ref(node);
} else {
size_t start = n;
size_t len = node->length - n;
@@ -878,10 +878,10 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
start += node->substring()->start;
node = node->substring()->child;
}
- node = NewSubstring(CordRep::Ref(node), start, len);
+ node = NewSubstring(CordRep::Ref(node), start, len);
}
while (!rhs_stack.empty()) {
- node = Concat(node, CordRep::Ref(rhs_stack.back()));
+ node = Concat(node, CordRep::Ref(rhs_stack.back()));
rhs_stack.pop_back();
}
return node;
@@ -892,7 +892,7 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
// 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);
+ if (n == 0) return CordRep::Ref(node);
y_absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
bool inplace_ok = node->refcount.IsMutable();
@@ -912,11 +912,11 @@ static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
assert(n <= node->length);
if (n == 0) {
- CordRep::Ref(node);
+ 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.
- CordRep::Ref(node);
+ CordRep::Ref(node);
node->length -= n;
} else {
size_t start = 0;
@@ -925,10 +925,10 @@ static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
start = node->substring()->start;
node = node->substring()->child;
}
- node = NewSubstring(CordRep::Ref(node), start, len);
+ node = NewSubstring(CordRep::Ref(node), start, len);
}
while (!lhs_stack.empty()) {
- node = Concat(CordRep::Ref(lhs_stack.back()), node);
+ node = Concat(CordRep::Ref(lhs_stack.back()), node);
lhs_stack.pop_back();
}
return node;
@@ -1006,13 +1006,13 @@ static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
results.pop_back();
results.push_back(Concat(left, right));
} else if (pos == 0 && n == node->length) {
- results.push_back(CordRep::Ref(node));
+ results.push_back(CordRep::Ref(node));
} else if (!node->IsConcat()) {
if (node->IsSubstring()) {
pos += node->substring()->start;
node = node->substring()->child;
}
- results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
+ 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) {
@@ -1056,7 +1056,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
++it;
}
cord_internal::SmallMemmove(dest, it->data(), remaining_size);
- sub_cord.contents_.set_inline_size(new_size);
+ sub_cord.contents_.set_inline_size(new_size);
return sub_cord;
}
@@ -1100,9 +1100,9 @@ class CordForest {
concat_node->left = concat_freelist_;
concat_freelist_ = concat_node;
} else {
- CordRep::Ref(concat_node->right);
- CordRep::Ref(concat_node->left);
- CordRep::Unref(concat_node);
+ CordRep::Ref(concat_node->right);
+ CordRep::Ref(concat_node->left);
+ CordRep::Unref(concat_node);
}
} else {
AddNode(node);
@@ -1135,7 +1135,7 @@ class CordForest {
void AddNode(CordRep* node) {
CordRep* sum = nullptr;
- // Collect together everything with which we will merge with node
+ // 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];
@@ -1252,13 +1252,13 @@ bool ComputeCompareResult<bool>(int memcmp_res) {
// 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 y_absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
- if (!is_tree()) {
- return y_absl::string_view(data_.as_chars(), data_.inline_size());
+ if (!is_tree()) {
+ return y_absl::string_view(data_.as_chars(), data_.inline_size());
}
CordRep* node = tree();
if (node->IsFlat()) {
- return y_absl::string_view(node->flat()->Data(), node->length);
+ return y_absl::string_view(node->flat()->Data(), node->length);
}
if (node->IsExternal()) {
@@ -1272,8 +1272,8 @@ inline y_absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
tree = tree->Edge(CordRepBtree::kFront)->btree();
}
return tree->Data(tree->begin());
- }
-
+ }
+
// Walk down the left branches until we hit a non-CONCAT node.
while (node->IsConcat()) {
node = node->concat()->left;
@@ -1290,7 +1290,7 @@ inline y_absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
}
if (node->IsFlat()) {
- return y_absl::string_view(node->flat()->Data() + offset, length);
+ return y_absl::string_view(node->flat()->Data() + offset, length);
}
assert(node->IsExternal() && "Expect FLAT or EXTERNAL node here");
@@ -1473,22 +1473,22 @@ void Cord::CopyToArraySlowPath(char* dst) const {
}
}
-Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
- auto& stack_of_right_children = stack_of_right_children_;
- if (stack_of_right_children.empty()) {
+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.
- CordRep* node = stack_of_right_children.back();
- stack_of_right_children.pop_back();
+ 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.
while (node->IsConcat()) {
- stack_of_right_children.push_back(node->concat()->right);
+ stack_of_right_children.push_back(node->concat()->right);
node = node->concat()->left;
}
@@ -1510,8 +1510,8 @@ Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
}
Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
- ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
- "Attempted to iterate past `end()`");
+ ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
+ "Attempted to iterate past `end()`");
Cord subcord;
auto constexpr method = CordzUpdateTracker::kCordReader;
@@ -1532,30 +1532,30 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
}
return subcord;
}
-
+
if (btree_reader_) {
- size_t chunk_size = current_chunk_.size();
- if (n <= chunk_size && n <= kMaxBytesToCopy) {
+ size_t chunk_size = current_chunk_.size();
+ if (n <= chunk_size && n <= kMaxBytesToCopy) {
subcord = Cord(current_chunk_.substr(0, n), method);
if (n < chunk_size) {
current_chunk_.remove_prefix(n);
} else {
current_chunk_ = btree_reader_.Next();
}
- } else {
+ } else {
CordRep* rep;
current_chunk_ = btree_reader_.Read(n, chunk_size, rep);
subcord.contents_.EmplaceTree(rep, method);
- }
+ }
bytes_remaining_ -= n;
- return subcord;
- }
-
- auto& stack_of_right_children = stack_of_right_children_;
+ return subcord;
+ }
+
+ 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);
- CordRep* subnode = CordRep::Ref(current_leaf_);
+ 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);
@@ -1567,7 +1567,7 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// 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_);
+ CordRep* subnode = CordRep::Ref(current_leaf_);
if (current_chunk_.size() < subnode->length) {
const char* data = subnode->IsExternal() ? subnode->external()->base
: subnode->flat()->Data();
@@ -1580,20 +1580,20 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// 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();
+ 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
- // current_leaf, keep current_subtree_ which points to the highest node
+ // 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).
- subnode = Concat(subnode, CordRep::Ref(node));
+ subnode = Concat(subnode, CordRep::Ref(node));
n -= node->length;
bytes_remaining_ -= node->length;
node = nullptr;
@@ -1611,11 +1611,11 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
while (node->IsConcat()) {
if (node->concat()->left->length > n) {
// Push right, descend left.
- stack_of_right_children.push_back(node->concat()->right);
+ stack_of_right_children.push_back(node->concat()->right);
node = node->concat()->left;
} else {
// Read left, descend right.
- subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
+ subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
n -= node->concat()->left->length;
bytes_remaining_ -= node->concat()->left->length;
node = node->concat()->right;
@@ -1634,9 +1634,9 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// chunk.
assert(node->IsExternal() || node->IsFlat());
assert(length > n);
- if (n > 0) {
- subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
- }
+ if (n > 0) {
+ subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
+ }
const char* data =
node->IsExternal() ? node->external()->base : node->flat()->Data();
current_chunk_ = y_absl::string_view(data + offset + n, length - n);
@@ -1654,19 +1654,19 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
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;
- }
-
+ 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;
- 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();
+ 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;
@@ -1684,7 +1684,7 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
while (node->IsConcat()) {
if (node->concat()->left->length > n) {
// Push right, descend left.
- stack_of_right_children.push_back(node->concat()->right);
+ stack_of_right_children.push_back(node->concat()->right);
node = node->concat()->left;
} else {
// Skip left, descend right.
@@ -1712,7 +1712,7 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
}
char Cord::operator[](size_t i) const {
- ABSL_HARDENING_ASSERT(i < size());
+ ABSL_HARDENING_ASSERT(i < size());
size_t offset = i;
const CordRep* rep = contents_.tree();
if (rep == nullptr) {
@@ -1723,7 +1723,7 @@ char Cord::operator[](size_t i) const {
assert(offset < rep->length);
if (rep->IsFlat()) {
// Get the "i"th character directly from the flat array.
- return rep->flat()->Data()[offset];
+ return rep->flat()->Data()[offset];
} else if (rep->IsBtree()) {
return rep->btree()->GetCharacter(offset);
} else if (rep->IsExternal()) {
@@ -1757,9 +1757,9 @@ y_absl::string_view Cord::FlattenSlowPath() {
// 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 = CordRepFlat::New(total_size);
new_rep->length = total_size;
- new_buffer = new_rep->flat()->Data();
+ new_buffer = new_rep->flat()->Data();
CopyToArraySlowPath(new_buffer);
} else {
new_buffer = std::allocator<char>().allocate(total_size);
@@ -1779,7 +1779,7 @@ y_absl::string_view Cord::FlattenSlowPath() {
/* static */ bool Cord::GetFlatAux(CordRep* rep, y_absl::string_view* fragment) {
assert(rep != nullptr);
if (rep->IsFlat()) {
- *fragment = y_absl::string_view(rep->flat()->Data(), rep->length);
+ *fragment = y_absl::string_view(rep->flat()->Data(), rep->length);
return true;
} else if (rep->IsExternal()) {
*fragment = y_absl::string_view(rep->external()->base, rep->length);
@@ -1789,8 +1789,8 @@ y_absl::string_view Cord::FlattenSlowPath() {
} else if (rep->IsSubstring()) {
CordRep* child = rep->substring()->child;
if (child->IsFlat()) {
- *fragment = y_absl::string_view(
- child->flat()->Data() + rep->substring()->start, rep->length);
+ *fragment = y_absl::string_view(
+ child->flat()->Data() + rep->substring()->start, rep->length);
return true;
} else if (child->IsExternal()) {
*fragment = y_absl::string_view(
@@ -1808,14 +1808,14 @@ y_absl::string_view Cord::FlattenSlowPath() {
y_absl::cord_internal::CordRep* rep,
y_absl::FunctionRef<void(y_absl::string_view)> callback) {
if (rep->IsBtree()) {
- ChunkIterator it(rep), end;
- while (it != end) {
- callback(*it);
- ++it;
- }
- return;
- }
-
+ ChunkIterator it(rep), end;
+ while (it != end) {
+ callback(*it);
+ ++it;
+ }
+ return;
+ }
+
assert(rep != nullptr);
int stack_pos = 0;
constexpr int stack_max = 128;
@@ -1857,8 +1857,8 @@ y_absl::string_view Cord::FlattenSlowPath() {
}
}
-static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
- int indent) {
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
+ int indent) {
const int kIndentStep = 1;
y_absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
y_absl::InlinedVector<int, kInlinedVectorSize> indents;
@@ -1880,7 +1880,7 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
*os << "SUBSTRING @ " << rep->substring()->start << "\n";
indent += kIndentStep;
rep = rep->substring()->child;
- } else { // Leaf or ring
+ } else { // Leaf or ring
if (rep->IsExternal()) {
*os << "EXTERNAL [";
if (include_data)
@@ -1889,9 +1889,9 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
} else if (rep->IsFlat()) {
*os << "FLAT cap=" << rep->flat()->Capacity() << " [";
if (include_data)
- *os << y_absl::CEscape(TString(rep->flat()->Data(), rep->length));
+ *os << y_absl::CEscape(TString(rep->flat()->Data(), rep->length));
*os << "]\n";
- } else {
+ } else {
CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os);
}
if (stack.empty()) break;
@@ -2026,14 +2026,14 @@ std::ostream& operator<<(std::ostream& out, const Cord& cord) {
}
namespace strings_internal {
-size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
-size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
+size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
+size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
- return cord_internal::TagToLength(tag);
+ return cord_internal::TagToLength(tag);
}
uint8_t CordTestAccess::LengthToTag(size_t s) {
ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, y_absl::StrCat("Invalid length ", s));
- return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
+ return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
}
size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
size_t CordTestAccess::SizeofCordRepExternal() {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.h
index 62359e0cf8..2bce9ffccf 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord.h
@@ -12,51 +12,51 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-// -----------------------------------------------------------------------------
-// File: cord.h
-// -----------------------------------------------------------------------------
-//
-// This file defines the `y_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 `TString`, 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
-// `TString`, 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 `TString` 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 `TString`.
-//
-// Thread Safety
-//
+// -----------------------------------------------------------------------------
+// File: cord.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the `y_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 `TString`, 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
+// `TString`, 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 `TString` 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 `TString`.
+//
+// Thread Safety
+//
// Cord has the same thread-safety properties as many other types like
// TString, 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.
+// 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_
@@ -65,10 +65,10 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <iosfwd>
+#include <iosfwd>
#include <iterator>
#include <util/generic/string.h>
-#include <type_traits>
+#include <type_traits>
#include "y_absl/base/config.h"
#include "y_absl/base/internal/endian.h"
@@ -81,16 +81,16 @@
#include "y_absl/strings/internal/cord_internal.h"
#include "y_absl/strings/internal/cord_rep_btree.h"
#include "y_absl/strings/internal/cord_rep_btree_reader.h"
-#include "y_absl/strings/internal/cord_rep_ring.h"
+#include "y_absl/strings/internal/cord_rep_ring.h"
#include "y_absl/strings/internal/cordz_functions.h"
#include "y_absl/strings/internal/cordz_info.h"
#include "y_absl/strings/internal/cordz_statistics.h"
#include "y_absl/strings/internal/cordz_update_scope.h"
#include "y_absl/strings/internal/cordz_update_tracker.h"
#include "y_absl/strings/internal/resize_uninitialized.h"
-#include "y_absl/strings/internal/string_constant.h"
+#include "y_absl/strings/internal/string_constant.h"
#include "y_absl/strings/string_view.h"
-#include "y_absl/types/optional.h"
+#include "y_absl/types/optional.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
@@ -100,34 +100,34 @@ template <typename Releaser>
Cord MakeCordFromExternal(y_absl::string_view, Releaser&&);
void CopyCordToString(const Cord& src, TString* dst);
-// Cord
-//
-// A Cord is a sequence of characters, designed to be more efficient than a
-// `TString` 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 `TString`
-//
-// Additionally, the API provides iterator utilities to iterate through Cord
-// data via chunks or character bytes.
-//
+// Cord
+//
+// A Cord is a sequence of characters, designed to be more efficient than a
+// `TString` 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 `TString`
+//
+// Additionally, the API provides iterator utilities to iterate through Cord
+// data via chunks or character bytes.
+//
class Cord {
private:
template <typename T>
@@ -135,54 +135,54 @@ class Cord {
y_absl::enable_if_t<std::is_same<T, TString>::value, int>;
public:
- // Cord::Cord() Constructors.
+ // Cord::Cord() Constructors.
- // Creates an empty Cord.
+ // 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.
+ // 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
- // `y_absl::string_view`.
+ // Creates a Cord from a `src` string. This constructor is marked explicit to
+ // prevent implicit Cord constructions from arguments convertible to an
+ // `y_absl::string_view`.
explicit Cord(y_absl::string_view src);
Cord& operator=(y_absl::string_view src);
- // Creates a Cord from a `TString&&` rvalue. These constructors are
- // templated to avoid ambiguities for types that are convertible to both
- // `y_absl::string_view` and `TString`, such as `const char*`.
+ // Creates a Cord from a `TString&&` rvalue. These constructors are
+ // templated to avoid ambiguities for types that are convertible to both
+ // `y_absl::string_view` and `TString`, such as `const char*`.
template <typename T, EnableIfString<T> = 0>
- explicit Cord(T&& src);
+ explicit Cord(T&& src);
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
- // Cord::~Cord()
- //
- // Destructs the Cord.
+ // 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()(y_absl::string_view) const` or `void operator()`
- //
+ // 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()(y_absl::string_view) const` or `void operator()`
+ //
// Example:
//
// Cord MakeCord(BlockPool* pool) {
@@ -190,13 +190,13 @@ class Cord {
// FillBlock(block);
// return y_absl::MakeCordFromExternal(
// block->ToStringView(),
- // [pool, block](y_absl::string_view v) {
- // pool->FreeBlock(block, v);
+ // [pool, block](y_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:
+ // 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 = y_absl::MakeCordFromExternal(y_absl::string_view(buffer, len),
@@ -210,107 +210,107 @@ class Cord {
template <typename Releaser>
friend Cord MakeCordFromExternal(y_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.
+ // 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.
+ // 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(y_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.
+ // Cord::Prepend()
+ //
+ // Prepends data to the Cord, which may come from another Cord or other string
+ // data.
void Prepend(const Cord& src);
void Prepend(y_absl::string_view src);
template <typename T, EnableIfString<T> = 0>
void Prepend(T&& src);
- // Cord::RemovePrefix()
- //
- // Removes the first `n` bytes of a Cord.
+ // 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
+ // 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;
+ // Cord::swap()
+ //
+ // Swaps the contents of the Cord with `other`.
+ void swap(Cord& other) noexcept;
- // swap()
- //
- // Swaps the contents of two Cords.
+ // 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.
+ // 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.
+
+ // 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.
+ // 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:
- //
+ // 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(y_absl::string_view rhs) const;
int Compare(const Cord& rhs) const;
- // Cord::StartsWith()
- //
- // Determines whether the Cord starts with the passed string data `rhs`.
+ // Cord::StartsWith()
+ //
+ // Determines whether the Cord starts with the passed string data `rhs`.
bool StartsWith(const Cord& rhs) const;
bool StartsWith(y_absl::string_view rhs) const;
-
- // Cord::EndsWith()
- //
- // Determines whether the Cord ends with the passed string data `rhs`.
+
+ // Cord::EndsWith()
+ //
+ // Determines whether the Cord ends with the passed string data `rhs`.
bool EndsWith(y_absl::string_view rhs) const;
bool EndsWith(const Cord& rhs) const;
- // Cord::operator TString()
- //
- // Converts a Cord into a `TString()`. This operator is marked explicit to
- // prevent unintended Cord usage in functions that take a string.
+ // Cord::operator TString()
+ //
+ // Converts a Cord into a `TString()`. This operator is marked explicit to
+ // prevent unintended Cord usage in functions that take a string.
explicit operator TString() const;
- // CopyCordToString()
+ // CopyCordToString()
//
- // Copies the contents of a `src` Cord into a `*dst` string.
- //
- // This function optimizes the case of reusing the destination string since it
+ // 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
@@ -319,32 +319,32 @@ class Cord {
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.
+ //----------------------------------------------------------------------------
+ // 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
+ // * 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 {
@@ -368,38 +368,38 @@ class Cord {
friend class CharIterator;
private:
- using CordRep = y_absl::cord_internal::CordRep;
+ using CordRep = y_absl::cord_internal::CordRep;
using CordRepBtree = y_absl::cord_internal::CordRepBtree;
using CordRepBtreeReader = y_absl::cord_internal::CordRepBtreeReader;
-
- // Stack of right children of concat nodes that we have to visit.
- // Keep this at the end of the structure to avoid cache-thrashing.
- // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
- // the inlined vector size (47 exists for backward compatibility).
- using Stack = y_absl::InlinedVector<y_absl::cord_internal::CordRep*, 47>;
-
- // Constructs a `begin()` iterator from `tree`. `tree` must not be null.
- explicit ChunkIterator(cord_internal::CordRep* tree);
-
+
+ // Stack of right children of concat nodes that we have to visit.
+ // Keep this at the end of the structure to avoid cache-thrashing.
+ // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+ // the inlined vector size (47 exists for backward compatibility).
+ using Stack = y_absl::InlinedVector<y_absl::cord_internal::CordRep*, 47>;
+
+ // 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);
- // Initializes this instance from a tree. Invoked by constructors.
- void InitTree(cord_internal::CordRep* tree);
-
+ // 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);
-
- // Stack specific operator++
- ChunkIterator& AdvanceStack();
-
+
+ // Stack specific operator++
+ ChunkIterator& AdvanceStack();
+
// Btree specific operator++
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);
@@ -413,21 +413,21 @@ class Cord {
y_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_;
+
+ // See 'Stack' alias definition.
+ Stack stack_of_right_children_;
};
- // Cord::ChunkIterator::chunk_begin()
- //
+ // 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.
+ // 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:
//
@@ -436,28 +436,28 @@ class Cord {
// return std::find(c.chunk_begin(), c.chunk_end(), s);
// }
ChunkIterator chunk_begin() const;
-
- // Cord::ChunkItertator::chunk_end()
- //
+
+ // 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.
+ //
+ // 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()`.
+ //----------------------------------------------------------------------------
+ // 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]
@@ -479,12 +479,12 @@ class Cord {
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.
+ // 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) {
@@ -500,30 +500,30 @@ class Cord {
// }
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
+ //----------------------------------------------------------------------------
+ // 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.
+ // * 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;
@@ -549,56 +549,56 @@ class Cord {
ChunkIterator chunk_iterator_;
};
- // Cord::CharIterator::AdvanceAndRead()
+ // 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`.
+ // 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()
+ // 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`.
+ // 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()
- //
+ // Cord::CharIterator::ChunkRemaining()
+ //
// Returns the longest contiguous view starting at the iterator's position.
//
// `it` must be dereferenceable.
static y_absl::string_view ChunkRemaining(const CharIterator& it);
- // Cord::CharIterator::char_begin()
- //
+ // 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.
+ //
+ // 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()
- //
+
+ // 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.
+ //
+ // 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.
+ // Cord::CharIterator::CharRange
//
- // Implementation note: `CharRange` is simply a convenience wrapper over
- // `Cord::char_begin()` and `Cord::char_end()`.
+ // `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]
@@ -620,12 +620,12 @@ class Cord {
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.
+ // 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) {
@@ -641,53 +641,53 @@ class Cord {
// }
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,
+ // 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.
+ // 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.
- y_absl::optional<y_absl::string_view> TryFlat() const;
-
- // Cord::Flatten()
- //
+ // Cord::TryFlat()
+ //
+ // If this cord's representation is a single flat array, returns a
+ // string_view referencing that array. Otherwise returns nullopt.
+ y_absl::optional<y_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.
y_absl::string_view Flatten();
- // Supports y_absl::Cord as a sink object for y_absl::Format().
- friend void AbslFormatFlush(y_absl::Cord* cord, y_absl::string_view part) {
- cord->Append(part);
- }
-
- template <typename H>
- friend H AbslHashValue(H hash_state, const y_absl::Cord& c) {
- y_absl::optional<y_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
- // be used by spelling y_absl::strings_internal::MakeStringConstant, which is
- // also an internal API.
- template <typename T>
- explicit constexpr Cord(strings_internal::StringConstant<T>);
-
+ // Supports y_absl::Cord as a sink object for y_absl::Format().
+ friend void AbslFormatFlush(y_absl::Cord* cord, y_absl::string_view part) {
+ cord->Append(part);
+ }
+
+ template <typename H>
+ friend H AbslHashValue(H hash_state, const y_absl::Cord& c) {
+ y_absl::optional<y_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
+ // be used by spelling y_absl::strings_internal::MakeStringConstant, which is
+ // also an internal API.
+ template <typename T>
+ explicit constexpr Cord(strings_internal::StringConstant<T>);
+
private:
using CordRep = y_absl::cord_internal::CordRep;
using CordRepFlat = y_absl::cord_internal::CordRepFlat;
@@ -707,7 +707,7 @@ class Cord {
friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord);
- // Calls the provided function once for each cord chunk, in order. Unlike
+ // Calls the provided function once for each cord chunk, in order. Unlike
// Chunks(), this API will not allocate memory.
void ForEachChunk(y_absl::FunctionRef<void(y_absl::string_view)>) const;
@@ -719,21 +719,21 @@ class Cord {
// 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.
+ // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
class InlineRep {
public:
- static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
+ static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
static_assert(kMaxInline >= sizeof(y_absl::cord_internal::CordRep*), "");
- constexpr InlineRep() : data_() {}
+ 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;
- explicit constexpr InlineRep(cord_internal::InlineData data);
-
+ explicit constexpr InlineRep(cord_internal::InlineData data);
+
void Swap(InlineRep* rhs);
bool empty() const;
size_t size() const;
@@ -743,10 +743,10 @@ class Cord {
char* set_data(size_t n); // Write data to the result
// Returns nullptr if holding bytes
y_absl::cord_internal::CordRep* tree() const;
- y_absl::cord_internal::CordRep* as_tree() const;
+ y_absl::cord_internal::CordRep* as_tree() const;
// Returns non-null iff was holding a pointer
y_absl::cord_internal::CordRep* clear();
- // Converts to pointer if necessary.
+ // Converts to pointer if necessary.
void reduce_size(size_t n); // REQUIRES: holding data
void remove_prefix(size_t n); // REQUIRES: holding data
void AppendArray(y_absl::string_view src, MethodIdentifier method);
@@ -795,16 +795,16 @@ class Cord {
void GetAppendRegion(char** region, size_t* size, size_t length);
bool IsSame(const InlineRep& other) const {
- return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
+ 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));
+ // 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));
+ 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 y_absl::big_endian::FromHost64(x) < y_absl::big_endian::FromHost64(y)
@@ -813,38 +813,38 @@ class Cord {
}
void CopyTo(TString* 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
+ // platforms, the small string optimization is large enough that resizing
// to 15 bytes does not cause a memory allocation.
y_absl::strings_internal::STLStringResizeUninitialized(dst,
sizeof(data_) - 1);
- memcpy(&(*dst)[0], &data_, 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());
+ dst->erase(inline_size());
}
// 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(); }
-
- // Returns the profiled CordzInfo, or nullptr if not sampled.
- y_absl::cord_internal::CordzInfo* cordz_info() const {
- return data_.cordz_info();
- }
-
- // Sets the profiled CordzInfo. `cordz_info` must not be null.
- void set_cordz_info(cord_internal::CordzInfo* cordz_info) {
- assert(cordz_info != nullptr);
- data_.set_cordz_info(cordz_info);
- }
-
- // Resets the current cordz_info to null / empty.
- void clear_cordz_info() { data_.clear_cordz_info(); }
-
+ 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(); }
+
+ // Returns the profiled CordzInfo, or nullptr if not sampled.
+ y_absl::cord_internal::CordzInfo* cordz_info() const {
+ return data_.cordz_info();
+ }
+
+ // Sets the profiled CordzInfo. `cordz_info` must not be null.
+ void set_cordz_info(cord_internal::CordzInfo* cordz_info) {
+ assert(cordz_info != nullptr);
+ data_.set_cordz_info(cordz_info);
+ }
+
+ // Resets the current cordz_info to null / empty.
+ void clear_cordz_info() { data_.clear_cordz_info(); }
+
private:
friend class Cord;
@@ -852,23 +852,23 @@ class Cord {
// Unrefs the tree and stops profiling.
void UnrefTree();
- 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_;
+ 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().
+ // Helper for MemoryUsage().
static size_t MemoryUsageAux(const y_absl::cord_internal::CordRep* rep);
- // Helper for GetFlat() and TryFlat().
+ // Helper for GetFlat() and TryFlat().
static bool GetFlatAux(y_absl::cord_internal::CordRep* rep,
y_absl::string_view* fragment);
- // Helper for ForEachChunk().
+ // Helper for ForEachChunk().
static void ForEachChunkAux(
y_absl::cord_internal::CordRep* rep,
y_absl::FunctionRef<void(y_absl::string_view)> callback);
@@ -897,10 +897,10 @@ class Cord {
y_absl::cord_internal::CordRep* TakeRep() const&;
y_absl::cord_internal::CordRep* TakeRep() &&;
- // Helper for Append().
+ // 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(y_absl::string_view src, MethodIdentifier method);
@@ -909,16 +909,16 @@ class Cord {
// Requires src.length() > kMaxBytesToCopy.
Cord& AssignLargeString(TString&& src);
- // Helper for AbslHashValue().
- template <typename H>
- H HashFragmented(H hash_state) const {
- typename H::AbslInternalPiecewiseCombiner combiner;
- ForEachChunk([&combiner, &hash_state](y_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());
- }
+ // Helper for AbslHashValue().
+ template <typename H>
+ H HashFragmented(H hash_state) const {
+ typename H::AbslInternalPiecewiseCombiner combiner;
+ ForEachChunk([&combiner, &hash_state](y_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
@@ -975,9 +975,9 @@ inline void SmallMemmove(char* dst, const char* src, size_t n,
}
}
-// Does non-template-specific `CordRepExternal` initialization.
+// Does non-template-specific `CordRepExternal` initialization.
// Expects `data` to be non-empty.
-void InitializeCordRepExternal(y_absl::string_view data, CordRepExternal* rep);
+void InitializeCordRepExternal(y_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.
@@ -987,15 +987,15 @@ CordRep* NewExternalRep(y_absl::string_view data, Releaser&& releaser) {
using ReleaserType = y_absl::decay_t<Releaser>;
if (data.empty()) {
// Never create empty external nodes.
- InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
- data);
+ 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;
+ 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
@@ -1019,21 +1019,21 @@ Cord MakeCordFromExternal(y_absl::string_view data, Releaser&& releaser) {
return cord;
}
-constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
- : data_(data) {}
-
-inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
+constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
+ : data_(data) {}
+
+inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
: data_(InlineData::kDefaultInit) {
if (CordRep* tree = src.tree()) {
EmplaceTree(CordRep::Ref(tree), src.data_,
CordzUpdateTracker::kConstructorCord);
} else {
data_ = src.data_;
- }
+ }
}
inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {
- src.ResetToEmpty();
+ src.ResetToEmpty();
}
inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
@@ -1041,7 +1041,7 @@ inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
return *this;
}
if (!is_tree() && !src.is_tree()) {
- data_ = src.data_;
+ data_ = src.data_;
return *this;
}
AssignSlow(src);
@@ -1053,8 +1053,8 @@ inline Cord::InlineRep& Cord::InlineRep::operator=(
if (is_tree()) {
UnrefTree();
}
- data_ = src.data_;
- src.ResetToEmpty();
+ data_ = src.data_;
+ src.ResetToEmpty();
return *this;
}
@@ -1062,30 +1062,30 @@ inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
if (rhs == this) {
return;
}
- std::swap(data_, rhs->data_);
+ std::swap(data_, rhs->data_);
}
inline const char* Cord::InlineRep::data() const {
- return is_tree() ? nullptr : data_.as_chars();
-}
-
-inline y_absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
- assert(data_.is_tree());
- return data_.as_tree();
+ return is_tree() ? nullptr : data_.as_chars();
}
+inline y_absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
+ assert(data_.is_tree());
+ return data_.as_tree();
+}
+
inline y_absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
if (is_tree()) {
- return as_tree();
+ return as_tree();
} else {
return nullptr;
}
}
-inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
+inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
inline size_t Cord::InlineRep::size() const {
- return is_tree() ? as_tree()->length : inline_size();
+ return is_tree() ? as_tree()->length : inline_size();
}
inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
@@ -1144,16 +1144,16 @@ inline y_absl::cord_internal::CordRep* Cord::InlineRep::clear() {
if (is_tree()) {
CordzInfo::MaybeUntrackCord(cordz_info());
}
- y_absl::cord_internal::CordRep* result = tree();
- ResetToEmpty();
+ y_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();
+ size_t n = inline_size();
assert(n != 0);
- cord_internal::SmallMemmove(dst, data_.as_chars(), n);
+ cord_internal::SmallMemmove(dst, data_.as_chars(), n);
}
constexpr inline Cord::Cord() noexcept {}
@@ -1161,16 +1161,16 @@ constexpr inline Cord::Cord() noexcept {}
inline Cord::Cord(y_absl::string_view src)
: Cord(src, CordzUpdateTracker::kConstructorString) {}
-template <typename T>
-constexpr Cord::Cord(strings_internal::StringConstant<T>)
- : contents_(strings_internal::StringConstant<T>::value.size() <=
- cord_internal::kMaxInline
- ? cord_internal::InlineData(
- strings_internal::StringConstant<T>::value)
- : cord_internal::InlineData(
- &cord_internal::ConstInitExternalStorage<
- strings_internal::StringConstant<T>>::value)) {}
-
+template <typename T>
+constexpr Cord::Cord(strings_internal::StringConstant<T>)
+ : contents_(strings_internal::StringConstant<T>::value.size() <=
+ cord_internal::kMaxInline
+ ? cord_internal::InlineData(
+ strings_internal::StringConstant<T>::value)
+ : cord_internal::InlineData(
+ &cord_internal::ConstInitExternalStorage<
+ strings_internal::StringConstant<T>>::value)) {}
+
inline Cord& Cord::operator=(const Cord& x) {
contents_ = x.contents_;
return *this;
@@ -1185,20 +1185,20 @@ Cord& Cord::operator=(T&& src) {
}
}
-inline Cord::Cord(const Cord& src) : contents_(src.contents_) {}
-
+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 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(TString&& src);
+extern template Cord::Cord(TString&& src);
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
@@ -1215,18 +1215,18 @@ inline size_t Cord::EstimatedMemoryUsage() const {
return result;
}
-inline y_absl::optional<y_absl::string_view> Cord::TryFlat() const {
- y_absl::cord_internal::CordRep* rep = contents_.tree();
- if (rep == nullptr) {
- return y_absl::string_view(contents_.data(), contents_.size());
- }
- y_absl::string_view fragment;
- if (GetFlatAux(rep, &fragment)) {
- return fragment;
- }
- return y_absl::nullopt;
-}
-
+inline y_absl::optional<y_absl::string_view> Cord::TryFlat() const {
+ y_absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return y_absl::string_view(contents_.data(), contents_.size());
+ }
+ y_absl::string_view fragment;
+ if (GetFlatAux(rep, &fragment)) {
+ return fragment;
+ }
+ return y_absl::nullopt;
+}
+
inline y_absl::string_view Cord::Flatten() {
y_absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
@@ -1248,8 +1248,8 @@ inline void Cord::Prepend(y_absl::string_view src) {
PrependArray(src, CordzUpdateTracker::kPrependString);
}
-extern template void Cord::Append(TString&& src);
-extern template void Cord::Prepend(TString&& src);
+extern template void Cord::Append(TString&& src);
+extern template void Cord::Prepend(TString&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
@@ -1273,64 +1273,64 @@ inline bool Cord::StartsWith(y_absl::string_view rhs) const {
return EqualsImpl(rhs, rhs_size);
}
-inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
+inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
if (tree->tag == cord_internal::BTREE) {
current_chunk_ = btree_reader_.Init(tree->btree());
- return;
- }
-
- stack_of_right_children_.push_back(tree);
- operator++();
-}
-
-inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree)
- : bytes_remaining_(tree->length) {
- InitTree(tree);
-}
-
+ return;
+ }
+
+ stack_of_right_children_.push_back(tree);
+ operator++();
+}
+
+inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree)
+ : bytes_remaining_(tree->length) {
+ InitTree(tree);
+}
+
inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
: bytes_remaining_(cord->size()) {
if (cord->contents_.is_tree()) {
- InitTree(cord->contents_.as_tree());
+ InitTree(cord->contents_.as_tree());
} else {
- current_chunk_ =
- y_absl::string_view(cord->contents_.data(), bytes_remaining_);
+ current_chunk_ =
+ y_absl::string_view(cord->contents_.data(), bytes_remaining_);
}
}
inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {
current_chunk_ = btree_reader_.Next();
- return *this;
-}
-
+ return *this;
+}
+
inline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) {
- assert(n >= current_chunk_.size());
- bytes_remaining_ -= n;
- if (bytes_remaining_) {
- if (n == current_chunk_.size()) {
+ assert(n >= current_chunk_.size());
+ bytes_remaining_ -= n;
+ if (bytes_remaining_) {
+ if (n == current_chunk_.size()) {
current_chunk_ = btree_reader_.Next();
- } else {
+ } else {
size_t offset = btree_reader_.length() - bytes_remaining_;
current_chunk_ = btree_reader_.Seek(offset);
- }
- } else {
- current_chunk_ = {};
- }
-}
-
-inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
- ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
- "Attempted to iterate past `end()`");
- assert(bytes_remaining_ >= current_chunk_.size());
- bytes_remaining_ -= current_chunk_.size();
- if (bytes_remaining_ > 0) {
+ }
+ } else {
+ current_chunk_ = {};
+ }
+}
+
+inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
+ "Attempted to iterate past `end()`");
+ assert(bytes_remaining_ >= current_chunk_.size());
+ bytes_remaining_ -= current_chunk_.size();
+ if (bytes_remaining_ > 0) {
return btree_reader_ ? AdvanceBtree() : AdvanceStack();
- } else {
- current_chunk_ = {};
- }
- return *this;
-}
-
+ } else {
+ current_chunk_ = {};
+ }
+ return *this;
+}
+
inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
ChunkIterator tmp(*this);
operator++();
@@ -1346,12 +1346,12 @@ inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
}
inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
return current_chunk_;
}
inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
return &current_chunk_;
}
@@ -1362,7 +1362,7 @@ inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
}
inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
- assert(bytes_remaining_ >= n);
+ assert(bytes_remaining_ >= n);
if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
RemoveChunkPrefix(n);
} else if (n != 0) {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord/ya.make
index 8f3ec1f20f..eae61fde3f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/cord/ya.make
@@ -1,30 +1,30 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
-WITHOUT_LICENSE_TEXTS()
-
-OWNER(
- somov
- g:cpp-contrib
-)
-
-LICENSE(Apache-2.0)
-
-PEERDIR(
- contrib/restricted/abseil-cpp-tstring/y_absl/base
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+WITHOUT_LICENSE_TEXTS()
+
+OWNER(
+ somov
+ g:cpp-contrib
+)
+
+LICENSE(Apache-2.0)
+
+PEERDIR(
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/low_level_alloc
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
- contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
contrib/restricted/abseil-cpp-tstring/y_absl/debugging
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/stacktrace
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize
contrib/restricted/abseil-cpp-tstring/y_absl/demangle
- contrib/restricted/abseil-cpp-tstring/y_absl/numeric
+ contrib/restricted/abseil-cpp-tstring/y_absl/numeric
contrib/restricted/abseil-cpp-tstring/y_absl/profiling/internal/exponential_biased
- contrib/restricted/abseil-cpp-tstring/y_absl/strings
+ contrib/restricted/abseil-cpp-tstring/y_absl/strings
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions
@@ -35,24 +35,24 @@ PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/time
contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time
contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone
- contrib/restricted/abseil-cpp-tstring/y_absl/types/bad_optional_access
- contrib/restricted/abseil-cpp-tstring/y_absl/algorithm
- contrib/restricted/abseil-cpp-tstring/y_absl/container
- contrib/restricted/abseil-cpp-tstring/y_absl/functional
- contrib/restricted/abseil-cpp-tstring/y_absl/types
- contrib/restricted/abseil-cpp-tstring/y_absl/utility
-)
-
-ADDINCL(
- GLOBAL contrib/restricted/abseil-cpp-tstring
-)
-
-NO_COMPILER_WARNINGS()
-
-SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings)
-
-SRCS(
- cord.cc
-)
-
-END()
+ contrib/restricted/abseil-cpp-tstring/y_absl/types/bad_optional_access
+ contrib/restricted/abseil-cpp-tstring/y_absl/algorithm
+ contrib/restricted/abseil-cpp-tstring/y_absl/container
+ contrib/restricted/abseil-cpp-tstring/y_absl/functional
+ contrib/restricted/abseil-cpp-tstring/y_absl/types
+ contrib/restricted/abseil-cpp-tstring/y_absl/utility
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/abseil-cpp-tstring
+)
+
+NO_COMPILER_WARNINGS()
+
+SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings)
+
+SRCS(
+ cord.cc
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
index 8c82740608..b347786a02 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/escaping.cc
@@ -137,7 +137,7 @@ bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
// Copy the escape sequence for the null character
const ptrdiff_t octal_size = p + 1 - octal_start;
*d++ = '\\';
- memmove(d, octal_start, octal_size);
+ memmove(d, octal_start, octal_size);
d += octal_size;
break;
}
@@ -170,7 +170,7 @@ bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
// Copy the escape sequence for the null character
const ptrdiff_t hex_size = p + 1 - hex_start;
*d++ = '\\';
- memmove(d, hex_start, hex_size);
+ memmove(d, hex_start, hex_size);
d += hex_size;
break;
}
@@ -203,7 +203,7 @@ bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
if ((rune == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
*d++ = '\\';
- memmove(d, hex_start, 5); // u0000
+ memmove(d, hex_start, 5); // u0000
d += 5;
break;
}
@@ -251,7 +251,7 @@ bool CUnescapeInternal(y_absl::string_view source, bool leave_nulls_escaped,
if ((rune == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
*d++ = '\\';
- memmove(d, hex_start, 9); // U00000000
+ memmove(d, hex_start, 9); // U00000000
d += 9;
break;
}
@@ -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);
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal/ya.make
index 42b7b6cd5e..5b0a4c0695 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal/ya.make
@@ -1,42 +1,42 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
-WITHOUT_LICENSE_TEXTS()
-
-OWNER(
- somov
- g:cpp-contrib
-)
-
-LICENSE(Apache-2.0)
-
-PEERDIR(
- contrib/restricted/abseil-cpp-tstring/y_absl/base
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
- contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
- contrib/restricted/abseil-cpp-tstring/y_absl/numeric
- contrib/restricted/abseil-cpp-tstring/y_absl/strings
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+WITHOUT_LICENSE_TEXTS()
+
+OWNER(
+ somov
+ g:cpp-contrib
+)
+
+LICENSE(Apache-2.0)
+
+PEERDIR(
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
+ contrib/restricted/abseil-cpp-tstring/y_absl/numeric
+ contrib/restricted/abseil-cpp-tstring/y_absl/strings
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
-)
-
-ADDINCL(
- GLOBAL contrib/restricted/abseil-cpp-tstring
-)
-
-NO_COMPILER_WARNINGS()
-
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/abseil-cpp-tstring
+)
+
+NO_COMPILER_WARNINGS()
+
SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal)
-
-SRCS(
+
+SRCS(
cord_internal.cc
cord_rep_btree.cc
cord_rep_btree_navigator.cc
cord_rep_btree_reader.cc
cord_rep_consume.cc
cord_rep_ring.cc
-)
-
-END()
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
index 4e57fc75f6..f1c30b2590 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal/ya.make
@@ -4,17 +4,17 @@ LIBRARY()
WITHOUT_LICENSE_TEXTS()
-OWNER(
- somov
- g:cpp-contrib
-)
+OWNER(
+ somov
+ g:cpp-contrib
+)
LICENSE(Apache-2.0)
PEERDIR(
- contrib/restricted/abseil-cpp-tstring/y_absl/base
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
index 25428e304c..873125a571 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/char_map.h
@@ -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) {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
index 72a4fa188b..2b6742a64e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.cc
@@ -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;
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
index a77aab14dd..75df41a2e1 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_bigint.h
@@ -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(y_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.
TString ToString() const;
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
index f0f78eb68c..cf92a22d56 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/charconv_parse.cc
@@ -246,8 +246,8 @@ constexpr int DigitMagnitude<16>() {
// ConsumeDigits does not protect against overflow on *out; max_digits must
// be chosen with respect to type T to avoid the possibility of overflow.
template <int base, typename T>
-int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
- bool* dropped_nonzero_digit) {
+int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
+ bool* dropped_nonzero_digit) {
if (base == 10) {
assert(max_digits <= std::numeric_limits<T>::digits10);
} else if (base == 16) {
@@ -282,7 +282,7 @@ int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
*dropped_nonzero_digit = true;
}
*out = accumulator;
- return static_cast<int>(begin - original_begin);
+ return static_cast<int>(begin - original_begin);
}
// Returns true if `v` is one of the chars allowed inside parentheses following
@@ -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 == '(') {
@@ -372,7 +372,7 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
int exponent_adjustment = 0;
bool mantissa_is_inexact = false;
- int pre_decimal_digits = ConsumeDigits<base>(
+ int pre_decimal_digits = ConsumeDigits<base>(
begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
begin += pre_decimal_digits;
int digits_left;
@@ -398,14 +398,14 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
while (begin < end && *begin == '0') {
++begin;
}
- int zeros_skipped = static_cast<int>(begin - begin_zeros);
+ int zeros_skipped = static_cast<int>(begin - begin_zeros);
if (zeros_skipped >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
}
exponent_adjustment -= static_cast<int>(zeros_skipped);
}
- int post_decimal_digits = ConsumeDigits<base>(
+ int post_decimal_digits = ConsumeDigits<base>(
begin, end, digits_left, &mantissa, &mantissa_is_inexact);
begin += post_decimal_digits;
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.cc
index 6fc39985d8..d32e638883 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.cc
@@ -1,89 +1,89 @@
-// 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 "y_absl/strings/internal/cord_internal.h"
-
-#include <atomic>
-#include <cassert>
-#include <memory>
-
-#include "y_absl/container/inlined_vector.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 "y_absl/strings/internal/cord_internal.h"
+
+#include <atomic>
+#include <cassert>
+#include <memory>
+
+#include "y_absl/container/inlined_vector.h"
#include "y_absl/strings/internal/cord_rep_btree.h"
-#include "y_absl/strings/internal/cord_rep_flat.h"
-#include "y_absl/strings/internal/cord_rep_ring.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
+#include "y_absl/strings/internal/cord_rep_flat.h"
+#include "y_absl/strings/internal/cord_rep_ring.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
ABSL_CONST_INIT std::atomic<bool> cord_btree_enabled(kCordEnableBtreeDefault);
-ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled(
- kCordEnableRingBufferDefault);
-ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(
- kCordShallowSubcordsDefault);
+ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled(
+ kCordEnableRingBufferDefault);
+ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(
+ kCordShallowSubcordsDefault);
ABSL_CONST_INIT std::atomic<bool> cord_btree_exhaustive_validation(false);
-
-void CordRep::Destroy(CordRep* rep) {
- assert(rep != nullptr);
-
- y_absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending;
- while (true) {
- assert(!rep->refcount.IsImmortal());
- if (rep->tag == CONCAT) {
- CordRepConcat* rep_concat = rep->concat();
- CordRep* right = rep_concat->right;
- if (!right->refcount.Decrement()) {
- pending.push_back(right);
- }
- CordRep* left = rep_concat->left;
- delete rep_concat;
- rep = nullptr;
- if (!left->refcount.Decrement()) {
- rep = left;
- continue;
- }
+
+void CordRep::Destroy(CordRep* rep) {
+ assert(rep != nullptr);
+
+ y_absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending;
+ while (true) {
+ assert(!rep->refcount.IsImmortal());
+ if (rep->tag == CONCAT) {
+ CordRepConcat* rep_concat = rep->concat();
+ CordRep* right = rep_concat->right;
+ if (!right->refcount.Decrement()) {
+ pending.push_back(right);
+ }
+ CordRep* left = rep_concat->left;
+ delete rep_concat;
+ rep = nullptr;
+ if (!left->refcount.Decrement()) {
+ rep = left;
+ continue;
+ }
} else if (rep->tag == BTREE) {
CordRepBtree::Destroy(rep->btree());
rep = nullptr;
- } else if (rep->tag == RING) {
- CordRepRing::Destroy(rep->ring());
- rep = nullptr;
- } else if (rep->tag == EXTERNAL) {
- CordRepExternal::Delete(rep);
- rep = nullptr;
- } else if (rep->tag == SUBSTRING) {
- CordRepSubstring* rep_substring = rep->substring();
- CordRep* child = rep_substring->child;
- delete rep_substring;
- rep = nullptr;
- if (!child->refcount.Decrement()) {
- rep = child;
- continue;
- }
- } else {
- CordRepFlat::Delete(rep);
- rep = nullptr;
- }
-
- if (!pending.empty()) {
- rep = pending.back();
- pending.pop_back();
- } else {
- break;
- }
- }
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
+ } else if (rep->tag == RING) {
+ CordRepRing::Destroy(rep->ring());
+ rep = nullptr;
+ } else if (rep->tag == EXTERNAL) {
+ CordRepExternal::Delete(rep);
+ rep = nullptr;
+ } else if (rep->tag == SUBSTRING) {
+ CordRepSubstring* rep_substring = rep->substring();
+ CordRep* child = rep_substring->child;
+ delete rep_substring;
+ rep = nullptr;
+ if (!child->refcount.Decrement()) {
+ rep = child;
+ continue;
+ }
+ } else {
+ CordRepFlat::Delete(rep);
+ rep = nullptr;
+ }
+
+ if (!pending.empty()) {
+ rep = pending.back();
+ pending.pop_back();
+ } else {
+ break;
+ }
+ }
+}
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.h
index 82f5ac7b81..02b215f61f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Abseil Authors.
+// 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.
@@ -21,11 +21,11 @@
#include <cstdint>
#include <type_traits>
-#include "y_absl/base/config.h"
-#include "y_absl/base/internal/endian.h"
-#include "y_absl/base/internal/invoke.h"
-#include "y_absl/base/optimization.h"
-#include "y_absl/container/internal/compressed_tuple.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/internal/endian.h"
+#include "y_absl/base/internal/invoke.h"
+#include "y_absl/base/optimization.h"
+#include "y_absl/container/internal/compressed_tuple.h"
#include "y_absl/meta/type_traits.h"
#include "y_absl/strings/string_view.h"
@@ -33,19 +33,19 @@ namespace y_absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
-class CordzInfo;
-
-// Default feature enable states for cord ring buffers
-enum CordFeatureDefaults {
+class CordzInfo;
+
+// Default feature enable states for cord ring buffers
+enum CordFeatureDefaults {
kCordEnableBtreeDefault = true,
- kCordEnableRingBufferDefault = false,
- kCordShallowSubcordsDefault = false
-};
-
+ kCordEnableRingBufferDefault = false,
+ kCordShallowSubcordsDefault = false
+};
+
extern std::atomic<bool> cord_btree_enabled;
-extern std::atomic<bool> cord_ring_buffer_enabled;
-extern std::atomic<bool> shallow_subcords_enabled;
-
+extern std::atomic<bool> cord_ring_buffer_enabled;
+extern std::atomic<bool> shallow_subcords_enabled;
+
// `cord_btree_exhaustive_validation` can be set to force exhaustive validation
// in debug assertions, and code that calls `IsValid()` explicitly. By default,
// assertions should be relatively cheap and AssertValid() can easily lead to
@@ -56,48 +56,48 @@ inline void enable_cord_btree(bool enable) {
cord_btree_enabled.store(enable, std::memory_order_relaxed);
}
-inline void enable_cord_ring_buffer(bool enable) {
- cord_ring_buffer_enabled.store(enable, std::memory_order_relaxed);
-}
-
-inline void enable_shallow_subcords(bool enable) {
- shallow_subcords_enabled.store(enable, std::memory_order_relaxed);
-}
-
-enum Constants {
- // The inlined size to use with y_absl::InlinedVector.
- //
- // Note: The InlinedVectors in this file (and in cord.h) do not need to use
- // the same value for their inlined size. The fact that they do is historical.
- // It may be desirable for each to use a different inlined size optimized for
- // that InlinedVector's usage.
- //
- // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
- // the inlined vector size (47 exists for backward compatibility).
- kInlinedVectorSize = 47,
-
- // Prefer copying blocks of at most this size, otherwise reference count.
- kMaxBytesToCopy = 511
-};
-
+inline void enable_cord_ring_buffer(bool enable) {
+ cord_ring_buffer_enabled.store(enable, std::memory_order_relaxed);
+}
+
+inline void enable_shallow_subcords(bool enable) {
+ shallow_subcords_enabled.store(enable, std::memory_order_relaxed);
+}
+
+enum Constants {
+ // The inlined size to use with y_absl::InlinedVector.
+ //
+ // Note: The InlinedVectors in this file (and in cord.h) do not need to use
+ // the same value for their inlined size. The fact that they do is historical.
+ // It may be desirable for each to use a different inlined size optimized for
+ // that InlinedVector's usage.
+ //
+ // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+ // the inlined vector size (47 exists for backward compatibility).
+ kInlinedVectorSize = 47,
+
+ // Prefer copying blocks of at most this size, otherwise reference count.
+ kMaxBytesToCopy = 511
+};
+
// 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:
constexpr RefcountAndFlags() : count_{kRefIncrement} {}
- struct Immortal {};
+ 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);
- }
+ // 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
- // greater than 1, decrements the reference count.
+ // 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
@@ -106,24 +106,24 @@ class RefcountAndFlags {
inline bool Decrement() {
int32_t refcount = count_.load(std::memory_order_acquire) & kRefcountMask;
assert(refcount > 0 || refcount & kImmortalFlag);
- return refcount != kRefIncrement &&
+ 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() {
- int32_t refcount =
+ int32_t refcount =
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) &
kRefcountMask;
assert(refcount > 0 || refcount & kImmortalFlag);
- return refcount != kRefIncrement;
+ return refcount != kRefIncrement;
}
// Returns the current reference count using acquire semantics.
- inline int32_t Get() const {
+ 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 {
@@ -151,22 +151,22 @@ class RefcountAndFlags {
//
// When this returns true, there are no other references, and data sinks
// may safely adopt the children of the CordRep.
- inline bool IsOne() {
+ inline bool IsOne() {
return (count_.load(std::memory_order_acquire) & kRefcountMask) ==
kRefIncrement;
- }
+ }
- bool IsImmortal() const {
+ bool IsImmortal() const {
return (count_.load(std::memory_order_relaxed) & kImmortalFlag) != 0;
- }
-
+ }
+
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
// constant cords.
// kReservedFlag is reserved for future use.
- enum {
+ enum {
kNumFlags = 2,
kImmortalFlag = 0x1,
@@ -178,8 +178,8 @@ class RefcountAndFlags {
// purposes of equality. (A refcount of 0 or 1 does not count as 0 or 1
// if the immortal bit is set.)
kRefcountMask = ~kCrcFlag,
- };
-
+ };
+
std::atomic<int32_t> count_;
};
@@ -189,30 +189,30 @@ class RefcountAndFlags {
// functions in the base class.
struct CordRepConcat;
-struct CordRepExternal;
-struct CordRepFlat;
+struct CordRepExternal;
+struct CordRepFlat;
struct CordRepSubstring;
-class CordRepRing;
+class CordRepRing;
class CordRepBtree;
-// Various representations that we allow
-enum CordRepKind {
- CONCAT = 0,
+// Various representations that we allow
+enum CordRepKind {
+ CONCAT = 0,
SUBSTRING = 1,
BTREE = 2,
- RING = 3,
+ 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
- // as the Tag <---> Size logic so that FLAT stil represents the minimum flat
- // allocation size. (32 bytes as of now).
+ // 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
+ // as the Tag <---> Size logic so that FLAT stil represents the minimum flat
+ // 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'
@@ -225,13 +225,13 @@ static_assert(EXTERNAL == RING + 1, "BTREE and EXTERNAL not consecutive");
static_assert(FLAT == EXTERNAL + 1, "EXTERNAL and FLAT not consecutive");
struct CordRep {
- CordRep() = default;
+ CordRep() = default;
constexpr CordRep(RefcountAndFlags::Immortal immortal, size_t l)
- : length(l), refcount(immortal), tag(EXTERNAL), storage{} {}
-
+ : 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;
+ 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.
@@ -255,32 +255,32 @@ struct CordRep {
constexpr bool IsFlat() const { return tag >= FLAT; }
constexpr bool IsBtree() const { return tag == BTREE; }
- inline CordRepRing* ring();
- inline const CordRepRing* ring() const;
+ 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 CordRepFlat* flat();
- inline const CordRepFlat* flat() const;
+ inline CordRepFlat* flat();
+ inline const CordRepFlat* flat() const;
inline CordRepBtree* btree();
inline const CordRepBtree* btree() const;
-
- // --------------------------------------------------------------------
- // Memory management
-
- // Destroys the provided `rep`.
- static void Destroy(CordRep* rep);
-
- // Increments the reference count of `rep`.
- // Requires `rep` to be a non-null pointer value.
- static inline CordRep* Ref(CordRep* rep);
-
- // 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);
+
+ // --------------------------------------------------------------------
+ // Memory management
+
+ // Destroys the provided `rep`.
+ static void Destroy(CordRep* rep);
+
+ // Increments the reference count of `rep`.
+ // Requires `rep` to be a non-null pointer value.
+ static inline CordRep* Ref(CordRep* rep);
+
+ // 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 {
@@ -296,151 +296,151 @@ struct CordRepSubstring : public CordRep {
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*);
+// 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(y_absl::string_view str)
+struct CordRepExternal : public CordRep {
+ CordRepExternal() = default;
+ explicit constexpr CordRepExternal(y_absl::string_view str)
: CordRep(RefcountAndFlags::Immortal{}, str.size()),
- base(str.data()),
- releaser_invoker(nullptr) {}
-
+ base(str.data()),
+ releaser_invoker(nullptr) {}
+
const char* base;
// Pointer to function that knows how to call and destroy the releaser.
ExternalReleaserInvoker releaser_invoker;
-
- // Deletes (releases) the external rep.
+
+ // Deletes (releases) the external rep.
// Requires rep != nullptr and rep->IsExternal()
- static void Delete(CordRep* rep);
+ static void Delete(CordRep* rep);
};
-struct Rank1 {};
-struct Rank0 : Rank1 {};
-
-template <typename Releaser, typename = ::y_absl::base_internal::invoke_result_t<
- Releaser, y_absl::string_view>>
-void InvokeReleaser(Rank0, Releaser&& releaser, y_absl::string_view data) {
- ::y_absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
-}
-
-template <typename Releaser,
- typename = ::y_absl::base_internal::invoke_result_t<Releaser>>
-void InvokeReleaser(Rank1, Releaser&& releaser, y_absl::string_view) {
- ::y_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 ::y_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>()),
- y_absl::string_view(base, length));
- }
-
- static void Release(CordRepExternal* rep) {
- delete static_cast<CordRepExternalImpl*>(rep);
- }
-};
-
-inline void CordRepExternal::Delete(CordRep* rep) {
+struct Rank1 {};
+struct Rank0 : Rank1 {};
+
+template <typename Releaser, typename = ::y_absl::base_internal::invoke_result_t<
+ Releaser, y_absl::string_view>>
+void InvokeReleaser(Rank0, Releaser&& releaser, y_absl::string_view data) {
+ ::y_absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+}
+
+template <typename Releaser,
+ typename = ::y_absl::base_internal::invoke_result_t<Releaser>>
+void InvokeReleaser(Rank1, Releaser&& releaser, y_absl::string_view) {
+ ::y_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 ::y_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>()),
+ y_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);
- assert(rep_external->releaser_invoker != nullptr);
- rep_external->releaser_invoker(rep_external);
-}
-
-template <typename Str>
-struct ConstInitExternalStorage {
- ABSL_CONST_INIT static CordRepExternal value;
-};
-
-template <typename Str>
-CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
-
-enum {
- kMaxInline = 15,
-};
-
-constexpr char GetOrNull(y_absl::string_view data, size_t pos) {
- return pos < data.size() ? data[pos] : '\0';
-}
-
-// We store cordz_info as 64 bit pointer value in big endian format. This
-// guarantees that the least significant byte of cordz_info matches the last
-// byte of the inline data representation in as_chars_, which holds the inlined
-// size or the 'is_tree' bit.
-using cordz_info_t = int64_t;
-
-// Assert that the `cordz_info` pointer value perfectly overlaps the last half
-// of `as_chars_` and can hold a pointer value.
-static_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, "");
-static_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), "");
-
-// BigEndianByte() creates a big endian representation of 'value', i.e.: a big
-// endian value where the last byte in the host's representation holds 'value`,
-// with all other bytes being 0.
-static constexpr cordz_info_t BigEndianByte(unsigned char value) {
-#if defined(ABSL_IS_BIG_ENDIAN)
- return value;
-#else
- return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
-#endif
-}
-
-class InlineData {
- public:
+ auto* rep_external = static_cast<CordRepExternal*>(rep);
+ assert(rep_external->releaser_invoker != nullptr);
+ rep_external->releaser_invoker(rep_external);
+}
+
+template <typename Str>
+struct ConstInitExternalStorage {
+ ABSL_CONST_INIT static CordRepExternal value;
+};
+
+template <typename Str>
+CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+
+enum {
+ kMaxInline = 15,
+};
+
+constexpr char GetOrNull(y_absl::string_view data, size_t pos) {
+ return pos < data.size() ? data[pos] : '\0';
+}
+
+// We store cordz_info as 64 bit pointer value in big endian format. This
+// guarantees that the least significant byte of cordz_info matches the last
+// byte of the inline data representation in as_chars_, which holds the inlined
+// size or the 'is_tree' bit.
+using cordz_info_t = int64_t;
+
+// Assert that the `cordz_info` pointer value perfectly overlaps the last half
+// of `as_chars_` and can hold a pointer value.
+static_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, "");
+static_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), "");
+
+// BigEndianByte() creates a big endian representation of 'value', i.e.: a big
+// endian value where the last byte in the host's representation holds 'value`,
+// with all other bytes being 0.
+static constexpr cordz_info_t BigEndianByte(unsigned char value) {
+#if defined(ABSL_IS_BIG_ENDIAN)
+ return value;
+#else
+ return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
+#endif
+}
+
+class InlineData {
+ public:
// DefaultInitType forces the use of the default initialization constructor.
enum DefaultInitType { kDefaultInit };
- // kNullCordzInfo holds the big endian representation of intptr_t(1)
- // This is the 'null' / initial value of 'cordz_info'. The null value
- // is specifically big endian 1 as with 64-bit pointers, the last
- // byte of cordz_info overlaps with the last byte holding the tag.
- static constexpr cordz_info_t kNullCordzInfo = BigEndianByte(1);
-
- constexpr InlineData() : as_chars_{0} {}
+ // kNullCordzInfo holds the big endian representation of intptr_t(1)
+ // This is the 'null' / initial value of 'cordz_info'. The null value
+ // is specifically big endian 1 as with 64-bit pointers, the last
+ // byte of cordz_info overlaps with the last byte holding the tag.
+ static constexpr cordz_info_t kNullCordzInfo = BigEndianByte(1);
+
+ constexpr InlineData() : as_chars_{0} {}
explicit InlineData(DefaultInitType) {}
- explicit constexpr InlineData(CordRep* rep) : as_tree_(rep) {}
- explicit constexpr InlineData(y_absl::string_view chars)
- : as_chars_{
- GetOrNull(chars, 0), GetOrNull(chars, 1),
- GetOrNull(chars, 2), GetOrNull(chars, 3),
- GetOrNull(chars, 4), GetOrNull(chars, 5),
- GetOrNull(chars, 6), GetOrNull(chars, 7),
- GetOrNull(chars, 8), GetOrNull(chars, 9),
- GetOrNull(chars, 10), GetOrNull(chars, 11),
- GetOrNull(chars, 12), GetOrNull(chars, 13),
- GetOrNull(chars, 14), static_cast<char>((chars.size() << 1))} {}
-
- // Returns true if the current instance is empty.
- // The 'empty value' is an inlined data value of zero length.
- bool is_empty() const { return tag() == 0; }
-
- // Returns true if the current instance holds a tree value.
- bool is_tree() const { return (tag() & 1) != 0; }
-
- // Returns true if the current instance holds a cordz_info value.
- // Requires the current instance to hold a tree value.
- bool is_profiled() const {
- assert(is_tree());
- return as_tree_.cordz_info != kNullCordzInfo;
- }
-
+ explicit constexpr InlineData(CordRep* rep) : as_tree_(rep) {}
+ explicit constexpr InlineData(y_absl::string_view chars)
+ : as_chars_{
+ GetOrNull(chars, 0), GetOrNull(chars, 1),
+ GetOrNull(chars, 2), GetOrNull(chars, 3),
+ GetOrNull(chars, 4), GetOrNull(chars, 5),
+ GetOrNull(chars, 6), GetOrNull(chars, 7),
+ GetOrNull(chars, 8), GetOrNull(chars, 9),
+ GetOrNull(chars, 10), GetOrNull(chars, 11),
+ GetOrNull(chars, 12), GetOrNull(chars, 13),
+ GetOrNull(chars, 14), static_cast<char>((chars.size() << 1))} {}
+
+ // Returns true if the current instance is empty.
+ // The 'empty value' is an inlined data value of zero length.
+ bool is_empty() const { return tag() == 0; }
+
+ // Returns true if the current instance holds a tree value.
+ bool is_tree() const { return (tag() & 1) != 0; }
+
+ // Returns true if the current instance holds a cordz_info value.
+ // Requires the current instance to hold a tree value.
+ bool is_profiled() const {
+ assert(is_tree());
+ return as_tree_.cordz_info != kNullCordzInfo;
+ }
+
// Returns true if either of the provided instances hold a cordz_info value.
// This method is more efficient than the equivalent `data1.is_profiled() ||
// data2.is_profiled()`. Requires both arguments to hold a tree.
@@ -451,170 +451,170 @@ class InlineData {
kNullCordzInfo;
}
- // Returns the cordz_info sampling instance for this instance, or nullptr
- // if the current instance is not sampled and does not have CordzInfo data.
- // Requires the current instance to hold a tree value.
- CordzInfo* cordz_info() const {
- assert(is_tree());
- intptr_t info =
- static_cast<intptr_t>(y_absl::big_endian::ToHost64(as_tree_.cordz_info));
- assert(info & 1);
- return reinterpret_cast<CordzInfo*>(info - 1);
- }
-
- // Sets the current cordz_info sampling instance for this instance, or nullptr
- // if the current instance is not sampled and does not have CordzInfo data.
- // Requires the current instance to hold a tree value.
- void set_cordz_info(CordzInfo* cordz_info) {
- assert(is_tree());
- intptr_t info = reinterpret_cast<intptr_t>(cordz_info) | 1;
- as_tree_.cordz_info = y_absl::big_endian::FromHost64(info);
- }
-
- // Resets the current cordz_info to null / empty.
- void clear_cordz_info() {
- assert(is_tree());
- as_tree_.cordz_info = kNullCordzInfo;
- }
-
- // Returns a read only pointer to the character data inside this instance.
- // Requires the current instance to hold inline data.
- const char* as_chars() const {
- assert(!is_tree());
- return as_chars_;
- }
-
- // Returns a mutable pointer to the character data inside this instance.
- // Should be used for 'write only' operations setting an inlined value.
- // Applications can set the value of inlined data either before or after
- // setting the inlined size, i.e., both of the below are valid:
- //
- // // Set inlined data and inline size
- // memcpy(data_.as_chars(), data, size);
- // data_.set_inline_size(size);
- //
- // // Set inlined size and inline data
- // data_.set_inline_size(size);
- // memcpy(data_.as_chars(), data, size);
- //
- // It's an error to read from the returned pointer without a preceding write
- // if the current instance does not hold inline data, i.e.: is_tree() == true.
- char* as_chars() { return as_chars_; }
-
- // Returns the tree value of this value.
- // Requires the current instance to hold a tree value.
- CordRep* as_tree() const {
- assert(is_tree());
- return as_tree_.rep;
- }
-
- // Initialize this instance to holding the tree value `rep`,
- // initializing the cordz_info to null, i.e.: 'not profiled'.
- void make_tree(CordRep* rep) {
- as_tree_.rep = rep;
- as_tree_.cordz_info = kNullCordzInfo;
- }
-
- // Set the tree value of this instance to 'rep`.
- // Requires the current instance to already hold a tree value.
- // Does not affect the value of cordz_info.
- void set_tree(CordRep* rep) {
- assert(is_tree());
- as_tree_.rep = rep;
- }
-
- // Returns the size of the inlined character data inside this instance.
- // Requires the current instance to hold inline data.
- size_t inline_size() const {
- assert(!is_tree());
- return tag() >> 1;
- }
-
- // Sets the size of the inlined character data inside this instance.
- // Requires `size` to be <= kMaxInline.
- // See the documentation on 'as_chars()' for more information and examples.
- void set_inline_size(size_t size) {
- ABSL_ASSERT(size <= kMaxInline);
- tag() = static_cast<char>(size << 1);
- }
-
- private:
- // See cordz_info_t for forced alignment and size of `cordz_info` details.
- struct AsTree {
- explicit constexpr AsTree(y_absl::cord_internal::CordRep* tree)
- : rep(tree), cordz_info(kNullCordzInfo) {}
- // This union uses up extra space so that whether rep is 32 or 64 bits,
- // cordz_info will still start at the eighth byte, and the last
- // byte of cordz_info will still be the last byte of InlineData.
- union {
- y_absl::cord_internal::CordRep* rep;
- cordz_info_t unused_aligner;
- };
- cordz_info_t cordz_info;
- };
-
- char& tag() { return reinterpret_cast<char*>(this)[kMaxInline]; }
- char tag() const { return reinterpret_cast<const char*>(this)[kMaxInline]; }
-
- // If the data has length <= kMaxInline, we store it in `as_chars_`, and
- // store the size in the last char of `as_chars_` shifted left + 1.
- // Else we store it in a tree and store a pointer to that tree in
- // `as_tree_.rep` and store a tag in `tagged_size`.
+ // Returns the cordz_info sampling instance for this instance, or nullptr
+ // if the current instance is not sampled and does not have CordzInfo data.
+ // Requires the current instance to hold a tree value.
+ CordzInfo* cordz_info() const {
+ assert(is_tree());
+ intptr_t info =
+ static_cast<intptr_t>(y_absl::big_endian::ToHost64(as_tree_.cordz_info));
+ assert(info & 1);
+ return reinterpret_cast<CordzInfo*>(info - 1);
+ }
+
+ // Sets the current cordz_info sampling instance for this instance, or nullptr
+ // if the current instance is not sampled and does not have CordzInfo data.
+ // Requires the current instance to hold a tree value.
+ void set_cordz_info(CordzInfo* cordz_info) {
+ assert(is_tree());
+ intptr_t info = reinterpret_cast<intptr_t>(cordz_info) | 1;
+ as_tree_.cordz_info = y_absl::big_endian::FromHost64(info);
+ }
+
+ // Resets the current cordz_info to null / empty.
+ void clear_cordz_info() {
+ assert(is_tree());
+ as_tree_.cordz_info = kNullCordzInfo;
+ }
+
+ // Returns a read only pointer to the character data inside this instance.
+ // Requires the current instance to hold inline data.
+ const char* as_chars() const {
+ assert(!is_tree());
+ return as_chars_;
+ }
+
+ // Returns a mutable pointer to the character data inside this instance.
+ // Should be used for 'write only' operations setting an inlined value.
+ // Applications can set the value of inlined data either before or after
+ // setting the inlined size, i.e., both of the below are valid:
+ //
+ // // Set inlined data and inline size
+ // memcpy(data_.as_chars(), data, size);
+ // data_.set_inline_size(size);
+ //
+ // // Set inlined size and inline data
+ // data_.set_inline_size(size);
+ // memcpy(data_.as_chars(), data, size);
+ //
+ // It's an error to read from the returned pointer without a preceding write
+ // if the current instance does not hold inline data, i.e.: is_tree() == true.
+ char* as_chars() { return as_chars_; }
+
+ // Returns the tree value of this value.
+ // Requires the current instance to hold a tree value.
+ CordRep* as_tree() const {
+ assert(is_tree());
+ return as_tree_.rep;
+ }
+
+ // Initialize this instance to holding the tree value `rep`,
+ // initializing the cordz_info to null, i.e.: 'not profiled'.
+ void make_tree(CordRep* rep) {
+ as_tree_.rep = rep;
+ as_tree_.cordz_info = kNullCordzInfo;
+ }
+
+ // Set the tree value of this instance to 'rep`.
+ // Requires the current instance to already hold a tree value.
+ // Does not affect the value of cordz_info.
+ void set_tree(CordRep* rep) {
+ assert(is_tree());
+ as_tree_.rep = rep;
+ }
+
+ // Returns the size of the inlined character data inside this instance.
+ // Requires the current instance to hold inline data.
+ size_t inline_size() const {
+ assert(!is_tree());
+ return tag() >> 1;
+ }
+
+ // Sets the size of the inlined character data inside this instance.
+ // Requires `size` to be <= kMaxInline.
+ // See the documentation on 'as_chars()' for more information and examples.
+ void set_inline_size(size_t size) {
+ ABSL_ASSERT(size <= kMaxInline);
+ tag() = static_cast<char>(size << 1);
+ }
+
+ private:
+ // See cordz_info_t for forced alignment and size of `cordz_info` details.
+ struct AsTree {
+ explicit constexpr AsTree(y_absl::cord_internal::CordRep* tree)
+ : rep(tree), cordz_info(kNullCordzInfo) {}
+ // This union uses up extra space so that whether rep is 32 or 64 bits,
+ // cordz_info will still start at the eighth byte, and the last
+ // byte of cordz_info will still be the last byte of InlineData.
+ union {
+ y_absl::cord_internal::CordRep* rep;
+ cordz_info_t unused_aligner;
+ };
+ cordz_info_t cordz_info;
+ };
+
+ char& tag() { return reinterpret_cast<char*>(this)[kMaxInline]; }
+ char tag() const { return reinterpret_cast<const char*>(this)[kMaxInline]; }
+
+ // If the data has length <= kMaxInline, we store it in `as_chars_`, and
+ // store the size in the last char of `as_chars_` shifted left + 1.
+ // Else we store it in a tree and store a pointer to that tree in
+ // `as_tree_.rep` and store a tag in `tagged_size`.
union {
- char as_chars_[kMaxInline + 1];
- AsTree as_tree_;
- };
-};
-
-static_assert(sizeof(InlineData) == kMaxInline + 1, "");
-
-inline CordRepConcat* CordRep::concat() {
+ char as_chars_[kMaxInline + 1];
+ AsTree as_tree_;
+ };
+};
+
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+
+inline CordRepConcat* CordRep::concat() {
assert(IsConcat());
- return static_cast<CordRepConcat*>(this);
-}
-
-inline const CordRepConcat* CordRep::concat() const {
+ return static_cast<CordRepConcat*>(this);
+}
+
+inline const CordRepConcat* CordRep::concat() const {
assert(IsConcat());
- return static_cast<const CordRepConcat*>(this);
-}
-
-inline CordRepSubstring* CordRep::substring() {
+ return static_cast<const CordRepConcat*>(this);
+}
+
+inline CordRepSubstring* CordRep::substring() {
assert(IsSubstring());
- return static_cast<CordRepSubstring*>(this);
-}
-
-inline const CordRepSubstring* CordRep::substring() const {
+ return static_cast<CordRepSubstring*>(this);
+}
+
+inline const CordRepSubstring* CordRep::substring() const {
assert(IsSubstring());
- return static_cast<const CordRepSubstring*>(this);
-}
-
-inline CordRepExternal* CordRep::external() {
+ return static_cast<const CordRepSubstring*>(this);
+}
+
+inline CordRepExternal* CordRep::external() {
assert(IsExternal());
- return static_cast<CordRepExternal*>(this);
-}
-
-inline const CordRepExternal* CordRep::external() const {
+ return static_cast<CordRepExternal*>(this);
+}
+
+inline const CordRepExternal* CordRep::external() const {
assert(IsExternal());
- return static_cast<const CordRepExternal*>(this);
-}
-
-inline CordRep* CordRep::Ref(CordRep* rep) {
- assert(rep != nullptr);
- rep->refcount.Increment();
- return rep;
-}
-
-inline void CordRep::Unref(CordRep* rep) {
- assert(rep != nullptr);
- // Expect refcount to be 0. Avoiding the cost of an atomic decrement should
- // typically outweigh the cost of an extra branch checking for ref == 1.
- if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {
- Destroy(rep);
- }
-}
-
+ return static_cast<const CordRepExternal*>(this);
+}
+
+inline CordRep* CordRep::Ref(CordRep* rep) {
+ assert(rep != nullptr);
+ rep->refcount.Increment();
+ return rep;
+}
+
+inline void CordRep::Unref(CordRep* rep) {
+ assert(rep != nullptr);
+ // Expect refcount to be 0. Avoiding the cost of an atomic decrement should
+ // typically outweigh the cost of an extra branch checking for ref == 1.
+ if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {
+ Destroy(rep);
+ }
+}
+
} // namespace cord_internal
-
+
ABSL_NAMESPACE_END
} // namespace y_absl
#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_flat.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_flat.h
index 976613031c..5557022553 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_flat.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_flat.h
@@ -1,146 +1,146 @@
-// 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_CORD_REP_FLAT_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-
-#include "y_absl/strings/internal/cord_internal.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// Note: all constants below are never ODR used and internal to cord, we define
-// these as static constexpr to avoid 'in struct' definition and usage clutter.
-
-// Largest and smallest flat node lengths we are willing to allocate
-// Flat allocation size is stored in tag, which currently can encode sizes up
-// to 4K, encoded as multiple of either 8 or 32 bytes.
-// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
-// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
-// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
-// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
-// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
-static constexpr size_t kFlatOverhead = offsetof(CordRep, storage);
-static constexpr size_t kMinFlatSize = 32;
-static constexpr size_t kMaxFlatSize = 4096;
-static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
-static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
-
-constexpr uint8_t AllocatedSizeToTagUnchecked(size_t size) {
+// 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_CORD_REP_FLAT_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+#include "y_absl/strings/internal/cord_internal.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// Note: all constants below are never ODR used and internal to cord, we define
+// these as static constexpr to avoid 'in struct' definition and usage clutter.
+
+// Largest and smallest flat node lengths we are willing to allocate
+// Flat allocation size is stored in tag, which currently can encode sizes up
+// to 4K, encoded as multiple of either 8 or 32 bytes.
+// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
+// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
+// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
+// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
+// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
+static constexpr size_t kFlatOverhead = offsetof(CordRep, storage);
+static constexpr size_t kMinFlatSize = 32;
+static constexpr size_t kMaxFlatSize = 4096;
+static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
+static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
+
+constexpr uint8_t AllocatedSizeToTagUnchecked(size_t size) {
return static_cast<uint8_t>((size <= 1024) ? size / 8 + 1
: 129 + size / 32 - 1024 / 32);
-}
-
+}
+
static_assert(kMinFlatSize / 8 + 1 >= FLAT, "");
-static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, "");
-
-// Helper functions for rounded div, and rounding to exact sizes.
-constexpr size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
-constexpr size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
-
-// Returns the size to the nearest equal or larger value that can be
-// expressed exactly as a tag value.
-inline size_t RoundUpForTag(size_t size) {
- return RoundUp(size, (size <= 1024) ? 8 : 32);
-}
-
-// Converts the allocated size to a tag, rounding down if the size
-// does not exactly match a 'tag expressible' size value. The result is
-// undefined if the size exceeds the maximum size that can be encoded in
-// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
-inline uint8_t AllocatedSizeToTag(size_t size) {
- const uint8_t tag = AllocatedSizeToTagUnchecked(size);
- assert(tag <= MAX_FLAT_TAG);
- return tag;
-}
-
-// Converts the provided tag to the corresponding allocated size
-constexpr size_t TagToAllocatedSize(uint8_t tag) {
+static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, "");
+
+// Helper functions for rounded div, and rounding to exact sizes.
+constexpr size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
+constexpr size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
+
+// Returns the size to the nearest equal or larger value that can be
+// expressed exactly as a tag value.
+inline size_t RoundUpForTag(size_t size) {
+ return RoundUp(size, (size <= 1024) ? 8 : 32);
+}
+
+// Converts the allocated size to a tag, rounding down if the size
+// does not exactly match a 'tag expressible' size value. The result is
+// undefined if the size exceeds the maximum size that can be encoded in
+// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
+inline uint8_t AllocatedSizeToTag(size_t size) {
+ const uint8_t tag = AllocatedSizeToTagUnchecked(size);
+ assert(tag <= MAX_FLAT_TAG);
+ return tag;
+}
+
+// Converts the provided tag to the corresponding allocated size
+constexpr size_t TagToAllocatedSize(uint8_t tag) {
return (tag <= 129) ? ((tag - 1) * 8) : (1024 + (tag - 129) * 32);
-}
-
-// Converts the provided tag to the corresponding available data length
-constexpr size_t TagToLength(uint8_t tag) {
- return TagToAllocatedSize(tag) - kFlatOverhead;
-}
-
-// Enforce that kMaxFlatSize maps to a well-known exact tag value.
+}
+
+// Converts the provided tag to the corresponding available data length
+constexpr size_t TagToLength(uint8_t tag) {
+ return TagToAllocatedSize(tag) - kFlatOverhead;
+}
+
+// Enforce that kMaxFlatSize maps to a well-known exact tag value.
static_assert(TagToAllocatedSize(225) == kMaxFlatSize, "Bad tag logic");
-
-struct CordRepFlat : public CordRep {
- // Creates a new flat node.
- static CordRepFlat* New(size_t len) {
- if (len <= kMinFlatLength) {
- len = kMinFlatLength;
- } else if (len > kMaxFlatLength) {
- len = kMaxFlatLength;
- }
-
- // Round size up so it matches a size we can exactly express in a tag.
- const size_t size = RoundUpForTag(len + kFlatOverhead);
- void* const raw_rep = ::operator new(size);
- CordRepFlat* rep = new (raw_rep) CordRepFlat();
- rep->tag = AllocatedSizeToTag(size);
- return rep;
- }
-
- // Deletes a CordRepFlat instance created previously through a call to New().
- // Flat CordReps are allocated and constructed with raw ::operator new and
- // placement new, and must be destructed and deallocated accordingly.
- static void Delete(CordRep*rep) {
- assert(rep->tag >= FLAT && rep->tag <= MAX_FLAT_TAG);
-
-#if defined(__cpp_sized_deallocation)
- size_t size = TagToAllocatedSize(rep->tag);
- rep->~CordRep();
- ::operator delete(rep, size);
-#else
- rep->~CordRep();
- ::operator delete(rep);
-#endif
- }
-
- // Returns a pointer to the data inside this flat rep.
+
+struct CordRepFlat : public CordRep {
+ // Creates a new flat node.
+ static CordRepFlat* New(size_t len) {
+ if (len <= kMinFlatLength) {
+ len = kMinFlatLength;
+ } else if (len > kMaxFlatLength) {
+ len = kMaxFlatLength;
+ }
+
+ // Round size up so it matches a size we can exactly express in a tag.
+ const size_t size = RoundUpForTag(len + kFlatOverhead);
+ void* const raw_rep = ::operator new(size);
+ CordRepFlat* rep = new (raw_rep) CordRepFlat();
+ rep->tag = AllocatedSizeToTag(size);
+ return rep;
+ }
+
+ // Deletes a CordRepFlat instance created previously through a call to New().
+ // Flat CordReps are allocated and constructed with raw ::operator new and
+ // placement new, and must be destructed and deallocated accordingly.
+ static void Delete(CordRep*rep) {
+ assert(rep->tag >= FLAT && rep->tag <= MAX_FLAT_TAG);
+
+#if defined(__cpp_sized_deallocation)
+ size_t size = TagToAllocatedSize(rep->tag);
+ rep->~CordRep();
+ ::operator delete(rep, size);
+#else
+ rep->~CordRep();
+ ::operator delete(rep);
+#endif
+ }
+
+ // Returns a pointer to the data inside this flat rep.
char* Data() { return reinterpret_cast<char*>(storage); }
const char* Data() const { return reinterpret_cast<const char*>(storage); }
-
- // Returns the maximum capacity (payload size) of this instance.
- size_t Capacity() const { return TagToLength(tag); }
-
- // Returns the allocated size (payload + overhead) of this instance.
- size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
-};
-
-// Now that CordRepFlat is defined, we can define CordRep's helper casts:
-inline CordRepFlat* CordRep::flat() {
- assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
- return reinterpret_cast<CordRepFlat*>(this);
-}
-
-inline const CordRepFlat* CordRep::flat() const {
- assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
- return reinterpret_cast<const CordRepFlat*>(this);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+
+ // Returns the maximum capacity (payload size) of this instance.
+ size_t Capacity() const { return TagToLength(tag); }
+
+ // Returns the allocated size (payload + overhead) of this instance.
+ size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
+};
+
+// Now that CordRepFlat is defined, we can define CordRep's helper casts:
+inline CordRepFlat* CordRep::flat() {
+ assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+ return reinterpret_cast<CordRepFlat*>(this);
+}
+
+inline const CordRepFlat* CordRep::flat() const {
+ assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+ return reinterpret_cast<const CordRepFlat*>(this);
+}
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.cc
index 06c7e75bd8..97dff05363 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.cc
@@ -1,771 +1,771 @@
-// 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 "y_absl/strings/internal/cord_rep_ring.h"
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <iostream>
-#include <limits>
-#include <memory>
-#include <util/generic/string.h>
-
-#include "y_absl/base/internal/raw_logging.h"
-#include "y_absl/base/internal/throw_delegate.h"
-#include "y_absl/base/macros.h"
-#include "y_absl/container/inlined_vector.h"
-#include "y_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 "y_absl/strings/internal/cord_rep_ring.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <memory>
+#include <util/generic/string.h>
+
+#include "y_absl/base/internal/raw_logging.h"
+#include "y_absl/base/internal/throw_delegate.h"
+#include "y_absl/base/macros.h"
+#include "y_absl/container/inlined_vector.h"
+#include "y_absl/strings/internal/cord_internal.h"
#include "y_absl/strings/internal/cord_rep_consume.h"
-#include "y_absl/strings/internal/cord_rep_flat.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-namespace {
-
-using index_type = CordRepRing::index_type;
-
-enum class Direction { kForward, kReversed };
-
-inline bool IsFlatOrExternal(CordRep* rep) {
+#include "y_absl/strings/internal/cord_rep_flat.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+namespace {
+
+using index_type = CordRepRing::index_type;
+
+enum class Direction { kForward, kReversed };
+
+inline bool IsFlatOrExternal(CordRep* rep) {
return rep->IsFlat() || rep->IsExternal();
-}
-
-// Verifies that n + extra <= kMaxCapacity: throws std::length_error otherwise.
-inline void CheckCapacity(size_t n, size_t extra) {
- if (ABSL_PREDICT_FALSE(extra > CordRepRing::kMaxCapacity - n)) {
- base_internal::ThrowStdLengthError("Maximum capacity exceeded");
- }
-}
-
-// Creates a flat from the provided string data, allocating up to `extra`
-// capacity in the returned flat depending on kMaxFlatLength limitations.
-// Requires `len` to be less or equal to `kMaxFlatLength`
-CordRepFlat* CreateFlat(const char* s, size_t n, size_t extra = 0) { // NOLINT
- assert(n <= kMaxFlatLength);
- auto* rep = CordRepFlat::New(n + extra);
- rep->length = n;
- memcpy(rep->Data(), s, n);
- return rep;
-}
-
-// Unrefs the entries in `[head, tail)`.
-// Requires all entries to be a FLAT or EXTERNAL node.
-void UnrefEntries(const CordRepRing* rep, index_type head, index_type tail) {
- rep->ForEach(head, tail, [rep](index_type ix) {
- CordRep* child = rep->entry_child(ix);
- if (!child->refcount.Decrement()) {
- if (child->tag >= FLAT) {
- CordRepFlat::Delete(child->flat());
- } else {
- CordRepExternal::Delete(child->external());
- }
- }
- });
-}
-
-} // namespace
-
-std::ostream& operator<<(std::ostream& s, const CordRepRing& rep) {
- // Note: 'pos' values are defined as size_t (for overflow reasons), but that
- // prints really awkward for small prepended values such as -5. ssize_t is not
- // portable (POSIX), so we use ptrdiff_t instead to cast to signed values.
- s << " CordRepRing(" << &rep << ", length = " << rep.length
- << ", head = " << rep.head_ << ", tail = " << rep.tail_
- << ", cap = " << rep.capacity_ << ", rc = " << rep.refcount.Get()
- << ", begin_pos_ = " << static_cast<ptrdiff_t>(rep.begin_pos_) << ") {\n";
- CordRepRing::index_type head = rep.head();
- do {
- CordRep* child = rep.entry_child(head);
- s << " entry[" << head << "] length = " << rep.entry_length(head)
- << ", child " << child << ", clen = " << child->length
- << ", tag = " << static_cast<int>(child->tag)
- << ", rc = " << child->refcount.Get()
- << ", offset = " << rep.entry_data_offset(head)
- << ", end_pos = " << static_cast<ptrdiff_t>(rep.entry_end_pos(head))
- << "\n";
- head = rep.advance(head);
- } while (head != rep.tail());
- return s << "}\n";
-}
-
-void CordRepRing::AddDataOffset(index_type index, size_t n) {
- entry_data_offset()[index] += static_cast<offset_type>(n);
-}
-
-void CordRepRing::SubLength(index_type index, size_t n) {
- entry_end_pos()[index] -= n;
-}
-
-class CordRepRing::Filler {
- public:
- Filler(CordRepRing* rep, index_type pos) : rep_(rep), head_(pos), pos_(pos) {}
-
- index_type head() const { return head_; }
- index_type pos() const { return pos_; }
-
- void Add(CordRep* child, size_t offset, pos_type end_pos) {
- rep_->entry_end_pos()[pos_] = end_pos;
- rep_->entry_child()[pos_] = child;
- rep_->entry_data_offset()[pos_] = static_cast<offset_type>(offset);
- pos_ = rep_->advance(pos_);
- }
-
- private:
- CordRepRing* rep_;
- index_type head_;
- index_type pos_;
-};
-
-constexpr size_t CordRepRing::kMaxCapacity; // NOLINT: needed for c++11
-
-bool CordRepRing::IsValid(std::ostream& output) const {
- if (capacity_ == 0) {
- output << "capacity == 0";
- return false;
- }
-
- if (head_ >= capacity_ || tail_ >= capacity_) {
- output << "head " << head_ << " and/or tail " << tail_ << "exceed capacity "
- << capacity_;
- return false;
- }
-
- const index_type back = retreat(tail_);
- size_t pos_length = Distance(begin_pos_, entry_end_pos(back));
- if (pos_length != length) {
- output << "length " << length << " does not match positional length "
- << pos_length << " from begin_pos " << begin_pos_ << " and entry["
- << back << "].end_pos " << entry_end_pos(back);
- return false;
- }
-
- index_type head = head_;
- pos_type begin_pos = begin_pos_;
- do {
- pos_type end_pos = entry_end_pos(head);
- size_t entry_length = Distance(begin_pos, end_pos);
- if (entry_length == 0) {
- output << "entry[" << head << "] has an invalid length " << entry_length
- << " from begin_pos " << begin_pos << " and end_pos " << end_pos;
- return false;
- }
-
- CordRep* child = entry_child(head);
- if (child == nullptr) {
- output << "entry[" << head << "].child == nullptr";
- return false;
- }
- if (child->tag < FLAT && child->tag != EXTERNAL) {
- output << "entry[" << head << "].child has an invalid tag "
- << static_cast<int>(child->tag);
- return false;
- }
-
- size_t offset = entry_data_offset(head);
- if (offset >= child->length || entry_length > child->length - offset) {
- output << "entry[" << head << "] has offset " << offset
- << " and entry length " << entry_length
+}
+
+// Verifies that n + extra <= kMaxCapacity: throws std::length_error otherwise.
+inline void CheckCapacity(size_t n, size_t extra) {
+ if (ABSL_PREDICT_FALSE(extra > CordRepRing::kMaxCapacity - n)) {
+ base_internal::ThrowStdLengthError("Maximum capacity exceeded");
+ }
+}
+
+// Creates a flat from the provided string data, allocating up to `extra`
+// capacity in the returned flat depending on kMaxFlatLength limitations.
+// Requires `len` to be less or equal to `kMaxFlatLength`
+CordRepFlat* CreateFlat(const char* s, size_t n, size_t extra = 0) { // NOLINT
+ assert(n <= kMaxFlatLength);
+ auto* rep = CordRepFlat::New(n + extra);
+ rep->length = n;
+ memcpy(rep->Data(), s, n);
+ return rep;
+}
+
+// Unrefs the entries in `[head, tail)`.
+// Requires all entries to be a FLAT or EXTERNAL node.
+void UnrefEntries(const CordRepRing* rep, index_type head, index_type tail) {
+ rep->ForEach(head, tail, [rep](index_type ix) {
+ CordRep* child = rep->entry_child(ix);
+ if (!child->refcount.Decrement()) {
+ if (child->tag >= FLAT) {
+ CordRepFlat::Delete(child->flat());
+ } else {
+ CordRepExternal::Delete(child->external());
+ }
+ }
+ });
+}
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& s, const CordRepRing& rep) {
+ // Note: 'pos' values are defined as size_t (for overflow reasons), but that
+ // prints really awkward for small prepended values such as -5. ssize_t is not
+ // portable (POSIX), so we use ptrdiff_t instead to cast to signed values.
+ s << " CordRepRing(" << &rep << ", length = " << rep.length
+ << ", head = " << rep.head_ << ", tail = " << rep.tail_
+ << ", cap = " << rep.capacity_ << ", rc = " << rep.refcount.Get()
+ << ", begin_pos_ = " << static_cast<ptrdiff_t>(rep.begin_pos_) << ") {\n";
+ CordRepRing::index_type head = rep.head();
+ do {
+ CordRep* child = rep.entry_child(head);
+ s << " entry[" << head << "] length = " << rep.entry_length(head)
+ << ", child " << child << ", clen = " << child->length
+ << ", tag = " << static_cast<int>(child->tag)
+ << ", rc = " << child->refcount.Get()
+ << ", offset = " << rep.entry_data_offset(head)
+ << ", end_pos = " << static_cast<ptrdiff_t>(rep.entry_end_pos(head))
+ << "\n";
+ head = rep.advance(head);
+ } while (head != rep.tail());
+ return s << "}\n";
+}
+
+void CordRepRing::AddDataOffset(index_type index, size_t n) {
+ entry_data_offset()[index] += static_cast<offset_type>(n);
+}
+
+void CordRepRing::SubLength(index_type index, size_t n) {
+ entry_end_pos()[index] -= n;
+}
+
+class CordRepRing::Filler {
+ public:
+ Filler(CordRepRing* rep, index_type pos) : rep_(rep), head_(pos), pos_(pos) {}
+
+ index_type head() const { return head_; }
+ index_type pos() const { return pos_; }
+
+ void Add(CordRep* child, size_t offset, pos_type end_pos) {
+ rep_->entry_end_pos()[pos_] = end_pos;
+ rep_->entry_child()[pos_] = child;
+ rep_->entry_data_offset()[pos_] = static_cast<offset_type>(offset);
+ pos_ = rep_->advance(pos_);
+ }
+
+ private:
+ CordRepRing* rep_;
+ index_type head_;
+ index_type pos_;
+};
+
+constexpr size_t CordRepRing::kMaxCapacity; // NOLINT: needed for c++11
+
+bool CordRepRing::IsValid(std::ostream& output) const {
+ if (capacity_ == 0) {
+ output << "capacity == 0";
+ return false;
+ }
+
+ if (head_ >= capacity_ || tail_ >= capacity_) {
+ output << "head " << head_ << " and/or tail " << tail_ << "exceed capacity "
+ << capacity_;
+ return false;
+ }
+
+ const index_type back = retreat(tail_);
+ size_t pos_length = Distance(begin_pos_, entry_end_pos(back));
+ if (pos_length != length) {
+ output << "length " << length << " does not match positional length "
+ << pos_length << " from begin_pos " << begin_pos_ << " and entry["
+ << back << "].end_pos " << entry_end_pos(back);
+ return false;
+ }
+
+ index_type head = head_;
+ pos_type begin_pos = begin_pos_;
+ do {
+ pos_type end_pos = entry_end_pos(head);
+ size_t entry_length = Distance(begin_pos, end_pos);
+ if (entry_length == 0) {
+ output << "entry[" << head << "] has an invalid length " << entry_length
+ << " from begin_pos " << begin_pos << " and end_pos " << end_pos;
+ return false;
+ }
+
+ CordRep* child = entry_child(head);
+ if (child == nullptr) {
+ output << "entry[" << head << "].child == nullptr";
+ return false;
+ }
+ if (child->tag < FLAT && child->tag != EXTERNAL) {
+ output << "entry[" << head << "].child has an invalid tag "
+ << static_cast<int>(child->tag);
+ return false;
+ }
+
+ size_t offset = entry_data_offset(head);
+ if (offset >= child->length || entry_length > child->length - offset) {
+ output << "entry[" << head << "] has offset " << offset
+ << " and entry length " << entry_length
<< " which are outside of the child's length of " << child->length;
- return false;
- }
-
- begin_pos = end_pos;
- head = advance(head);
- } while (head != tail_);
-
- return true;
-}
-
-#ifdef EXTRA_CORD_RING_VALIDATION
-CordRepRing* CordRepRing::Validate(CordRepRing* rep, const char* file,
- int line) {
- if (!rep->IsValid(std::cerr)) {
- std::cerr << "\nERROR: CordRepRing corrupted";
- if (line) std::cerr << " at line " << line;
- if (file) std::cerr << " in file " << file;
- std::cerr << "\nContent = " << *rep;
- abort();
- }
- return rep;
-}
-#endif // EXTRA_CORD_RING_VALIDATION
-
-CordRepRing* CordRepRing::New(size_t capacity, size_t extra) {
- CheckCapacity(capacity, extra);
-
- size_t size = AllocSize(capacity += extra);
- void* mem = ::operator new(size);
- auto* rep = new (mem) CordRepRing(static_cast<index_type>(capacity));
- rep->tag = RING;
- rep->capacity_ = static_cast<index_type>(capacity);
- rep->begin_pos_ = 0;
- return rep;
-}
-
-void CordRepRing::SetCapacityForTesting(size_t capacity) {
- // Adjust for the changed layout
- assert(capacity <= capacity_);
- assert(head() == 0 || head() < tail());
- memmove(Layout::Partial(capacity).Pointer<1>(data_) + head(),
- Layout::Partial(capacity_).Pointer<1>(data_) + head(),
- entries() * sizeof(Layout::ElementType<1>));
- memmove(Layout::Partial(capacity, capacity).Pointer<2>(data_) + head(),
- Layout::Partial(capacity_, capacity_).Pointer<2>(data_) + head(),
- entries() * sizeof(Layout::ElementType<2>));
- capacity_ = static_cast<index_type>(capacity);
-}
-
-void CordRepRing::Delete(CordRepRing* rep) {
+ return false;
+ }
+
+ begin_pos = end_pos;
+ head = advance(head);
+ } while (head != tail_);
+
+ return true;
+}
+
+#ifdef EXTRA_CORD_RING_VALIDATION
+CordRepRing* CordRepRing::Validate(CordRepRing* rep, const char* file,
+ int line) {
+ if (!rep->IsValid(std::cerr)) {
+ std::cerr << "\nERROR: CordRepRing corrupted";
+ if (line) std::cerr << " at line " << line;
+ if (file) std::cerr << " in file " << file;
+ std::cerr << "\nContent = " << *rep;
+ abort();
+ }
+ return rep;
+}
+#endif // EXTRA_CORD_RING_VALIDATION
+
+CordRepRing* CordRepRing::New(size_t capacity, size_t extra) {
+ CheckCapacity(capacity, extra);
+
+ size_t size = AllocSize(capacity += extra);
+ void* mem = ::operator new(size);
+ auto* rep = new (mem) CordRepRing(static_cast<index_type>(capacity));
+ rep->tag = RING;
+ rep->capacity_ = static_cast<index_type>(capacity);
+ rep->begin_pos_ = 0;
+ return rep;
+}
+
+void CordRepRing::SetCapacityForTesting(size_t capacity) {
+ // Adjust for the changed layout
+ assert(capacity <= capacity_);
+ assert(head() == 0 || head() < tail());
+ memmove(Layout::Partial(capacity).Pointer<1>(data_) + head(),
+ Layout::Partial(capacity_).Pointer<1>(data_) + head(),
+ entries() * sizeof(Layout::ElementType<1>));
+ memmove(Layout::Partial(capacity, capacity).Pointer<2>(data_) + head(),
+ Layout::Partial(capacity_, capacity_).Pointer<2>(data_) + head(),
+ entries() * sizeof(Layout::ElementType<2>));
+ capacity_ = static_cast<index_type>(capacity);
+}
+
+void CordRepRing::Delete(CordRepRing* rep) {
assert(rep != nullptr && rep->IsRing());
-#if defined(__cpp_sized_deallocation)
- size_t size = AllocSize(rep->capacity_);
- rep->~CordRepRing();
- ::operator delete(rep, size);
-#else
- rep->~CordRepRing();
- ::operator delete(rep);
-#endif
-}
-
-void CordRepRing::Destroy(CordRepRing* rep) {
- UnrefEntries(rep, rep->head(), rep->tail());
- Delete(rep);
-}
-
-template <bool ref>
-void CordRepRing::Fill(const CordRepRing* src, index_type head,
- index_type tail) {
- this->length = src->length;
- head_ = 0;
- tail_ = advance(0, src->entries(head, tail));
- begin_pos_ = src->begin_pos_;
-
- // TODO(mvels): there may be opportunities here for large buffers.
- auto* dst_pos = entry_end_pos();
- auto* dst_child = entry_child();
- auto* dst_offset = entry_data_offset();
- src->ForEach(head, tail, [&](index_type index) {
- *dst_pos++ = src->entry_end_pos(index);
- CordRep* child = src->entry_child(index);
- *dst_child++ = ref ? CordRep::Ref(child) : child;
- *dst_offset++ = src->entry_data_offset(index);
- });
-}
-
-CordRepRing* CordRepRing::Copy(CordRepRing* rep, index_type head,
- index_type tail, size_t extra) {
- CordRepRing* newrep = CordRepRing::New(rep->entries(head, tail), extra);
- newrep->Fill<true>(rep, head, tail);
- CordRep::Unref(rep);
- return newrep;
-}
-
-CordRepRing* CordRepRing::Mutable(CordRepRing* rep, size_t extra) {
- // Get current number of entries, and check for max capacity.
- size_t entries = rep->entries();
-
+#if defined(__cpp_sized_deallocation)
+ size_t size = AllocSize(rep->capacity_);
+ rep->~CordRepRing();
+ ::operator delete(rep, size);
+#else
+ rep->~CordRepRing();
+ ::operator delete(rep);
+#endif
+}
+
+void CordRepRing::Destroy(CordRepRing* rep) {
+ UnrefEntries(rep, rep->head(), rep->tail());
+ Delete(rep);
+}
+
+template <bool ref>
+void CordRepRing::Fill(const CordRepRing* src, index_type head,
+ index_type tail) {
+ this->length = src->length;
+ head_ = 0;
+ tail_ = advance(0, src->entries(head, tail));
+ begin_pos_ = src->begin_pos_;
+
+ // TODO(mvels): there may be opportunities here for large buffers.
+ auto* dst_pos = entry_end_pos();
+ auto* dst_child = entry_child();
+ auto* dst_offset = entry_data_offset();
+ src->ForEach(head, tail, [&](index_type index) {
+ *dst_pos++ = src->entry_end_pos(index);
+ CordRep* child = src->entry_child(index);
+ *dst_child++ = ref ? CordRep::Ref(child) : child;
+ *dst_offset++ = src->entry_data_offset(index);
+ });
+}
+
+CordRepRing* CordRepRing::Copy(CordRepRing* rep, index_type head,
+ index_type tail, size_t extra) {
+ CordRepRing* newrep = CordRepRing::New(rep->entries(head, tail), extra);
+ newrep->Fill<true>(rep, head, tail);
+ CordRep::Unref(rep);
+ return newrep;
+}
+
+CordRepRing* CordRepRing::Mutable(CordRepRing* rep, size_t extra) {
+ // Get current number of entries, and check for max capacity.
+ size_t entries = rep->entries();
+
if (!rep->refcount.IsMutable()) {
return Copy(rep, rep->head(), rep->tail(), extra);
- } else if (entries + extra > rep->capacity()) {
+ } else if (entries + extra > rep->capacity()) {
const size_t min_grow = rep->capacity() + rep->capacity() / 2;
const size_t min_extra = (std::max)(extra, min_grow - entries);
- CordRepRing* newrep = CordRepRing::New(entries, min_extra);
- newrep->Fill<false>(rep, rep->head(), rep->tail());
- CordRepRing::Delete(rep);
- return newrep;
- } else {
- return rep;
- }
-}
-
-Span<char> CordRepRing::GetAppendBuffer(size_t size) {
+ CordRepRing* newrep = CordRepRing::New(entries, min_extra);
+ newrep->Fill<false>(rep, rep->head(), rep->tail());
+ CordRepRing::Delete(rep);
+ return newrep;
+ } else {
+ return rep;
+ }
+}
+
+Span<char> CordRepRing::GetAppendBuffer(size_t size) {
assert(refcount.IsMutable());
- index_type back = retreat(tail_);
- CordRep* child = entry_child(back);
+ index_type back = retreat(tail_);
+ CordRep* child = entry_child(back);
if (child->tag >= FLAT && child->refcount.IsMutable()) {
- size_t capacity = child->flat()->Capacity();
- pos_type end_pos = entry_end_pos(back);
- size_t data_offset = entry_data_offset(back);
- size_t entry_length = Distance(entry_begin_pos(back), end_pos);
- size_t used = data_offset + entry_length;
- if (size_t n = (std::min)(capacity - used, size)) {
- child->length = data_offset + entry_length + n;
- entry_end_pos()[back] = end_pos + n;
- this->length += n;
- return {child->flat()->Data() + used, n};
- }
- }
- return {nullptr, 0};
-}
-
-Span<char> CordRepRing::GetPrependBuffer(size_t size) {
+ size_t capacity = child->flat()->Capacity();
+ pos_type end_pos = entry_end_pos(back);
+ size_t data_offset = entry_data_offset(back);
+ size_t entry_length = Distance(entry_begin_pos(back), end_pos);
+ size_t used = data_offset + entry_length;
+ if (size_t n = (std::min)(capacity - used, size)) {
+ child->length = data_offset + entry_length + n;
+ entry_end_pos()[back] = end_pos + n;
+ this->length += n;
+ return {child->flat()->Data() + used, n};
+ }
+ }
+ return {nullptr, 0};
+}
+
+Span<char> CordRepRing::GetPrependBuffer(size_t size) {
assert(refcount.IsMutable());
- CordRep* child = entry_child(head_);
- size_t data_offset = entry_data_offset(head_);
+ CordRep* child = entry_child(head_);
+ size_t data_offset = entry_data_offset(head_);
if (data_offset && child->refcount.IsMutable() && child->tag >= FLAT) {
- size_t n = (std::min)(data_offset, size);
- this->length += n;
- begin_pos_ -= n;
- data_offset -= n;
- entry_data_offset()[head_] = static_cast<offset_type>(data_offset);
- return {child->flat()->Data() + data_offset, n};
- }
- return {nullptr, 0};
-}
-
-CordRepRing* CordRepRing::CreateFromLeaf(CordRep* child, size_t offset,
+ size_t n = (std::min)(data_offset, size);
+ this->length += n;
+ begin_pos_ -= n;
+ data_offset -= n;
+ entry_data_offset()[head_] = static_cast<offset_type>(data_offset);
+ return {child->flat()->Data() + data_offset, n};
+ }
+ return {nullptr, 0};
+}
+
+CordRepRing* CordRepRing::CreateFromLeaf(CordRep* child, size_t offset,
size_t len, size_t extra) {
- CordRepRing* rep = CordRepRing::New(1, extra);
- rep->head_ = 0;
- rep->tail_ = rep->advance(0);
+ CordRepRing* rep = CordRepRing::New(1, extra);
+ rep->head_ = 0;
+ rep->tail_ = rep->advance(0);
rep->length = len;
rep->entry_end_pos()[0] = len;
- rep->entry_child()[0] = child;
- rep->entry_data_offset()[0] = static_cast<offset_type>(offset);
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::CreateSlow(CordRep* child, size_t extra) {
- CordRepRing* rep = nullptr;
+ rep->entry_child()[0] = child;
+ rep->entry_data_offset()[0] = static_cast<offset_type>(offset);
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::CreateSlow(CordRep* child, size_t extra) {
+ CordRepRing* rep = nullptr;
Consume(child, [&](CordRep* child_arg, size_t offset, size_t len) {
if (IsFlatOrExternal(child_arg)) {
rep = rep ? AppendLeaf(rep, child_arg, offset, len)
: CreateFromLeaf(child_arg, offset, len, extra);
- } else if (rep) {
+ } else if (rep) {
rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len);
} else if (offset == 0 && child_arg->length == len) {
rep = Mutable(child_arg->ring(), extra);
- } else {
+ } else {
rep = SubRing(child_arg->ring(), offset, len, extra);
- }
- });
- return Validate(rep, nullptr, __LINE__);
-}
-
-CordRepRing* CordRepRing::Create(CordRep* child, size_t extra) {
- size_t length = child->length;
- if (IsFlatOrExternal(child)) {
- return CreateFromLeaf(child, 0, length, extra);
- }
+ }
+ });
+ return Validate(rep, nullptr, __LINE__);
+}
+
+CordRepRing* CordRepRing::Create(CordRep* child, size_t extra) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return CreateFromLeaf(child, 0, length, extra);
+ }
if (child->IsRing()) {
- return Mutable(child->ring(), extra);
- }
- return CreateSlow(child, extra);
-}
-
-template <CordRepRing::AddMode mode>
-CordRepRing* CordRepRing::AddRing(CordRepRing* rep, CordRepRing* ring,
+ return Mutable(child->ring(), extra);
+ }
+ return CreateSlow(child, extra);
+}
+
+template <CordRepRing::AddMode mode>
+CordRepRing* CordRepRing::AddRing(CordRepRing* rep, CordRepRing* ring,
size_t offset, size_t len) {
- assert(offset < ring->length);
- constexpr bool append = mode == AddMode::kAppend;
- Position head = ring->Find(offset);
+ assert(offset < ring->length);
+ constexpr bool append = mode == AddMode::kAppend;
+ Position head = ring->Find(offset);
Position tail = ring->FindTail(head.index, offset + len);
- const index_type entries = ring->entries(head.index, tail.index);
-
- rep = Mutable(rep, entries);
-
- // The delta for making ring[head].end_pos into 'len - offset'
- const pos_type delta_length =
+ const index_type entries = ring->entries(head.index, tail.index);
+
+ rep = Mutable(rep, entries);
+
+ // The delta for making ring[head].end_pos into 'len - offset'
+ const pos_type delta_length =
(append ? rep->begin_pos_ + rep->length : rep->begin_pos_ - len) -
- ring->entry_begin_pos(head.index) - head.offset;
-
- // Start filling at `tail`, or `entries` before `head`
- Filler filler(rep, append ? rep->tail_ : rep->retreat(rep->head_, entries));
-
- if (ring->refcount.IsOne()) {
- // Copy entries from source stealing the ref and adjusting the end position.
- // Commit the filler as this is no-op.
- ring->ForEach(head.index, tail.index, [&](index_type ix) {
- filler.Add(ring->entry_child(ix), ring->entry_data_offset(ix),
- ring->entry_end_pos(ix) + delta_length);
- });
-
- // Unref entries we did not copy over, and delete source.
- if (head.index != ring->head_) UnrefEntries(ring, ring->head_, head.index);
- if (tail.index != ring->tail_) UnrefEntries(ring, tail.index, ring->tail_);
- CordRepRing::Delete(ring);
- } else {
- ring->ForEach(head.index, tail.index, [&](index_type ix) {
- CordRep* child = ring->entry_child(ix);
- filler.Add(child, ring->entry_data_offset(ix),
- ring->entry_end_pos(ix) + delta_length);
- CordRep::Ref(child);
- });
- CordRepRing::Unref(ring);
- }
-
- if (head.offset) {
- // Increase offset of first 'source' entry appended or prepended.
- // This is always the entry in `filler.head()`
- rep->AddDataOffset(filler.head(), head.offset);
- }
-
- if (tail.offset) {
- // Reduce length of last 'source' entry appended or prepended.
- // This is always the entry tailed by `filler.pos()`
- rep->SubLength(rep->retreat(filler.pos()), tail.offset);
- }
-
- // Commit changes
+ ring->entry_begin_pos(head.index) - head.offset;
+
+ // Start filling at `tail`, or `entries` before `head`
+ Filler filler(rep, append ? rep->tail_ : rep->retreat(rep->head_, entries));
+
+ if (ring->refcount.IsOne()) {
+ // Copy entries from source stealing the ref and adjusting the end position.
+ // Commit the filler as this is no-op.
+ ring->ForEach(head.index, tail.index, [&](index_type ix) {
+ filler.Add(ring->entry_child(ix), ring->entry_data_offset(ix),
+ ring->entry_end_pos(ix) + delta_length);
+ });
+
+ // Unref entries we did not copy over, and delete source.
+ if (head.index != ring->head_) UnrefEntries(ring, ring->head_, head.index);
+ if (tail.index != ring->tail_) UnrefEntries(ring, tail.index, ring->tail_);
+ CordRepRing::Delete(ring);
+ } else {
+ ring->ForEach(head.index, tail.index, [&](index_type ix) {
+ CordRep* child = ring->entry_child(ix);
+ filler.Add(child, ring->entry_data_offset(ix),
+ ring->entry_end_pos(ix) + delta_length);
+ CordRep::Ref(child);
+ });
+ CordRepRing::Unref(ring);
+ }
+
+ if (head.offset) {
+ // Increase offset of first 'source' entry appended or prepended.
+ // This is always the entry in `filler.head()`
+ rep->AddDataOffset(filler.head(), head.offset);
+ }
+
+ if (tail.offset) {
+ // Reduce length of last 'source' entry appended or prepended.
+ // This is always the entry tailed by `filler.pos()`
+ rep->SubLength(rep->retreat(filler.pos()), tail.offset);
+ }
+
+ // Commit changes
rep->length += len;
- if (append) {
- rep->tail_ = filler.pos();
- } else {
- rep->head_ = filler.head();
+ if (append) {
+ rep->tail_ = filler.pos();
+ } else {
+ rep->head_ = filler.head();
rep->begin_pos_ -= len;
- }
-
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::AppendSlow(CordRepRing* rep, CordRep* child) {
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::AppendSlow(CordRepRing* rep, CordRep* child) {
Consume(child, [&rep](CordRep* child_arg, size_t offset, size_t len) {
if (child_arg->IsRing()) {
rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len);
- } else {
+ } else {
rep = AppendLeaf(rep, child_arg, offset, len);
- }
- });
- return rep;
-}
-
-CordRepRing* CordRepRing::AppendLeaf(CordRepRing* rep, CordRep* child,
+ }
+ });
+ return rep;
+}
+
+CordRepRing* CordRepRing::AppendLeaf(CordRepRing* rep, CordRep* child,
size_t offset, size_t len) {
- rep = Mutable(rep, 1);
- index_type back = rep->tail_;
- const pos_type begin_pos = rep->begin_pos_ + rep->length;
- rep->tail_ = rep->advance(rep->tail_);
+ rep = Mutable(rep, 1);
+ index_type back = rep->tail_;
+ const pos_type begin_pos = rep->begin_pos_ + rep->length;
+ rep->tail_ = rep->advance(rep->tail_);
rep->length += len;
rep->entry_end_pos()[back] = begin_pos + len;
- rep->entry_child()[back] = child;
- rep->entry_data_offset()[back] = static_cast<offset_type>(offset);
- return Validate(rep, nullptr, __LINE__);
-}
-
-CordRepRing* CordRepRing::Append(CordRepRing* rep, CordRep* child) {
- size_t length = child->length;
- if (IsFlatOrExternal(child)) {
- return AppendLeaf(rep, child, 0, length);
- }
+ rep->entry_child()[back] = child;
+ rep->entry_data_offset()[back] = static_cast<offset_type>(offset);
+ return Validate(rep, nullptr, __LINE__);
+}
+
+CordRepRing* CordRepRing::Append(CordRepRing* rep, CordRep* child) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return AppendLeaf(rep, child, 0, length);
+ }
if (child->IsRing()) {
- return AddRing<AddMode::kAppend>(rep, child->ring(), 0, length);
- }
- return AppendSlow(rep, child);
-}
-
-CordRepRing* CordRepRing::PrependSlow(CordRepRing* rep, CordRep* child) {
+ return AddRing<AddMode::kAppend>(rep, child->ring(), 0, length);
+ }
+ return AppendSlow(rep, child);
+}
+
+CordRepRing* CordRepRing::PrependSlow(CordRepRing* rep, CordRep* child) {
ReverseConsume(child, [&](CordRep* child_arg, size_t offset, size_t len) {
if (IsFlatOrExternal(child_arg)) {
rep = PrependLeaf(rep, child_arg, offset, len);
- } else {
+ } else {
rep = AddRing<AddMode::kPrepend>(rep, child_arg->ring(), offset, len);
- }
- });
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::PrependLeaf(CordRepRing* rep, CordRep* child,
+ }
+ });
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::PrependLeaf(CordRepRing* rep, CordRep* child,
size_t offset, size_t len) {
- rep = Mutable(rep, 1);
- index_type head = rep->retreat(rep->head_);
- pos_type end_pos = rep->begin_pos_;
- rep->head_ = head;
+ rep = Mutable(rep, 1);
+ index_type head = rep->retreat(rep->head_);
+ pos_type end_pos = rep->begin_pos_;
+ rep->head_ = head;
rep->length += len;
rep->begin_pos_ -= len;
- rep->entry_end_pos()[head] = end_pos;
- rep->entry_child()[head] = child;
- rep->entry_data_offset()[head] = static_cast<offset_type>(offset);
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::Prepend(CordRepRing* rep, CordRep* child) {
- size_t length = child->length;
- if (IsFlatOrExternal(child)) {
- return PrependLeaf(rep, child, 0, length);
- }
+ rep->entry_end_pos()[head] = end_pos;
+ rep->entry_child()[head] = child;
+ rep->entry_data_offset()[head] = static_cast<offset_type>(offset);
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::Prepend(CordRepRing* rep, CordRep* child) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return PrependLeaf(rep, child, 0, length);
+ }
if (child->IsRing()) {
- return AddRing<AddMode::kPrepend>(rep, child->ring(), 0, length);
- }
- return PrependSlow(rep, child);
-}
-
-CordRepRing* CordRepRing::Append(CordRepRing* rep, y_absl::string_view data,
- size_t extra) {
+ return AddRing<AddMode::kPrepend>(rep, child->ring(), 0, length);
+ }
+ return PrependSlow(rep, child);
+}
+
+CordRepRing* CordRepRing::Append(CordRepRing* rep, y_absl::string_view data,
+ size_t extra) {
if (rep->refcount.IsMutable()) {
- Span<char> avail = rep->GetAppendBuffer(data.length());
- if (!avail.empty()) {
- memcpy(avail.data(), data.data(), avail.length());
- data.remove_prefix(avail.length());
- }
- }
- if (data.empty()) return Validate(rep);
-
- const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
- rep = Mutable(rep, flats);
-
- Filler filler(rep, rep->tail_);
- pos_type pos = rep->begin_pos_ + rep->length;
-
- while (data.length() >= kMaxFlatLength) {
- auto* flat = CreateFlat(data.data(), kMaxFlatLength);
- filler.Add(flat, 0, pos += kMaxFlatLength);
- data.remove_prefix(kMaxFlatLength);
- }
-
- if (data.length()) {
- auto* flat = CreateFlat(data.data(), data.length(), extra);
- filler.Add(flat, 0, pos += data.length());
- }
-
- rep->length = pos - rep->begin_pos_;
- rep->tail_ = filler.pos();
-
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::Prepend(CordRepRing* rep, y_absl::string_view data,
- size_t extra) {
+ Span<char> avail = rep->GetAppendBuffer(data.length());
+ if (!avail.empty()) {
+ memcpy(avail.data(), data.data(), avail.length());
+ data.remove_prefix(avail.length());
+ }
+ }
+ if (data.empty()) return Validate(rep);
+
+ const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
+ rep = Mutable(rep, flats);
+
+ Filler filler(rep, rep->tail_);
+ pos_type pos = rep->begin_pos_ + rep->length;
+
+ while (data.length() >= kMaxFlatLength) {
+ auto* flat = CreateFlat(data.data(), kMaxFlatLength);
+ filler.Add(flat, 0, pos += kMaxFlatLength);
+ data.remove_prefix(kMaxFlatLength);
+ }
+
+ if (data.length()) {
+ auto* flat = CreateFlat(data.data(), data.length(), extra);
+ filler.Add(flat, 0, pos += data.length());
+ }
+
+ rep->length = pos - rep->begin_pos_;
+ rep->tail_ = filler.pos();
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::Prepend(CordRepRing* rep, y_absl::string_view data,
+ size_t extra) {
if (rep->refcount.IsMutable()) {
- Span<char> avail = rep->GetPrependBuffer(data.length());
- if (!avail.empty()) {
- const char* tail = data.data() + data.length() - avail.length();
- memcpy(avail.data(), tail, avail.length());
- data.remove_suffix(avail.length());
- }
- }
- if (data.empty()) return rep;
-
- const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
- rep = Mutable(rep, flats);
- pos_type pos = rep->begin_pos_;
- Filler filler(rep, rep->retreat(rep->head_, static_cast<index_type>(flats)));
-
- size_t first_size = data.size() - (flats - 1) * kMaxFlatLength;
- CordRepFlat* flat = CordRepFlat::New(first_size + extra);
- flat->length = first_size + extra;
- memcpy(flat->Data() + extra, data.data(), first_size);
- data.remove_prefix(first_size);
- filler.Add(flat, extra, pos);
- pos -= first_size;
-
- while (!data.empty()) {
- assert(data.size() >= kMaxFlatLength);
- flat = CreateFlat(data.data(), kMaxFlatLength);
- filler.Add(flat, 0, pos);
- pos -= kMaxFlatLength;
- data.remove_prefix(kMaxFlatLength);
- }
-
- rep->head_ = filler.head();
- rep->length += rep->begin_pos_ - pos;
- rep->begin_pos_ = pos;
-
- return Validate(rep);
-}
-
-// 32 entries is 32 * sizeof(pos_type) = 4 cache lines on x86
-static constexpr index_type kBinarySearchThreshold = 32;
-static constexpr index_type kBinarySearchEndCount = 8;
-
-template <bool wrap>
-CordRepRing::index_type CordRepRing::FindBinary(index_type head,
- index_type tail,
- size_t offset) const {
- index_type count = tail + (wrap ? capacity_ : 0) - head;
- do {
- count = (count - 1) / 2;
- assert(count < entries(head, tail_));
- index_type mid = wrap ? advance(head, count) : head + count;
- index_type after_mid = wrap ? advance(mid) : mid + 1;
- bool larger = (offset >= entry_end_offset(mid));
- head = larger ? after_mid : head;
- tail = larger ? tail : mid;
- assert(head != tail);
- } while (ABSL_PREDICT_TRUE(count > kBinarySearchEndCount));
- return head;
-}
-
-CordRepRing::Position CordRepRing::FindSlow(index_type head,
- size_t offset) const {
- index_type tail = tail_;
-
- // Binary search until we are good for linear search
- // Optimize for branchless / non wrapping ops
- if (tail > head) {
- index_type count = tail - head;
- if (count > kBinarySearchThreshold) {
- head = FindBinary<false>(head, tail, offset);
- }
- } else {
- index_type count = capacity_ + tail - head;
- if (count > kBinarySearchThreshold) {
- head = FindBinary<true>(head, tail, offset);
- }
- }
-
- pos_type pos = entry_begin_pos(head);
- pos_type end_pos = entry_end_pos(head);
- while (offset >= Distance(begin_pos_, end_pos)) {
- head = advance(head);
- pos = end_pos;
- end_pos = entry_end_pos(head);
- }
-
- return {head, offset - Distance(begin_pos_, pos)};
-}
-
-CordRepRing::Position CordRepRing::FindTailSlow(index_type head,
- size_t offset) const {
- index_type tail = tail_;
- const size_t tail_offset = offset - 1;
-
- // Binary search until we are good for linear search
- // Optimize for branchless / non wrapping ops
- if (tail > head) {
- index_type count = tail - head;
- if (count > kBinarySearchThreshold) {
- head = FindBinary<false>(head, tail, tail_offset);
- }
- } else {
- index_type count = capacity_ + tail - head;
- if (count > kBinarySearchThreshold) {
- head = FindBinary<true>(head, tail, tail_offset);
- }
- }
-
- size_t end_offset = entry_end_offset(head);
- while (tail_offset >= end_offset) {
- head = advance(head);
- end_offset = entry_end_offset(head);
- }
-
- return {advance(head), end_offset - offset};
-}
-
-char CordRepRing::GetCharacter(size_t offset) const {
- assert(offset < length);
-
- Position pos = Find(offset);
- size_t data_offset = entry_data_offset(pos.index) + pos.offset;
- return GetRepData(entry_child(pos.index))[data_offset];
-}
-
-CordRepRing* CordRepRing::SubRing(CordRepRing* rep, size_t offset,
+ Span<char> avail = rep->GetPrependBuffer(data.length());
+ if (!avail.empty()) {
+ const char* tail = data.data() + data.length() - avail.length();
+ memcpy(avail.data(), tail, avail.length());
+ data.remove_suffix(avail.length());
+ }
+ }
+ if (data.empty()) return rep;
+
+ const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
+ rep = Mutable(rep, flats);
+ pos_type pos = rep->begin_pos_;
+ Filler filler(rep, rep->retreat(rep->head_, static_cast<index_type>(flats)));
+
+ size_t first_size = data.size() - (flats - 1) * kMaxFlatLength;
+ CordRepFlat* flat = CordRepFlat::New(first_size + extra);
+ flat->length = first_size + extra;
+ memcpy(flat->Data() + extra, data.data(), first_size);
+ data.remove_prefix(first_size);
+ filler.Add(flat, extra, pos);
+ pos -= first_size;
+
+ while (!data.empty()) {
+ assert(data.size() >= kMaxFlatLength);
+ flat = CreateFlat(data.data(), kMaxFlatLength);
+ filler.Add(flat, 0, pos);
+ pos -= kMaxFlatLength;
+ data.remove_prefix(kMaxFlatLength);
+ }
+
+ rep->head_ = filler.head();
+ rep->length += rep->begin_pos_ - pos;
+ rep->begin_pos_ = pos;
+
+ return Validate(rep);
+}
+
+// 32 entries is 32 * sizeof(pos_type) = 4 cache lines on x86
+static constexpr index_type kBinarySearchThreshold = 32;
+static constexpr index_type kBinarySearchEndCount = 8;
+
+template <bool wrap>
+CordRepRing::index_type CordRepRing::FindBinary(index_type head,
+ index_type tail,
+ size_t offset) const {
+ index_type count = tail + (wrap ? capacity_ : 0) - head;
+ do {
+ count = (count - 1) / 2;
+ assert(count < entries(head, tail_));
+ index_type mid = wrap ? advance(head, count) : head + count;
+ index_type after_mid = wrap ? advance(mid) : mid + 1;
+ bool larger = (offset >= entry_end_offset(mid));
+ head = larger ? after_mid : head;
+ tail = larger ? tail : mid;
+ assert(head != tail);
+ } while (ABSL_PREDICT_TRUE(count > kBinarySearchEndCount));
+ return head;
+}
+
+CordRepRing::Position CordRepRing::FindSlow(index_type head,
+ size_t offset) const {
+ index_type tail = tail_;
+
+ // Binary search until we are good for linear search
+ // Optimize for branchless / non wrapping ops
+ if (tail > head) {
+ index_type count = tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<false>(head, tail, offset);
+ }
+ } else {
+ index_type count = capacity_ + tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<true>(head, tail, offset);
+ }
+ }
+
+ pos_type pos = entry_begin_pos(head);
+ pos_type end_pos = entry_end_pos(head);
+ while (offset >= Distance(begin_pos_, end_pos)) {
+ head = advance(head);
+ pos = end_pos;
+ end_pos = entry_end_pos(head);
+ }
+
+ return {head, offset - Distance(begin_pos_, pos)};
+}
+
+CordRepRing::Position CordRepRing::FindTailSlow(index_type head,
+ size_t offset) const {
+ index_type tail = tail_;
+ const size_t tail_offset = offset - 1;
+
+ // Binary search until we are good for linear search
+ // Optimize for branchless / non wrapping ops
+ if (tail > head) {
+ index_type count = tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<false>(head, tail, tail_offset);
+ }
+ } else {
+ index_type count = capacity_ + tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<true>(head, tail, tail_offset);
+ }
+ }
+
+ size_t end_offset = entry_end_offset(head);
+ while (tail_offset >= end_offset) {
+ head = advance(head);
+ end_offset = entry_end_offset(head);
+ }
+
+ return {advance(head), end_offset - offset};
+}
+
+char CordRepRing::GetCharacter(size_t offset) const {
+ assert(offset < length);
+
+ Position pos = Find(offset);
+ size_t data_offset = entry_data_offset(pos.index) + pos.offset;
+ return GetRepData(entry_child(pos.index))[data_offset];
+}
+
+CordRepRing* CordRepRing::SubRing(CordRepRing* rep, size_t offset,
size_t len, size_t extra) {
- assert(offset <= rep->length);
+ assert(offset <= rep->length);
assert(offset <= rep->length - len);
-
+
if (len == 0) {
- CordRep::Unref(rep);
- return nullptr;
- }
-
- // Find position of first byte
- Position head = rep->Find(offset);
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ // Find position of first byte
+ Position head = rep->Find(offset);
Position tail = rep->FindTail(head.index, offset + len);
- const size_t new_entries = rep->entries(head.index, tail.index);
-
+ const size_t new_entries = rep->entries(head.index, tail.index);
+
if (rep->refcount.IsMutable() && extra <= (rep->capacity() - new_entries)) {
- // We adopt a privately owned rep and no extra entries needed.
- if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
- if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
- rep->head_ = head.index;
- rep->tail_ = tail.index;
- } else {
- // Copy subset to new rep
- rep = Copy(rep, head.index, tail.index, extra);
- head.index = rep->head_;
- tail.index = rep->tail_;
- }
-
- // Adjust begin_pos and length
+ // We adopt a privately owned rep and no extra entries needed.
+ if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
+ if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
+ rep->head_ = head.index;
+ rep->tail_ = tail.index;
+ } else {
+ // Copy subset to new rep
+ rep = Copy(rep, head.index, tail.index, extra);
+ head.index = rep->head_;
+ tail.index = rep->tail_;
+ }
+
+ // Adjust begin_pos and length
rep->length = len;
- rep->begin_pos_ += offset;
-
- // Adjust head and tail blocks
- if (head.offset) {
- rep->AddDataOffset(head.index, head.offset);
- }
- if (tail.offset) {
- rep->SubLength(rep->retreat(tail.index), tail.offset);
- }
-
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::RemovePrefix(CordRepRing* rep, size_t len,
- size_t extra) {
- assert(len <= rep->length);
- if (len == rep->length) {
- CordRep::Unref(rep);
- return nullptr;
- }
-
- Position head = rep->Find(len);
+ rep->begin_pos_ += offset;
+
+ // Adjust head and tail blocks
+ if (head.offset) {
+ rep->AddDataOffset(head.index, head.offset);
+ }
+ if (tail.offset) {
+ rep->SubLength(rep->retreat(tail.index), tail.offset);
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::RemovePrefix(CordRepRing* rep, size_t len,
+ size_t extra) {
+ assert(len <= rep->length);
+ if (len == rep->length) {
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ Position head = rep->Find(len);
if (rep->refcount.IsMutable()) {
- if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
- rep->head_ = head.index;
- } else {
- rep = Copy(rep, head.index, rep->tail_, extra);
- head.index = rep->head_;
- }
-
- // Adjust begin_pos and length
- rep->length -= len;
- rep->begin_pos_ += len;
-
- // Adjust head block
- if (head.offset) {
- rep->AddDataOffset(head.index, head.offset);
- }
-
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::RemoveSuffix(CordRepRing* rep, size_t len,
- size_t extra) {
- assert(len <= rep->length);
-
- if (len == rep->length) {
- CordRep::Unref(rep);
- return nullptr;
- }
-
- Position tail = rep->FindTail(rep->length - len);
+ if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
+ rep->head_ = head.index;
+ } else {
+ rep = Copy(rep, head.index, rep->tail_, extra);
+ head.index = rep->head_;
+ }
+
+ // Adjust begin_pos and length
+ rep->length -= len;
+ rep->begin_pos_ += len;
+
+ // Adjust head block
+ if (head.offset) {
+ rep->AddDataOffset(head.index, head.offset);
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::RemoveSuffix(CordRepRing* rep, size_t len,
+ size_t extra) {
+ assert(len <= rep->length);
+
+ if (len == rep->length) {
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ Position tail = rep->FindTail(rep->length - len);
if (rep->refcount.IsMutable()) {
- // We adopt a privately owned rep, scrub.
- if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
- rep->tail_ = tail.index;
- } else {
- // Copy subset to new rep
- rep = Copy(rep, rep->head_, tail.index, extra);
- tail.index = rep->tail_;
- }
-
- // Adjust length
- rep->length -= len;
-
- // Adjust tail block
- if (tail.offset) {
- rep->SubLength(rep->retreat(tail.index), tail.offset);
- }
-
- return Validate(rep);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
+ // We adopt a privately owned rep, scrub.
+ if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
+ rep->tail_ = tail.index;
+ } else {
+ // Copy subset to new rep
+ rep = Copy(rep, rep->head_, tail.index, extra);
+ tail.index = rep->tail_;
+ }
+
+ // Adjust length
+ rep->length -= len;
+
+ // Adjust tail block
+ if (tail.offset) {
+ rep->SubLength(rep->retreat(tail.index), tail.offset);
+ }
+
+ return Validate(rep);
+}
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.h
index 5f9784d8da..a6a4890ab4 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring.h
@@ -1,233 +1,233 @@
-// 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_CORD_REP_RING_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <iosfwd>
-#include <limits>
-#include <memory>
-
-#include "y_absl/container/internal/layout.h"
-#include "y_absl/strings/internal/cord_internal.h"
-#include "y_absl/strings/internal/cord_rep_flat.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// All operations modifying a ring buffer are implemented as static methods
-// requiring a CordRepRing instance with a reference adopted by the method.
-//
-// The methods return the modified ring buffer, which may be equal to the input
-// if the input was not shared, and having large enough capacity to accommodate
-// any newly added node(s). Otherwise, a copy of the input rep with the new
-// node(s) added is returned.
-//
-// Any modification on non shared ring buffers with enough capacity will then
-// require minimum atomic operations. Caller should where possible provide
-// reasonable `extra` hints for both anticipated extra `flat` byte space, as
-// well as anticipated extra nodes required for complex operations.
-//
-// Example of code creating a ring buffer, adding some data to it,
-// and discarding the buffer when done:
-//
-// void FunWithRings() {
-// // Create ring with 3 flats
-// CordRep* flat = CreateFlat("Hello");
-// CordRepRing* ring = CordRepRing::Create(flat, 2);
-// ring = CordRepRing::Append(ring, CreateFlat(" "));
-// ring = CordRepRing::Append(ring, CreateFlat("world"));
-// DoSomethingWithRing(ring);
-// CordRep::Unref(ring);
-// }
-//
-// Example of code Copying an existing ring buffer and modifying it:
-//
-// void MoreFunWithRings(CordRepRing* src) {
-// CordRepRing* ring = CordRep::Ref(src)->ring();
-// ring = CordRepRing::Append(ring, CreateFlat("Hello"));
-// ring = CordRepRing::Append(ring, CreateFlat(" "));
-// ring = CordRepRing::Append(ring, CreateFlat("world"));
-// DoSomethingWithRing(ring);
-// CordRep::Unref(ring);
-// }
-//
-class CordRepRing : public CordRep {
- public:
- // `pos_type` represents a 'logical position'. A CordRepRing instance has a
- // `begin_pos` (default 0), and each node inside the buffer will have an
- // `end_pos` which is the `end_pos` of the previous node (or `begin_pos`) plus
- // this node's length. The purpose is to allow for a binary search on this
- // position, while allowing O(1) prepend and append operations.
- using pos_type = size_t;
-
- // `index_type` is the type for the `head`, `tail` and `capacity` indexes.
- // Ring buffers are limited to having no more than four billion entries.
- using index_type = uint32_t;
-
- // `offset_type` is the type for the data offset inside a child rep's data.
- using offset_type = uint32_t;
-
- // Position holds the node index and relative offset into the node for
- // some physical offset in the contained data as returned by the Find()
- // and FindTail() methods.
- struct Position {
- index_type index;
- size_t offset;
- };
-
- // The maximum # of child nodes that can be hosted inside a CordRepRing.
- static constexpr size_t kMaxCapacity = (std::numeric_limits<uint32_t>::max)();
-
- // CordRepring can not be default constructed, moved, copied or assigned.
- CordRepRing() = delete;
- CordRepRing(const CordRepRing&) = delete;
- CordRepRing& operator=(const CordRepRing&) = delete;
-
- // Returns true if this instance is valid, false if some or all of the
- // invariants are broken. Intended for debug purposes only.
- // `output` receives an explanation of the broken invariants.
- bool IsValid(std::ostream& output) const;
-
- // Returns the size in bytes for a CordRepRing with `capacity' entries.
- static constexpr size_t AllocSize(size_t capacity);
-
- // Returns the distance in bytes from `pos` to `end_pos`.
- static constexpr size_t Distance(pos_type pos, pos_type end_pos);
-
- // Creates a new ring buffer from the provided `rep`. Adopts a reference
- // on `rep`. The returned ring buffer has a capacity of at least `extra + 1`
- static CordRepRing* Create(CordRep* child, size_t extra = 0);
-
- // `head`, `tail` and `capacity` indexes defining the ring buffer boundaries.
- index_type head() const { return head_; }
- index_type tail() const { return tail_; }
- index_type capacity() const { return capacity_; }
-
- // Returns the number of entries in this instance.
- index_type entries() const { return entries(head_, tail_); }
-
- // Returns the logical begin position of this instance.
- pos_type begin_pos() const { return begin_pos_; }
-
- // Returns the number of entries for a given head-tail range.
- // Requires `head` and `tail` values to be less than `capacity()`.
- index_type entries(index_type head, index_type tail) const {
- assert(head < capacity_ && tail < capacity_);
- return tail - head + ((tail > head) ? 0 : capacity_);
- }
-
- // Returns the logical end position of entry `index`.
- pos_type const& entry_end_pos(index_type index) const {
- assert(IsValidIndex(index));
- return Layout::Partial().Pointer<0>(data_)[index];
- }
-
- // Returns the child pointer of entry `index`.
- CordRep* const& entry_child(index_type index) const {
- assert(IsValidIndex(index));
- return Layout::Partial(capacity()).Pointer<1>(data_)[index];
- }
-
- // Returns the data offset of entry `index`
- offset_type const& entry_data_offset(index_type index) const {
- assert(IsValidIndex(index));
- return Layout::Partial(capacity(), capacity()).Pointer<2>(data_)[index];
- }
-
- // Appends the provided child node to the `rep` instance.
- // Adopts a reference from `rep` and `child` which may not be null.
- // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
- // containing a FLAT or EXTERNAL node, then flat or external the node is added
- // 'as is', with an offset added for the SUBSTRING case.
- // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING or
- // CONCAT tree, then all child nodes not excluded by any start offset or
- // length values are added recursively.
- static CordRepRing* Append(CordRepRing* rep, CordRep* child);
-
- // Appends the provided string data to the `rep` instance.
- // This function will attempt to utilize any remaining capacity in the last
- // node of the input if that node is not shared (directly or indirectly), and
- // of type FLAT. Remaining data will be added as one or more FLAT nodes.
- // Any last node added to the ring buffer will be allocated with up to
- // `extra` bytes of capacity for (anticipated) subsequent append actions.
- static CordRepRing* Append(CordRepRing* rep, string_view data,
- size_t extra = 0);
-
- // Prepends the provided child node to the `rep` instance.
- // Adopts a reference from `rep` and `child` which may not be null.
- // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
- // containing a FLAT or EXTERNAL node, then flat or external the node is
- // prepended 'as is', with an optional offset added for the SUBSTRING case.
- // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING
- // or CONCAT tree, then all child nodes not excluded by any start offset or
- // length values are added recursively.
- static CordRepRing* Prepend(CordRepRing* rep, CordRep* child);
-
- // Prepends the provided string data to the `rep` instance.
- // This function will attempt to utilize any remaining capacity in the first
- // node of the input if that node is not shared (directly or indirectly), and
- // of type FLAT. Remaining data will be added as one or more FLAT nodes.
- // Any first node prepnded to the ring buffer will be allocated with up to
- // `extra` bytes of capacity for (anticipated) subsequent prepend actions.
- static CordRepRing* Prepend(CordRepRing* rep, string_view data,
- size_t extra = 0);
-
- // Returns a span referencing potentially unused capacity in the last node.
- // The returned span may be empty if no such capacity is available, or if the
- // current instance is shared. Else, a span of size `n <= size` is returned.
- // If non empty, the ring buffer is adjusted to the new length, with the newly
- // added capacity left uninitialized. Callers should assign a value to the
- // entire span before any other operations on this instance.
- Span<char> GetAppendBuffer(size_t size);
-
- // Returns a span referencing potentially unused capacity in the first node.
- // This function is identical to GetAppendBuffer except that it returns a span
- // referencing up to `size` capacity directly before the existing data.
- Span<char> GetPrependBuffer(size_t size);
-
+// 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_CORD_REP_RING_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iosfwd>
+#include <limits>
+#include <memory>
+
+#include "y_absl/container/internal/layout.h"
+#include "y_absl/strings/internal/cord_internal.h"
+#include "y_absl/strings/internal/cord_rep_flat.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// All operations modifying a ring buffer are implemented as static methods
+// requiring a CordRepRing instance with a reference adopted by the method.
+//
+// The methods return the modified ring buffer, which may be equal to the input
+// if the input was not shared, and having large enough capacity to accommodate
+// any newly added node(s). Otherwise, a copy of the input rep with the new
+// node(s) added is returned.
+//
+// Any modification on non shared ring buffers with enough capacity will then
+// require minimum atomic operations. Caller should where possible provide
+// reasonable `extra` hints for both anticipated extra `flat` byte space, as
+// well as anticipated extra nodes required for complex operations.
+//
+// Example of code creating a ring buffer, adding some data to it,
+// and discarding the buffer when done:
+//
+// void FunWithRings() {
+// // Create ring with 3 flats
+// CordRep* flat = CreateFlat("Hello");
+// CordRepRing* ring = CordRepRing::Create(flat, 2);
+// ring = CordRepRing::Append(ring, CreateFlat(" "));
+// ring = CordRepRing::Append(ring, CreateFlat("world"));
+// DoSomethingWithRing(ring);
+// CordRep::Unref(ring);
+// }
+//
+// Example of code Copying an existing ring buffer and modifying it:
+//
+// void MoreFunWithRings(CordRepRing* src) {
+// CordRepRing* ring = CordRep::Ref(src)->ring();
+// ring = CordRepRing::Append(ring, CreateFlat("Hello"));
+// ring = CordRepRing::Append(ring, CreateFlat(" "));
+// ring = CordRepRing::Append(ring, CreateFlat("world"));
+// DoSomethingWithRing(ring);
+// CordRep::Unref(ring);
+// }
+//
+class CordRepRing : public CordRep {
+ public:
+ // `pos_type` represents a 'logical position'. A CordRepRing instance has a
+ // `begin_pos` (default 0), and each node inside the buffer will have an
+ // `end_pos` which is the `end_pos` of the previous node (or `begin_pos`) plus
+ // this node's length. The purpose is to allow for a binary search on this
+ // position, while allowing O(1) prepend and append operations.
+ using pos_type = size_t;
+
+ // `index_type` is the type for the `head`, `tail` and `capacity` indexes.
+ // Ring buffers are limited to having no more than four billion entries.
+ using index_type = uint32_t;
+
+ // `offset_type` is the type for the data offset inside a child rep's data.
+ using offset_type = uint32_t;
+
+ // Position holds the node index and relative offset into the node for
+ // some physical offset in the contained data as returned by the Find()
+ // and FindTail() methods.
+ struct Position {
+ index_type index;
+ size_t offset;
+ };
+
+ // The maximum # of child nodes that can be hosted inside a CordRepRing.
+ static constexpr size_t kMaxCapacity = (std::numeric_limits<uint32_t>::max)();
+
+ // CordRepring can not be default constructed, moved, copied or assigned.
+ CordRepRing() = delete;
+ CordRepRing(const CordRepRing&) = delete;
+ CordRepRing& operator=(const CordRepRing&) = delete;
+
+ // Returns true if this instance is valid, false if some or all of the
+ // invariants are broken. Intended for debug purposes only.
+ // `output` receives an explanation of the broken invariants.
+ bool IsValid(std::ostream& output) const;
+
+ // Returns the size in bytes for a CordRepRing with `capacity' entries.
+ static constexpr size_t AllocSize(size_t capacity);
+
+ // Returns the distance in bytes from `pos` to `end_pos`.
+ static constexpr size_t Distance(pos_type pos, pos_type end_pos);
+
+ // Creates a new ring buffer from the provided `rep`. Adopts a reference
+ // on `rep`. The returned ring buffer has a capacity of at least `extra + 1`
+ static CordRepRing* Create(CordRep* child, size_t extra = 0);
+
+ // `head`, `tail` and `capacity` indexes defining the ring buffer boundaries.
+ index_type head() const { return head_; }
+ index_type tail() const { return tail_; }
+ index_type capacity() const { return capacity_; }
+
+ // Returns the number of entries in this instance.
+ index_type entries() const { return entries(head_, tail_); }
+
+ // Returns the logical begin position of this instance.
+ pos_type begin_pos() const { return begin_pos_; }
+
+ // Returns the number of entries for a given head-tail range.
+ // Requires `head` and `tail` values to be less than `capacity()`.
+ index_type entries(index_type head, index_type tail) const {
+ assert(head < capacity_ && tail < capacity_);
+ return tail - head + ((tail > head) ? 0 : capacity_);
+ }
+
+ // Returns the logical end position of entry `index`.
+ pos_type const& entry_end_pos(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial().Pointer<0>(data_)[index];
+ }
+
+ // Returns the child pointer of entry `index`.
+ CordRep* const& entry_child(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial(capacity()).Pointer<1>(data_)[index];
+ }
+
+ // Returns the data offset of entry `index`
+ offset_type const& entry_data_offset(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial(capacity(), capacity()).Pointer<2>(data_)[index];
+ }
+
+ // Appends the provided child node to the `rep` instance.
+ // Adopts a reference from `rep` and `child` which may not be null.
+ // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
+ // containing a FLAT or EXTERNAL node, then flat or external the node is added
+ // 'as is', with an offset added for the SUBSTRING case.
+ // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING or
+ // CONCAT tree, then all child nodes not excluded by any start offset or
+ // length values are added recursively.
+ static CordRepRing* Append(CordRepRing* rep, CordRep* child);
+
+ // Appends the provided string data to the `rep` instance.
+ // This function will attempt to utilize any remaining capacity in the last
+ // node of the input if that node is not shared (directly or indirectly), and
+ // of type FLAT. Remaining data will be added as one or more FLAT nodes.
+ // Any last node added to the ring buffer will be allocated with up to
+ // `extra` bytes of capacity for (anticipated) subsequent append actions.
+ static CordRepRing* Append(CordRepRing* rep, string_view data,
+ size_t extra = 0);
+
+ // Prepends the provided child node to the `rep` instance.
+ // Adopts a reference from `rep` and `child` which may not be null.
+ // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
+ // containing a FLAT or EXTERNAL node, then flat or external the node is
+ // prepended 'as is', with an optional offset added for the SUBSTRING case.
+ // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING
+ // or CONCAT tree, then all child nodes not excluded by any start offset or
+ // length values are added recursively.
+ static CordRepRing* Prepend(CordRepRing* rep, CordRep* child);
+
+ // Prepends the provided string data to the `rep` instance.
+ // This function will attempt to utilize any remaining capacity in the first
+ // node of the input if that node is not shared (directly or indirectly), and
+ // of type FLAT. Remaining data will be added as one or more FLAT nodes.
+ // Any first node prepnded to the ring buffer will be allocated with up to
+ // `extra` bytes of capacity for (anticipated) subsequent prepend actions.
+ static CordRepRing* Prepend(CordRepRing* rep, string_view data,
+ size_t extra = 0);
+
+ // Returns a span referencing potentially unused capacity in the last node.
+ // The returned span may be empty if no such capacity is available, or if the
+ // current instance is shared. Else, a span of size `n <= size` is returned.
+ // If non empty, the ring buffer is adjusted to the new length, with the newly
+ // added capacity left uninitialized. Callers should assign a value to the
+ // entire span before any other operations on this instance.
+ Span<char> GetAppendBuffer(size_t size);
+
+ // Returns a span referencing potentially unused capacity in the first node.
+ // This function is identical to GetAppendBuffer except that it returns a span
+ // referencing up to `size` capacity directly before the existing data.
+ Span<char> GetPrependBuffer(size_t size);
+
// Returns a cord ring buffer containing `len` bytes of data starting at
- // `offset`. If the input is not shared, this function will remove all head
- // and tail child nodes outside of the requested range, and adjust the new
- // head and tail nodes as required. If the input is shared, this function
- // returns a new instance sharing some or all of the nodes from the input.
+ // `offset`. If the input is not shared, this function will remove all head
+ // and tail child nodes outside of the requested range, and adjust the new
+ // head and tail nodes as required. If the input is shared, this function
+ // returns a new instance sharing some or all of the nodes from the input.
static CordRepRing* SubRing(CordRepRing* r, size_t offset, size_t len,
- size_t extra = 0);
-
+ size_t extra = 0);
+
// Returns a cord ring buffer with the first `len` bytes removed.
- // If the input is not shared, this function will remove all head child nodes
- // fully inside the first `length` bytes, and adjust the new head as required.
- // If the input is shared, this function returns a new instance sharing some
- // or all of the nodes from the input.
+ // If the input is not shared, this function will remove all head child nodes
+ // fully inside the first `length` bytes, and adjust the new head as required.
+ // If the input is shared, this function returns a new instance sharing some
+ // or all of the nodes from the input.
static CordRepRing* RemoveSuffix(CordRepRing* r, size_t len,
- size_t extra = 0);
-
+ size_t extra = 0);
+
// Returns a cord ring buffer with the last `len` bytes removed.
- // If the input is not shared, this function will remove all head child nodes
- // fully inside the first `length` bytes, and adjust the new head as required.
- // If the input is shared, this function returns a new instance sharing some
- // or all of the nodes from the input.
- static CordRepRing* RemovePrefix(CordRepRing* r, size_t len,
- size_t extra = 0);
-
- // Returns the character at `offset`. Requires that `offset < length`.
- char GetCharacter(size_t offset) const;
-
+ // If the input is not shared, this function will remove all head child nodes
+ // fully inside the first `length` bytes, and adjust the new head as required.
+ // If the input is shared, this function returns a new instance sharing some
+ // or all of the nodes from the input.
+ static CordRepRing* RemovePrefix(CordRepRing* r, size_t len,
+ size_t extra = 0);
+
+ // Returns the character at `offset`. Requires that `offset < length`.
+ char GetCharacter(size_t offset) const;
+
// Returns true if this instance manages a single contiguous buffer, in which
// case the (optional) output parameter `fragment` is set. Otherwise, the
// function returns false, and `fragment` is left unchanged.
@@ -240,345 +240,345 @@ class CordRepRing : public CordRep {
// returns false, and `fragment` is left unchanged.
bool IsFlat(size_t offset, size_t len, y_absl::string_view* fragment) const;
- // Testing only: set capacity to requested capacity.
- void SetCapacityForTesting(size_t capacity);
-
- // Returns the CordRep data pointer for the provided CordRep.
- // Requires that the provided `rep` is either a FLAT or EXTERNAL CordRep.
- static const char* GetLeafData(const CordRep* rep);
-
- // Returns the CordRep data pointer for the provided CordRep.
- // Requires that `rep` is either a FLAT, EXTERNAL, or SUBSTRING CordRep.
- static const char* GetRepData(const CordRep* rep);
-
- // Advances the provided position, wrapping around capacity as needed.
- // Requires `index` < capacity()
- inline index_type advance(index_type index) const;
-
- // Advances the provided position by 'n`, wrapping around capacity as needed.
- // Requires `index` < capacity() and `n` <= capacity.
- inline index_type advance(index_type index, index_type n) const;
-
- // Retreats the provided position, wrapping around 0 as needed.
- // Requires `index` < capacity()
- inline index_type retreat(index_type index) const;
-
- // Retreats the provided position by 'n', wrapping around 0 as needed.
- // Requires `index` < capacity()
- inline index_type retreat(index_type index, index_type n) const;
-
- // Returns the logical begin position of entry `index`
- pos_type const& entry_begin_pos(index_type index) const {
- return (index == head_) ? begin_pos_ : entry_end_pos(retreat(index));
- }
-
- // Returns the physical start offset of entry `index`
- size_t entry_start_offset(index_type index) const {
- return Distance(begin_pos_, entry_begin_pos(index));
- }
-
- // Returns the physical end offset of entry `index`
- size_t entry_end_offset(index_type index) const {
- return Distance(begin_pos_, entry_end_pos(index));
- }
-
- // Returns the data length for entry `index`
- size_t entry_length(index_type index) const {
- return Distance(entry_begin_pos(index), entry_end_pos(index));
- }
-
- // Returns the data for entry `index`
- y_absl::string_view entry_data(index_type index) const;
-
- // Returns the position for `offset` as {index, prefix}. `index` holds the
- // index of the entry at the specified offset and `prefix` holds the relative
- // offset inside that entry.
- // Requires `offset` < length.
- //
- // For example we can implement GetCharacter(offset) as:
- // char GetCharacter(size_t offset) {
- // Position pos = this->Find(offset);
- // return this->entry_data(pos.pos)[pos.offset];
- // }
- inline Position Find(size_t offset) const;
-
- // Find starting at `head`
- inline Position Find(index_type head, size_t offset) const;
-
- // Returns the tail position for `offset` as {tail index, suffix}.
- // `tail index` holds holds the index of the entry holding the offset directly
- // before 'offset` advanced by one. 'suffix` holds the relative offset from
- // that relative offset in the entry to the end of the entry.
- // For example, FindTail(length) will return {tail(), 0}, FindTail(length - 5)
- // will return {retreat(tail), 5)} provided the preceding entry contains at
- // least 5 bytes of data.
- // Requires offset >= 1 && offset <= length.
- //
- // This function is very useful in functions that need to clip the end of some
- // ring buffer such as 'RemovePrefix'.
- // For example, we could implement RemovePrefix for non shared instances as:
- // void RemoveSuffix(size_t n) {
- // Position pos = FindTail(length - n);
- // UnrefEntries(pos.pos, this->tail_);
- // this->tail_ = pos.pos;
- // entry(retreat(pos.pos)).end_pos -= pos.offset;
- // }
- inline Position FindTail(size_t offset) const;
-
- // Find tail starting at `head`
- inline Position FindTail(index_type head, size_t offset) const;
-
- // Invokes f(index_type index) for each entry inside the range [head, tail>
- template <typename F>
- void ForEach(index_type head, index_type tail, F&& f) const {
- index_type n1 = (tail > head) ? tail : capacity_;
- for (index_type i = head; i < n1; ++i) f(i);
- if (tail <= head) {
- for (index_type i = 0; i < tail; ++i) f(i);
- }
- }
-
- // Invokes f(index_type index) for each entry inside this instance.
- template <typename F>
- void ForEach(F&& f) const {
- ForEach(head_, tail_, std::forward<F>(f));
- }
-
- // Dump this instance's data tp stream `s` in human readable format, excluding
- // the actual data content itself. Intended for debug purposes only.
- friend std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
-
- private:
- enum class AddMode { kAppend, kPrepend };
-
- using Layout = container_internal::Layout<pos_type, CordRep*, offset_type>;
-
- class Filler;
- class Transaction;
- class CreateTransaction;
-
- static constexpr size_t kLayoutAlignment = Layout::Partial().Alignment();
-
- // Creates a new CordRepRing.
- explicit CordRepRing(index_type capacity) : capacity_(capacity) {}
-
- // Returns true if `index` is a valid index into this instance.
- bool IsValidIndex(index_type index) const;
-
- // Debug use only: validates the provided CordRepRing invariants.
- // Verification of all CordRepRing methods can be enabled by defining
- // EXTRA_CORD_RING_VALIDATION, i.e.: `--copts=-DEXTRA_CORD_RING_VALIDATION`
- // Verification is VERY expensive, so only do it for debugging purposes.
- static CordRepRing* Validate(CordRepRing* rep, const char* file = nullptr,
- int line = 0);
-
- // Allocates a CordRepRing large enough to hold `capacity + extra' entries.
- // The returned capacity may be larger if the allocated memory allows for it.
- // The maximum capacity of a CordRepRing is capped at kMaxCapacity.
- // Throws `std::length_error` if `capacity + extra' exceeds kMaxCapacity.
- static CordRepRing* New(size_t capacity, size_t extra);
-
- // Deallocates (but does not destroy) the provided ring buffer.
- static void Delete(CordRepRing* rep);
-
- // Destroys the provided ring buffer, decrementing the reference count of all
- // contained child CordReps. The provided 1\`rep` should have a ref count of
+ // Testing only: set capacity to requested capacity.
+ void SetCapacityForTesting(size_t capacity);
+
+ // Returns the CordRep data pointer for the provided CordRep.
+ // Requires that the provided `rep` is either a FLAT or EXTERNAL CordRep.
+ static const char* GetLeafData(const CordRep* rep);
+
+ // Returns the CordRep data pointer for the provided CordRep.
+ // Requires that `rep` is either a FLAT, EXTERNAL, or SUBSTRING CordRep.
+ static const char* GetRepData(const CordRep* rep);
+
+ // Advances the provided position, wrapping around capacity as needed.
+ // Requires `index` < capacity()
+ inline index_type advance(index_type index) const;
+
+ // Advances the provided position by 'n`, wrapping around capacity as needed.
+ // Requires `index` < capacity() and `n` <= capacity.
+ inline index_type advance(index_type index, index_type n) const;
+
+ // Retreats the provided position, wrapping around 0 as needed.
+ // Requires `index` < capacity()
+ inline index_type retreat(index_type index) const;
+
+ // Retreats the provided position by 'n', wrapping around 0 as needed.
+ // Requires `index` < capacity()
+ inline index_type retreat(index_type index, index_type n) const;
+
+ // Returns the logical begin position of entry `index`
+ pos_type const& entry_begin_pos(index_type index) const {
+ return (index == head_) ? begin_pos_ : entry_end_pos(retreat(index));
+ }
+
+ // Returns the physical start offset of entry `index`
+ size_t entry_start_offset(index_type index) const {
+ return Distance(begin_pos_, entry_begin_pos(index));
+ }
+
+ // Returns the physical end offset of entry `index`
+ size_t entry_end_offset(index_type index) const {
+ return Distance(begin_pos_, entry_end_pos(index));
+ }
+
+ // Returns the data length for entry `index`
+ size_t entry_length(index_type index) const {
+ return Distance(entry_begin_pos(index), entry_end_pos(index));
+ }
+
+ // Returns the data for entry `index`
+ y_absl::string_view entry_data(index_type index) const;
+
+ // Returns the position for `offset` as {index, prefix}. `index` holds the
+ // index of the entry at the specified offset and `prefix` holds the relative
+ // offset inside that entry.
+ // Requires `offset` < length.
+ //
+ // For example we can implement GetCharacter(offset) as:
+ // char GetCharacter(size_t offset) {
+ // Position pos = this->Find(offset);
+ // return this->entry_data(pos.pos)[pos.offset];
+ // }
+ inline Position Find(size_t offset) const;
+
+ // Find starting at `head`
+ inline Position Find(index_type head, size_t offset) const;
+
+ // Returns the tail position for `offset` as {tail index, suffix}.
+ // `tail index` holds holds the index of the entry holding the offset directly
+ // before 'offset` advanced by one. 'suffix` holds the relative offset from
+ // that relative offset in the entry to the end of the entry.
+ // For example, FindTail(length) will return {tail(), 0}, FindTail(length - 5)
+ // will return {retreat(tail), 5)} provided the preceding entry contains at
+ // least 5 bytes of data.
+ // Requires offset >= 1 && offset <= length.
+ //
+ // This function is very useful in functions that need to clip the end of some
+ // ring buffer such as 'RemovePrefix'.
+ // For example, we could implement RemovePrefix for non shared instances as:
+ // void RemoveSuffix(size_t n) {
+ // Position pos = FindTail(length - n);
+ // UnrefEntries(pos.pos, this->tail_);
+ // this->tail_ = pos.pos;
+ // entry(retreat(pos.pos)).end_pos -= pos.offset;
+ // }
+ inline Position FindTail(size_t offset) const;
+
+ // Find tail starting at `head`
+ inline Position FindTail(index_type head, size_t offset) const;
+
+ // Invokes f(index_type index) for each entry inside the range [head, tail>
+ template <typename F>
+ void ForEach(index_type head, index_type tail, F&& f) const {
+ index_type n1 = (tail > head) ? tail : capacity_;
+ for (index_type i = head; i < n1; ++i) f(i);
+ if (tail <= head) {
+ for (index_type i = 0; i < tail; ++i) f(i);
+ }
+ }
+
+ // Invokes f(index_type index) for each entry inside this instance.
+ template <typename F>
+ void ForEach(F&& f) const {
+ ForEach(head_, tail_, std::forward<F>(f));
+ }
+
+ // Dump this instance's data tp stream `s` in human readable format, excluding
+ // the actual data content itself. Intended for debug purposes only.
+ friend std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
+
+ private:
+ enum class AddMode { kAppend, kPrepend };
+
+ using Layout = container_internal::Layout<pos_type, CordRep*, offset_type>;
+
+ class Filler;
+ class Transaction;
+ class CreateTransaction;
+
+ static constexpr size_t kLayoutAlignment = Layout::Partial().Alignment();
+
+ // Creates a new CordRepRing.
+ explicit CordRepRing(index_type capacity) : capacity_(capacity) {}
+
+ // Returns true if `index` is a valid index into this instance.
+ bool IsValidIndex(index_type index) const;
+
+ // Debug use only: validates the provided CordRepRing invariants.
+ // Verification of all CordRepRing methods can be enabled by defining
+ // EXTRA_CORD_RING_VALIDATION, i.e.: `--copts=-DEXTRA_CORD_RING_VALIDATION`
+ // Verification is VERY expensive, so only do it for debugging purposes.
+ static CordRepRing* Validate(CordRepRing* rep, const char* file = nullptr,
+ int line = 0);
+
+ // Allocates a CordRepRing large enough to hold `capacity + extra' entries.
+ // The returned capacity may be larger if the allocated memory allows for it.
+ // The maximum capacity of a CordRepRing is capped at kMaxCapacity.
+ // Throws `std::length_error` if `capacity + extra' exceeds kMaxCapacity.
+ static CordRepRing* New(size_t capacity, size_t extra);
+
+ // Deallocates (but does not destroy) the provided ring buffer.
+ static void Delete(CordRepRing* rep);
+
+ // Destroys the provided ring buffer, decrementing the reference count of all
+ // contained child CordReps. The provided 1\`rep` should have a ref count of
// one (pre decrement destroy call observing `refcount.IsOne()`) or zero
// (post decrement destroy call observing `!refcount.Decrement()`).
- static void Destroy(CordRepRing* rep);
-
- // Returns a mutable reference to the logical end position array.
- pos_type* entry_end_pos() {
- return Layout::Partial().Pointer<0>(data_);
- }
-
- // Returns a mutable reference to the child pointer array.
- CordRep** entry_child() {
- return Layout::Partial(capacity()).Pointer<1>(data_);
- }
-
- // Returns a mutable reference to the data offset array.
- offset_type* entry_data_offset() {
- return Layout::Partial(capacity(), capacity()).Pointer<2>(data_);
- }
-
- // Find implementations for the non fast path 0 / length cases.
- Position FindSlow(index_type head, size_t offset) const;
- Position FindTailSlow(index_type head, size_t offset) const;
-
- // Finds the index of the first node that is inside a reasonable distance
- // of the node at `offset` from which we can continue with a linear search.
- template <bool wrap>
- index_type FindBinary(index_type head, index_type tail, size_t offset) const;
-
- // Fills the current (initialized) instance from the provided source, copying
- // entries [head, tail). Adds a reference to copied entries if `ref` is true.
- template <bool ref>
- void Fill(const CordRepRing* src, index_type head, index_type tail);
-
- // Create a copy of 'rep', copying all entries [head, tail), allocating room
- // for `extra` entries. Adds a reference on all copied entries.
- static CordRepRing* Copy(CordRepRing* rep, index_type head, index_type tail,
- size_t extra = 0);
-
- // Returns a Mutable CordRepRing reference from `rep` with room for at least
- // `extra` additional nodes. Adopts a reference count from `rep`.
- // This function will return `rep` if, and only if:
- // - rep.entries + extra <= rep.capacity
- // - rep.refcount == 1
- // Otherwise, this function will create a new copy of `rep` with additional
- // capacity to satisfy `extra` extra nodes, and unref the old `rep` instance.
- //
- // If a new CordRepRing can not be allocated, or the new capacity would exceed
- // the maxmimum capacity, then the input is consumed only, and an exception is
- // thrown.
- static CordRepRing* Mutable(CordRepRing* rep, size_t extra);
-
- // Slow path for Append(CordRepRing* rep, CordRep* child). This function is
- // exercised if the provided `child` in Append() is not a leaf node, i.e., a
- // ring buffer or old (concat) cord tree.
- static CordRepRing* AppendSlow(CordRepRing* rep, CordRep* child);
-
- // Appends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
- static CordRepRing* AppendLeaf(CordRepRing* rep, CordRep* child,
- size_t offset, size_t length);
-
- // Prepends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
- static CordRepRing* PrependLeaf(CordRepRing* rep, CordRep* child,
- size_t offset, size_t length);
-
- // Slow path for Prepend(CordRepRing* rep, CordRep* child). This function is
- // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
- // ring buffer or old (concat) cord tree.
- static CordRepRing* PrependSlow(CordRepRing* rep, CordRep* child);
-
- // Slow path for Create(CordRep* child, size_t extra). This function is
- // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
- // ring buffer or old (concat) cord tree.
- static CordRepRing* CreateSlow(CordRep* child, size_t extra);
-
- // Creates a new ring buffer from the provided `child` leaf node. Requires
- // `child` to be FLAT or EXTERNAL. on `rep`.
- // The returned ring buffer has a capacity of at least `1 + extra`
- static CordRepRing* CreateFromLeaf(CordRep* child, size_t offset,
- size_t length, size_t extra);
-
- // Appends or prepends (depending on AddMode) the ring buffer in `ring' to
+ static void Destroy(CordRepRing* rep);
+
+ // Returns a mutable reference to the logical end position array.
+ pos_type* entry_end_pos() {
+ return Layout::Partial().Pointer<0>(data_);
+ }
+
+ // Returns a mutable reference to the child pointer array.
+ CordRep** entry_child() {
+ return Layout::Partial(capacity()).Pointer<1>(data_);
+ }
+
+ // Returns a mutable reference to the data offset array.
+ offset_type* entry_data_offset() {
+ return Layout::Partial(capacity(), capacity()).Pointer<2>(data_);
+ }
+
+ // Find implementations for the non fast path 0 / length cases.
+ Position FindSlow(index_type head, size_t offset) const;
+ Position FindTailSlow(index_type head, size_t offset) const;
+
+ // Finds the index of the first node that is inside a reasonable distance
+ // of the node at `offset` from which we can continue with a linear search.
+ template <bool wrap>
+ index_type FindBinary(index_type head, index_type tail, size_t offset) const;
+
+ // Fills the current (initialized) instance from the provided source, copying
+ // entries [head, tail). Adds a reference to copied entries if `ref` is true.
+ template <bool ref>
+ void Fill(const CordRepRing* src, index_type head, index_type tail);
+
+ // Create a copy of 'rep', copying all entries [head, tail), allocating room
+ // for `extra` entries. Adds a reference on all copied entries.
+ static CordRepRing* Copy(CordRepRing* rep, index_type head, index_type tail,
+ size_t extra = 0);
+
+ // Returns a Mutable CordRepRing reference from `rep` with room for at least
+ // `extra` additional nodes. Adopts a reference count from `rep`.
+ // This function will return `rep` if, and only if:
+ // - rep.entries + extra <= rep.capacity
+ // - rep.refcount == 1
+ // Otherwise, this function will create a new copy of `rep` with additional
+ // capacity to satisfy `extra` extra nodes, and unref the old `rep` instance.
+ //
+ // If a new CordRepRing can not be allocated, or the new capacity would exceed
+ // the maxmimum capacity, then the input is consumed only, and an exception is
+ // thrown.
+ static CordRepRing* Mutable(CordRepRing* rep, size_t extra);
+
+ // Slow path for Append(CordRepRing* rep, CordRep* child). This function is
+ // exercised if the provided `child` in Append() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* AppendSlow(CordRepRing* rep, CordRep* child);
+
+ // Appends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
+ static CordRepRing* AppendLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length);
+
+ // Prepends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
+ static CordRepRing* PrependLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length);
+
+ // Slow path for Prepend(CordRepRing* rep, CordRep* child). This function is
+ // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* PrependSlow(CordRepRing* rep, CordRep* child);
+
+ // Slow path for Create(CordRep* child, size_t extra). This function is
+ // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* CreateSlow(CordRep* child, size_t extra);
+
+ // Creates a new ring buffer from the provided `child` leaf node. Requires
+ // `child` to be FLAT or EXTERNAL. on `rep`.
+ // The returned ring buffer has a capacity of at least `1 + extra`
+ static CordRepRing* CreateFromLeaf(CordRep* child, size_t offset,
+ size_t length, size_t extra);
+
+ // Appends or prepends (depending on AddMode) the ring buffer in `ring' to
// `rep` starting at `offset` with length `len`.
- template <AddMode mode>
- static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring,
+ template <AddMode mode>
+ static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring,
size_t offset, size_t len);
-
- // Increases the data offset for entry `index` by `n`.
- void AddDataOffset(index_type index, size_t n);
-
- // Descreases the length for entry `index` by `n`.
- void SubLength(index_type index, size_t n);
-
- index_type head_;
- index_type tail_;
- index_type capacity_;
- pos_type begin_pos_;
-
- alignas(kLayoutAlignment) char data_[kLayoutAlignment];
-
- friend struct CordRep;
-};
-
-constexpr size_t CordRepRing::AllocSize(size_t capacity) {
- return sizeof(CordRepRing) - sizeof(data_) +
- Layout(capacity, capacity, capacity).AllocSize();
-}
-
-inline constexpr size_t CordRepRing::Distance(pos_type pos, pos_type end_pos) {
- return (end_pos - pos);
-}
-
-inline const char* CordRepRing::GetLeafData(const CordRep* rep) {
- return rep->tag != EXTERNAL ? rep->flat()->Data() : rep->external()->base;
-}
-
-inline const char* CordRepRing::GetRepData(const CordRep* rep) {
- if (rep->tag >= FLAT) return rep->flat()->Data();
- if (rep->tag == EXTERNAL) return rep->external()->base;
- return GetLeafData(rep->substring()->child) + rep->substring()->start;
-}
-
-inline CordRepRing::index_type CordRepRing::advance(index_type index) const {
- assert(index < capacity_);
- return ++index == capacity_ ? 0 : index;
-}
-
-inline CordRepRing::index_type CordRepRing::advance(index_type index,
- index_type n) const {
- assert(index < capacity_ && n <= capacity_);
- return (index += n) >= capacity_ ? index - capacity_ : index;
-}
-
-inline CordRepRing::index_type CordRepRing::retreat(index_type index) const {
- assert(index < capacity_);
- return (index > 0 ? index : capacity_) - 1;
-}
-
-inline CordRepRing::index_type CordRepRing::retreat(index_type index,
- index_type n) const {
- assert(index < capacity_ && n <= capacity_);
- return index >= n ? index - n : capacity_ - n + index;
-}
-
-inline y_absl::string_view CordRepRing::entry_data(index_type index) const {
- size_t data_offset = entry_data_offset(index);
- return {GetRepData(entry_child(index)) + data_offset, entry_length(index)};
-}
-
-inline bool CordRepRing::IsValidIndex(index_type index) const {
- if (index >= capacity_) return false;
- return (tail_ > head_) ? (index >= head_ && index < tail_)
- : (index >= head_ || index < tail_);
-}
-
-#ifndef EXTRA_CORD_RING_VALIDATION
-inline CordRepRing* CordRepRing::Validate(CordRepRing* rep,
- const char* /*file*/, int /*line*/) {
- return rep;
-}
-#endif
-
-inline CordRepRing::Position CordRepRing::Find(size_t offset) const {
- assert(offset < length);
- return (offset == 0) ? Position{head_, 0} : FindSlow(head_, offset);
-}
-
-inline CordRepRing::Position CordRepRing::Find(index_type head,
- size_t offset) const {
- assert(offset < length);
- assert(IsValidIndex(head) && offset >= entry_start_offset(head));
- return (offset == 0) ? Position{head_, 0} : FindSlow(head, offset);
-}
-
-inline CordRepRing::Position CordRepRing::FindTail(size_t offset) const {
- assert(offset > 0 && offset <= length);
- return (offset == length) ? Position{tail_, 0} : FindTailSlow(head_, offset);
-}
-
-inline CordRepRing::Position CordRepRing::FindTail(index_type head,
- size_t offset) const {
- assert(offset > 0 && offset <= length);
- assert(IsValidIndex(head) && offset >= entry_start_offset(head) + 1);
- return (offset == length) ? Position{tail_, 0} : FindTailSlow(head, offset);
-}
-
-// Now that CordRepRing is defined, we can define CordRep's helper casts:
-inline CordRepRing* CordRep::ring() {
+
+ // Increases the data offset for entry `index` by `n`.
+ void AddDataOffset(index_type index, size_t n);
+
+ // Descreases the length for entry `index` by `n`.
+ void SubLength(index_type index, size_t n);
+
+ index_type head_;
+ index_type tail_;
+ index_type capacity_;
+ pos_type begin_pos_;
+
+ alignas(kLayoutAlignment) char data_[kLayoutAlignment];
+
+ friend struct CordRep;
+};
+
+constexpr size_t CordRepRing::AllocSize(size_t capacity) {
+ return sizeof(CordRepRing) - sizeof(data_) +
+ Layout(capacity, capacity, capacity).AllocSize();
+}
+
+inline constexpr size_t CordRepRing::Distance(pos_type pos, pos_type end_pos) {
+ return (end_pos - pos);
+}
+
+inline const char* CordRepRing::GetLeafData(const CordRep* rep) {
+ return rep->tag != EXTERNAL ? rep->flat()->Data() : rep->external()->base;
+}
+
+inline const char* CordRepRing::GetRepData(const CordRep* rep) {
+ if (rep->tag >= FLAT) return rep->flat()->Data();
+ if (rep->tag == EXTERNAL) return rep->external()->base;
+ return GetLeafData(rep->substring()->child) + rep->substring()->start;
+}
+
+inline CordRepRing::index_type CordRepRing::advance(index_type index) const {
+ assert(index < capacity_);
+ return ++index == capacity_ ? 0 : index;
+}
+
+inline CordRepRing::index_type CordRepRing::advance(index_type index,
+ index_type n) const {
+ assert(index < capacity_ && n <= capacity_);
+ return (index += n) >= capacity_ ? index - capacity_ : index;
+}
+
+inline CordRepRing::index_type CordRepRing::retreat(index_type index) const {
+ assert(index < capacity_);
+ return (index > 0 ? index : capacity_) - 1;
+}
+
+inline CordRepRing::index_type CordRepRing::retreat(index_type index,
+ index_type n) const {
+ assert(index < capacity_ && n <= capacity_);
+ return index >= n ? index - n : capacity_ - n + index;
+}
+
+inline y_absl::string_view CordRepRing::entry_data(index_type index) const {
+ size_t data_offset = entry_data_offset(index);
+ return {GetRepData(entry_child(index)) + data_offset, entry_length(index)};
+}
+
+inline bool CordRepRing::IsValidIndex(index_type index) const {
+ if (index >= capacity_) return false;
+ return (tail_ > head_) ? (index >= head_ && index < tail_)
+ : (index >= head_ || index < tail_);
+}
+
+#ifndef EXTRA_CORD_RING_VALIDATION
+inline CordRepRing* CordRepRing::Validate(CordRepRing* rep,
+ const char* /*file*/, int /*line*/) {
+ return rep;
+}
+#endif
+
+inline CordRepRing::Position CordRepRing::Find(size_t offset) const {
+ assert(offset < length);
+ return (offset == 0) ? Position{head_, 0} : FindSlow(head_, offset);
+}
+
+inline CordRepRing::Position CordRepRing::Find(index_type head,
+ size_t offset) const {
+ assert(offset < length);
+ assert(IsValidIndex(head) && offset >= entry_start_offset(head));
+ return (offset == 0) ? Position{head_, 0} : FindSlow(head, offset);
+}
+
+inline CordRepRing::Position CordRepRing::FindTail(size_t offset) const {
+ assert(offset > 0 && offset <= length);
+ return (offset == length) ? Position{tail_, 0} : FindTailSlow(head_, offset);
+}
+
+inline CordRepRing::Position CordRepRing::FindTail(index_type head,
+ size_t offset) const {
+ assert(offset > 0 && offset <= length);
+ assert(IsValidIndex(head) && offset >= entry_start_offset(head) + 1);
+ return (offset == length) ? Position{tail_, 0} : FindTailSlow(head, offset);
+}
+
+// Now that CordRepRing is defined, we can define CordRep's helper casts:
+inline CordRepRing* CordRep::ring() {
assert(IsRing());
- return static_cast<CordRepRing*>(this);
-}
-
-inline const CordRepRing* CordRep::ring() const {
+ return static_cast<CordRepRing*>(this);
+}
+
+inline const CordRepRing* CordRep::ring() const {
assert(IsRing());
- return static_cast<const CordRepRing*>(this);
-}
-
+ return static_cast<const CordRepRing*>(this);
+}
+
inline bool CordRepRing::IsFlat(y_absl::string_view* fragment) const {
if (entries() == 1) {
if (fragment) *fragment = entry_data(head());
@@ -598,10 +598,10 @@ inline bool CordRepRing::IsFlat(size_t offset, size_t len,
return false;
}
-std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
+std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring_reader.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring_reader.h
index 3f64d04fae..98ea8c170a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring_reader.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cord_rep_ring_reader.h
@@ -1,118 +1,118 @@
-// 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_REP_RING_READER_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-
-#include "y_absl/strings/internal/cord_internal.h"
-#include "y_absl/strings/internal/cord_rep_ring.h"
-#include "y_absl/strings/string_view.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordRepRingReader provides basic navigation over CordRepRing data.
-class CordRepRingReader {
- public:
- // Returns true if this instance is not empty.
- explicit operator bool() const { return ring_ != nullptr; }
-
- // Returns the ring buffer reference for this instance, or nullptr if empty.
- CordRepRing* ring() const { return ring_; }
-
- // Returns the current node index inside the ring buffer for this instance.
- // The returned value is undefined if this instance is empty.
- CordRepRing::index_type index() const { return index_; }
-
+// 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_REP_RING_READER_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+#include "y_absl/strings/internal/cord_internal.h"
+#include "y_absl/strings/internal/cord_rep_ring.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// CordRepRingReader provides basic navigation over CordRepRing data.
+class CordRepRingReader {
+ public:
+ // Returns true if this instance is not empty.
+ explicit operator bool() const { return ring_ != nullptr; }
+
+ // Returns the ring buffer reference for this instance, or nullptr if empty.
+ CordRepRing* ring() const { return ring_; }
+
+ // Returns the current node index inside the ring buffer for this instance.
+ // The returned value is undefined if this instance is empty.
+ CordRepRing::index_type index() const { return index_; }
+
// Returns the current node inside the ring buffer for this instance.
// The returned value is undefined if this instance is empty.
CordRep* node() const { return ring_->entry_child(index_); }
- // Returns the length of the referenced ring buffer.
- // Requires the current instance to be non empty.
- size_t length() const {
- assert(ring_);
- return ring_->length;
- }
-
- // Returns the end offset of the last navigated-to chunk, which represents the
- // total bytes 'consumed' relative to the start of the ring. The returned
- // value is never zero. For example, initializing a reader with a ring buffer
- // with a first chunk of 19 bytes will return consumed() = 19.
- // Requires the current instance to be non empty.
- size_t consumed() const {
- assert(ring_);
- return ring_->entry_end_offset(index_);
- }
-
- // Returns the number of bytes remaining beyond the last navigated-to chunk.
- // Requires the current instance to be non empty.
- size_t remaining() const {
- assert(ring_);
- return length() - consumed();
- }
-
- // Resets this instance to an empty value
- void Reset() { ring_ = nullptr; }
-
- // Resets this instance to the start of `ring`. `ring` must not be null.
- // Returns a reference into the first chunk of the provided ring.
- y_absl::string_view Reset(CordRepRing* ring) {
- assert(ring);
- ring_ = ring;
- index_ = ring_->head();
- return ring_->entry_data(index_);
- }
-
- // Navigates to the next chunk inside the reference ring buffer.
- // Returns a reference into the navigated-to chunk.
- // Requires remaining() to be non zero.
- y_absl::string_view Next() {
- assert(remaining());
- index_ = ring_->advance(index_);
- return ring_->entry_data(index_);
- }
-
- // Navigates to the chunk at offset `offset`.
- // Returns a reference into the navigated-to chunk, adjusted for the relative
- // position of `offset` into that chunk. For example, calling Seek(13) on a
- // ring buffer containing 2 chunks of 10 and 20 bytes respectively will return
- // a string view into the second chunk starting at offset 3 with a size of 17.
- // Requires `offset` to be less than `length()`
- y_absl::string_view Seek(size_t offset) {
- assert(offset < length());
- size_t current = ring_->entry_end_offset(index_);
- CordRepRing::index_type hint = (offset >= current) ? index_ : ring_->head();
- const CordRepRing::Position head = ring_->Find(hint, offset);
- index_ = head.index;
- auto data = ring_->entry_data(head.index);
- data.remove_prefix(head.offset);
- return data;
- }
-
- private:
- CordRepRing* ring_ = nullptr;
- CordRepRing::index_type index_;
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
+ // Returns the length of the referenced ring buffer.
+ // Requires the current instance to be non empty.
+ size_t length() const {
+ assert(ring_);
+ return ring_->length;
+ }
+
+ // Returns the end offset of the last navigated-to chunk, which represents the
+ // total bytes 'consumed' relative to the start of the ring. The returned
+ // value is never zero. For example, initializing a reader with a ring buffer
+ // with a first chunk of 19 bytes will return consumed() = 19.
+ // Requires the current instance to be non empty.
+ size_t consumed() const {
+ assert(ring_);
+ return ring_->entry_end_offset(index_);
+ }
+
+ // Returns the number of bytes remaining beyond the last navigated-to chunk.
+ // Requires the current instance to be non empty.
+ size_t remaining() const {
+ assert(ring_);
+ return length() - consumed();
+ }
+
+ // Resets this instance to an empty value
+ void Reset() { ring_ = nullptr; }
+
+ // Resets this instance to the start of `ring`. `ring` must not be null.
+ // Returns a reference into the first chunk of the provided ring.
+ y_absl::string_view Reset(CordRepRing* ring) {
+ assert(ring);
+ ring_ = ring;
+ index_ = ring_->head();
+ return ring_->entry_data(index_);
+ }
+
+ // Navigates to the next chunk inside the reference ring buffer.
+ // Returns a reference into the navigated-to chunk.
+ // Requires remaining() to be non zero.
+ y_absl::string_view Next() {
+ assert(remaining());
+ index_ = ring_->advance(index_);
+ return ring_->entry_data(index_);
+ }
+
+ // Navigates to the chunk at offset `offset`.
+ // Returns a reference into the navigated-to chunk, adjusted for the relative
+ // position of `offset` into that chunk. For example, calling Seek(13) on a
+ // ring buffer containing 2 chunks of 10 and 20 bytes respectively will return
+ // a string view into the second chunk starting at offset 3 with a size of 17.
+ // Requires `offset` to be less than `length()`
+ y_absl::string_view Seek(size_t offset) {
+ assert(offset < length());
+ size_t current = ring_->entry_end_offset(index_);
+ CordRepRing::index_type hint = (offset >= current) ? index_ : ring_->head();
+ const CordRepRing::Position head = ring_->Find(hint, offset);
+ index_ = head.index;
+ auto data = ring_->entry_data(head.index);
+ data.remove_prefix(head.offset);
+ return data;
+ }
+
+ private:
+ CordRepRing* ring_ = nullptr;
+ CordRepRing::index_type index_;
+};
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
index 06e99346da..d2522532e2 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions/ya.make
@@ -2,13 +2,13 @@
LIBRARY()
-WITHOUT_LICENSE_TEXTS()
-
-OWNER(
- somov
- g:cpp-contrib
-)
+WITHOUT_LICENSE_TEXTS()
+OWNER(
+ somov
+ g:cpp-contrib
+)
+
LICENSE(Apache-2.0)
PEERDIR(
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_handle/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_handle/ya.make
index e181217139..0220a75bd1 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_handle/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_handle/ya.make
@@ -1,47 +1,47 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
-WITHOUT_LICENSE_TEXTS()
-
-OWNER(
- somov
- g:cpp-contrib
-)
-
-LICENSE(Apache-2.0)
-
-PEERDIR(
- contrib/restricted/abseil-cpp-tstring/y_absl/base
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+WITHOUT_LICENSE_TEXTS()
+
+OWNER(
+ somov
+ g:cpp-contrib
+)
+
+LICENSE(Apache-2.0)
+
+PEERDIR(
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/low_level_alloc
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
- contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
contrib/restricted/abseil-cpp-tstring/y_absl/debugging
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/stacktrace
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize
contrib/restricted/abseil-cpp-tstring/y_absl/demangle
- contrib/restricted/abseil-cpp-tstring/y_absl/numeric
- contrib/restricted/abseil-cpp-tstring/y_absl/strings
+ contrib/restricted/abseil-cpp-tstring/y_absl/numeric
+ contrib/restricted/abseil-cpp-tstring/y_absl/strings
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
contrib/restricted/abseil-cpp-tstring/y_absl/synchronization
contrib/restricted/abseil-cpp-tstring/y_absl/synchronization/internal
contrib/restricted/abseil-cpp-tstring/y_absl/time
contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time
contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone
-)
-
-ADDINCL(
- GLOBAL contrib/restricted/abseil-cpp-tstring
-)
-
-NO_COMPILER_WARNINGS()
-
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/abseil-cpp-tstring
+)
+
+NO_COMPILER_WARNINGS()
+
SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal)
-
-SRCS(
+
+SRCS(
cordz_handle.cc
-)
-
-END()
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_info/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_info/ya.make
index 930eaa8b05..4d749dc50b 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_info/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_info/ya.make
@@ -1,30 +1,30 @@
-# Generated by devtools/yamaker.
-
-LIBRARY()
-
-WITHOUT_LICENSE_TEXTS()
-
-OWNER(
- somov
- g:cpp-contrib
-)
-
-LICENSE(Apache-2.0)
-
-PEERDIR(
- contrib/restricted/abseil-cpp-tstring/y_absl/base
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+WITHOUT_LICENSE_TEXTS()
+
+OWNER(
+ somov
+ g:cpp-contrib
+)
+
+LICENSE(Apache-2.0)
+
+PEERDIR(
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/low_level_alloc
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
- contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
- contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/throw_delegate
+ contrib/restricted/abseil-cpp-tstring/y_absl/base/log_severity
contrib/restricted/abseil-cpp-tstring/y_absl/debugging
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/stacktrace
contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize
contrib/restricted/abseil-cpp-tstring/y_absl/demangle
- contrib/restricted/abseil-cpp-tstring/y_absl/numeric
+ contrib/restricted/abseil-cpp-tstring/y_absl/numeric
contrib/restricted/abseil-cpp-tstring/y_absl/profiling/internal/exponential_biased
- contrib/restricted/abseil-cpp-tstring/y_absl/strings
+ contrib/restricted/abseil-cpp-tstring/y_absl/strings
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_cord_internal
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal
contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/cordz_functions
@@ -34,18 +34,18 @@ PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/time
contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time
contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone
-)
-
-ADDINCL(
- GLOBAL contrib/restricted/abseil-cpp-tstring
-)
-
-NO_COMPILER_WARNINGS()
-
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/abseil-cpp-tstring
+)
+
+NO_COMPILER_WARNINGS()
+
SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal)
-
-SRCS(
+
+SRCS(
cordz_info.cc
-)
-
-END()
+)
+
+END()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
index 12aec3ac11..022633ac82 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/numbers_test_common.h
@@ -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},
}};
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/.yandex_meta/licenses.list.txt
index 33d60b3d2b..95cff783b8 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/.yandex_meta/licenses.list.txt
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/.yandex_meta/licenses.list.txt
@@ -1,20 +1,20 @@
-====================Apache-2.0====================
-// 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====================
-// Copyright 2017 The Abseil Authors.
-
-
-====================COPYRIGHT====================
-// Copyright 2020 The Abseil Authors.
+====================Apache-2.0====================
+// 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====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc
index 8d5c3b61ac..dbd80e7052 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_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,7 +26,7 @@
#include "y_absl/base/port.h"
#include "y_absl/strings/internal/str_format/float_conversion.h"
-#include "y_absl/strings/numbers.h"
+#include "y_absl/strings/numbers.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
@@ -61,179 +61,179 @@ struct IsSigned<y_absl::int128> : std::true_type {};
template <>
struct IsSigned<y_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()) &&
+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 TString &v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(const TString &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) {
@@ -381,99 +381,99 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
}
// ==================== 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(y_absl::int128 v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(y_absl::uint128 v,
- const FormatConversionSpecImpl conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h
index 59b7bcc727..fee261cbe3 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/arg.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_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_
@@ -24,7 +24,7 @@
#include <memory>
#include <sstream>
#include <util/generic/string.h>
-#include <util/stream/str.h>
+#include <util/stream/str.h>
#include <type_traits>
#include "y_absl/base/port.h"
@@ -40,52 +40,52 @@ class Cord;
class FormatCountCapture;
class FormatSink;
-template <y_absl::FormatConversionCharSet C>
-struct FormatConvertResult;
-class FormatConversionSpec;
-
+template <y_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 =
- y_absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
- using FormatSinkT =
- y_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 =
+ y_absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+ using FormatSinkT =
+ y_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;
@@ -96,33 +96,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 TString& v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-StringConvertResult FormatConvertImpl(string_view v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+StringConvertResult FormatConvertImpl(const TString& 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,
@@ -131,17 +131,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, y_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, y_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();
@@ -174,63 +174,63 @@ StringConvertResult FormatConvertImpl(const AbslCord& value,
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);
}
@@ -241,41 +241,41 @@ 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) {
- TString buf;
- TStringOutput oss(buf);
+StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* out) {
+ TString buf;
+ TStringOutput oss(buf);
oss << v.v_;
- if (!buf) return {false};
- return str_format_internal::FormatConvertImpl(buf, conv, out);
+ if (!buf) return {false};
+ return str_format_internal::FormatConvertImpl(buf, conv, out);
}
// Use templates and dependent types to delay evaluation of the function
// 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 y_absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
- if (conv.conversion_char() !=
- str_format_internal::FormatConversionCharInternal::n) {
- return {false};
- }
+ 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);
}
@@ -284,13 +284,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);
}
@@ -301,15 +301,15 @@ struct FormatArgImplFriend {
}
};
-template <typename Arg>
-constexpr FormatConversionCharSet ArgumentToConv() {
- return y_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 y_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:
@@ -323,7 +323,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
@@ -465,20 +465,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;
}
@@ -486,9 +486,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, \
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc
index 211ce25dea..5a62088bff 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_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 "y_absl/strings/internal/str_format/bind.h"
#include <cerrno>
@@ -160,7 +160,7 @@ class SummarizingConverter {
<< 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;
}
@@ -234,7 +234,7 @@ int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
errno = sink.error();
return -1;
}
- if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
+ if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
errno = EFBIG;
return -1;
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h
index 3966610710..f0e73a6db2 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/bind.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_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_
@@ -33,7 +33,7 @@ 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,7 +82,7 @@ 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;
@@ -90,11 +90,11 @@ class FormatSpecTemplate
public:
#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
@@ -133,11 +133,11 @@ class FormatSpecTemplate
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- template <
- FormatConversionCharSet... C,
- typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
- typename = typename std::enable_if<AllOf(Contains(Args,
- C)...)>::type>
+ template <
+ FormatConversionCharSet... C,
+ typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
+ typename = typename std::enable_if<AllOf(Contains(Args,
+ C)...)>::type>
FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
: Base(&pc) {}
};
@@ -204,9 +204,9 @@ 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_;
};
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h
index 7c530d2507..ba3b3d02f3 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/checker.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_CHECKER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
@@ -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)})
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
index f2a4169ae7..13c452cb8e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.cc
@@ -33,40 +33,40 @@ TString FlagsToString(Flags v) {
return s;
}
-#define ABSL_INTERNAL_X_VAL(id) \
- constexpr y_absl::FormatConversionChar FormatConversionCharInternal::id;
-ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
-#undef ABSL_INTERNAL_X_VAL
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr y_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
-
-// 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) {
+#define ABSL_INTERNAL_X_VAL(id) \
+ constexpr y_absl::FormatConversionChar FormatConversionCharInternal::id;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr y_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
+
+// 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;
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
index e5de5cb6a1..1548d56578 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/extension.h
@@ -24,16 +24,16 @@
#include "y_absl/base/config.h"
#include "y_absl/base/port.h"
-#include "y_absl/meta/type_traits.h"
+#include "y_absl/meta/type_traits.h"
#include "y_absl/strings/internal/str_format/output.h"
#include "y_absl/strings/string_view.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-
-enum class FormatConversionChar : uint8_t;
-enum class FormatConversionCharSet : uint64_t;
-
+
+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() {
@@ -158,7 +158,7 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
// clang-format off
#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 \
@@ -167,39 +167,39 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
/* misc */ \
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
-// (y_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
+// 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
+// (y_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
- };
- // 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);
+ kNone
+ };
+ // 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
@@ -207,54 +207,54 @@ inline FormatConversionChar FormatConversionCharFromChar(char c) {
switch (c) {
#define ABSL_INTERNAL_X_VAL(id) \
case #id[0]: \
- return FormatConversionCharInternal::id;
+ return FormatConversionCharInternal::id;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
}
- return FormatConversionCharInternal::kNone;
+ 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;
+ 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;
+ 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) { \
+ 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';
- }
-
+ 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
}
@@ -268,7 +268,7 @@ inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
struct FormatConversionSpecImplFriend;
-class FormatConversionSpecImpl {
+class FormatConversionSpecImpl {
public:
// Width and precison are not specified, no flags are set.
bool is_basic() const { return flags_ == Flags::kBasic; }
@@ -285,7 +285,7 @@ class FormatConversionSpecImpl {
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,65 +296,65 @@ 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;
+ FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
Flags flags_;
int width_;
int precision_;
};
struct FormatConversionSpecImplFriend final {
- static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
+ static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
conv->flags_ = f;
}
static void SetConversionChar(FormatConversionChar c,
- FormatConversionSpecImpl* conv) {
+ FormatConversionSpecImpl* conv) {
conv->conv_ = c;
}
- static void SetWidth(int w, FormatConversionSpecImpl* conv) {
- conv->width_ = w;
- }
- static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
+ static void SetWidth(int w, FormatConversionSpecImpl* conv) {
+ conv->width_ = w;
+ }
+ static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
conv->precision_ = p;
}
- static TString FlagsToString(const FormatConversionSpecImpl& spec) {
+ static TString 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) \
+#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
@@ -363,29 +363,29 @@ constexpr uint64_t FormatConversionCharToConvInt(char conv) {
: 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]);
+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.
@@ -395,29 +395,29 @@ struct FormatConversionCharSetInternal {
// 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);
-}
-
-// Overloaded conversion functions to support y_absl::ParsedFormat.
-// Get a conversion with a single character in it.
-constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
- return static_cast<FormatConversionCharSet>(
- FormatConversionCharToConvValue(c));
+ return FormatConversionCharSetUnion(a, b);
}
+// Overloaded conversion functions to support y_absl::ParsedFormat.
// Get a conversion with a single character in it.
-constexpr FormatConversionCharSet ToFormatConversionCharSet(
- FormatConversionCharSet c) {
- return c;
+constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
+ return static_cast<FormatConversionCharSet>(
+ FormatConversionCharToConvValue(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;
+ return (static_cast<uint64_t>(set) &
+ static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
@@ -427,10 +427,10 @@ constexpr bool Contains(FormatConversionCharSet set,
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) {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
index c49062538d..af48a71cde 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.cc
@@ -1,38 +1,38 @@
-// 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 "y_absl/strings/internal/str_format/float_conversion.h"
#include <string.h>
-
+
#include <algorithm>
#include <cassert>
#include <cmath>
-#include <limits>
+#include <limits>
#include <util/generic/string.h>
-#include "y_absl/base/attributes.h"
+#include "y_absl/base/attributes.h"
#include "y_absl/base/config.h"
-#include "y_absl/base/optimization.h"
-#include "y_absl/functional/function_ref.h"
-#include "y_absl/meta/type_traits.h"
-#include "y_absl/numeric/bits.h"
-#include "y_absl/numeric/int128.h"
-#include "y_absl/numeric/internal/representation.h"
-#include "y_absl/strings/numbers.h"
-#include "y_absl/types/optional.h"
-#include "y_absl/types/span.h"
+#include "y_absl/base/optimization.h"
+#include "y_absl/functional/function_ref.h"
+#include "y_absl/meta/type_traits.h"
+#include "y_absl/numeric/bits.h"
+#include "y_absl/numeric/int128.h"
+#include "y_absl/numeric/internal/representation.h"
+#include "y_absl/strings/numbers.h"
+#include "y_absl/types/optional.h"
+#include "y_absl/types/span.h"
namespace y_absl {
ABSL_NAMESPACE_BEGIN
@@ -40,905 +40,905 @@ namespace str_format_internal {
namespace {
-using ::y_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 = y_absl::FunctionRef<void(y_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(y_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 = y_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.
-//
-// 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,
- y_absl::FunctionRef<void(BinaryToDecimal)> f) {
- assert(exp > 0);
- assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
- static_assert(
- static_cast<int>(StackArray::kMaxCapacity) >=
- ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
- "");
-
- StackArray::RunWithCapacity(
- ChunksNeeded(exp),
- [=](y_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.
- y_absl::string_view CurrentDigits() const {
- return y_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(y_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;
-
- y_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, y_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,
- [=](y_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(y_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_;
- y_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);
- 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, y_absl::string_view data,
- int padding_offset, int trailing_zeros,
- y_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, y_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(y_absl::string_view v, char *out) {
+using ::y_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 = y_absl::FunctionRef<void(y_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(y_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 = y_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.
+//
+// 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,
+ y_absl::FunctionRef<void(BinaryToDecimal)> f) {
+ assert(exp > 0);
+ assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
+ static_assert(
+ static_cast<int>(StackArray::kMaxCapacity) >=
+ ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
+ "");
+
+ StackArray::RunWithCapacity(
+ ChunksNeeded(exp),
+ [=](y_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.
+ y_absl::string_view CurrentDigits() const {
+ return y_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(y_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;
+
+ y_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, y_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,
+ [=](y_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(y_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_;
+ y_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);
+ 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, y_absl::string_view data,
+ int padding_offset, int trailing_zeros,
+ y_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, y_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(y_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;
@@ -951,17 +951,17 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
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));
}
TString space(512, '\0');
- y_absl::string_view result;
+ y_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 = y_absl::string_view(space.data(), n);
+ result = y_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 =
- y_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 =
+ y_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, y_absl::string_view str,
- const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+void WriteBufferToSink(char sign_char, y_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,91 +1329,91 @@ 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,
- y_absl::string_view(buffer.begin, buffer.end - buffer.begin),
- conv, sink);
+ y_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);
- }
-
+ 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 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);
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h
index d93a415756..44e8ee2da2 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/float_conversion.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_FLOAT_CONVERSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
@@ -21,13 +21,13 @@ namespace y_absl {
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
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
index 8fc46fbafa..ae997ae7f7 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/output.h
@@ -82,11 +82,11 @@ 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
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc
index af07e32fe5..c48cdc9ea3 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_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 "y_absl/strings/internal/str_format/parser.h"
#include <assert.h>
@@ -31,7 +31,7 @@ namespace y_absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-using CC = FormatConversionCharInternal;
+using CC = FormatConversionCharInternal;
using LM = LengthMod;
// Abbreviations to fit in the table below.
@@ -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() ||
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h
index ba614bb8b4..4fcdc28c5f 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/parser.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_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_
@@ -78,7 +78,7 @@ struct UnboundConversion {
Flags flags = Flags::kBasic;
LengthMod length_mod = LengthMod::none;
- FormatConversionChar conv = FormatConversionCharInternal::kNone;
+ FormatConversionChar conv = FormatConversionCharInternal::kNone;
};
// Consume conversion spec prefix (not including '%') of [p, end) if valid.
@@ -94,7 +94,7 @@ const char* ConsumeUnboundConversion(const char* p, const char* end,
// 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
: tag_(0x80 | static_cast<uint8_t>(length_mod)) {}
@@ -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
__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
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
index ff8069cd0f..2c855146e6 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_format/ya.make
@@ -2,15 +2,15 @@
LIBRARY()
-OWNER(
- somov
- g:cpp-contrib
-)
+OWNER(
+ somov
+ g:cpp-contrib
+)
LICENSE(Apache-2.0)
-LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
index 237864c0ed..874f6f1d45 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/str_split_internal.h
@@ -51,9 +51,9 @@ ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// This class is implicitly constructible from everything that y_absl::string_view
-// is implicitly constructible from, except for rvalue strings. This means it
-// can be used as a function parameter in places where passing a temporary
-// string might cause memory lifetime issues.
+// is implicitly constructible from, except for rvalue strings. This means it
+// can be used as a function parameter in places where passing a temporary
+// string might cause memory lifetime issues.
class ConvertibleToStringView {
public:
ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit)
@@ -65,8 +65,8 @@ class ConvertibleToStringView {
: value_(s) {}
// Disable conversion from rvalue strings.
- ConvertibleToStringView(TString&& s) = delete;
- ConvertibleToStringView(const TString&& s) = delete;
+ ConvertibleToStringView(TString&& s) = delete;
+ ConvertibleToStringView(const TString&& s) = delete;
y_absl::string_view value() const { return value_; }
@@ -251,11 +251,11 @@ struct SplitterIsConvertibleTo
// the split strings: only strings for which the predicate returns true will be
// kept. A Predicate object is any unary functor that takes an y_absl::string_view
// and returns bool.
-//
-// The StringType parameter can be either string_view or string, depending on
-// whether the Splitter refers to a string stored elsewhere, or if the string
-// resides inside the Splitter itself.
-template <typename Delimiter, typename Predicate, typename StringType>
+//
+// The StringType parameter can be either string_view or string, depending on
+// whether the Splitter refers to a string stored elsewhere, or if the string
+// resides inside the Splitter itself.
+template <typename Delimiter, typename Predicate, typename StringType>
class Splitter {
public:
using DelimiterType = Delimiter;
@@ -263,12 +263,12 @@ class Splitter {
using const_iterator = strings_internal::SplitIterator<Splitter>;
using value_type = typename std::iterator_traits<const_iterator>::value_type;
- Splitter(StringType input_text, Delimiter d, Predicate p)
+ Splitter(StringType input_text, Delimiter d, Predicate p)
: text_(std::move(input_text)),
delimiter_(std::move(d)),
predicate_(std::move(p)) {}
- y_absl::string_view text() const { return text_; }
+ y_absl::string_view text() const { return text_; }
const Delimiter& delimiter() const { return delimiter_; }
const Predicate& predicate() const { return predicate_; }
@@ -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;
@@ -418,7 +418,7 @@ class Splitter {
static iterator ToIter(iterator iter) { return iter; }
};
- StringType text_;
+ StringType text_;
Delimiter delimiter_;
Predicate predicate_;
};
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/string_constant.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/string_constant.h
index b18e821b49..df4fc0357e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/string_constant.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/string_constant.h
@@ -1,64 +1,64 @@
-// 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_STRING_CONSTANT_H_
-#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
-
-#include "y_absl/meta/type_traits.h"
-#include "y_absl/strings/string_view.h"
-
-namespace y_absl {
-ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-// StringConstant<T> represents a compile time string constant.
-// It can be accessed via its `y_absl::string_view value` static member.
-// It is guaranteed that the `string_view` returned has constant `.data()`,
-// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
-//
-// The `T` is an opaque type. It is guaranteed that different string constants
-// will have different values of `T`. This allows users to associate the string
-// constant with other static state at compile time.
-//
-// Instances should be made using the `MakeStringConstant()` factory function
-// below.
-template <typename T>
-struct StringConstant {
- static constexpr y_absl::string_view value = T{}();
- constexpr y_absl::string_view operator()() const { return value; }
-
- // Check to be sure `view` points to constant data.
- // Otherwise, it can't be constant evaluated.
- static_assert(value.empty() || 2 * value[0] != 1,
- "The input string_view must point to constant data.");
-};
-
-template <typename T>
-constexpr y_absl::string_view StringConstant<T>::value; // NOLINT
-
-// Factory function for `StringConstant` instances.
-// It supports callables that have a constexpr default constructor and a
-// constexpr operator().
-// It must return an `y_absl::string_view` or `const char*` pointing to constant
-// data. This is validated at compile time.
-template <typename T>
-constexpr StringConstant<T> MakeStringConstant(T) {
- return {};
-}
-
-} // namespace strings_internal
-ABSL_NAMESPACE_END
-} // namespace y_absl
-
-#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_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_STRING_CONSTANT_H_
+#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+
+#include "y_absl/meta/type_traits.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// StringConstant<T> represents a compile time string constant.
+// It can be accessed via its `y_absl::string_view value` static member.
+// It is guaranteed that the `string_view` returned has constant `.data()`,
+// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
+//
+// The `T` is an opaque type. It is guaranteed that different string constants
+// will have different values of `T`. This allows users to associate the string
+// constant with other static state at compile time.
+//
+// Instances should be made using the `MakeStringConstant()` factory function
+// below.
+template <typename T>
+struct StringConstant {
+ static constexpr y_absl::string_view value = T{}();
+ constexpr y_absl::string_view operator()() const { return value; }
+
+ // Check to be sure `view` points to constant data.
+ // Otherwise, it can't be constant evaluated.
+ static_assert(value.empty() || 2 * value[0] != 1,
+ "The input string_view must point to constant data.");
+};
+
+template <typename T>
+constexpr y_absl::string_view StringConstant<T>::value; // NOLINT
+
+// Factory function for `StringConstant` instances.
+// It supports callables that have a constexpr default constructor and a
+// constexpr operator().
+// It must return an `y_absl::string_view` or `const char*` pointing to constant
+// data. This is validated at compile time.
+template <typename T>
+constexpr StringConstant<T> MakeStringConstant(T) {
+ return {};
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
index 3197bdf432..d60b195954 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.cc
@@ -19,22 +19,22 @@
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-bool EqualsIgnoreCase(y_absl::string_view piece1,
- y_absl::string_view piece2) noexcept {
+bool EqualsIgnoreCase(y_absl::string_view piece1,
+ y_absl::string_view piece2) noexcept {
return (piece1.size() == piece2.size() &&
0 == y_absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
piece1.size()));
// memcasecmp uses y_absl::ascii_tolower().
}
-bool StartsWithIgnoreCase(y_absl::string_view text,
- y_absl::string_view prefix) noexcept {
+bool StartsWithIgnoreCase(y_absl::string_view text,
+ y_absl::string_view prefix) noexcept {
return (text.size() >= prefix.size()) &&
EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
}
-bool EndsWithIgnoreCase(y_absl::string_view text,
- y_absl::string_view suffix) noexcept {
+bool EndsWithIgnoreCase(y_absl::string_view text,
+ y_absl::string_view suffix) noexcept {
return (text.size() >= suffix.size()) &&
EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
index 4709abc93f..65f0f439d0 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/match.h
@@ -43,20 +43,20 @@ ABSL_NAMESPACE_BEGIN
// StrContains()
//
// Returns whether a given string `haystack` contains the substring `needle`.
-inline bool StrContains(y_absl::string_view haystack,
- y_absl::string_view needle) noexcept {
+inline bool StrContains(y_absl::string_view haystack,
+ y_absl::string_view needle) noexcept {
return haystack.find(needle, 0) != haystack.npos;
}
-inline bool StrContains(y_absl::string_view haystack, char needle) noexcept {
- return haystack.find(needle) != haystack.npos;
-}
-
+inline bool StrContains(y_absl::string_view haystack, char needle) noexcept {
+ return haystack.find(needle) != haystack.npos;
+}
+
// StartsWith()
//
// Returns whether a given string `text` begins with `prefix`.
-inline bool StartsWith(y_absl::string_view text,
- y_absl::string_view prefix) noexcept {
+inline bool StartsWith(y_absl::string_view text,
+ y_absl::string_view prefix) noexcept {
return prefix.empty() ||
(text.size() >= prefix.size() &&
memcmp(text.data(), prefix.data(), prefix.size()) == 0);
@@ -65,8 +65,8 @@ inline bool StartsWith(y_absl::string_view text,
// EndsWith()
//
// Returns whether a given string `text` ends with `suffix`.
-inline bool EndsWith(y_absl::string_view text,
- y_absl::string_view suffix) noexcept {
+inline bool EndsWith(y_absl::string_view text,
+ y_absl::string_view suffix) noexcept {
return suffix.empty() ||
(text.size() >= suffix.size() &&
memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
@@ -77,22 +77,22 @@ inline bool EndsWith(y_absl::string_view text,
//
// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
// case in the comparison.
-bool EqualsIgnoreCase(y_absl::string_view piece1,
- y_absl::string_view piece2) noexcept;
+bool EqualsIgnoreCase(y_absl::string_view piece1,
+ y_absl::string_view piece2) noexcept;
// StartsWithIgnoreCase()
//
// Returns whether a given ASCII string `text` starts with `prefix`,
// ignoring case in the comparison.
-bool StartsWithIgnoreCase(y_absl::string_view text,
- y_absl::string_view prefix) noexcept;
+bool StartsWithIgnoreCase(y_absl::string_view text,
+ y_absl::string_view prefix) noexcept;
// EndsWithIgnoreCase()
//
// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
// case in the comparison.
-bool EndsWithIgnoreCase(y_absl::string_view text,
- y_absl::string_view suffix) noexcept;
+bool EndsWithIgnoreCase(y_absl::string_view text,
+ y_absl::string_view suffix) noexcept;
ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
index 528d044fa6..fa7797a415 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.cc
@@ -32,7 +32,7 @@
#include "y_absl/base/attributes.h"
#include "y_absl/base/internal/raw_logging.h"
-#include "y_absl/numeric/bits.h"
+#include "y_absl/numeric/bits.h"
#include "y_absl/strings/ascii.h"
#include "y_absl/strings/charconv.h"
#include "y_absl/strings/escaping.h"
@@ -46,13 +46,13 @@ ABSL_NAMESPACE_BEGIN
bool SimpleAtof(y_absl::string_view str, float* out) {
*out = 0.0;
str = StripAsciiWhitespace(str);
- // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
- // is present, skip it, while avoiding accepting "+-0" as valid.
+ // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
- if (!str.empty() && str[0] == '-') {
- return false;
- }
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
auto result = y_absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
@@ -77,13 +77,13 @@ bool SimpleAtof(y_absl::string_view str, float* out) {
bool SimpleAtod(y_absl::string_view str, double* out) {
*out = 0.0;
str = StripAsciiWhitespace(str);
- // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
- // is present, skip it, while avoiding accepting "+-0" as valid.
+ // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
- if (!str.empty() && str[0] == '-') {
- return false;
- }
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
auto result = y_absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
@@ -313,7 +313,7 @@ static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,
uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
if (bits128_up == 0) return {bits64_127, bits0_63};
- auto shift = static_cast<unsigned>(bit_width(bits128_up));
+ auto shift = static_cast<unsigned>(bit_width(bits128_up));
uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
return {hi, lo};
@@ -344,7 +344,7 @@ static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
result = Mul32(result, powers_of_five[expfive & 15]);
- int shift = countl_zero(result.first);
+ int shift = countl_zero(result.first);
if (shift != 0) {
result.first = (result.first << shift) + (result.second >> (64 - shift));
result.second = (result.second << shift);
@@ -746,18 +746,18 @@ struct LookupTables {
X / 35, X / 36, \
}
-// This kVmaxOverBase is generated with
-// for (int base = 2; base < 37; ++base) {
-// y_absl::uint128 max = std::numeric_limits<y_absl::uint128>::max();
-// auto result = max / base;
-// std::cout << " MakeUint128(" << y_absl::Uint128High64(result) << "u, "
-// << y_absl::Uint128Low64(result) << "u),\n";
-// }
-// See https://godbolt.org/z/aneYsb
-//
+// This kVmaxOverBase is generated with
+// for (int base = 2; base < 37; ++base) {
+// y_absl::uint128 max = std::numeric_limits<y_absl::uint128>::max();
+// auto result = max / base;
+// std::cout << " MakeUint128(" << y_absl::Uint128High64(result) << "u, "
+// << y_absl::Uint128Low64(result) << "u),\n";
+// }
+// See https://godbolt.org/z/aneYsb
+//
// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
// array to avoid a static initializer.
-template<>
+template<>
const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
0,
0,
@@ -798,111 +798,111 @@ const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
MakeUint128(512409557603043100u, 8198552921648689607u),
};
-// This kVmaxOverBase generated with
-// for (int base = 2; base < 37; ++base) {
-// y_absl::int128 max = std::numeric_limits<y_absl::int128>::max();
-// auto result = max / base;
-// std::cout << "\tMakeInt128(" << y_absl::Int128High64(result) << ", "
-// << y_absl::Int128Low64(result) << "u),\n";
-// }
-// See https://godbolt.org/z/7djYWz
-//
-// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
-// to avoid a static initializer.
-template<>
-const int128 LookupTables<int128>::kVmaxOverBase[] = {
- 0,
- 0,
- MakeInt128(4611686018427387903, 18446744073709551615u),
- MakeInt128(3074457345618258602, 12297829382473034410u),
- MakeInt128(2305843009213693951, 18446744073709551615u),
- MakeInt128(1844674407370955161, 11068046444225730969u),
- MakeInt128(1537228672809129301, 6148914691236517205u),
- MakeInt128(1317624576693539401, 2635249153387078802u),
- MakeInt128(1152921504606846975, 18446744073709551615u),
- MakeInt128(1024819115206086200, 16397105843297379214u),
- MakeInt128(922337203685477580, 14757395258967641292u),
- MakeInt128(838488366986797800, 13415813871788764811u),
- MakeInt128(768614336404564650, 12297829382473034410u),
- MakeInt128(709490156681136600, 11351842506898185609u),
- MakeInt128(658812288346769700, 10540996613548315209u),
- MakeInt128(614891469123651720, 9838263505978427528u),
- MakeInt128(576460752303423487, 18446744073709551615u),
- MakeInt128(542551296285575047, 9765923333140350855u),
- MakeInt128(512409557603043100, 8198552921648689607u),
- MakeInt128(485440633518672410, 17475862806672206794u),
- MakeInt128(461168601842738790, 7378697629483820646u),
- MakeInt128(439208192231179800, 7027331075698876806u),
- MakeInt128(419244183493398900, 6707906935894382405u),
- MakeInt128(401016175515425035, 2406097053092550210u),
- MakeInt128(384307168202282325, 6148914691236517205u),
- MakeInt128(368934881474191032, 5902958103587056517u),
- MakeInt128(354745078340568300, 5675921253449092804u),
- MakeInt128(341606371735362066, 17763531330238827482u),
- MakeInt128(329406144173384850, 5270498306774157604u),
- MakeInt128(318047311615681924, 7633135478776366185u),
- MakeInt128(307445734561825860, 4919131752989213764u),
- MakeInt128(297528130221121800, 4760450083537948804u),
- MakeInt128(288230376151711743, 18446744073709551615u),
- MakeInt128(279496122328932600, 4471937957262921603u),
- MakeInt128(271275648142787523, 14106333703424951235u),
- MakeInt128(263524915338707880, 4216398645419326083u),
- MakeInt128(256204778801521550, 4099276460824344803u),
-};
-
-// This kVminOverBase generated with
-// for (int base = 2; base < 37; ++base) {
-// y_absl::int128 min = std::numeric_limits<y_absl::int128>::min();
-// auto result = min / base;
-// std::cout << "\tMakeInt128(" << y_absl::Int128High64(result) << ", "
-// << y_absl::Int128Low64(result) << "u),\n";
-// }
-//
-// See https://godbolt.org/z/7djYWz
-//
-// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
-// to avoid a static initializer.
-template<>
-const int128 LookupTables<int128>::kVminOverBase[] = {
- 0,
- 0,
- MakeInt128(-4611686018427387904, 0u),
- MakeInt128(-3074457345618258603, 6148914691236517206u),
- MakeInt128(-2305843009213693952, 0u),
- MakeInt128(-1844674407370955162, 7378697629483820647u),
- MakeInt128(-1537228672809129302, 12297829382473034411u),
- MakeInt128(-1317624576693539402, 15811494920322472814u),
- MakeInt128(-1152921504606846976, 0u),
- MakeInt128(-1024819115206086201, 2049638230412172402u),
- MakeInt128(-922337203685477581, 3689348814741910324u),
- MakeInt128(-838488366986797801, 5030930201920786805u),
- MakeInt128(-768614336404564651, 6148914691236517206u),
- MakeInt128(-709490156681136601, 7094901566811366007u),
- MakeInt128(-658812288346769701, 7905747460161236407u),
- MakeInt128(-614891469123651721, 8608480567731124088u),
- MakeInt128(-576460752303423488, 0u),
- MakeInt128(-542551296285575048, 8680820740569200761u),
- MakeInt128(-512409557603043101, 10248191152060862009u),
- MakeInt128(-485440633518672411, 970881267037344822u),
- MakeInt128(-461168601842738791, 11068046444225730970u),
- MakeInt128(-439208192231179801, 11419412998010674810u),
- MakeInt128(-419244183493398901, 11738837137815169211u),
- MakeInt128(-401016175515425036, 16040647020617001406u),
- MakeInt128(-384307168202282326, 12297829382473034411u),
- MakeInt128(-368934881474191033, 12543785970122495099u),
- MakeInt128(-354745078340568301, 12770822820260458812u),
- MakeInt128(-341606371735362067, 683212743470724134u),
- MakeInt128(-329406144173384851, 13176245766935394012u),
- MakeInt128(-318047311615681925, 10813608594933185431u),
- MakeInt128(-307445734561825861, 13527612320720337852u),
- MakeInt128(-297528130221121801, 13686293990171602812u),
- MakeInt128(-288230376151711744, 0u),
- MakeInt128(-279496122328932601, 13974806116446630013u),
- MakeInt128(-271275648142787524, 4340410370284600381u),
- MakeInt128(-263524915338707881, 14230345428290225533u),
- MakeInt128(-256204778801521551, 14347467612885206813u),
-};
-
+// This kVmaxOverBase generated with
+// for (int base = 2; base < 37; ++base) {
+// y_absl::int128 max = std::numeric_limits<y_absl::int128>::max();
+// auto result = max / base;
+// std::cout << "\tMakeInt128(" << y_absl::Int128High64(result) << ", "
+// << y_absl::Int128Low64(result) << "u),\n";
+// }
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVmaxOverBase[] = {
+ 0,
+ 0,
+ MakeInt128(4611686018427387903, 18446744073709551615u),
+ MakeInt128(3074457345618258602, 12297829382473034410u),
+ MakeInt128(2305843009213693951, 18446744073709551615u),
+ MakeInt128(1844674407370955161, 11068046444225730969u),
+ MakeInt128(1537228672809129301, 6148914691236517205u),
+ MakeInt128(1317624576693539401, 2635249153387078802u),
+ MakeInt128(1152921504606846975, 18446744073709551615u),
+ MakeInt128(1024819115206086200, 16397105843297379214u),
+ MakeInt128(922337203685477580, 14757395258967641292u),
+ MakeInt128(838488366986797800, 13415813871788764811u),
+ MakeInt128(768614336404564650, 12297829382473034410u),
+ MakeInt128(709490156681136600, 11351842506898185609u),
+ MakeInt128(658812288346769700, 10540996613548315209u),
+ MakeInt128(614891469123651720, 9838263505978427528u),
+ MakeInt128(576460752303423487, 18446744073709551615u),
+ MakeInt128(542551296285575047, 9765923333140350855u),
+ MakeInt128(512409557603043100, 8198552921648689607u),
+ MakeInt128(485440633518672410, 17475862806672206794u),
+ MakeInt128(461168601842738790, 7378697629483820646u),
+ MakeInt128(439208192231179800, 7027331075698876806u),
+ MakeInt128(419244183493398900, 6707906935894382405u),
+ MakeInt128(401016175515425035, 2406097053092550210u),
+ MakeInt128(384307168202282325, 6148914691236517205u),
+ MakeInt128(368934881474191032, 5902958103587056517u),
+ MakeInt128(354745078340568300, 5675921253449092804u),
+ MakeInt128(341606371735362066, 17763531330238827482u),
+ MakeInt128(329406144173384850, 5270498306774157604u),
+ MakeInt128(318047311615681924, 7633135478776366185u),
+ MakeInt128(307445734561825860, 4919131752989213764u),
+ MakeInt128(297528130221121800, 4760450083537948804u),
+ MakeInt128(288230376151711743, 18446744073709551615u),
+ MakeInt128(279496122328932600, 4471937957262921603u),
+ MakeInt128(271275648142787523, 14106333703424951235u),
+ MakeInt128(263524915338707880, 4216398645419326083u),
+ MakeInt128(256204778801521550, 4099276460824344803u),
+};
+
+// This kVminOverBase generated with
+// for (int base = 2; base < 37; ++base) {
+// y_absl::int128 min = std::numeric_limits<y_absl::int128>::min();
+// auto result = min / base;
+// std::cout << "\tMakeInt128(" << y_absl::Int128High64(result) << ", "
+// << y_absl::Int128Low64(result) << "u),\n";
+// }
+//
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVminOverBase[] = {
+ 0,
+ 0,
+ MakeInt128(-4611686018427387904, 0u),
+ MakeInt128(-3074457345618258603, 6148914691236517206u),
+ MakeInt128(-2305843009213693952, 0u),
+ MakeInt128(-1844674407370955162, 7378697629483820647u),
+ MakeInt128(-1537228672809129302, 12297829382473034411u),
+ MakeInt128(-1317624576693539402, 15811494920322472814u),
+ MakeInt128(-1152921504606846976, 0u),
+ MakeInt128(-1024819115206086201, 2049638230412172402u),
+ MakeInt128(-922337203685477581, 3689348814741910324u),
+ MakeInt128(-838488366986797801, 5030930201920786805u),
+ MakeInt128(-768614336404564651, 6148914691236517206u),
+ MakeInt128(-709490156681136601, 7094901566811366007u),
+ MakeInt128(-658812288346769701, 7905747460161236407u),
+ MakeInt128(-614891469123651721, 8608480567731124088u),
+ MakeInt128(-576460752303423488, 0u),
+ MakeInt128(-542551296285575048, 8680820740569200761u),
+ MakeInt128(-512409557603043101, 10248191152060862009u),
+ MakeInt128(-485440633518672411, 970881267037344822u),
+ MakeInt128(-461168601842738791, 11068046444225730970u),
+ MakeInt128(-439208192231179801, 11419412998010674810u),
+ MakeInt128(-419244183493398901, 11738837137815169211u),
+ MakeInt128(-401016175515425036, 16040647020617001406u),
+ MakeInt128(-384307168202282326, 12297829382473034411u),
+ MakeInt128(-368934881474191033, 12543785970122495099u),
+ MakeInt128(-354745078340568301, 12770822820260458812u),
+ MakeInt128(-341606371735362067, 683212743470724134u),
+ MakeInt128(-329406144173384851, 13176245766935394012u),
+ MakeInt128(-318047311615681925, 10813608594933185431u),
+ MakeInt128(-307445734561825861, 13527612320720337852u),
+ MakeInt128(-297528130221121801, 13686293990171602812u),
+ MakeInt128(-288230376151711744, 0u),
+ MakeInt128(-279496122328932601, 13974806116446630013u),
+ MakeInt128(-271275648142787524, 4340410370284600381u),
+ MakeInt128(-263524915338707881, 14230345428290225533u),
+ MakeInt128(-256204778801521551, 14347467612885206813u),
+};
+
template <typename IntType>
const IntType LookupTables<IntType>::kVmaxOverBase[] =
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -1072,10 +1072,10 @@ bool safe_strto64_base(y_absl::string_view text, int64_t* value, int base) {
return safe_int_internal<int64_t>(text, value, base);
}
-bool safe_strto128_base(y_absl::string_view text, int128* value, int base) {
- return safe_int_internal<y_absl::int128>(text, value, base);
-}
-
+bool safe_strto128_base(y_absl::string_view text, int128* value, int base) {
+ return safe_int_internal<y_absl::int128>(text, value, base);
+}
+
bool safe_strtou32_base(y_absl::string_view text, uint32_t* value, int base) {
return safe_uint_internal<uint32_t>(text, value, base);
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
index ce181d8eb1..b65ab85904 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/numbers.h
@@ -54,7 +54,7 @@
#endif
#include "y_absl/base/macros.h"
#include "y_absl/base/port.h"
-#include "y_absl/numeric/bits.h"
+#include "y_absl/numeric/bits.h"
#include "y_absl/numeric/int128.h"
#include "y_absl/strings/string_view.h"
@@ -151,11 +151,11 @@ inline void PutTwoDigits(size_t i, char* buf) {
}
// safe_strto?() functions for implementing SimpleAtoi()
-
+
bool safe_strto32_base(y_absl::string_view text, int32_t* value, int base);
bool safe_strto64_base(y_absl::string_view text, int64_t* value, int base);
-bool safe_strto128_base(y_absl::string_view text, y_absl::int128* value,
- int base);
+bool safe_strto128_base(y_absl::string_view text, y_absl::int128* value,
+ int base);
bool safe_strtou32_base(y_absl::string_view text, uint32_t* value, int base);
bool safe_strtou64_base(y_absl::string_view text, uint64_t* value, int base);
bool safe_strtou128_base(y_absl::string_view text, y_absl::uint128* value,
@@ -267,7 +267,7 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
}
#endif
// | 0x1 so that even 0 has 1 digit.
- return 16 - countl_zero(val | 0x1) / 4;
+ return 16 - countl_zero(val | 0x1) / 4;
}
} // namespace numbers_internal
@@ -278,11 +278,11 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(y_absl::string_view str, int_type* out) {
}
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
- y_absl::int128* out) {
- return numbers_internal::safe_strto128_base(str, out, 10);
-}
-
-ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
+ y_absl::int128* out) {
+ return numbers_internal::safe_strto128_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(y_absl::string_view str,
y_absl::uint128* out) {
return numbers_internal::safe_strtou128_base(str, out, 10);
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
index 9e11702eae..9b154a60b8 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.cc
@@ -141,12 +141,12 @@ namespace strings_internal {
TString CatPieces(std::initializer_list<y_absl::string_view> pieces) {
TString result;
size_t total_size = 0;
- for (const y_absl::string_view& piece : pieces) total_size += piece.size();
+ for (const y_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 y_absl::string_view& piece : pieces) {
+ for (const y_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(TString* dest,
std::initializer_list<y_absl::string_view> pieces) {
size_t old_size = dest->size();
size_t total_size = old_size;
- for (const y_absl::string_view& piece : pieces) {
+ for (const y_absl::string_view& piece : pieces) {
ASSERT_NO_OVERLAP(*dest, piece);
total_size += piece.size();
}
@@ -178,7 +178,7 @@ void AppendPieces(TString* dest,
char* const begin = &(*dest)[0];
char* out = begin + old_size;
- for (const y_absl::string_view& piece : pieces) {
+ for (const y_absl::string_view& piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
index a77c9ae906..9322fdf3d5 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_cat.h
@@ -256,7 +256,7 @@ class AlphaNum {
AlphaNum(const TString& str)
: piece_(str.data(), str.size()) {}
- // 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;
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h
index 4079f38fb4..82e9902202 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_format.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_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_
@@ -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
-// `y_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 `y_absl::FormatConversionCharSet::kIntegral`.
-//
-// Example:
-// // Extended format supports multiple conversion characters per argument,
-// // specified via a combination of `FormatConversionCharSet` enums.
-// using MyFormat = y_absl::ParsedFormat<y_absl::FormatConversionCharSet::d |
-// y_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 = y_absl::str_format_internal::ExtendedParsedFormat<
- y_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
+// `y_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 `y_absl::FormatConversionCharSet::kIntegral`.
+//
+// Example:
+// // Extended format supports multiple conversion characters per argument,
+// // specified via a combination of `FormatConversionCharSet` enums.
+// using MyFormat = y_absl::ParsedFormat<y_absl::FormatConversionCharSet::d |
+// y_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 = y_absl::str_format_internal::ExtendedParsedFormat<
+ y_absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#else
template <char... Conv>
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
- y_absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
-#endif // defined(__cpp_nontype_template_parameter_auto)
+ y_absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#endif // defined(__cpp_nontype_template_parameter_auto)
// StrFormat()
//
@@ -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, y_absl::string_view part);
-//
-// where `dest` is the pointer passed to `y_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, y_absl::string_view part);
+//
+// where `dest` is the pointer passed to `y_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 {
// `y_absl::FormatRawSink` interface), using a format string and zero or more
// additional arguments.
//
-// By default, `TString`, `std::ostream`, and `y_absl::Cord` are supported as
-// destination objects. If a `TString` is used the formatted string is
-// appended to it.
+// By default, `TString`, `std::ostream`, and `y_absl::Cord` are supported as
+// destination objects. If a `TString` is used the formatted string is
+// appended to it.
//
-// `y_absl::Format()` is a generic version of `y_absl::StrAppendFormat()`, for
-// custom sinks. The format string, like format strings for `StrFormat()`, is
-// checked at compile-time.
+// `y_absl::Format()` is a generic version of `y_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,246 +566,246 @@ 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 y_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:
-//
-// y_absl::FormatConvertResult<...> AbslFormatConvert(
-// const X& value,
-// const y_absl::FormatConversionSpec& spec,
-// y_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 `y_absl::FormatConversionSpec` to specify the fields to pull from a
-// user-defined type's format string
-// * An `y_absl::FormatSink` to hold the converted string data during the
-// conversion process.
-// * An `y_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 y_absl::FormatConvertResult<y_absl::FormatConversionCharSet::kString |
-// y_absl::FormatConversionCharSet::kIntegral>
-// AbslFormatConvert(const Point& p, const y_absl::FormatConversionSpec& spec,
-// y_absl::FormatSink* s) {
-// if (spec.conversion_char() == y_absl::FormatConversionChar::s) {
-// s->Append(y_absl::StrCat("x=", p.x, " y=", p.y));
-// } else {
-// s->Append(y_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;
-
- y_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>(
- y_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;
-};
-
+//------------------------------------------------------------------------------
+// StrFormat Extensions
+//------------------------------------------------------------------------------
+//
+// AbslFormatConvert()
+//
+// The StrFormat library provides a customization API for formatting
+// user-defined types using y_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:
+//
+// y_absl::FormatConvertResult<...> AbslFormatConvert(
+// const X& value,
+// const y_absl::FormatConversionSpec& spec,
+// y_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 `y_absl::FormatConversionSpec` to specify the fields to pull from a
+// user-defined type's format string
+// * An `y_absl::FormatSink` to hold the converted string data during the
+// conversion process.
+// * An `y_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 y_absl::FormatConvertResult<y_absl::FormatConversionCharSet::kString |
+// y_absl::FormatConversionCharSet::kIntegral>
+// AbslFormatConvert(const Point& p, const y_absl::FormatConversionSpec& spec,
+// y_absl::FormatSink* s) {
+// if (spec.conversion_char() == y_absl::FormatConversionChar::s) {
+// s->Append(y_absl::StrCat("x=", p.x, " y=", p.y));
+// } else {
+// s->Append(y_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;
+
+ y_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>(
+ y_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 y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
index 46a0323c6e..b362d5a24d 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_join.h
@@ -144,7 +144,7 @@ strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
std::forward<Formatter>(f));
}
-// Function overload of `DereferenceFormatter()` for using a default
+// Function overload of `DereferenceFormatter()` for using a default
// `AlphaNumFormatter()`.
inline strings_internal::DereferenceFormatterImpl<
strings_internal::AlphaNumFormatterImpl>
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
index 5f9193e6ba..eb0228ac1b 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.cc
@@ -42,7 +42,7 @@ y_absl::string_view GenericFind(y_absl::string_view text,
y_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
// y_absl::string_view referring to the item at position 1 past pos.
return y_absl::string_view(text.data() + pos + 1, 0);
}
@@ -127,7 +127,7 @@ y_absl::string_view ByLength::Find(y_absl::string_view text,
size_t pos) const {
pos = std::min(pos, text.size()); // truncate `pos`
y_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 y_absl::string_view(text.data() + text.size(), 0);
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
index d32d54813e..35df211020 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/str_split.h
@@ -44,7 +44,7 @@
#include <vector>
#include "y_absl/base/internal/raw_logging.h"
-#include "y_absl/base/macros.h"
+#include "y_absl/base/macros.h"
#include "y_absl/strings/internal/str_split_internal.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
@@ -369,12 +369,12 @@ struct SkipWhitespace {
}
};
-template <typename T>
-using EnableSplitIfString =
- typename std::enable_if<std::is_same<T, TString>::value ||
- std::is_same<T, const TString>::value,
- int>::type;
-
+template <typename T>
+using EnableSplitIfString =
+ typename std::enable_if<std::is_same<T, TString>::value ||
+ std::is_same<T, const TString>::value,
+ int>::type;
+
//------------------------------------------------------------------------------
// StrSplit()
//------------------------------------------------------------------------------
@@ -495,50 +495,50 @@ using EnableSplitIfString =
// Try not to depend on this distinction because the bug may one day be fixed.
template <typename Delimiter>
strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
- y_absl::string_view>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+ y_absl::string_view>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, AllowEmpty,
- y_absl::string_view>(
- text.value(), DelimiterType(d), AllowEmpty());
-}
-
-template <typename Delimiter, typename StringType,
- EnableSplitIfString<StringType> = 0>
-strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
- TString>
-StrSplit(StringType&& text, Delimiter d) {
- using DelimiterType =
- typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, AllowEmpty, TString>(
+ return strings_internal::Splitter<DelimiterType, AllowEmpty,
+ y_absl::string_view>(
+ text.value(), DelimiterType(d), AllowEmpty());
+}
+
+template <typename Delimiter, typename StringType,
+ EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+ typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+ TString>
+StrSplit(StringType&& text, Delimiter d) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
+ return strings_internal::Splitter<DelimiterType, AllowEmpty, TString>(
std::move(text), DelimiterType(d), AllowEmpty());
}
template <typename Delimiter, typename Predicate>
strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
- y_absl::string_view>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+ y_absl::string_view>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
Predicate p) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, Predicate,
- y_absl::string_view>(
- text.value(), DelimiterType(d), std::move(p));
-}
-
-template <typename Delimiter, typename Predicate, typename StringType,
- EnableSplitIfString<StringType> = 0>
-strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
- TString>
-StrSplit(StringType&& text, Delimiter d, Predicate p) {
- using DelimiterType =
- typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, Predicate, TString>(
+ return strings_internal::Splitter<DelimiterType, Predicate,
+ y_absl::string_view>(
+ text.value(), DelimiterType(d), std::move(p));
+}
+
+template <typename Delimiter, typename Predicate, typename StringType,
+ EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+ typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+ TString>
+StrSplit(StringType&& text, Delimiter d, Predicate p) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
+ return strings_internal::Splitter<DelimiterType, Predicate, TString>(
std::move(text), DelimiterType(d), std::move(p));
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
index c3906fe1c5..447e0f0dcd 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/string_view.h
@@ -49,7 +49,7 @@
namespace y_absl {
ABSL_NAMESPACE_BEGIN
-using string_view = std::string_view;
+using string_view = std::string_view;
ABSL_NAMESPACE_END
} // namespace y_absl
@@ -120,11 +120,11 @@ ABSL_NAMESPACE_BEGIN
// example, when splitting a string, `std::vector<y_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.
-//
+// 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
@@ -297,7 +297,7 @@ 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];
+ return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
}
// string_view::at()
@@ -317,14 +317,14 @@ class string_view {
//
// Returns the first element of a `string_view`.
constexpr const_reference front() const {
- return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+ 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];
+ return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
}
// string_view::data()
@@ -333,7 +333,7 @@ class string_view {
// 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.
+ // 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 y_absl::ClippedSubstr if you need a truncating substr operation.
+ // Use y_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(
- "y_absl::string_view::substr"),
- string_view())
- : string_view(ptr_ + pos, Min(n, length_ - pos));
+ return ABSL_PREDICT_FALSE(pos > length_)
+ ? (base_internal::ThrowStdOutOfRange(
+ "y_absl::string_view::substr"),
+ string_view())
+ : string_view(ptr_ + pos, Min(n, length_ - pos));
}
// string_view::compare()
@@ -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) {
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
index 177fba8cbe..75035a5706 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.cc
@@ -36,7 +36,7 @@ void SubstituteAndAppendArray(TString* output, y_absl::string_view format,
if (i + 1 >= format.size()) {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid y_absl::Substitute() format string: \"%s\".",
+ "Invalid y_absl::Substitute() format string: \"%s\".",
y_absl::CEscape(format).c_str());
#endif
return;
@@ -46,8 +46,8 @@ void SubstituteAndAppendArray(TString* output, y_absl::string_view format,
#ifndef NDEBUG
ABSL_RAW_LOG(
FATAL,
- "Invalid y_absl::Substitute() format string: asked for \"$"
- "%d\", but only %d args were given. Full format string was: "
+ "Invalid y_absl::Substitute() format string: asked for \"$"
+ "%d\", but only %d args were given. Full format string was: "
"\"%s\".",
index, static_cast<int>(num_args), y_absl::CEscape(format).c_str());
#endif
@@ -61,7 +61,7 @@ void SubstituteAndAppendArray(TString* output, y_absl::string_view format,
} else {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid y_absl::Substitute() format string: \"%s\".",
+ "Invalid y_absl::Substitute() format string: \"%s\".",
y_absl::CEscape(format).c_str());
#endif
return;
@@ -73,7 +73,7 @@ void SubstituteAndAppendArray(TString* output, y_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);
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
index c31191fbda..8b750f9787 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/substitute.h
@@ -50,7 +50,7 @@
//
// Supported types:
// * y_absl::string_view, TString, 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>",
@@ -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)
@@ -122,9 +122,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_) {}
@@ -207,11 +207,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
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
index 77c5a47dc9..bc65e01f18 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/strings/ya.make
@@ -2,15 +2,15 @@
LIBRARY()
-OWNER(
- somov
- g:cpp-contrib
-)
+OWNER(
+ somov
+ g:cpp-contrib
+)
LICENSE(Apache-2.0)
-LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging