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