1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // -----------------------------------------------------------------------------
16 // File: cord.h
17 // -----------------------------------------------------------------------------
18 //
19 // This file defines the `absl::Cord` data structure and operations on that data
20 // structure. A Cord is a string-like sequence of characters optimized for
21 // specific use cases. Unlike a `std::string`, which stores an array of
22 // contiguous characters, Cord data is stored in a structure consisting of
23 // separate, reference-counted "chunks." (Currently, this implementation is a
24 // tree structure, though that implementation may change.)
25 //
26 // Because a Cord consists of these chunks, data can be added to or removed from
27 // a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
28 // `std::string`, a Cord can therefore accommodate data that changes over its
29 // lifetime, though it's not quite "mutable"; it can change only in the
30 // attachment, detachment, or rearrangement of chunks of its constituent data.
31 //
32 // A Cord provides some benefit over `std::string` under the following (albeit
33 // narrow) circumstances:
34 //
35 // * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
36 // provides efficient insertions and deletions at the start and end of the
37 // character sequences, avoiding copies in those cases. Static data should
38 // generally be stored as strings.
39 // * External memory consisting of string-like data can be directly added to
40 // a Cord without requiring copies or allocations.
41 // * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
42 // implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
43 // operation.
44 //
45 // As a consequence to the above, Cord data is generally large. Small data
46 // should generally use strings, as construction of a Cord requires some
47 // overhead. Small Cords (<= 15 bytes) are represented inline, but most small
48 // Cords are expected to grow over their lifetimes.
49 //
50 // Note that because a Cord is made up of separate chunked data, random access
51 // to character data within a Cord is slower than within a `std::string`.
52 //
53 // Thread Safety
54 //
55 // Cord has the same thread-safety properties as many other types like
56 // std::string, std::vector<>, int, etc -- it is thread-compatible. In
57 // particular, if threads do not call non-const methods, then it is safe to call
58 // const methods without synchronization. Copying a Cord produces a new instance
59 // that can be used concurrently with the original in arbitrary ways.
60
61 #ifndef ABSL_STRINGS_CORD_H_
62 #define ABSL_STRINGS_CORD_H_
63
64 #include <algorithm>
65 #include <cstddef>
66 #include <cstdint>
67 #include <cstring>
68 #include <iosfwd>
69 #include <iterator>
70 #include <string>
71 #include <type_traits>
72
73 #include "absl/base/config.h"
74 #include "absl/base/internal/endian.h"
75 #include "absl/base/internal/per_thread_tls.h"
76 #include "absl/base/macros.h"
77 #include "absl/base/port.h"
78 #include "absl/container/inlined_vector.h"
79 #include "absl/functional/function_ref.h"
80 #include "absl/meta/type_traits.h"
81 #include "absl/strings/internal/cord_internal.h"
82 #include "absl/strings/internal/cord_rep_btree.h"
83 #include "absl/strings/internal/cord_rep_btree_reader.h"
84 #include "absl/strings/internal/cord_rep_ring.h"
85 #include "absl/strings/internal/cordz_functions.h"
86 #include "absl/strings/internal/cordz_info.h"
87 #include "absl/strings/internal/cordz_statistics.h"
88 #include "absl/strings/internal/cordz_update_scope.h"
89 #include "absl/strings/internal/cordz_update_tracker.h"
90 #include "absl/strings/internal/resize_uninitialized.h"
91 #include "absl/strings/internal/string_constant.h"
92 #include "absl/strings/string_view.h"
93 #include "absl/types/optional.h"
94
95 namespace absl {
96 ABSL_NAMESPACE_BEGIN
97 class Cord;
98 class CordTestPeer;
99 template <typename Releaser>
100 Cord MakeCordFromExternal(absl::string_view, Releaser&&);
101 void CopyCordToString(const Cord& src, std::string* dst);
102
103 // Cord
104 //
105 // A Cord is a sequence of characters, designed to be more efficient than a
106 // `std::string` in certain circumstances: namely, large string data that needs
107 // to change over its lifetime or shared, especially when such data is shared
108 // across API boundaries.
109 //
110 // A Cord stores its character data in a structure that allows efficient prepend
111 // and append operations. This makes a Cord useful for large string data sent
112 // over in a wire format that may need to be prepended or appended at some point
113 // during the data exchange (e.g. HTTP, protocol buffers). For example, a
114 // Cord is useful for storing an HTTP request, and prepending an HTTP header to
115 // such a request.
116 //
117 // Cords should not be used for storing general string data, however. They
118 // require overhead to construct and are slower than strings for random access.
119 //
120 // The Cord API provides the following common API operations:
121 //
122 // * Create or assign Cords out of existing string data, memory, or other Cords
123 // * Append and prepend data to an existing Cord
124 // * Create new Sub-Cords from existing Cord data
125 // * Swap Cord data and compare Cord equality
126 // * Write out Cord data by constructing a `std::string`
127 //
128 // Additionally, the API provides iterator utilities to iterate through Cord
129 // data via chunks or character bytes.
130 //
131 class Cord {
132 private:
133 template <typename T>
134 using EnableIfString =
135 absl::enable_if_t<std::is_same<T, std::string>::value, int>;
136
137 public:
138 // Cord::Cord() Constructors.
139
140 // Creates an empty Cord.
141 constexpr Cord() noexcept;
142
143 // Creates a Cord from an existing Cord. Cord is copyable and efficiently
144 // movable. The moved-from state is valid but unspecified.
145 Cord(const Cord& src);
146 Cord(Cord&& src) noexcept;
147 Cord& operator=(const Cord& x);
148 Cord& operator=(Cord&& x) noexcept;
149
150 // Creates a Cord from a `src` string. This constructor is marked explicit to
151 // prevent implicit Cord constructions from arguments convertible to an
152 // `absl::string_view`.
153 explicit Cord(absl::string_view src);
154 Cord& operator=(absl::string_view src);
155
156 // Creates a Cord from a `std::string&&` rvalue. These constructors are
157 // templated to avoid ambiguities for types that are convertible to both
158 // `absl::string_view` and `std::string`, such as `const char*`.
159 template <typename T, EnableIfString<T> = 0>
160 explicit Cord(T&& src);
161 template <typename T, EnableIfString<T> = 0>
162 Cord& operator=(T&& src);
163
164 // Cord::~Cord()
165 //
166 // Destructs the Cord.
~Cord()167 ~Cord() {
168 if (contents_.is_tree()) DestroyCordSlow();
169 }
170
171 // MakeCordFromExternal()
172 //
173 // Creates a Cord that takes ownership of external string memory. The
174 // contents of `data` are not copied to the Cord; instead, the external
175 // memory is added to the Cord and reference-counted. This data may not be
176 // changed for the life of the Cord, though it may be prepended or appended
177 // to.
178 //
179 // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
180 // the reference count for `data` reaches zero. As noted above, this data must
181 // remain live until the releaser is invoked. The callable releaser also must:
182 //
183 // * be move constructible
184 // * support `void operator()(absl::string_view) const` or `void operator()`
185 //
186 // Example:
187 //
188 // Cord MakeCord(BlockPool* pool) {
189 // Block* block = pool->NewBlock();
190 // FillBlock(block);
191 // return absl::MakeCordFromExternal(
192 // block->ToStringView(),
193 // [pool, block](absl::string_view v) {
194 // pool->FreeBlock(block, v);
195 // });
196 // }
197 //
198 // WARNING: Because a Cord can be reference-counted, it's likely a bug if your
199 // releaser doesn't do anything. For example, consider the following:
200 //
201 // void Foo(const char* buffer, int len) {
202 // auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
203 // [](absl::string_view) {});
204 //
205 // // BUG: If Bar() copies its cord for any reason, including keeping a
206 // // substring of it, the lifetime of buffer might be extended beyond
207 // // when Foo() returns.
208 // Bar(c);
209 // }
210 template <typename Releaser>
211 friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
212
213 // Cord::Clear()
214 //
215 // Releases the Cord data. Any nodes that share data with other Cords, if
216 // applicable, will have their reference counts reduced by 1.
217 void Clear();
218
219 // Cord::Append()
220 //
221 // Appends data to the Cord, which may come from another Cord or other string
222 // data.
223 void Append(const Cord& src);
224 void Append(Cord&& src);
225 void Append(absl::string_view src);
226 template <typename T, EnableIfString<T> = 0>
227 void Append(T&& src);
228
229 // Cord::Prepend()
230 //
231 // Prepends data to the Cord, which may come from another Cord or other string
232 // data.
233 void Prepend(const Cord& src);
234 void Prepend(absl::string_view src);
235 template <typename T, EnableIfString<T> = 0>
236 void Prepend(T&& src);
237
238 // Cord::RemovePrefix()
239 //
240 // Removes the first `n` bytes of a Cord.
241 void RemovePrefix(size_t n);
242 void RemoveSuffix(size_t n);
243
244 // Cord::Subcord()
245 //
246 // Returns a new Cord representing the subrange [pos, pos + new_size) of
247 // *this. If pos >= size(), the result is empty(). If
248 // (pos + new_size) >= size(), the result is the subrange [pos, size()).
249 Cord Subcord(size_t pos, size_t new_size) const;
250
251 // Cord::swap()
252 //
253 // Swaps the contents of the Cord with `other`.
254 void swap(Cord& other) noexcept;
255
256 // swap()
257 //
258 // Swaps the contents of two Cords.
swap(Cord & x,Cord & y)259 friend void swap(Cord& x, Cord& y) noexcept {
260 x.swap(y);
261 }
262
263 // Cord::size()
264 //
265 // Returns the size of the Cord.
266 size_t size() const;
267
268 // Cord::empty()
269 //
270 // Determines whether the given Cord is empty, returning `true` is so.
271 bool empty() const;
272
273 // Cord::EstimatedMemoryUsage()
274 //
275 // Returns the *approximate* number of bytes held in full or in part by this
276 // Cord (which may not remain the same between invocations). Note that Cords
277 // that share memory could each be "charged" independently for the same shared
278 // memory.
279 size_t EstimatedMemoryUsage() const;
280
281 // Cord::Compare()
282 //
283 // Compares 'this' Cord with rhs. This function and its relatives treat Cords
284 // as sequences of unsigned bytes. The comparison is a straightforward
285 // lexicographic comparison. `Cord::Compare()` returns values as follows:
286 //
287 // -1 'this' Cord is smaller
288 // 0 two Cords are equal
289 // 1 'this' Cord is larger
290 int Compare(absl::string_view rhs) const;
291 int Compare(const Cord& rhs) const;
292
293 // Cord::StartsWith()
294 //
295 // Determines whether the Cord starts with the passed string data `rhs`.
296 bool StartsWith(const Cord& rhs) const;
297 bool StartsWith(absl::string_view rhs) const;
298
299 // Cord::EndsWith()
300 //
301 // Determines whether the Cord ends with the passed string data `rhs`.
302 bool EndsWith(absl::string_view rhs) const;
303 bool EndsWith(const Cord& rhs) const;
304
305 // Cord::operator std::string()
306 //
307 // Converts a Cord into a `std::string()`. This operator is marked explicit to
308 // prevent unintended Cord usage in functions that take a string.
309 explicit operator std::string() const;
310
311 // CopyCordToString()
312 //
313 // Copies the contents of a `src` Cord into a `*dst` string.
314 //
315 // This function optimizes the case of reusing the destination string since it
316 // can reuse previously allocated capacity. However, this function does not
317 // guarantee that pointers previously returned by `dst->data()` remain valid
318 // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
319 // object, prefer to simply use the conversion operator to `std::string`.
320 friend void CopyCordToString(const Cord& src, std::string* dst);
321
322 class CharIterator;
323
324 //----------------------------------------------------------------------------
325 // Cord::ChunkIterator
326 //----------------------------------------------------------------------------
327 //
328 // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
329 // Cord. Such iteration allows you to perform non-const operatons on the data
330 // of a Cord without modifying it.
331 //
332 // Generally, you do not instantiate a `Cord::ChunkIterator` directly;
333 // instead, you create one implicitly through use of the `Cord::Chunks()`
334 // member function.
335 //
336 // The `Cord::ChunkIterator` has the following properties:
337 //
338 // * The iterator is invalidated after any non-const operation on the
339 // Cord object over which it iterates.
340 // * The `string_view` returned by dereferencing a valid, non-`end()`
341 // iterator is guaranteed to be non-empty.
342 // * Two `ChunkIterator` objects can be compared equal if and only if they
343 // remain valid and iterate over the same Cord.
344 // * The iterator in this case is a proxy iterator; the `string_view`
345 // returned by the iterator does not live inside the Cord, and its
346 // lifetime is limited to the lifetime of the iterator itself. To help
347 // prevent lifetime issues, `ChunkIterator::reference` is not a true
348 // reference type and is equivalent to `value_type`.
349 // * The iterator keeps state that can grow for Cords that contain many
350 // nodes and are imbalanced due to sharing. Prefer to pass this type by
351 // const reference instead of by value.
352 class ChunkIterator {
353 public:
354 using iterator_category = std::input_iterator_tag;
355 using value_type = absl::string_view;
356 using difference_type = ptrdiff_t;
357 using pointer = const value_type*;
358 using reference = value_type;
359
360 ChunkIterator() = default;
361
362 ChunkIterator& operator++();
363 ChunkIterator operator++(int);
364 bool operator==(const ChunkIterator& other) const;
365 bool operator!=(const ChunkIterator& other) const;
366 reference operator*() const;
367 pointer operator->() const;
368
369 friend class Cord;
370 friend class CharIterator;
371
372 private:
373 using CordRep = absl::cord_internal::CordRep;
374 using CordRepBtree = absl::cord_internal::CordRepBtree;
375 using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
376
377 // Stack of right children of concat nodes that we have to visit.
378 // Keep this at the end of the structure to avoid cache-thrashing.
379 // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
380 // the inlined vector size (47 exists for backward compatibility).
381 using Stack = absl::InlinedVector<absl::cord_internal::CordRep*, 47>;
382
383 // Constructs a `begin()` iterator from `tree`. `tree` must not be null.
384 explicit ChunkIterator(cord_internal::CordRep* tree);
385
386 // Constructs a `begin()` iterator from `cord`.
387 explicit ChunkIterator(const Cord* cord);
388
389 // Initializes this instance from a tree. Invoked by constructors.
390 void InitTree(cord_internal::CordRep* tree);
391
392 // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
393 // `current_chunk_.size()`.
394 void RemoveChunkPrefix(size_t n);
395 Cord AdvanceAndReadBytes(size_t n);
396 void AdvanceBytes(size_t n);
397
398 // Stack specific operator++
399 ChunkIterator& AdvanceStack();
400
401 // Btree specific operator++
402 ChunkIterator& AdvanceBtree();
403 void AdvanceBytesBtree(size_t n);
404
405 // Iterates `n` bytes, where `n` is expected to be greater than or equal to
406 // `current_chunk_.size()`.
407 void AdvanceBytesSlowPath(size_t n);
408
409 // A view into bytes of the current `CordRep`. It may only be a view to a
410 // suffix of bytes if this is being used by `CharIterator`.
411 absl::string_view current_chunk_;
412 // The current leaf, or `nullptr` if the iterator points to short data.
413 // If the current chunk is a substring node, current_leaf_ points to the
414 // underlying flat or external node.
415 absl::cord_internal::CordRep* current_leaf_ = nullptr;
416 // The number of bytes left in the `Cord` over which we are iterating.
417 size_t bytes_remaining_ = 0;
418
419 // Cord reader for cord btrees. Empty if not traversing a btree.
420 CordRepBtreeReader btree_reader_;
421
422 // See 'Stack' alias definition.
423 Stack stack_of_right_children_;
424 };
425
426 // Cord::ChunkIterator::chunk_begin()
427 //
428 // Returns an iterator to the first chunk of the `Cord`.
429 //
430 // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
431 // iterating over the chunks of a Cord. This method may be useful for getting
432 // a `ChunkIterator` where range-based for-loops are not useful.
433 //
434 // Example:
435 //
436 // absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
437 // absl::string_view s) {
438 // return std::find(c.chunk_begin(), c.chunk_end(), s);
439 // }
440 ChunkIterator chunk_begin() const;
441
442 // Cord::ChunkItertator::chunk_end()
443 //
444 // Returns an iterator one increment past the last chunk of the `Cord`.
445 //
446 // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
447 // iterating over the chunks of a Cord. This method may be useful for getting
448 // a `ChunkIterator` where range-based for-loops may not be available.
449 ChunkIterator chunk_end() const;
450
451 //----------------------------------------------------------------------------
452 // Cord::ChunkIterator::ChunkRange
453 //----------------------------------------------------------------------------
454 //
455 // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
456 // producing an iterator which can be used within a range-based for loop.
457 // Construction of a `ChunkRange` will return an iterator pointing to the
458 // first chunk of the Cord. Generally, do not construct a `ChunkRange`
459 // directly; instead, prefer to use the `Cord::Chunks()` method.
460 //
461 // Implementation note: `ChunkRange` is simply a convenience wrapper over
462 // `Cord::chunk_begin()` and `Cord::chunk_end()`.
463 class ChunkRange {
464 public:
ChunkRange(const Cord * cord)465 explicit ChunkRange(const Cord* cord) : cord_(cord) {}
466
467 ChunkIterator begin() const;
468 ChunkIterator end() const;
469
470 private:
471 const Cord* cord_;
472 };
473
474 // Cord::Chunks()
475 //
476 // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks
477 // of a `Cord` with a range-based for-loop. For most iteration tasks on a
478 // Cord, use `Cord::Chunks()` to retrieve this iterator.
479 //
480 // Example:
481 //
482 // void ProcessChunks(const Cord& cord) {
483 // for (absl::string_view chunk : cord.Chunks()) { ... }
484 // }
485 //
486 // Note that the ordinary caveats of temporary lifetime extension apply:
487 //
488 // void Process() {
489 // for (absl::string_view chunk : CordFactory().Chunks()) {
490 // // The temporary Cord returned by CordFactory has been destroyed!
491 // }
492 // }
493 ChunkRange Chunks() const;
494
495 //----------------------------------------------------------------------------
496 // Cord::CharIterator
497 //----------------------------------------------------------------------------
498 //
499 // A `Cord::CharIterator` allows iteration over the constituent characters of
500 // a `Cord`.
501 //
502 // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
503 // you create one implicitly through use of the `Cord::Chars()` member
504 // function.
505 //
506 // A `Cord::CharIterator` has the following properties:
507 //
508 // * The iterator is invalidated after any non-const operation on the
509 // Cord object over which it iterates.
510 // * Two `CharIterator` objects can be compared equal if and only if they
511 // remain valid and iterate over the same Cord.
512 // * The iterator keeps state that can grow for Cords that contain many
513 // nodes and are imbalanced due to sharing. Prefer to pass this type by
514 // const reference instead of by value.
515 // * This type cannot act as a forward iterator because a `Cord` can reuse
516 // sections of memory. This fact violates the requirement for forward
517 // iterators to compare equal if dereferencing them returns the same
518 // object.
519 class CharIterator {
520 public:
521 using iterator_category = std::input_iterator_tag;
522 using value_type = char;
523 using difference_type = ptrdiff_t;
524 using pointer = const char*;
525 using reference = const char&;
526
527 CharIterator() = default;
528
529 CharIterator& operator++();
530 CharIterator operator++(int);
531 bool operator==(const CharIterator& other) const;
532 bool operator!=(const CharIterator& other) const;
533 reference operator*() const;
534 pointer operator->() const;
535
536 friend Cord;
537
538 private:
CharIterator(const Cord * cord)539 explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {}
540
541 ChunkIterator chunk_iterator_;
542 };
543
544 // Cord::CharIterator::AdvanceAndRead()
545 //
546 // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
547 // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
548 // number of bytes within the Cord; otherwise, behavior is undefined. It is
549 // valid to pass `char_end()` and `0`.
550 static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes);
551
552 // Cord::CharIterator::Advance()
553 //
554 // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
555 // or equal to the number of bytes remaining within the Cord; otherwise,
556 // behavior is undefined. It is valid to pass `char_end()` and `0`.
557 static void Advance(CharIterator* it, size_t n_bytes);
558
559 // Cord::CharIterator::ChunkRemaining()
560 //
561 // Returns the longest contiguous view starting at the iterator's position.
562 //
563 // `it` must be dereferenceable.
564 static absl::string_view ChunkRemaining(const CharIterator& it);
565
566 // Cord::CharIterator::char_begin()
567 //
568 // Returns an iterator to the first character of the `Cord`.
569 //
570 // Generally, prefer using `Cord::Chars()` within a range-based for loop for
571 // iterating over the chunks of a Cord. This method may be useful for getting
572 // a `CharIterator` where range-based for-loops may not be available.
573 CharIterator char_begin() const;
574
575 // Cord::CharIterator::char_end()
576 //
577 // Returns an iterator to one past the last character of the `Cord`.
578 //
579 // Generally, prefer using `Cord::Chars()` within a range-based for loop for
580 // iterating over the chunks of a Cord. This method may be useful for getting
581 // a `CharIterator` where range-based for-loops are not useful.
582 CharIterator char_end() const;
583
584 // Cord::CharIterator::CharRange
585 //
586 // `CharRange` is a helper class for iterating over the characters of a
587 // producing an iterator which can be used within a range-based for loop.
588 // Construction of a `CharRange` will return an iterator pointing to the first
589 // character of the Cord. Generally, do not construct a `CharRange` directly;
590 // instead, prefer to use the `Cord::Chars()` method show below.
591 //
592 // Implementation note: `CharRange` is simply a convenience wrapper over
593 // `Cord::char_begin()` and `Cord::char_end()`.
594 class CharRange {
595 public:
CharRange(const Cord * cord)596 explicit CharRange(const Cord* cord) : cord_(cord) {}
597
598 CharIterator begin() const;
599 CharIterator end() const;
600
601 private:
602 const Cord* cord_;
603 };
604
605 // Cord::CharIterator::Chars()
606 //
607 // Returns a `Cord::CharIterator` for iterating over the characters of a
608 // `Cord` with a range-based for-loop. For most character-based iteration
609 // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator.
610 //
611 // Example:
612 //
613 // void ProcessCord(const Cord& cord) {
614 // for (char c : cord.Chars()) { ... }
615 // }
616 //
617 // Note that the ordinary caveats of temporary lifetime extension apply:
618 //
619 // void Process() {
620 // for (char c : CordFactory().Chars()) {
621 // // The temporary Cord returned by CordFactory has been destroyed!
622 // }
623 // }
624 CharRange Chars() const;
625
626 // Cord::operator[]
627 //
628 // Gets the "i"th character of the Cord and returns it, provided that
629 // 0 <= i < Cord.size().
630 //
631 // NOTE: This routine is reasonably efficient. It is roughly
632 // logarithmic based on the number of chunks that make up the cord. Still,
633 // if you need to iterate over the contents of a cord, you should
634 // use a CharIterator/ChunkIterator rather than call operator[] or Get()
635 // repeatedly in a loop.
636 char operator[](size_t i) const;
637
638 // Cord::TryFlat()
639 //
640 // If this cord's representation is a single flat array, returns a
641 // string_view referencing that array. Otherwise returns nullopt.
642 absl::optional<absl::string_view> TryFlat() const;
643
644 // Cord::Flatten()
645 //
646 // Flattens the cord into a single array and returns a view of the data.
647 //
648 // If the cord was already flat, the contents are not modified.
649 absl::string_view Flatten();
650
651 // Supports absl::Cord as a sink object for absl::Format().
AbslFormatFlush(absl::Cord * cord,absl::string_view part)652 friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) {
653 cord->Append(part);
654 }
655
656 template <typename H>
AbslHashValue(H hash_state,const absl::Cord & c)657 friend H AbslHashValue(H hash_state, const absl::Cord& c) {
658 absl::optional<absl::string_view> maybe_flat = c.TryFlat();
659 if (maybe_flat.has_value()) {
660 return H::combine(std::move(hash_state), *maybe_flat);
661 }
662 return c.HashFragmented(std::move(hash_state));
663 }
664
665 // Create a Cord with the contents of StringConstant<T>::value.
666 // No allocations will be done and no data will be copied.
667 // This is an INTERNAL API and subject to change or removal. This API can only
668 // be used by spelling absl::strings_internal::MakeStringConstant, which is
669 // also an internal API.
670 template <typename T>
671 explicit constexpr Cord(strings_internal::StringConstant<T>);
672
673 private:
674 using CordRep = absl::cord_internal::CordRep;
675 using CordRepFlat = absl::cord_internal::CordRepFlat;
676 using CordzInfo = cord_internal::CordzInfo;
677 using CordzUpdateScope = cord_internal::CordzUpdateScope;
678 using CordzUpdateTracker = cord_internal::CordzUpdateTracker;
679 using InlineData = cord_internal::InlineData;
680 using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
681
682 // Creates a cord instance with `method` representing the originating
683 // public API call causing the cord to be created.
684 explicit Cord(absl::string_view src, MethodIdentifier method);
685
686 friend class CordTestPeer;
687 friend bool operator==(const Cord& lhs, const Cord& rhs);
688 friend bool operator==(const Cord& lhs, absl::string_view rhs);
689
690 friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord);
691
692 // Calls the provided function once for each cord chunk, in order. Unlike
693 // Chunks(), this API will not allocate memory.
694 void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
695
696 // Allocates new contiguous storage for the contents of the cord. This is
697 // called by Flatten() when the cord was not already flat.
698 absl::string_view FlattenSlowPath();
699
700 // Actual cord contents are hidden inside the following simple
701 // class so that we can isolate the bulk of cord.cc from changes
702 // to the representation.
703 //
704 // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
705 class InlineRep {
706 public:
707 static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
708 static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
709
InlineRep()710 constexpr InlineRep() : data_() {}
InlineRep(InlineData::DefaultInitType init)711 explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {}
712 InlineRep(const InlineRep& src);
713 InlineRep(InlineRep&& src);
714 InlineRep& operator=(const InlineRep& src);
715 InlineRep& operator=(InlineRep&& src) noexcept;
716
717 explicit constexpr InlineRep(cord_internal::InlineData data);
718
719 void Swap(InlineRep* rhs);
720 bool empty() const;
721 size_t size() const;
722 const char* data() const; // Returns nullptr if holding pointer
723 void set_data(const char* data, size_t n,
724 bool nullify_tail); // Discards pointer, if any
725 char* set_data(size_t n); // Write data to the result
726 // Returns nullptr if holding bytes
727 absl::cord_internal::CordRep* tree() const;
728 absl::cord_internal::CordRep* as_tree() const;
729 // Returns non-null iff was holding a pointer
730 absl::cord_internal::CordRep* clear();
731 // Converts to pointer if necessary.
732 void reduce_size(size_t n); // REQUIRES: holding data
733 void remove_prefix(size_t n); // REQUIRES: holding data
734 void AppendArray(absl::string_view src, MethodIdentifier method);
735 absl::string_view FindFlatStartPiece() const;
736
737 // Creates a CordRepFlat instance from the current inlined data with `extra'
738 // bytes of desired additional capacity.
739 CordRepFlat* MakeFlatWithExtraCapacity(size_t extra);
740
741 // Sets the tree value for this instance. `rep` must not be null.
742 // Requires the current instance to hold a tree, and a lock to be held on
743 // any CordzInfo referenced by this instance. The latter is enforced through
744 // the CordzUpdateScope argument. If the current instance is sampled, then
745 // the CordzInfo instance is updated to reference the new `rep` value.
746 void SetTree(CordRep* rep, const CordzUpdateScope& scope);
747
748 // Identical to SetTree(), except that `rep` is allowed to be null, in
749 // which case the current instance is reset to an empty value.
750 void SetTreeOrEmpty(CordRep* rep, const CordzUpdateScope& scope);
751
752 // Sets the tree value for this instance, and randomly samples this cord.
753 // This function disregards existing contents in `data_`, and should be
754 // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'
755 // value to a non-inlined (tree / ring) value.
756 void EmplaceTree(CordRep* rep, MethodIdentifier method);
757
758 // Identical to EmplaceTree, except that it copies the parent stack from
759 // the provided `parent` data if the parent is sampled.
760 void EmplaceTree(CordRep* rep, const InlineData& parent,
761 MethodIdentifier method);
762
763 // Commits the change of a newly created, or updated `rep` root value into
764 // this cord. `old_rep` indicates the old (inlined or tree) value of the
765 // cord, and determines if the commit invokes SetTree() or EmplaceTree().
766 void CommitTree(const CordRep* old_rep, CordRep* rep,
767 const CordzUpdateScope& scope, MethodIdentifier method);
768
769 void AppendTreeToInlined(CordRep* tree, MethodIdentifier method);
770 void AppendTreeToTree(CordRep* tree, MethodIdentifier method);
771 void AppendTree(CordRep* tree, MethodIdentifier method);
772 void PrependTreeToInlined(CordRep* tree, MethodIdentifier method);
773 void PrependTreeToTree(CordRep* tree, MethodIdentifier method);
774 void PrependTree(CordRep* tree, MethodIdentifier method);
775
776 template <bool has_length>
777 void GetAppendRegion(char** region, size_t* size, size_t length);
778
IsSame(const InlineRep & other)779 bool IsSame(const InlineRep& other) const {
780 return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
781 }
BitwiseCompare(const InlineRep & other)782 int BitwiseCompare(const InlineRep& other) const {
783 uint64_t x, y;
784 // Use memcpy to avoid aliasing issues.
785 memcpy(&x, &data_, sizeof(x));
786 memcpy(&y, &other.data_, sizeof(y));
787 if (x == y) {
788 memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
789 memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
790 if (x == y) return 0;
791 }
792 return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
793 ? -1
794 : 1;
795 }
CopyTo(std::string * dst)796 void CopyTo(std::string* dst) const {
797 // memcpy is much faster when operating on a known size. On most supported
798 // platforms, the small string optimization is large enough that resizing
799 // to 15 bytes does not cause a memory allocation.
800 absl::strings_internal::STLStringResizeUninitialized(dst,
801 sizeof(data_) - 1);
802 memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
803 // erase is faster than resize because the logic for memory allocation is
804 // not needed.
805 dst->erase(inline_size());
806 }
807
808 // Copies the inline contents into `dst`. Assumes the cord is not empty.
809 void CopyToArray(char* dst) const;
810
is_tree()811 bool is_tree() const { return data_.is_tree(); }
812
813 // Returns true if the Cord is being profiled by cordz.
is_profiled()814 bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); }
815
816 // Returns the profiled CordzInfo, or nullptr if not sampled.
cordz_info()817 absl::cord_internal::CordzInfo* cordz_info() const {
818 return data_.cordz_info();
819 }
820
821 // Sets the profiled CordzInfo. `cordz_info` must not be null.
set_cordz_info(cord_internal::CordzInfo * cordz_info)822 void set_cordz_info(cord_internal::CordzInfo* cordz_info) {
823 assert(cordz_info != nullptr);
824 data_.set_cordz_info(cordz_info);
825 }
826
827 // Resets the current cordz_info to null / empty.
clear_cordz_info()828 void clear_cordz_info() { data_.clear_cordz_info(); }
829
830 private:
831 friend class Cord;
832
833 void AssignSlow(const InlineRep& src);
834 // Unrefs the tree and stops profiling.
835 void UnrefTree();
836
ResetToEmpty()837 void ResetToEmpty() { data_ = {}; }
838
set_inline_size(size_t size)839 void set_inline_size(size_t size) { data_.set_inline_size(size); }
inline_size()840 size_t inline_size() const { return data_.inline_size(); }
841
842 cord_internal::InlineData data_;
843 };
844 InlineRep contents_;
845
846 // Helper for MemoryUsage().
847 static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
848
849 // Helper for GetFlat() and TryFlat().
850 static bool GetFlatAux(absl::cord_internal::CordRep* rep,
851 absl::string_view* fragment);
852
853 // Helper for ForEachChunk().
854 static void ForEachChunkAux(
855 absl::cord_internal::CordRep* rep,
856 absl::FunctionRef<void(absl::string_view)> callback);
857
858 // The destructor for non-empty Cords.
859 void DestroyCordSlow();
860
861 // Out-of-line implementation of slower parts of logic.
862 void CopyToArraySlowPath(char* dst) const;
863 int CompareSlowPath(absl::string_view rhs, size_t compared_size,
864 size_t size_to_compare) const;
865 int CompareSlowPath(const Cord& rhs, size_t compared_size,
866 size_t size_to_compare) const;
867 bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
868 bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
869 int CompareImpl(const Cord& rhs) const;
870
871 template <typename ResultType, typename RHS>
872 friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
873 size_t size_to_compare);
874 static absl::string_view GetFirstChunk(const Cord& c);
875 static absl::string_view GetFirstChunk(absl::string_view sv);
876
877 // Returns a new reference to contents_.tree(), or steals an existing
878 // reference if called on an rvalue.
879 absl::cord_internal::CordRep* TakeRep() const&;
880 absl::cord_internal::CordRep* TakeRep() &&;
881
882 // Helper for Append().
883 template <typename C>
884 void AppendImpl(C&& src);
885
886 // Assigns the value in 'src' to this instance, 'stealing' its contents.
887 // Requires src.length() > kMaxBytesToCopy.
888 Cord& AssignLargeString(std::string&& src);
889
890 // Helper for AbslHashValue().
891 template <typename H>
HashFragmented(H hash_state)892 H HashFragmented(H hash_state) const {
893 typename H::AbslInternalPiecewiseCombiner combiner;
894 ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
895 hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
896 chunk.size());
897 });
898 return H::combine(combiner.finalize(std::move(hash_state)), size());
899 }
900 };
901
902 ABSL_NAMESPACE_END
903 } // namespace absl
904
905 namespace absl {
906 ABSL_NAMESPACE_BEGIN
907
908 // allow a Cord to be logged
909 extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
910
911 // ------------------------------------------------------------------
912 // Internal details follow. Clients should ignore.
913
914 namespace cord_internal {
915
916 // Fast implementation of memmove for up to 15 bytes. This implementation is
917 // safe for overlapping regions. If nullify_tail is true, the destination is
918 // padded with '\0' up to 16 bytes.
919 inline void SmallMemmove(char* dst, const char* src, size_t n,
920 bool nullify_tail = false) {
921 if (n >= 8) {
922 assert(n <= 16);
923 uint64_t buf1;
924 uint64_t buf2;
925 memcpy(&buf1, src, 8);
926 memcpy(&buf2, src + n - 8, 8);
927 if (nullify_tail) {
928 memset(dst + 8, 0, 8);
929 }
930 memcpy(dst, &buf1, 8);
931 memcpy(dst + n - 8, &buf2, 8);
932 } else if (n >= 4) {
933 uint32_t buf1;
934 uint32_t buf2;
935 memcpy(&buf1, src, 4);
936 memcpy(&buf2, src + n - 4, 4);
937 if (nullify_tail) {
938 memset(dst + 4, 0, 4);
939 memset(dst + 8, 0, 8);
940 }
941 memcpy(dst, &buf1, 4);
942 memcpy(dst + n - 4, &buf2, 4);
943 } else {
944 if (n != 0) {
945 dst[0] = src[0];
946 dst[n / 2] = src[n / 2];
947 dst[n - 1] = src[n - 1];
948 }
949 if (nullify_tail) {
950 memset(dst + 8, 0, 8);
951 memset(dst + n, 0, 8);
952 }
953 }
954 }
955
956 // Does non-template-specific `CordRepExternal` initialization.
957 // Expects `data` to be non-empty.
958 void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
959
960 // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
961 // to it, or `nullptr` if `data` was empty.
962 template <typename Releaser>
963 // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
NewExternalRep(absl::string_view data,Releaser && releaser)964 CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
965 using ReleaserType = absl::decay_t<Releaser>;
966 if (data.empty()) {
967 // Never create empty external nodes.
968 InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
969 data);
970 return nullptr;
971 }
972
973 CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
974 std::forward<Releaser>(releaser), 0);
975 InitializeCordRepExternal(data, rep);
976 return rep;
977 }
978
979 // Overload for function reference types that dispatches using a function
980 // pointer because there are no `alignof()` or `sizeof()` a function reference.
981 // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
NewExternalRep(absl::string_view data,void (& releaser)(absl::string_view))982 inline CordRep* NewExternalRep(absl::string_view data,
983 void (&releaser)(absl::string_view)) {
984 return NewExternalRep(data, &releaser);
985 }
986
987 } // namespace cord_internal
988
989 template <typename Releaser>
MakeCordFromExternal(absl::string_view data,Releaser && releaser)990 Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
991 Cord cord;
992 if (auto* rep = ::absl::cord_internal::NewExternalRep(
993 data, std::forward<Releaser>(releaser))) {
994 cord.contents_.EmplaceTree(rep,
995 Cord::MethodIdentifier::kMakeCordFromExternal);
996 }
997 return cord;
998 }
999
InlineRep(cord_internal::InlineData data)1000 constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
1001 : data_(data) {}
1002
InlineRep(const Cord::InlineRep & src)1003 inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
1004 : data_(InlineData::kDefaultInit) {
1005 if (CordRep* tree = src.tree()) {
1006 EmplaceTree(CordRep::Ref(tree), src.data_,
1007 CordzUpdateTracker::kConstructorCord);
1008 } else {
1009 data_ = src.data_;
1010 }
1011 }
1012
InlineRep(Cord::InlineRep && src)1013 inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {
1014 src.ResetToEmpty();
1015 }
1016
1017 inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
1018 if (this == &src) {
1019 return *this;
1020 }
1021 if (!is_tree() && !src.is_tree()) {
1022 data_ = src.data_;
1023 return *this;
1024 }
1025 AssignSlow(src);
1026 return *this;
1027 }
1028
1029 inline Cord::InlineRep& Cord::InlineRep::operator=(
1030 Cord::InlineRep&& src) noexcept {
1031 if (is_tree()) {
1032 UnrefTree();
1033 }
1034 data_ = src.data_;
1035 src.ResetToEmpty();
1036 return *this;
1037 }
1038
Swap(Cord::InlineRep * rhs)1039 inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
1040 if (rhs == this) {
1041 return;
1042 }
1043 std::swap(data_, rhs->data_);
1044 }
1045
data()1046 inline const char* Cord::InlineRep::data() const {
1047 return is_tree() ? nullptr : data_.as_chars();
1048 }
1049
as_tree()1050 inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
1051 assert(data_.is_tree());
1052 return data_.as_tree();
1053 }
1054
tree()1055 inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
1056 if (is_tree()) {
1057 return as_tree();
1058 } else {
1059 return nullptr;
1060 }
1061 }
1062
empty()1063 inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
1064
size()1065 inline size_t Cord::InlineRep::size() const {
1066 return is_tree() ? as_tree()->length : inline_size();
1067 }
1068
MakeFlatWithExtraCapacity(size_t extra)1069 inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
1070 size_t extra) {
1071 static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
1072 size_t len = data_.inline_size();
1073 auto* result = CordRepFlat::New(len + extra);
1074 result->length = len;
1075 memcpy(result->Data(), data_.as_chars(), sizeof(data_));
1076 return result;
1077 }
1078
EmplaceTree(CordRep * rep,MethodIdentifier method)1079 inline void Cord::InlineRep::EmplaceTree(CordRep* rep,
1080 MethodIdentifier method) {
1081 assert(rep);
1082 data_.make_tree(rep);
1083 CordzInfo::MaybeTrackCord(data_, method);
1084 }
1085
EmplaceTree(CordRep * rep,const InlineData & parent,MethodIdentifier method)1086 inline void Cord::InlineRep::EmplaceTree(CordRep* rep, const InlineData& parent,
1087 MethodIdentifier method) {
1088 data_.make_tree(rep);
1089 CordzInfo::MaybeTrackCord(data_, parent, method);
1090 }
1091
SetTree(CordRep * rep,const CordzUpdateScope & scope)1092 inline void Cord::InlineRep::SetTree(CordRep* rep,
1093 const CordzUpdateScope& scope) {
1094 assert(rep);
1095 assert(data_.is_tree());
1096 data_.set_tree(rep);
1097 scope.SetCordRep(rep);
1098 }
1099
SetTreeOrEmpty(CordRep * rep,const CordzUpdateScope & scope)1100 inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep,
1101 const CordzUpdateScope& scope) {
1102 assert(data_.is_tree());
1103 if (rep) {
1104 data_.set_tree(rep);
1105 } else {
1106 data_ = {};
1107 }
1108 scope.SetCordRep(rep);
1109 }
1110
CommitTree(const CordRep * old_rep,CordRep * rep,const CordzUpdateScope & scope,MethodIdentifier method)1111 inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep,
1112 const CordzUpdateScope& scope,
1113 MethodIdentifier method) {
1114 if (old_rep) {
1115 SetTree(rep, scope);
1116 } else {
1117 EmplaceTree(rep, method);
1118 }
1119 }
1120
clear()1121 inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
1122 if (is_tree()) {
1123 CordzInfo::MaybeUntrackCord(cordz_info());
1124 }
1125 absl::cord_internal::CordRep* result = tree();
1126 ResetToEmpty();
1127 return result;
1128 }
1129
CopyToArray(char * dst)1130 inline void Cord::InlineRep::CopyToArray(char* dst) const {
1131 assert(!is_tree());
1132 size_t n = inline_size();
1133 assert(n != 0);
1134 cord_internal::SmallMemmove(dst, data_.as_chars(), n);
1135 }
1136
Cord()1137 constexpr inline Cord::Cord() noexcept {}
1138
Cord(absl::string_view src)1139 inline Cord::Cord(absl::string_view src)
1140 : Cord(src, CordzUpdateTracker::kConstructorString) {}
1141
1142 template <typename T>
Cord(strings_internal::StringConstant<T>)1143 constexpr Cord::Cord(strings_internal::StringConstant<T>)
1144 : contents_(strings_internal::StringConstant<T>::value.size() <=
1145 cord_internal::kMaxInline
1146 ? cord_internal::InlineData(
1147 strings_internal::StringConstant<T>::value)
1148 : cord_internal::InlineData(
1149 &cord_internal::ConstInitExternalStorage<
1150 strings_internal::StringConstant<T>>::value)) {}
1151
1152 inline Cord& Cord::operator=(const Cord& x) {
1153 contents_ = x.contents_;
1154 return *this;
1155 }
1156
1157 template <typename T, Cord::EnableIfString<T>>
1158 Cord& Cord::operator=(T&& src) {
1159 if (src.size() <= cord_internal::kMaxBytesToCopy) {
1160 return operator=(absl::string_view(src));
1161 } else {
1162 return AssignLargeString(std::forward<T>(src));
1163 }
1164 }
1165
Cord(const Cord & src)1166 inline Cord::Cord(const Cord& src) : contents_(src.contents_) {}
1167
Cord(Cord && src)1168 inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
1169
swap(Cord & other)1170 inline void Cord::swap(Cord& other) noexcept {
1171 contents_.Swap(&other.contents_);
1172 }
1173
1174 inline Cord& Cord::operator=(Cord&& x) noexcept {
1175 contents_ = std::move(x.contents_);
1176 return *this;
1177 }
1178
1179 extern template Cord::Cord(std::string&& src);
1180
size()1181 inline size_t Cord::size() const {
1182 // Length is 1st field in str.rep_
1183 return contents_.size();
1184 }
1185
empty()1186 inline bool Cord::empty() const { return contents_.empty(); }
1187
EstimatedMemoryUsage()1188 inline size_t Cord::EstimatedMemoryUsage() const {
1189 size_t result = sizeof(Cord);
1190 if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
1191 result += MemoryUsageAux(rep);
1192 }
1193 return result;
1194 }
1195
TryFlat()1196 inline absl::optional<absl::string_view> Cord::TryFlat() const {
1197 absl::cord_internal::CordRep* rep = contents_.tree();
1198 if (rep == nullptr) {
1199 return absl::string_view(contents_.data(), contents_.size());
1200 }
1201 absl::string_view fragment;
1202 if (GetFlatAux(rep, &fragment)) {
1203 return fragment;
1204 }
1205 return absl::nullopt;
1206 }
1207
Flatten()1208 inline absl::string_view Cord::Flatten() {
1209 absl::cord_internal::CordRep* rep = contents_.tree();
1210 if (rep == nullptr) {
1211 return absl::string_view(contents_.data(), contents_.size());
1212 } else {
1213 absl::string_view already_flat_contents;
1214 if (GetFlatAux(rep, &already_flat_contents)) {
1215 return already_flat_contents;
1216 }
1217 }
1218 return FlattenSlowPath();
1219 }
1220
Append(absl::string_view src)1221 inline void Cord::Append(absl::string_view src) {
1222 contents_.AppendArray(src, CordzUpdateTracker::kAppendString);
1223 }
1224
1225 extern template void Cord::Append(std::string&& src);
1226 extern template void Cord::Prepend(std::string&& src);
1227
Compare(const Cord & rhs)1228 inline int Cord::Compare(const Cord& rhs) const {
1229 if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
1230 return contents_.BitwiseCompare(rhs.contents_);
1231 }
1232
1233 return CompareImpl(rhs);
1234 }
1235
1236 // Does 'this' cord start/end with rhs
StartsWith(const Cord & rhs)1237 inline bool Cord::StartsWith(const Cord& rhs) const {
1238 if (contents_.IsSame(rhs.contents_)) return true;
1239 size_t rhs_size = rhs.size();
1240 if (size() < rhs_size) return false;
1241 return EqualsImpl(rhs, rhs_size);
1242 }
1243
StartsWith(absl::string_view rhs)1244 inline bool Cord::StartsWith(absl::string_view rhs) const {
1245 size_t rhs_size = rhs.size();
1246 if (size() < rhs_size) return false;
1247 return EqualsImpl(rhs, rhs_size);
1248 }
1249
InitTree(cord_internal::CordRep * tree)1250 inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
1251 if (tree->tag == cord_internal::BTREE) {
1252 current_chunk_ = btree_reader_.Init(tree->btree());
1253 return;
1254 }
1255
1256 stack_of_right_children_.push_back(tree);
1257 operator++();
1258 }
1259
ChunkIterator(cord_internal::CordRep * tree)1260 inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree)
1261 : bytes_remaining_(tree->length) {
1262 InitTree(tree);
1263 }
1264
ChunkIterator(const Cord * cord)1265 inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
1266 : bytes_remaining_(cord->size()) {
1267 if (cord->contents_.is_tree()) {
1268 InitTree(cord->contents_.as_tree());
1269 } else {
1270 current_chunk_ =
1271 absl::string_view(cord->contents_.data(), bytes_remaining_);
1272 }
1273 }
1274
AdvanceBtree()1275 inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {
1276 current_chunk_ = btree_reader_.Next();
1277 return *this;
1278 }
1279
AdvanceBytesBtree(size_t n)1280 inline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) {
1281 assert(n >= current_chunk_.size());
1282 bytes_remaining_ -= n;
1283 if (bytes_remaining_) {
1284 if (n == current_chunk_.size()) {
1285 current_chunk_ = btree_reader_.Next();
1286 } else {
1287 size_t offset = btree_reader_.length() - bytes_remaining_;
1288 current_chunk_ = btree_reader_.Seek(offset);
1289 }
1290 } else {
1291 current_chunk_ = {};
1292 }
1293 }
1294
1295 inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
1296 ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
1297 "Attempted to iterate past `end()`");
1298 assert(bytes_remaining_ >= current_chunk_.size());
1299 bytes_remaining_ -= current_chunk_.size();
1300 if (bytes_remaining_ > 0) {
1301 return btree_reader_ ? AdvanceBtree() : AdvanceStack();
1302 } else {
1303 current_chunk_ = {};
1304 }
1305 return *this;
1306 }
1307
1308 inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
1309 ChunkIterator tmp(*this);
1310 operator++();
1311 return tmp;
1312 }
1313
1314 inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
1315 return bytes_remaining_ == other.bytes_remaining_;
1316 }
1317
1318 inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
1319 return !(*this == other);
1320 }
1321
1322 inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
1323 ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
1324 return current_chunk_;
1325 }
1326
1327 inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
1328 ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
1329 return ¤t_chunk_;
1330 }
1331
RemoveChunkPrefix(size_t n)1332 inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
1333 assert(n < current_chunk_.size());
1334 current_chunk_.remove_prefix(n);
1335 bytes_remaining_ -= n;
1336 }
1337
AdvanceBytes(size_t n)1338 inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
1339 assert(bytes_remaining_ >= n);
1340 if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
1341 RemoveChunkPrefix(n);
1342 } else if (n != 0) {
1343 btree_reader_ ? AdvanceBytesBtree(n) : AdvanceBytesSlowPath(n);
1344 }
1345 }
1346
chunk_begin()1347 inline Cord::ChunkIterator Cord::chunk_begin() const {
1348 return ChunkIterator(this);
1349 }
1350
chunk_end()1351 inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
1352
begin()1353 inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
1354 return cord_->chunk_begin();
1355 }
1356
end()1357 inline Cord::ChunkIterator Cord::ChunkRange::end() const {
1358 return cord_->chunk_end();
1359 }
1360
Chunks()1361 inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
1362
1363 inline Cord::CharIterator& Cord::CharIterator::operator++() {
1364 if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
1365 chunk_iterator_.RemoveChunkPrefix(1);
1366 } else {
1367 ++chunk_iterator_;
1368 }
1369 return *this;
1370 }
1371
1372 inline Cord::CharIterator Cord::CharIterator::operator++(int) {
1373 CharIterator tmp(*this);
1374 operator++();
1375 return tmp;
1376 }
1377
1378 inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
1379 return chunk_iterator_ == other.chunk_iterator_;
1380 }
1381
1382 inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
1383 return !(*this == other);
1384 }
1385
1386 inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
1387 return *chunk_iterator_->data();
1388 }
1389
1390 inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
1391 return chunk_iterator_->data();
1392 }
1393
AdvanceAndRead(CharIterator * it,size_t n_bytes)1394 inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) {
1395 assert(it != nullptr);
1396 return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
1397 }
1398
Advance(CharIterator * it,size_t n_bytes)1399 inline void Cord::Advance(CharIterator* it, size_t n_bytes) {
1400 assert(it != nullptr);
1401 it->chunk_iterator_.AdvanceBytes(n_bytes);
1402 }
1403
ChunkRemaining(const CharIterator & it)1404 inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
1405 return *it.chunk_iterator_;
1406 }
1407
char_begin()1408 inline Cord::CharIterator Cord::char_begin() const {
1409 return CharIterator(this);
1410 }
1411
char_end()1412 inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
1413
begin()1414 inline Cord::CharIterator Cord::CharRange::begin() const {
1415 return cord_->char_begin();
1416 }
1417
end()1418 inline Cord::CharIterator Cord::CharRange::end() const {
1419 return cord_->char_end();
1420 }
1421
Chars()1422 inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
1423
ForEachChunk(absl::FunctionRef<void (absl::string_view)> callback)1424 inline void Cord::ForEachChunk(
1425 absl::FunctionRef<void(absl::string_view)> callback) const {
1426 absl::cord_internal::CordRep* rep = contents_.tree();
1427 if (rep == nullptr) {
1428 callback(absl::string_view(contents_.data(), contents_.size()));
1429 } else {
1430 return ForEachChunkAux(rep, callback);
1431 }
1432 }
1433
1434 // Nonmember Cord-to-Cord relational operarators.
1435 inline bool operator==(const Cord& lhs, const Cord& rhs) {
1436 if (lhs.contents_.IsSame(rhs.contents_)) return true;
1437 size_t rhs_size = rhs.size();
1438 if (lhs.size() != rhs_size) return false;
1439 return lhs.EqualsImpl(rhs, rhs_size);
1440 }
1441
1442 inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
1443 inline bool operator<(const Cord& x, const Cord& y) {
1444 return x.Compare(y) < 0;
1445 }
1446 inline bool operator>(const Cord& x, const Cord& y) {
1447 return x.Compare(y) > 0;
1448 }
1449 inline bool operator<=(const Cord& x, const Cord& y) {
1450 return x.Compare(y) <= 0;
1451 }
1452 inline bool operator>=(const Cord& x, const Cord& y) {
1453 return x.Compare(y) >= 0;
1454 }
1455
1456 // Nonmember Cord-to-absl::string_view relational operators.
1457 //
1458 // Due to implicit conversions, these also enable comparisons of Cord with
1459 // with std::string, ::string, and const char*.
1460 inline bool operator==(const Cord& lhs, absl::string_view rhs) {
1461 size_t lhs_size = lhs.size();
1462 size_t rhs_size = rhs.size();
1463 if (lhs_size != rhs_size) return false;
1464 return lhs.EqualsImpl(rhs, rhs_size);
1465 }
1466
1467 inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
1468 inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
1469 inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
1470 inline bool operator<(const Cord& x, absl::string_view y) {
1471 return x.Compare(y) < 0;
1472 }
1473 inline bool operator<(absl::string_view x, const Cord& y) {
1474 return y.Compare(x) > 0;
1475 }
1476 inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
1477 inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
1478 inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
1479 inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
1480 inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
1481 inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
1482
1483 // Some internals exposed to test code.
1484 namespace strings_internal {
1485 class CordTestAccess {
1486 public:
1487 static size_t FlatOverhead();
1488 static size_t MaxFlatLength();
1489 static size_t SizeofCordRepConcat();
1490 static size_t SizeofCordRepExternal();
1491 static size_t SizeofCordRepSubstring();
1492 static size_t FlatTagToLength(uint8_t tag);
1493 static uint8_t LengthToTag(size_t s);
1494 };
1495 } // namespace strings_internal
1496 ABSL_NAMESPACE_END
1497 } // namespace absl
1498
1499 #endif // ABSL_STRINGS_CORD_H_
1500