Go to the documentation of this file.
22 #include "absl/base/attributes.h"
23 #include "absl/base/config.h"
24 #include "absl/base/internal/raw_logging.h"
26 #include "absl/strings/internal/cord_internal.h"
28 #include "absl/strings/internal/cord_rep_flat.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/string_view.h"
34 namespace cord_internal {
36 #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
44 using OpResult = CordRepBtree::OpResult;
45 using CopyResult = CordRepBtree::CopyResult;
50 inline bool exhaustive_validation() {
58 void DumpAll(
const CordRep*
rep,
bool include_contents, std::ostream&
stream,
69 auto maybe_dump_data = [&
stream, include_contents](
const CordRep*
r) {
70 if (include_contents) {
73 constexpr
size_t kMaxDataLength = 60;
76 << (
r->length > kMaxDataLength ?
"\"..." :
"\"");
86 const CordRepBtree* node =
rep->
btree();
88 node->height() ?
absl::StrCat(
"Node(", node->height(),
")") :
"Leaf";
90 <<
", begin = " << node->begin() <<
", end = " << node->end()
92 for (CordRep* edge : node->Edges()) {
98 <<
", start = " << substring->start;
100 DumpAll(substring->child, include_contents,
stream,
depth + 1);
104 maybe_dump_data(
rep);
107 maybe_dump_data(
rep);
114 CordRepSubstring* CreateSubstring(CordRep*
rep,
size_t offset,
size_t n) {
126 CordRepSubstring* substring =
new CordRepSubstring();
127 substring->length =
n;
129 substring->start =
offset;
130 substring->child =
rep;
153 CordRep* ResizeEdge(CordRep* edge,
size_t length,
bool is_mutable) {
155 assert(length <= edge->
length);
157 if (
length >= edge->length)
return edge;
159 if (is_mutable && (edge->tag >=
FLAT || edge->tag ==
SUBSTRING)) {
164 return CreateSubstring(edge, 0,
length);
167 template <EdgeType edge_type>
169 return edge_type == kBack ?
s.substr(n) :
s.substr(0,
s.size() - n);
172 template <EdgeType edge_type>
174 if (edge_type == kBack) {
188 template <
typename R,
typename Fn>
189 inline void FastUnref(R*
r,
Fn&&
fn) {
190 if (
r->refcount.IsOne()) {
192 }
else if (!
r->refcount.DecrementExpectHighRefcount()) {
198 void DeleteSubstring(CordRepSubstring* substring) {
199 CordRep*
rep = substring->child;
212 void DeleteLeafEdge(CordRep*
rep) {
226 template <EdgeType edge_type>
227 struct StackOperations {
237 inline CordRepBtree* BuildStack(CordRepBtree* tree,
int depth) {
238 assert(depth <= tree->
height());
239 int current_depth = 0;
240 while (current_depth < depth && tree->
refcount.IsOne()) {
241 stack[current_depth++] = tree;
242 tree = tree->Edge(edge_type)->btree();
244 share_depth = current_depth + (tree->refcount.IsOne() ? 1 : 0);
245 while (current_depth <
depth) {
246 stack[current_depth++] = tree;
247 tree = tree->Edge(edge_type)->btree();
255 inline void BuildOwnedStack(CordRepBtree* tree,
int height) {
259 assert(tree->refcount.IsOne());
261 tree = tree->Edge(edge_type)->btree();
263 assert(tree->refcount.IsOne());
269 static inline CordRepBtree* Finalize(CordRepBtree* tree, OpResult
result) {
277 "Max height exceeded");
296 template <
bool propagate = false>
339 return Finalize(tree,
result);
343 inline CordRepBtree* Propagate(CordRepBtree* tree,
int depth,
size_t length,
362 bool include_contents, std::ostream&
stream) {
363 stream <<
"===================================\n";
364 if (!
label.empty()) {
366 stream <<
"-----------------------------------\n";
384 template <
size_t size>
387 if (node->refcount.Decrement())
continue;
389 if (edge->refcount.Decrement())
continue;
391 DeleteLeafEdge(edge);
405 if (!edge->refcount.Decrement()) {
406 DeleteLeafEdge(edge);
411 return DestroyTree<1>(tree);
413 return DestroyTree<2>(tree);
418 #define NODE_CHECK_VALID(x) \
420 ABSL_RAW_LOG(ERROR, "CordRepBtree::CheckValid() FAILED: %s", #x); \
423 #define NODE_CHECK_EQ(x, y) \
425 ABSL_RAW_LOG(ERROR, \
426 "CordRepBtree::CheckValid() FAILED: %s != %s (%s vs %s)", #x, \
427 #y, absl::StrCat(x).c_str(), absl::StrCat(y).c_str()); \
437 size_t child_length = 0;
446 child_length += edge->length;
449 if ((!shallow || exhaustive_validation()) && tree->
height() > 0) {
451 if (!
IsValid(edge->btree(), shallow))
return false;
456 #undef NODE_CHECK_VALID
464 Dump(tree,
"CordRepBtree validation failed:",
false, std::cout);
473 Dump(tree,
"CordRepBtree validation failed:",
false, std::cout);
481 template <EdgeType edge_type>
485 result.tree->Add<edge_type>(edge);
486 result.tree->length += delta;
490 template <EdgeType edge_type>
493 const size_t idx =
index(edge_type);
503 constexpr
int shift = edge_type ==
kFront ? 1 : 0;
509 result.tree->length += delta;
513 template <EdgeType edge_type>
517 StackOperations<edge_type>
ops;
530 const size_t cap = leaf->
capacity();
531 while (!
data.empty() &&
end != cap) {
565 assert(!
data.empty());
575 }
while (!
data.empty() &&
end() != cap);
582 assert(!
data.empty());
595 template <EdgeType edge_type>
600 const size_t original_data_size =
data.size();
602 StackOperations<edge_type>
ops;
611 result.tree->length += original_data_size;
619 size_t delta = original_data_size -
data.size();
621 result.tree->length += delta;
646 template <EdgeType edge_type>
655 StackOperations<edge_type>
ops;
703 node =
back->btree();
721 assert(
pos.index >= 1);
734 node = edge->
btree();
747 assert(n <= this->
length);
760 node = front->
btree();
789 node = edge->
btree();
815 assert(end <= tree->
end());
819 tree->
length = new_length;
830 assert(tree !=
nullptr);
831 assert(n <= tree->
length);
847 while (
pos.index == tree->
begin()) {
850 if (
height-- == 0)
return ResizeEdge(edge,
length, is_mutable);
851 tree = edge->
btree();
873 if (!edge_is_mutable) {
882 tree = edge->
btree();
893 assert(n <= this->
length);
901 while (front.
n + n <= left->
length) {
903 node = left->
btree();
956 return left->
height() >= right->
height() ? Merge<kBack>(left, right)
957 : Merge<kFront>(right, left);
970 assert(n <= this->
length);
978 if (edge->
length < front.
n +
n)
return false;
1022 if (avail == 0)
return {};
1028 this->length += delta;
1030 stack[
i]->length += delta;
1036 if (
rep->IsBtree())
return rep->btree();
1041 if (node ==
nullptr) {
1044 node = CordRepBtree::AddCordRep<kBack>(node,
r);
1057 tree = CordRepBtree::AddCordRep<kBack>(tree,
r);
1069 tree = CordRepBtree::AddCordRep<kFront>(tree,
r);
1077 return CordRepBtree::AddData<kBack>(tree,
data, extra);
1082 return CordRepBtree::AddData<kFront>(tree,
data, extra);
1099 if (tree->
height() == 0) {
1103 size_t length = edge->length;
1144 if (parent ==
nullptr)
return node;
1161 result.extracted =
nullptr;
1164 while (tree->
height() > 0) {
1173 if (!(
rep->IsFlat() &&
rep->refcount.IsOne()))
return result;
1179 if (extra_capacity > avail)
return result;
1185 while (tree->
size() == 1) {
1209 while (tree->
size() == 1) {
1218 tree =
rep->btree();
#define ABSL_PREDICT_FALSE(x)
#define ABSL_RAW_CHECK(condition, message)
CordRepSubstring * MakeSubstring(size_t start, size_t len, CordRep *rep)
void ReverseConsume(CordRep *rep, ConsumeFn consume_fn)
static constexpr size_t kMaxCapacity
constexpr bool IsBtree() const
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
CordRepBtree * CopyBeginTo(size_t end, size_t new_length) const
absl::string_view EdgeData(const CordRep *edge)
CordRep * edges_[kMaxCapacity]
static CordRepBtree * PrependSlow(CordRepBtree *, CordRep *rep)
static void Unref(CordRep *rep)
static CordRepFlat * New(size_t len)
CordRepExternal * external()
Position IndexBefore(size_t offset) const
static void Delete(CordRep *rep)
void Consume(CordRep *rep, ConsumeFn consume_fn)
void set_begin(size_t begin)
CordRepBtree * CopyToEndFrom(size_t begin, size_t new_length) const
Position IndexOf(size_t offset) const
absl::string_view Data(size_t index) const
#define ABSL_NAMESPACE_END
static constexpr int kMaxHeight
static CordRepBtree * Prepend(CordRepBtree *tree, CordRep *rep)
absl::string_view AddData(absl::string_view data, size_t extra)
static CordRep * RemoveSuffix(CordRepBtree *tree, size_t n)
CopyResult CopyPrefix(size_t n, bool allow_folding=true)
static CordRepBtree * New(int height=0)
static GraphId Get(const IdMap &id, int num)
static constexpr EdgeType kFront
static void Delete(CordRepBtree *tree)
ABSL_ATTRIBUTE_ALWAYS_INLINE int Unwind(void **result, int *sizes, int max_depth, int skip_count, const void *uc, int *min_dropped_frames)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static constexpr int kMaxDepth
char GetCharacter(size_t offset) const
#define ABSL_NAMESPACE_BEGIN
static void Dump(const CordRep *rep, std::ostream &stream)
static void DestroyTree(CordRepBtree *tree)
static void Destroy(CordRepBtree *tree)
RefcountAndFlags refcount
OpResult SetEdge(bool owned, CordRep *edge, size_t delta)
constexpr bool IsFlat() const
static CordRepBtree * Merge(CordRepBtree *dst, CordRepBtree *src)
Position IndexBeyond(size_t offset) const
size_t index(EdgeType edge) const
CordRepBtree * CopyRaw() const
Position IndexOfLength(size_t n) const
static CordRepBtree * AppendSlow(CordRepBtree *, CordRep *rep)
static ExtractResult ExtractAppendBuffer(CordRepBtree *tree, size_t extra_capacity=1)
static CordRepBtree * Append(CordRepBtree *tree, CordRep *rep)
#define ABSL_PREDICT_TRUE(x)
static CordRepBtree * AddCordRep(CordRepBtree *tree, CordRep *rep)
CopyResult CopySuffix(size_t offset)
constexpr bool IsExternal() const
static CordRepBtree * MergeTrees(CordRepBtree *left, CordRepBtree *right)
CordRep * SubTree(size_t offset, size_t n)
static bool IsValid(const CordRepBtree *tree, bool shallow=false)
unsigned char suffix[65536]
OpResult AddEdge(bool owned, CordRep *edge, size_t delta)
static CordRepBtree * Rebuild(CordRepBtree *tree)
#define ABSL_INTERNAL_UNREACHABLE
CordRep * Edge(size_t index) const
static const char prefix[]
absl::Span< CordRep *const > Edges() const
static CordRep * Ref(CordRep *rep)
static CordRep * ExtractFront(CordRepBtree *tree)
static CordRepBtree * AssertValid(CordRepBtree *tree, bool shallow=true)
static CordRepBtree * ConsumeBeginTo(CordRepBtree *tree, size_t end, size_t new_length)
size_t sub_fetch_begin(size_t n)
static void Delete(CordRep *rep)
bool IsDataEdge(const CordRep *edge)
#define NODE_CHECK_EQ(x, y)
static constexpr EdgeType kBack
#define ABSL_FALLTHROUGH_INTENDED
static void Unref(absl::Span< CordRep *const > edges)
std::atomic< bool > cord_btree_exhaustive_validation
#define ABSL_RAW_LOG(severity,...)
constexpr string_view substr(size_type pos=0, size_type n=npos) const
static upb_pb_encoder_segment * top(upb_pb_encoder *e)
size_t fetch_add_end(size_t n)
CordRepSubstring * substring()
#define NODE_CHECK_VALID(x)
static CordRepBtree * CreateSlow(CordRep *rep)
Span< char > GetAppendBufferSlow(size_t size)
OpResult ToOpResult(bool owned)
grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:03