/src/abseil-cpp/absl/strings/cord.h
Line  | Count  | Source  | 
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."  | 
24  |  | //  | 
25  |  | // Because a Cord consists of these chunks, data can be added to or removed from  | 
26  |  | // a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a  | 
27  |  | // `std::string`, a Cord can therefore accommodate data that changes over its  | 
28  |  | // lifetime, though it's not quite "mutable"; it can change only in the  | 
29  |  | // attachment, detachment, or rearrangement of chunks of its constituent data.  | 
30  |  | //  | 
31  |  | // A Cord provides some benefit over `std::string` under the following (albeit  | 
32  |  | // narrow) circumstances:  | 
33  |  | //  | 
34  |  | //   * Cord data is designed to grow and shrink over a Cord's lifetime. Cord  | 
35  |  | //     provides efficient insertions and deletions at the start and end of the  | 
36  |  | //     character sequences, avoiding copies in those cases. Static data should  | 
37  |  | //     generally be stored as strings.  | 
38  |  | //   * External memory consisting of string-like data can be directly added to  | 
39  |  | //     a Cord without requiring copies or allocations.  | 
40  |  | //   * Cord data may be shared and copied cheaply. Cord provides a copy-on-write  | 
41  |  | //     implementation and cheap sub-Cord operations. Copying a Cord is an O(1)  | 
42  |  | //     operation.  | 
43  |  | //  | 
44  |  | // As a consequence to the above, Cord data is generally large. Small data  | 
45  |  | // should generally use strings, as construction of a Cord requires some  | 
46  |  | // overhead. Small Cords (<= 15 bytes) are represented inline, but most small  | 
47  |  | // Cords are expected to grow over their lifetimes.  | 
48  |  | //  | 
49  |  | // Note that because a Cord is made up of separate chunked data, random access  | 
50  |  | // to character data within a Cord is slower than within a `std::string`.  | 
51  |  | //  | 
52  |  | // Thread Safety  | 
53  |  | //  | 
54  |  | // Cord has the same thread-safety properties as many other types like  | 
55  |  | // std::string, std::vector<>, int, etc -- it is thread-compatible. In  | 
56  |  | // particular, if threads do not call non-const methods, then it is safe to call  | 
57  |  | // const methods without synchronization. Copying a Cord produces a new instance  | 
58  |  | // that can be used concurrently with the original in arbitrary ways.  | 
59  |  |  | 
60  |  | #ifndef ABSL_STRINGS_CORD_H_  | 
61  |  | #define ABSL_STRINGS_CORD_H_  | 
62  |  |  | 
63  |  | #include <algorithm>  | 
64  |  | #include <cassert>  | 
65  |  | #include <cstddef>  | 
66  |  | #include <cstdint>  | 
67  |  | #include <cstring>  | 
68  |  | #include <iosfwd>  | 
69  |  | #include <iterator>  | 
70  |  | #include <string>  | 
71  |  | #include <type_traits>  | 
72  |  | #include <utility>  | 
73  |  |  | 
74  |  | #include "absl/base/attributes.h"  | 
75  |  | #include "absl/base/config.h"  | 
76  |  | #include "absl/base/internal/endian.h"  | 
77  |  | #include "absl/base/macros.h"  | 
78  |  | #include "absl/base/nullability.h"  | 
79  |  | #include "absl/base/optimization.h"  | 
80  |  | #include "absl/crc/internal/crc_cord_state.h"  | 
81  |  | #include "absl/functional/function_ref.h"  | 
82  |  | #include "absl/hash/internal/weakly_mixed_integer.h"  | 
83  |  | #include "absl/meta/type_traits.h"  | 
84  |  | #include "absl/strings/cord_analysis.h"  | 
85  |  | #include "absl/strings/cord_buffer.h"  | 
86  |  | #include "absl/strings/internal/cord_data_edge.h"  | 
87  |  | #include "absl/strings/internal/cord_internal.h"  | 
88  |  | #include "absl/strings/internal/cord_rep_btree.h"  | 
89  |  | #include "absl/strings/internal/cord_rep_btree_reader.h"  | 
90  |  | #include "absl/strings/internal/cord_rep_crc.h"  | 
91  |  | #include "absl/strings/internal/cord_rep_flat.h"  | 
92  |  | #include "absl/strings/internal/cordz_info.h"  | 
93  |  | #include "absl/strings/internal/cordz_update_scope.h"  | 
94  |  | #include "absl/strings/internal/cordz_update_tracker.h"  | 
95  |  | #include "absl/strings/internal/string_constant.h"  | 
96  |  | #include "absl/strings/string_view.h"  | 
97  |  | #include "absl/types/compare.h"  | 
98  |  | #include "absl/types/optional.h"  | 
99  |  |  | 
100  |  | namespace absl { | 
101  |  | ABSL_NAMESPACE_BEGIN  | 
102  |  | class Cord;  | 
103  |  | class CordTestPeer;  | 
104  |  | template <typename Releaser>  | 
105  |  | Cord MakeCordFromExternal(absl::string_view, Releaser&&);  | 
106  |  | void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);  | 
107  |  | void AppendCordToString(const Cord& src, std::string* absl_nonnull dst);  | 
108  |  |  | 
109  |  | // Cord memory accounting modes  | 
110  |  | enum class CordMemoryAccounting { | 
111  |  |   // Counts the *approximate* number of bytes held in full or in part by this  | 
112  |  |   // Cord (which may not remain the same between invocations). Cords that share  | 
113  |  |   // memory could each be "charged" independently for the same shared memory.  | 
114  |  |   // See also comment on `kTotalMorePrecise` on internally shared memory.  | 
115  |  |   kTotal,  | 
116  |  |  | 
117  |  |   // Counts the *approximate* number of bytes held in full or in part by this  | 
118  |  |   // Cord for the distinct memory held by this cord. This option is similar  | 
119  |  |   // to `kTotal`, except that if the cord has multiple references to the same  | 
120  |  |   // memory, that memory is only counted once.  | 
121  |  |   //  | 
122  |  |   // For example:  | 
123  |  |   //   absl::Cord cord;  | 
124  |  |   //   cord.Append(some_other_cord);  | 
125  |  |   //   cord.Append(some_other_cord);  | 
126  |  |   //   // Counts `some_other_cord` twice:  | 
127  |  |   //   cord.EstimatedMemoryUsage(kTotal);  | 
128  |  |   //   // Counts `some_other_cord` once:  | 
129  |  |   //   cord.EstimatedMemoryUsage(kTotalMorePrecise);  | 
130  |  |   //  | 
131  |  |   // The `kTotalMorePrecise` number is more expensive to compute as it requires  | 
132  |  |   // deduplicating all memory references. Applications should prefer to use  | 
133  |  |   // `kFairShare` or `kTotal` unless they really need a more precise estimate  | 
134  |  |   // on "how much memory is potentially held / kept alive by this cord?"  | 
135  |  |   kTotalMorePrecise,  | 
136  |  |  | 
137  |  |   // Counts the *approximate* number of bytes held in full or in part by this  | 
138  |  |   // Cord weighted by the sharing ratio of that data. For example, if some data  | 
139  |  |   // edge is shared by 4 different Cords, then each cord is attributed 1/4th of  | 
140  |  |   // the total memory usage as a 'fair share' of the total memory usage.  | 
141  |  |   kFairShare,  | 
142  |  | };  | 
143  |  |  | 
144  |  | // Cord  | 
145  |  | //  | 
146  |  | // A Cord is a sequence of characters, designed to be more efficient than a  | 
147  |  | // `std::string` in certain circumstances: namely, large string data that needs  | 
148  |  | // to change over its lifetime or shared, especially when such data is shared  | 
149  |  | // across API boundaries.  | 
150  |  | //  | 
151  |  | // A Cord stores its character data in a structure that allows efficient prepend  | 
152  |  | // and append operations. This makes a Cord useful for large string data sent  | 
153  |  | // over in a wire format that may need to be prepended or appended at some point  | 
154  |  | // during the data exchange (e.g. HTTP, protocol buffers). For example, a  | 
155  |  | // Cord is useful for storing an HTTP request, and prepending an HTTP header to  | 
156  |  | // such a request.  | 
157  |  | //  | 
158  |  | // Cords should not be used for storing general string data, however. They  | 
159  |  | // require overhead to construct and are slower than strings for random access.  | 
160  |  | //  | 
161  |  | // The Cord API provides the following common API operations:  | 
162  |  | //  | 
163  |  | // * Create or assign Cords out of existing string data, memory, or other Cords  | 
164  |  | // * Append and prepend data to an existing Cord  | 
165  |  | // * Create new Sub-Cords from existing Cord data  | 
166  |  | // * Swap Cord data and compare Cord equality  | 
167  |  | // * Write out Cord data by constructing a `std::string`  | 
168  |  | //  | 
169  |  | // Additionally, the API provides iterator utilities to iterate through Cord  | 
170  |  | // data via chunks or character bytes.  | 
171  |  | //  | 
172  |  | class Cord { | 
173  |  |  private:  | 
174  |  |   template <typename T>  | 
175  |  |   using EnableIfString =  | 
176  |  |       absl::enable_if_t<std::is_same<T, std::string>::value, int>;  | 
177  |  |  | 
178  |  |  public:  | 
179  |  |   // Cord::Cord() Constructors.  | 
180  |  |  | 
181  |  |   // Creates an empty Cord.  | 
182  |  |   constexpr Cord() noexcept;  | 
183  |  |  | 
184  |  |   // Creates a Cord from an existing Cord. Cord is copyable and efficiently  | 
185  |  |   // movable. The moved-from state is valid but unspecified.  | 
186  |  |   Cord(const Cord& src);  | 
187  |  |   Cord(Cord&& src) noexcept;  | 
188  |  |   Cord& operator=(const Cord& x);  | 
189  |  |   Cord& operator=(Cord&& x) noexcept;  | 
190  |  |  | 
191  |  |   // Creates a Cord from a `src` string. This constructor is marked explicit to  | 
192  |  |   // prevent implicit Cord constructions from arguments convertible to an  | 
193  |  |   // `absl::string_view`.  | 
194  |  |   explicit Cord(absl::string_view src);  | 
195  |  |   Cord& operator=(absl::string_view src);  | 
196  |  |  | 
197  |  |   // Creates a Cord from a `std::string&&` rvalue. These constructors are  | 
198  |  |   // templated to avoid ambiguities for types that are convertible to both  | 
199  |  |   // `absl::string_view` and `std::string`, such as `const char*`.  | 
200  |  |   template <typename T, EnableIfString<T> = 0>  | 
201  |  |   explicit Cord(T&& src);  | 
202  |  |   template <typename T, EnableIfString<T> = 0>  | 
203  |  |   Cord& operator=(T&& src);  | 
204  |  |  | 
205  |  |   // Cord::~Cord()  | 
206  |  |   //  | 
207  |  |   // Destructs the Cord.  | 
208  | 0  |   ~Cord() { | 
209  | 0  |     if (contents_.is_tree()) DestroyCordSlow();  | 
210  | 0  |   }  | 
211  |  |  | 
212  |  |   // MakeCordFromExternal()  | 
213  |  |   //  | 
214  |  |   // Creates a Cord that takes ownership of external string memory. The  | 
215  |  |   // contents of `data` are not copied to the Cord; instead, the external  | 
216  |  |   // memory is added to the Cord and reference-counted. This data may not be  | 
217  |  |   // changed for the life of the Cord, though it may be prepended or appended  | 
218  |  |   // to.  | 
219  |  |   //  | 
220  |  |   // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when  | 
221  |  |   // the reference count for `data` reaches zero. As noted above, this data must  | 
222  |  |   // remain live until the releaser is invoked. The callable releaser also must:  | 
223  |  |   //  | 
224  |  |   //   * be move constructible  | 
225  |  |   //   * support `void operator()(absl::string_view) const` or `void operator()`  | 
226  |  |   //  | 
227  |  |   // Example:  | 
228  |  |   //  | 
229  |  |   // Cord MakeCord(BlockPool* pool) { | 
230  |  |   //   Block* block = pool->NewBlock();  | 
231  |  |   //   FillBlock(block);  | 
232  |  |   //   return absl::MakeCordFromExternal(  | 
233  |  |   //       block->ToStringView(),  | 
234  |  |   //       [pool, block](absl::string_view v) { | 
235  |  |   //         pool->FreeBlock(block, v);  | 
236  |  |   //       });  | 
237  |  |   // }  | 
238  |  |   //  | 
239  |  |   // WARNING: Because a Cord can be reference-counted, it's likely a bug if your  | 
240  |  |   // releaser doesn't do anything. For example, consider the following:  | 
241  |  |   //  | 
242  |  |   // void Foo(const char* buffer, int len) { | 
243  |  |   //   auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),  | 
244  |  |   //                                       [](absl::string_view) {}); | 
245  |  |   //  | 
246  |  |   //   // BUG: If Bar() copies its cord for any reason, including keeping a  | 
247  |  |   //   // substring of it, the lifetime of buffer might be extended beyond  | 
248  |  |   //   // when Foo() returns.  | 
249  |  |   //   Bar(c);  | 
250  |  |   // }  | 
251  |  |   template <typename Releaser>  | 
252  |  |   friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);  | 
253  |  |  | 
254  |  |   // Cord::Clear()  | 
255  |  |   //  | 
256  |  |   // Releases the Cord data. Any nodes that share data with other Cords, if  | 
257  |  |   // applicable, will have their reference counts reduced by 1.  | 
258  |  |   ABSL_ATTRIBUTE_REINITIALIZES void Clear();  | 
259  |  |  | 
260  |  |   // Cord::Append()  | 
261  |  |   //  | 
262  |  |   // Appends data to the Cord, which may come from another Cord or other string  | 
263  |  |   // data.  | 
264  |  |   void Append(const Cord& src);  | 
265  |  |   void Append(Cord&& src);  | 
266  |  |   void Append(absl::string_view src);  | 
267  |  |   template <typename T, EnableIfString<T> = 0>  | 
268  |  |   void Append(T&& src);  | 
269  |  |  | 
270  |  |   // Appends `buffer` to this cord, unless `buffer` has a zero length in which  | 
271  |  |   // case this method has no effect on this cord instance.  | 
272  |  |   // This method is guaranteed to consume `buffer`.  | 
273  |  |   void Append(CordBuffer buffer);  | 
274  |  |  | 
275  |  |   // Returns a CordBuffer, re-using potential existing capacity in this cord.  | 
276  |  |   //  | 
277  |  |   // Cord instances may have additional unused capacity in the last (or first)  | 
278  |  |   // nodes of the underlying tree to facilitate amortized growth. This method  | 
279  |  |   // allows applications to explicitly use this spare capacity if available,  | 
280  |  |   // or create a new CordBuffer instance otherwise.  | 
281  |  |   // If this cord has a final non-shared node with at least `min_capacity`  | 
282  |  |   // available, then this method will return that buffer including its data  | 
283  |  |   // contents. I.e.; the returned buffer will have a non-zero length, and  | 
284  |  |   // a capacity of at least `buffer.length + min_capacity`. Otherwise, this  | 
285  |  |   // method will return `CordBuffer::CreateWithDefaultLimit(capacity)`.  | 
286  |  |   //  | 
287  |  |   // Below an example of using GetAppendBuffer. Notice that in this example we  | 
288  |  |   // use `GetAppendBuffer()` only on the first iteration. As we know nothing  | 
289  |  |   // about any initial extra capacity in `cord`, we may be able to use the extra  | 
290  |  |   // capacity. But as we add new buffers with fully utilized contents after that  | 
291  |  |   // we avoid calling `GetAppendBuffer()` on subsequent iterations: while this  | 
292  |  |   // works fine, it results in an unnecessary inspection of cord contents:  | 
293  |  |   //  | 
294  |  |   //   void AppendRandomDataToCord(absl::Cord &cord, size_t n) { | 
295  |  |   //     bool first = true;  | 
296  |  |   //     while (n > 0) { | 
297  |  |   //       CordBuffer buffer = first ? cord.GetAppendBuffer(n)  | 
298  |  |   //                                 : CordBuffer::CreateWithDefaultLimit(n);  | 
299  |  |   //       absl::Span<char> data = buffer.available_up_to(n);  | 
300  |  |   //       FillRandomValues(data.data(), data.size());  | 
301  |  |   //       buffer.IncreaseLengthBy(data.size());  | 
302  |  |   //       cord.Append(std::move(buffer));  | 
303  |  |   //       n -= data.size();  | 
304  |  |   //       first = false;  | 
305  |  |   //     }  | 
306  |  |   //   }  | 
307  |  |   CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity = 16);  | 
308  |  |  | 
309  |  |   // Returns a CordBuffer, re-using potential existing capacity in this cord.  | 
310  |  |   //  | 
311  |  |   // This function is identical to `GetAppendBuffer`, except that in the case  | 
312  |  |   // where a new `CordBuffer` is allocated, it is allocated using the provided  | 
313  |  |   // custom limit instead of the default limit. `GetAppendBuffer` will default  | 
314  |  |   // to `CordBuffer::CreateWithDefaultLimit(capacity)` whereas this method  | 
315  |  |   // will default to `CordBuffer::CreateWithCustomLimit(block_size, capacity)`.  | 
316  |  |   // This method is equivalent to `GetAppendBuffer` if `block_size` is zero.  | 
317  |  |   // See the documentation for `CreateWithCustomLimit` for more details on the  | 
318  |  |   // restrictions and legal values for `block_size`.  | 
319  |  |   CordBuffer GetCustomAppendBuffer(size_t block_size, size_t capacity,  | 
320  |  |                                    size_t min_capacity = 16);  | 
321  |  |  | 
322  |  |   // Cord::Prepend()  | 
323  |  |   //  | 
324  |  |   // Prepends data to the Cord, which may come from another Cord or other string  | 
325  |  |   // data.  | 
326  |  |   void Prepend(const Cord& src);  | 
327  |  |   void Prepend(absl::string_view src);  | 
328  |  |   template <typename T, EnableIfString<T> = 0>  | 
329  |  |   void Prepend(T&& src);  | 
330  |  |  | 
331  |  |   // Prepends `buffer` to this cord, unless `buffer` has a zero length in which  | 
332  |  |   // case this method has no effect on this cord instance.  | 
333  |  |   // This method is guaranteed to consume `buffer`.  | 
334  |  |   void Prepend(CordBuffer buffer);  | 
335  |  |  | 
336  |  |   // Cord::RemovePrefix()  | 
337  |  |   //  | 
338  |  |   // Removes the first `n` bytes of a Cord.  | 
339  |  |   void RemovePrefix(size_t n);  | 
340  |  |   void RemoveSuffix(size_t n);  | 
341  |  |  | 
342  |  |   // Cord::Subcord()  | 
343  |  |   //  | 
344  |  |   // Returns a new Cord representing the subrange [pos, pos + new_size) of  | 
345  |  |   // *this. If pos >= size(), the result is empty(). If  | 
346  |  |   // (pos + new_size) >= size(), the result is the subrange [pos, size()).  | 
347  |  |   Cord Subcord(size_t pos, size_t new_size) const;  | 
348  |  |  | 
349  |  |   // Cord::swap()  | 
350  |  |   //  | 
351  |  |   // Swaps the contents of the Cord with `other`.  | 
352  |  |   void swap(Cord& other) noexcept;  | 
353  |  |  | 
354  |  |   // swap()  | 
355  |  |   //  | 
356  |  |   // Swaps the contents of two Cords.  | 
357  | 0  |   friend void swap(Cord& x, Cord& y) noexcept { x.swap(y); } | 
358  |  |  | 
359  |  |   // Cord::size()  | 
360  |  |   //  | 
361  |  |   // Returns the size of the Cord.  | 
362  |  |   size_t size() const;  | 
363  |  |  | 
364  |  |   // Cord::empty()  | 
365  |  |   //  | 
366  |  |   // Determines whether the given Cord is empty, returning `true` if so.  | 
367  |  |   bool empty() const;  | 
368  |  |  | 
369  |  |   // Cord::EstimatedMemoryUsage()  | 
370  |  |   //  | 
371  |  |   // Returns the *approximate* number of bytes held by this cord.  | 
372  |  |   // See CordMemoryAccounting for more information on the accounting method.  | 
373  |  |   size_t EstimatedMemoryUsage(CordMemoryAccounting accounting_method =  | 
374  |  |                                   CordMemoryAccounting::kTotal) const;  | 
375  |  |  | 
376  |  |   // Cord::Compare()  | 
377  |  |   //  | 
378  |  |   // Compares 'this' Cord with rhs. This function and its relatives treat Cords  | 
379  |  |   // as sequences of unsigned bytes. The comparison is a straightforward  | 
380  |  |   // lexicographic comparison. `Cord::Compare()` returns values as follows:  | 
381  |  |   //  | 
382  |  |   //   -1  'this' Cord is smaller  | 
383  |  |   //    0  two Cords are equal  | 
384  |  |   //    1  'this' Cord is larger  | 
385  |  |   int Compare(absl::string_view rhs) const;  | 
386  |  |   int Compare(const Cord& rhs) const;  | 
387  |  |  | 
388  |  |   // Cord::StartsWith()  | 
389  |  |   //  | 
390  |  |   // Determines whether the Cord starts with the passed string data `rhs`.  | 
391  |  |   bool StartsWith(const Cord& rhs) const;  | 
392  |  |   bool StartsWith(absl::string_view rhs) const;  | 
393  |  |  | 
394  |  |   // Cord::EndsWith()  | 
395  |  |   //  | 
396  |  |   // Determines whether the Cord ends with the passed string data `rhs`.  | 
397  |  |   bool EndsWith(absl::string_view rhs) const;  | 
398  |  |   bool EndsWith(const Cord& rhs) const;  | 
399  |  |  | 
400  |  |   // Cord::Contains()  | 
401  |  |   //  | 
402  |  |   // Determines whether the Cord contains the passed string data `rhs`.  | 
403  |  |   bool Contains(absl::string_view rhs) const;  | 
404  |  |   bool Contains(const Cord& rhs) const;  | 
405  |  |  | 
406  |  |   // Cord::operator std::string()  | 
407  |  |   //  | 
408  |  |   // Converts a Cord into a `std::string()`. This operator is marked explicit to  | 
409  |  |   // prevent unintended Cord usage in functions that take a string.  | 
410  |  |   explicit operator std::string() const;  | 
411  |  |  | 
412  |  |   // CopyCordToString()  | 
413  |  |   //  | 
414  |  |   // Copies the contents of a `src` Cord into a `*dst` string.  | 
415  |  |   //  | 
416  |  |   // This function optimizes the case of reusing the destination string since it  | 
417  |  |   // can reuse previously allocated capacity. However, this function does not  | 
418  |  |   // guarantee that pointers previously returned by `dst->data()` remain valid  | 
419  |  |   // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new  | 
420  |  |   // object, prefer to simply use the conversion operator to `std::string`.  | 
421  |  |   friend void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);  | 
422  |  |  | 
423  |  |   // AppendCordToString()  | 
424  |  |   //  | 
425  |  |   // Appends the contents of a `src` Cord to a `*dst` string.  | 
426  |  |   //  | 
427  |  |   // This function optimizes the case of appending to a non-empty destination  | 
428  |  |   // string. If `*dst` already has capacity to store the contents of the cord,  | 
429  |  |   // this function does not invalidate pointers previously returned by  | 
430  |  |   // `dst->data()`. If `*dst` is a new object, prefer to simply use the  | 
431  |  |   // conversion operator to `std::string`.  | 
432  |  |   friend void AppendCordToString(const Cord& src,  | 
433  |  |                                  std::string* absl_nonnull dst);  | 
434  |  |  | 
435  |  |   class CharIterator;  | 
436  |  |  | 
437  |  |   //----------------------------------------------------------------------------  | 
438  |  |   // Cord::ChunkIterator  | 
439  |  |   //----------------------------------------------------------------------------  | 
440  |  |   //  | 
441  |  |   // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its  | 
442  |  |   // Cord. Such iteration allows you to perform non-const operations on the data  | 
443  |  |   // of a Cord without modifying it.  | 
444  |  |   //  | 
445  |  |   // Generally, you do not instantiate a `Cord::ChunkIterator` directly;  | 
446  |  |   // instead, you create one implicitly through use of the `Cord::Chunks()`  | 
447  |  |   // member function.  | 
448  |  |   //  | 
449  |  |   // The `Cord::ChunkIterator` has the following properties:  | 
450  |  |   //  | 
451  |  |   //   * The iterator is invalidated after any non-const operation on the  | 
452  |  |   //     Cord object over which it iterates.  | 
453  |  |   //   * The `string_view` returned by dereferencing a valid, non-`end()`  | 
454  |  |   //     iterator is guaranteed to be non-empty.  | 
455  |  |   //   * Two `ChunkIterator` objects can be compared equal if and only if they  | 
456  |  |   //     remain valid and iterate over the same Cord.  | 
457  |  |   //   * The iterator in this case is a proxy iterator; the `string_view`  | 
458  |  |   //     returned by the iterator does not live inside the Cord, and its  | 
459  |  |   //     lifetime is limited to the lifetime of the iterator itself. To help  | 
460  |  |   //     prevent lifetime issues, `ChunkIterator::reference` is not a true  | 
461  |  |   //     reference type and is equivalent to `value_type`.  | 
462  |  |   //   * The iterator keeps state that can grow for Cords that contain many  | 
463  |  |   //     nodes and are imbalanced due to sharing. Prefer to pass this type by  | 
464  |  |   //     const reference instead of by value.  | 
465  |  |   class ChunkIterator { | 
466  |  |    public:  | 
467  |  |     using iterator_category = std::input_iterator_tag;  | 
468  |  |     using value_type = absl::string_view;  | 
469  |  |     using difference_type = ptrdiff_t;  | 
470  |  |     using pointer = const value_type* absl_nonnull;  | 
471  |  |     using reference = value_type;  | 
472  |  |  | 
473  |  |     ChunkIterator() = default;  | 
474  |  |  | 
475  |  |     ChunkIterator& operator++();  | 
476  |  |     ChunkIterator operator++(int);  | 
477  |  |     bool operator==(const ChunkIterator& other) const;  | 
478  |  |     bool operator!=(const ChunkIterator& other) const;  | 
479  |  |     reference operator*() const;  | 
480  |  |     pointer operator->() const;  | 
481  |  |  | 
482  |  |     friend class Cord;  | 
483  |  |     friend class CharIterator;  | 
484  |  |  | 
485  |  |    private:  | 
486  |  |     using CordRep = absl::cord_internal::CordRep;  | 
487  |  |     using CordRepBtree = absl::cord_internal::CordRepBtree;  | 
488  |  |     using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;  | 
489  |  |  | 
490  |  |     // Constructs a `begin()` iterator from `tree`.  | 
491  |  |     explicit ChunkIterator(cord_internal::CordRep* absl_nonnull tree);  | 
492  |  |  | 
493  |  |     // Constructs a `begin()` iterator from `cord`.  | 
494  |  |     explicit ChunkIterator(const Cord* absl_nonnull cord);  | 
495  |  |  | 
496  |  |     // Initializes this instance from a tree. Invoked by constructors.  | 
497  |  |     void InitTree(cord_internal::CordRep* absl_nonnull tree);  | 
498  |  |  | 
499  |  |     // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than  | 
500  |  |     // `current_chunk_.size()`.  | 
501  |  |     void RemoveChunkPrefix(size_t n);  | 
502  |  |     Cord AdvanceAndReadBytes(size_t n);  | 
503  |  |     void AdvanceBytes(size_t n);  | 
504  |  |  | 
505  |  |     // Btree specific operator++  | 
506  |  |     ChunkIterator& AdvanceBtree();  | 
507  |  |     void AdvanceBytesBtree(size_t n);  | 
508  |  |  | 
509  |  |     // A view into bytes of the current `CordRep`. It may only be a view to a  | 
510  |  |     // suffix of bytes if this is being used by `CharIterator`.  | 
511  |  |     absl::string_view current_chunk_;  | 
512  |  |     // The current leaf, or `nullptr` if the iterator points to short data.  | 
513  |  |     // If the current chunk is a substring node, current_leaf_ points to the  | 
514  |  |     // underlying flat or external node.  | 
515  |  |     absl::cord_internal::CordRep* absl_nullable current_leaf_ = nullptr;  | 
516  |  |     // The number of bytes left in the `Cord` over which we are iterating.  | 
517  |  |     size_t bytes_remaining_ = 0;  | 
518  |  |  | 
519  |  |     // Cord reader for cord btrees. Empty if not traversing a btree.  | 
520  |  |     CordRepBtreeReader btree_reader_;  | 
521  |  |   };  | 
522  |  |  | 
523  |  |   // Cord::chunk_begin()  | 
524  |  |   //  | 
525  |  |   // Returns an iterator to the first chunk of the `Cord`.  | 
526  |  |   //  | 
527  |  |   // Generally, prefer using `Cord::Chunks()` within a range-based for loop for  | 
528  |  |   // iterating over the chunks of a Cord. This method may be useful for getting  | 
529  |  |   // a `ChunkIterator` where range-based for-loops are not useful.  | 
530  |  |   //  | 
531  |  |   // Example:  | 
532  |  |   //  | 
533  |  |   //   absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,  | 
534  |  |   //                                         absl::string_view s) { | 
535  |  |   //     return std::find(c.chunk_begin(), c.chunk_end(), s);  | 
536  |  |   //   }  | 
537  |  |   ChunkIterator chunk_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
538  |  |  | 
539  |  |   // Cord::chunk_end()  | 
540  |  |   //  | 
541  |  |   // Returns an iterator one increment past the last chunk of the `Cord`.  | 
542  |  |   //  | 
543  |  |   // Generally, prefer using `Cord::Chunks()` within a range-based for loop for  | 
544  |  |   // iterating over the chunks of a Cord. This method may be useful for getting  | 
545  |  |   // a `ChunkIterator` where range-based for-loops may not be available.  | 
546  |  |   ChunkIterator chunk_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
547  |  |  | 
548  |  |   //----------------------------------------------------------------------------  | 
549  |  |   // Cord::ChunkRange  | 
550  |  |   //----------------------------------------------------------------------------  | 
551  |  |   //  | 
552  |  |   // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,  | 
553  |  |   // producing an iterator which can be used within a range-based for loop.  | 
554  |  |   // Construction of a `ChunkRange` will return an iterator pointing to the  | 
555  |  |   // first chunk of the Cord. Generally, do not construct a `ChunkRange`  | 
556  |  |   // directly; instead, prefer to use the `Cord::Chunks()` method.  | 
557  |  |   //  | 
558  |  |   // Implementation note: `ChunkRange` is simply a convenience wrapper over  | 
559  |  |   // `Cord::chunk_begin()` and `Cord::chunk_end()`.  | 
560  |  |   class ChunkRange { | 
561  |  |    public:  | 
562  |  |     // Fulfill minimum c++ container requirements [container.requirements]  | 
563  |  |     // These (partial) container type definitions allow ChunkRange to be used  | 
564  |  |     // in various utilities expecting a subset of [container.requirements].  | 
565  |  |     // For example, the below enables using `::testing::ElementsAre(...)`  | 
566  |  |     using value_type = absl::string_view;  | 
567  |  |     using reference = value_type&;  | 
568  |  |     using const_reference = const value_type&;  | 
569  |  |     using iterator = ChunkIterator;  | 
570  |  |     using const_iterator = ChunkIterator;  | 
571  |  |  | 
572  | 0  |     explicit ChunkRange(const Cord* absl_nonnull cord) : cord_(cord) {} | 
573  |  |  | 
574  |  |     ChunkIterator begin() const;  | 
575  |  |     ChunkIterator end() const;  | 
576  |  |  | 
577  |  |    private:  | 
578  |  |     const Cord* absl_nonnull cord_;  | 
579  |  |   };  | 
580  |  |  | 
581  |  |   // Cord::Chunks()  | 
582  |  |   //  | 
583  |  |   // Returns a `Cord::ChunkRange` for iterating over the chunks of a `Cord` with  | 
584  |  |   // a range-based for-loop. For most iteration tasks on a Cord, use  | 
585  |  |   // `Cord::Chunks()` to retrieve this iterator.  | 
586  |  |   //  | 
587  |  |   // Example:  | 
588  |  |   //  | 
589  |  |   //   void ProcessChunks(const Cord& cord) { | 
590  |  |   //     for (absl::string_view chunk : cord.Chunks()) { ... } | 
591  |  |   //   }  | 
592  |  |   //  | 
593  |  |   // Note that the ordinary caveats of temporary lifetime extension apply:  | 
594  |  |   //  | 
595  |  |   //   void Process() { | 
596  |  |   //     for (absl::string_view chunk : CordFactory().Chunks()) { | 
597  |  |   //       // The temporary Cord returned by CordFactory has been destroyed!  | 
598  |  |   //     }  | 
599  |  |   //   }  | 
600  |  |   ChunkRange Chunks() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
601  |  |  | 
602  |  |   //----------------------------------------------------------------------------  | 
603  |  |   // Cord::CharIterator  | 
604  |  |   //----------------------------------------------------------------------------  | 
605  |  |   //  | 
606  |  |   // A `Cord::CharIterator` allows iteration over the constituent characters of  | 
607  |  |   // a `Cord`.  | 
608  |  |   //  | 
609  |  |   // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,  | 
610  |  |   // you create one implicitly through use of the `Cord::Chars()` member  | 
611  |  |   // function.  | 
612  |  |   //  | 
613  |  |   // A `Cord::CharIterator` has the following properties:  | 
614  |  |   //  | 
615  |  |   //   * The iterator is invalidated after any non-const operation on the  | 
616  |  |   //     Cord object over which it iterates.  | 
617  |  |   //   * Two `CharIterator` objects can be compared equal if and only if they  | 
618  |  |   //     remain valid and iterate over the same Cord.  | 
619  |  |   //   * The iterator keeps state that can grow for Cords that contain many  | 
620  |  |   //     nodes and are imbalanced due to sharing. Prefer to pass this type by  | 
621  |  |   //     const reference instead of by value.  | 
622  |  |   //   * This type cannot act as a forward iterator because a `Cord` can reuse  | 
623  |  |   //     sections of memory. This fact violates the requirement for forward  | 
624  |  |   //     iterators to compare equal if dereferencing them returns the same  | 
625  |  |   //     object.  | 
626  |  |   class CharIterator { | 
627  |  |    public:  | 
628  |  |     using iterator_category = std::input_iterator_tag;  | 
629  |  |     using value_type = char;  | 
630  |  |     using difference_type = ptrdiff_t;  | 
631  |  |     using pointer = const char* absl_nonnull;  | 
632  |  |     using reference = const char&;  | 
633  |  |  | 
634  |  |     CharIterator() = default;  | 
635  |  |  | 
636  |  |     CharIterator& operator++();  | 
637  |  |     CharIterator operator++(int);  | 
638  |  |     bool operator==(const CharIterator& other) const;  | 
639  |  |     bool operator!=(const CharIterator& other) const;  | 
640  |  |     reference operator*() const;  | 
641  |  |  | 
642  |  |     friend Cord;  | 
643  |  |  | 
644  |  |    private:  | 
645  |  |     explicit CharIterator(const Cord* absl_nonnull cord)  | 
646  | 0  |         : chunk_iterator_(cord) {} | 
647  |  |  | 
648  |  |     ChunkIterator chunk_iterator_;  | 
649  |  |   };  | 
650  |  |  | 
651  |  |   // Cord::AdvanceAndRead()  | 
652  |  |   //  | 
653  |  |   // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes  | 
654  |  |   // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the  | 
655  |  |   // number of bytes within the Cord; otherwise, behavior is undefined. It is  | 
656  |  |   // valid to pass `char_end()` and `0`.  | 
657  |  |   static Cord AdvanceAndRead(CharIterator* absl_nonnull it, size_t n_bytes);  | 
658  |  |  | 
659  |  |   // Cord::Advance()  | 
660  |  |   //  | 
661  |  |   // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than  | 
662  |  |   // or equal to the number of bytes remaining within the Cord; otherwise,  | 
663  |  |   // behavior is undefined. It is valid to pass `char_end()` and `0`.  | 
664  |  |   static void Advance(CharIterator* absl_nonnull it, size_t n_bytes);  | 
665  |  |  | 
666  |  |   // Cord::ChunkRemaining()  | 
667  |  |   //  | 
668  |  |   // Returns the longest contiguous view starting at the iterator's position.  | 
669  |  |   //  | 
670  |  |   // `it` must be dereferenceable.  | 
671  |  |   static absl::string_view ChunkRemaining(const CharIterator& it);  | 
672  |  |  | 
673  |  |   // Cord::Distance()  | 
674  |  |   //  | 
675  |  |   // Returns the distance between `first` and `last`, as if  | 
676  |  |   // `std::distance(first, last)` was called.  | 
677  |  |   static ptrdiff_t Distance(const CharIterator& first,  | 
678  |  |                             const CharIterator& last);  | 
679  |  |  | 
680  |  |   // Cord::char_begin()  | 
681  |  |   //  | 
682  |  |   // Returns an iterator to the first character of the `Cord`.  | 
683  |  |   //  | 
684  |  |   // Generally, prefer using `Cord::Chars()` within a range-based for loop for  | 
685  |  |   // iterating over the chunks of a Cord. This method may be useful for getting  | 
686  |  |   // a `CharIterator` where range-based for-loops may not be available.  | 
687  |  |   CharIterator char_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
688  |  |  | 
689  |  |   // Cord::char_end()  | 
690  |  |   //  | 
691  |  |   // Returns an iterator to one past the last character of the `Cord`.  | 
692  |  |   //  | 
693  |  |   // Generally, prefer using `Cord::Chars()` within a range-based for loop for  | 
694  |  |   // iterating over the chunks of a Cord. This method may be useful for getting  | 
695  |  |   // a `CharIterator` where range-based for-loops are not useful.  | 
696  |  |   CharIterator char_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
697  |  |  | 
698  |  |   // Cord::CharRange  | 
699  |  |   //  | 
700  |  |   // `CharRange` is a helper class for iterating over the characters of a  | 
701  |  |   // producing an iterator which can be used within a range-based for loop.  | 
702  |  |   // Construction of a `CharRange` will return an iterator pointing to the first  | 
703  |  |   // character of the Cord. Generally, do not construct a `CharRange` directly;  | 
704  |  |   // instead, prefer to use the `Cord::Chars()` method shown below.  | 
705  |  |   //  | 
706  |  |   // Implementation note: `CharRange` is simply a convenience wrapper over  | 
707  |  |   // `Cord::char_begin()` and `Cord::char_end()`.  | 
708  |  |   class CharRange { | 
709  |  |    public:  | 
710  |  |     // Fulfill minimum c++ container requirements [container.requirements]  | 
711  |  |     // These (partial) container type definitions allow CharRange to be used  | 
712  |  |     // in various utilities expecting a subset of [container.requirements].  | 
713  |  |     // For example, the below enables using `::testing::ElementsAre(...)`  | 
714  |  |     using value_type = char;  | 
715  |  |     using reference = value_type&;  | 
716  |  |     using const_reference = const value_type&;  | 
717  |  |     using iterator = CharIterator;  | 
718  |  |     using const_iterator = CharIterator;  | 
719  |  |  | 
720  | 0  |     explicit CharRange(const Cord* absl_nonnull cord) : cord_(cord) {} | 
721  |  |  | 
722  |  |     CharIterator begin() const;  | 
723  |  |     CharIterator end() const;  | 
724  |  |  | 
725  |  |    private:  | 
726  |  |     const Cord* absl_nonnull cord_;  | 
727  |  |   };  | 
728  |  |  | 
729  |  |   // Cord::Chars()  | 
730  |  |   //  | 
731  |  |   // Returns a `Cord::CharRange` for iterating over the characters of a `Cord`  | 
732  |  |   // with a range-based for-loop. For most character-based iteration tasks on a  | 
733  |  |   // Cord, use `Cord::Chars()` to retrieve this iterator.  | 
734  |  |   //  | 
735  |  |   // Example:  | 
736  |  |   //  | 
737  |  |   //   void ProcessCord(const Cord& cord) { | 
738  |  |   //     for (char c : cord.Chars()) { ... } | 
739  |  |   //   }  | 
740  |  |   //  | 
741  |  |   // Note that the ordinary caveats of temporary lifetime extension apply:  | 
742  |  |   //  | 
743  |  |   //   void Process() { | 
744  |  |   //     for (char c : CordFactory().Chars()) { | 
745  |  |   //       // The temporary Cord returned by CordFactory has been destroyed!  | 
746  |  |   //     }  | 
747  |  |   //   }  | 
748  |  |   CharRange Chars() const ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
749  |  |  | 
750  |  |   // Cord::operator[]  | 
751  |  |   //  | 
752  |  |   // Gets the "i"th character of the Cord and returns it, provided that  | 
753  |  |   // 0 <= i < Cord.size().  | 
754  |  |   //  | 
755  |  |   // NOTE: This routine is reasonably efficient. It is roughly  | 
756  |  |   // logarithmic based on the number of chunks that make up the cord. Still,  | 
757  |  |   // if you need to iterate over the contents of a cord, you should  | 
758  |  |   // use a CharIterator/ChunkIterator rather than call operator[]  | 
759  |  |   // repeatedly in a loop.  | 
760  |  |   char operator[](size_t i) const;  | 
761  |  |  | 
762  |  |   // Cord::TryFlat()  | 
763  |  |   //  | 
764  |  |   // If this cord's representation is a single flat array, returns a  | 
765  |  |   // string_view referencing that array.  Otherwise returns nullopt.  | 
766  |  |   absl::optional<absl::string_view> TryFlat() const  | 
767  |  |       ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
768  |  |  | 
769  |  |   // Cord::Flatten()  | 
770  |  |   //  | 
771  |  |   // Flattens the cord into a single array and returns a view of the data.  | 
772  |  |   //  | 
773  |  |   // If the cord was already flat, the contents are not modified.  | 
774  |  |   absl::string_view Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND;  | 
775  |  |  | 
776  |  |   // Cord::Find()  | 
777  |  |   //  | 
778  |  |   // Returns an iterator to the first occurrence of the substring `needle`.  | 
779  |  |   //  | 
780  |  |   // If the substring `needle` does not occur, `Cord::char_end()` is returned.  | 
781  |  |   CharIterator Find(absl::string_view needle) const;  | 
782  |  |   CharIterator Find(const absl::Cord& needle) const;  | 
783  |  |  | 
784  |  |   // Supports absl::Cord as a sink object for absl::Format().  | 
785  |  |   friend void AbslFormatFlush(absl::Cord* absl_nonnull cord,  | 
786  | 0  |                               absl::string_view part) { | 
787  | 0  |     cord->Append(part);  | 
788  | 0  |   }  | 
789  |  |  | 
790  |  |   // Support automatic stringification with absl::StrCat and absl::StrFormat.  | 
791  |  |   template <typename Sink>  | 
792  |  |   friend void AbslStringify(Sink& sink, const absl::Cord& cord) { | 
793  |  |     for (absl::string_view chunk : cord.Chunks()) { | 
794  |  |       sink.Append(chunk);  | 
795  |  |     }  | 
796  |  |   }  | 
797  |  |  | 
798  |  |   // Cord::SetExpectedChecksum()  | 
799  |  |   //  | 
800  |  |   // Stores a checksum value with this non-empty cord instance, for later  | 
801  |  |   // retrieval.  | 
802  |  |   //  | 
803  |  |   // The expected checksum is a number stored out-of-band, alongside the data.  | 
804  |  |   // It is preserved across copies and assignments, but any mutations to a cord  | 
805  |  |   // will cause it to lose its expected checksum.  | 
806  |  |   //  | 
807  |  |   // The expected checksum is not part of a Cord's value, and does not affect  | 
808  |  |   // operations such as equality or hashing.  | 
809  |  |   //  | 
810  |  |   // This field is intended to store a CRC32C checksum for later validation, to  | 
811  |  |   // help support end-to-end checksum workflows.  However, the Cord API itself  | 
812  |  |   // does no CRC validation, and assigns no meaning to this number.  | 
813  |  |   //  | 
814  |  |   // This call has no effect if this cord is empty.  | 
815  |  |   void SetExpectedChecksum(uint32_t crc);  | 
816  |  |  | 
817  |  |   // Returns this cord's expected checksum, if it has one.  Otherwise, returns  | 
818  |  |   // nullopt.  | 
819  |  |   absl::optional<uint32_t> ExpectedChecksum() const;  | 
820  |  |  | 
821  |  |   template <typename H>  | 
822  | 0  |   friend H AbslHashValue(H hash_state, const absl::Cord& c) { | 
823  | 0  |     absl::optional<absl::string_view> maybe_flat = c.TryFlat();  | 
824  | 0  |     if (maybe_flat.has_value()) { | 
825  | 0  |       return H::combine(std::move(hash_state), *maybe_flat);  | 
826  | 0  |     }  | 
827  | 0  |     return c.HashFragmented(std::move(hash_state));  | 
828  | 0  |   }  | 
829  |  |  | 
830  |  |   // Create a Cord with the contents of StringConstant<T>::value.  | 
831  |  |   // No allocations will be done and no data will be copied.  | 
832  |  |   // This is an INTERNAL API and subject to change or removal. This API can only  | 
833  |  |   // be used by spelling absl::strings_internal::MakeStringConstant, which is  | 
834  |  |   // also an internal API.  | 
835  |  |   template <typename T>  | 
836  |  |   // NOLINTNEXTLINE(google-explicit-constructor)  | 
837  |  |   constexpr Cord(strings_internal::StringConstant<T>);  | 
838  |  |  | 
839  |  |  private:  | 
840  |  |   using CordRep = absl::cord_internal::CordRep;  | 
841  |  |   using CordRepFlat = absl::cord_internal::CordRepFlat;  | 
842  |  |   using CordzInfo = cord_internal::CordzInfo;  | 
843  |  |   using CordzUpdateScope = cord_internal::CordzUpdateScope;  | 
844  |  |   using CordzUpdateTracker = cord_internal::CordzUpdateTracker;  | 
845  |  |   using InlineData = cord_internal::InlineData;  | 
846  |  |   using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;  | 
847  |  |  | 
848  |  |   // Creates a cord instance with `method` representing the originating  | 
849  |  |   // public API call causing the cord to be created.  | 
850  |  |   explicit Cord(absl::string_view src, MethodIdentifier method);  | 
851  |  |  | 
852  |  |   friend class CordTestPeer;  | 
853  |  |   friend bool operator==(const Cord& lhs, const Cord& rhs);  | 
854  |  |   friend bool operator==(const Cord& lhs, absl::string_view rhs);  | 
855  |  |  | 
856  |  | #ifdef __cpp_impl_three_way_comparison  | 
857  |  |  | 
858  |  |   // Cords support comparison with other Cords and string_views via operator<  | 
859  |  |   // and others; here we provide a wrapper for the C++20 three-way comparison  | 
860  |  |   // <=> operator.  | 
861  |  |  | 
862  |  |   static inline std::strong_ordering ConvertCompareResultToStrongOrdering(  | 
863  |  |       int c) { | 
864  |  |     if (c == 0) { | 
865  |  |       return std::strong_ordering::equal;  | 
866  |  |     } else if (c < 0) { | 
867  |  |       return std::strong_ordering::less;  | 
868  |  |     } else { | 
869  |  |       return std::strong_ordering::greater;  | 
870  |  |     }  | 
871  |  |   }  | 
872  |  |  | 
873  |  |   friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) { | 
874  |  |     return ConvertCompareResultToStrongOrdering(x.Compare(y));  | 
875  |  |   }  | 
876  |  |  | 
877  |  |   friend inline std::strong_ordering operator<=>(const Cord& lhs,  | 
878  |  |                                                  absl::string_view rhs) { | 
879  |  |     return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs));  | 
880  |  |   }  | 
881  |  |  | 
882  |  |   friend inline std::strong_ordering operator<=>(absl::string_view lhs,  | 
883  |  |                                                  const Cord& rhs) { | 
884  |  |     return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs));  | 
885  |  |   }  | 
886  |  | #endif  | 
887  |  |  | 
888  |  |   friend const CordzInfo* absl_nullable GetCordzInfoForTesting(  | 
889  |  |       const Cord& cord);  | 
890  |  |  | 
891  |  |   // Calls the provided function once for each cord chunk, in order.  Unlike  | 
892  |  |   // Chunks(), this API will not allocate memory.  | 
893  |  |   void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;  | 
894  |  |  | 
895  |  |   // Allocates new contiguous storage for the contents of the cord. This is  | 
896  |  |   // called by Flatten() when the cord was not already flat.  | 
897  |  |   absl::string_view FlattenSlowPath();  | 
898  |  |  | 
899  |  |   // Actual cord contents are hidden inside the following simple  | 
900  |  |   // class so that we can isolate the bulk of cord.cc from changes  | 
901  |  |   // to the representation.  | 
902  |  |   //  | 
903  |  |   // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.  | 
904  |  |   class InlineRep { | 
905  |  |    public:  | 
906  |  |     static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;  | 
907  |  |     static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");  | 
908  |  |  | 
909  | 0  |     constexpr InlineRep() : data_() {} | 
910  | 0  |     explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {} | 
911  |  |     InlineRep(const InlineRep& src);  | 
912  |  |     InlineRep(InlineRep&& src);  | 
913  |  |     InlineRep& operator=(const InlineRep& src);  | 
914  |  |     InlineRep& operator=(InlineRep&& src) noexcept;  | 
915  |  |  | 
916  |  |     explicit constexpr InlineRep(absl::string_view sv,  | 
917  |  |                                  CordRep* absl_nullable rep);  | 
918  |  |  | 
919  |  |     void Swap(InlineRep* absl_nonnull rhs);  | 
920  |  |     size_t size() const;  | 
921  |  |     // Returns nullptr if holding pointer  | 
922  |  |     const char* absl_nullable data() const;  | 
923  |  |     // Discards pointer, if any  | 
924  |  |     void set_data(const char* absl_nullable data, size_t n);  | 
925  |  |     char* absl_nonnull set_data(size_t n);  // Write data to the result  | 
926  |  |     // Returns nullptr if holding bytes  | 
927  |  |     absl::cord_internal::CordRep* absl_nullable tree() const;  | 
928  |  |     absl::cord_internal::CordRep* absl_nonnull as_tree() const;  | 
929  |  |     const char* absl_nonnull as_chars() const;  | 
930  |  |     // Returns non-null iff was holding a pointer  | 
931  |  |     absl::cord_internal::CordRep* absl_nullable clear();  | 
932  |  |     // Converts to pointer if necessary.  | 
933  |  |     void reduce_size(size_t n);    // REQUIRES: holding data  | 
934  |  |     void remove_prefix(size_t n);  // REQUIRES: holding data  | 
935  |  |     void AppendArray(absl::string_view src, MethodIdentifier method);  | 
936  |  |     absl::string_view FindFlatStartPiece() const;  | 
937  |  |  | 
938  |  |     // Creates a CordRepFlat instance from the current inlined data with `extra'  | 
939  |  |     // bytes of desired additional capacity.  | 
940  |  |     CordRepFlat* absl_nonnull MakeFlatWithExtraCapacity(size_t extra);  | 
941  |  |  | 
942  |  |     // Sets the tree value for this instance. `rep` must not be null.  | 
943  |  |     // Requires the current instance to hold a tree, and a lock to be held on  | 
944  |  |     // any CordzInfo referenced by this instance. The latter is enforced through  | 
945  |  |     // the CordzUpdateScope argument. If the current instance is sampled, then  | 
946  |  |     // the CordzInfo instance is updated to reference the new `rep` value.  | 
947  |  |     void SetTree(CordRep* absl_nonnull rep, const CordzUpdateScope& scope);  | 
948  |  |  | 
949  |  |     // Identical to SetTree(), except that `rep` is allowed to be null, in  | 
950  |  |     // which case the current instance is reset to an empty value.  | 
951  |  |     void SetTreeOrEmpty(CordRep* absl_nullable rep,  | 
952  |  |                         const CordzUpdateScope& scope);  | 
953  |  |  | 
954  |  |     // Sets the tree value for this instance, and randomly samples this cord.  | 
955  |  |     // This function disregards existing contents in `data_`, and should be  | 
956  |  |     // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'  | 
957  |  |     // value to a non-inlined (tree / ring) value.  | 
958  |  |     void EmplaceTree(CordRep* absl_nonnull rep, MethodIdentifier method);  | 
959  |  |  | 
960  |  |     // Identical to EmplaceTree, except that it copies the parent stack from  | 
961  |  |     // the provided `parent` data if the parent is sampled.  | 
962  |  |     void EmplaceTree(CordRep* absl_nonnull rep, const InlineData& parent,  | 
963  |  |                      MethodIdentifier method);  | 
964  |  |  | 
965  |  |     // Commits the change of a newly created, or updated `rep` root value into  | 
966  |  |     // this cord. `old_rep` indicates the old (inlined or tree) value of the  | 
967  |  |     // cord, and determines if the commit invokes SetTree() or EmplaceTree().  | 
968  |  |     void CommitTree(const CordRep* absl_nullable old_rep,  | 
969  |  |                     CordRep* absl_nonnull rep, const CordzUpdateScope& scope,  | 
970  |  |                     MethodIdentifier method);  | 
971  |  |  | 
972  |  |     void AppendTreeToInlined(CordRep* absl_nonnull tree,  | 
973  |  |                              MethodIdentifier method);  | 
974  |  |     void AppendTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);  | 
975  |  |     void AppendTree(CordRep* absl_nonnull tree, MethodIdentifier method);  | 
976  |  |     void PrependTreeToInlined(CordRep* absl_nonnull tree,  | 
977  |  |                               MethodIdentifier method);  | 
978  |  |     void PrependTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);  | 
979  |  |     void PrependTree(CordRep* absl_nonnull tree, MethodIdentifier method);  | 
980  |  |  | 
981  | 0  |     bool IsSame(const InlineRep& other) const { return data_ == other.data_; } | 
982  |  |  | 
983  |  |     // Copies the inline contents into `dst`. Assumes the cord is not empty.  | 
984  | 0  |     void CopyTo(std::string* absl_nonnull dst) const { | 
985  | 0  |       data_.CopyInlineToString(dst);  | 
986  | 0  |     }  | 
987  |  |  | 
988  |  |     // Copies the inline contents into `dst`. Assumes the cord is not empty.  | 
989  |  |     void CopyToArray(char* absl_nonnull dst) const;  | 
990  |  |  | 
991  | 0  |     bool is_tree() const { return data_.is_tree(); } | 
992  |  |  | 
993  |  |     // Returns true if the Cord is being profiled by cordz.  | 
994  | 0  |     bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); } | 
995  |  |  | 
996  |  |     // Returns the available inlined capacity, or 0 if is_tree() == true.  | 
997  | 0  |     size_t remaining_inline_capacity() const { | 
998  | 0  |       return data_.is_tree() ? 0 : kMaxInline - data_.inline_size();  | 
999  | 0  |     }  | 
1000  |  |  | 
1001  |  |     // Returns the profiled CordzInfo, or nullptr if not sampled.  | 
1002  | 0  |     absl::cord_internal::CordzInfo* absl_nullable cordz_info() const { | 
1003  | 0  |       return data_.cordz_info();  | 
1004  | 0  |     }  | 
1005  |  |  | 
1006  |  |     // Sets the profiled CordzInfo.  | 
1007  | 0  |     void set_cordz_info(cord_internal::CordzInfo* absl_nonnull cordz_info) { | 
1008  | 0  |       assert(cordz_info != nullptr);  | 
1009  | 0  |       data_.set_cordz_info(cordz_info);  | 
1010  | 0  |     }  | 
1011  |  |  | 
1012  |  |     // Resets the current cordz_info to null / empty.  | 
1013  | 0  |     void clear_cordz_info() { data_.clear_cordz_info(); } | 
1014  |  |  | 
1015  |  |    private:  | 
1016  |  |     friend class Cord;  | 
1017  |  |  | 
1018  |  |     void AssignSlow(const InlineRep& src);  | 
1019  |  |     // Unrefs the tree and stops profiling.  | 
1020  |  |     void UnrefTree();  | 
1021  |  |  | 
1022  | 0  |     void ResetToEmpty() { data_ = {}; } | 
1023  |  |  | 
1024  | 0  |     void set_inline_size(size_t size) { data_.set_inline_size(size); } | 
1025  | 0  |     size_t inline_size() const { return data_.inline_size(); } | 
1026  |  |  | 
1027  |  |     // Empty cords that carry a checksum have a CordRepCrc node with a null  | 
1028  |  |     // child node. The code can avoid lots of special cases where it would  | 
1029  |  |     // otherwise transition from tree to inline storage if we just remove the  | 
1030  |  |     // CordRepCrc node before mutations. Must never be called inside a  | 
1031  |  |     // CordzUpdateScope since it untracks the cordz info.  | 
1032  |  |     void MaybeRemoveEmptyCrcNode();  | 
1033  |  |  | 
1034  |  |     cord_internal::InlineData data_;  | 
1035  |  |   };  | 
1036  |  |   InlineRep contents_;  | 
1037  |  |  | 
1038  |  |   // Helper for GetFlat() and TryFlat().  | 
1039  |  |   static bool GetFlatAux(absl::cord_internal::CordRep* absl_nonnull rep,  | 
1040  |  |                          absl::string_view* absl_nonnull fragment);  | 
1041  |  |  | 
1042  |  |   // Helper for ForEachChunk().  | 
1043  |  |   static void ForEachChunkAux(  | 
1044  |  |       absl::cord_internal::CordRep* absl_nonnull rep,  | 
1045  |  |       absl::FunctionRef<void(absl::string_view)> callback);  | 
1046  |  |  | 
1047  |  |   // The destructor for non-empty Cords.  | 
1048  |  |   void DestroyCordSlow();  | 
1049  |  |  | 
1050  |  |   // Out-of-line implementation of slower parts of logic.  | 
1051  |  |   void CopyToArraySlowPath(char* absl_nonnull dst) const;  | 
1052  |  |   int CompareSlowPath(absl::string_view rhs, size_t compared_size,  | 
1053  |  |                       size_t size_to_compare) const;  | 
1054  |  |   int CompareSlowPath(const Cord& rhs, size_t compared_size,  | 
1055  |  |                       size_t size_to_compare) const;  | 
1056  |  |   bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;  | 
1057  |  |   bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;  | 
1058  |  |   int CompareImpl(const Cord& rhs) const;  | 
1059  |  |  | 
1060  |  |   template <typename ResultType, typename RHS>  | 
1061  |  |   friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,  | 
1062  |  |                                    size_t size_to_compare);  | 
1063  |  |   static absl::string_view GetFirstChunk(const Cord& c);  | 
1064  |  |   static absl::string_view GetFirstChunk(absl::string_view sv);  | 
1065  |  |  | 
1066  |  |   // Returns a new reference to contents_.tree(), or steals an existing  | 
1067  |  |   // reference if called on an rvalue.  | 
1068  |  |   absl::cord_internal::CordRep* absl_nonnull TakeRep() const&;  | 
1069  |  |   absl::cord_internal::CordRep* absl_nonnull TakeRep() &&;  | 
1070  |  |  | 
1071  |  |   // Helper for Append().  | 
1072  |  |   template <typename C>  | 
1073  |  |   void AppendImpl(C&& src);  | 
1074  |  |  | 
1075  |  |   // Appends / Prepends `src` to this instance, using precise sizing.  | 
1076  |  |   // This method does explicitly not attempt to use any spare capacity  | 
1077  |  |   // in any pending last added private owned flat.  | 
1078  |  |   // Requires `src` to be <= kMaxFlatLength.  | 
1079  |  |   void AppendPrecise(absl::string_view src, MethodIdentifier method);  | 
1080  |  |   void PrependPrecise(absl::string_view src, MethodIdentifier method);  | 
1081  |  |  | 
1082  |  |   CordBuffer GetAppendBufferSlowPath(size_t block_size, size_t capacity,  | 
1083  |  |                                      size_t min_capacity);  | 
1084  |  |  | 
1085  |  |   // Prepends the provided data to this instance. `method` contains the public  | 
1086  |  |   // API method for this action which is tracked for Cordz sampling purposes.  | 
1087  |  |   void PrependArray(absl::string_view src, MethodIdentifier method);  | 
1088  |  |  | 
1089  |  |   // Assigns the value in 'src' to this instance, 'stealing' its contents.  | 
1090  |  |   // Requires src.length() > kMaxBytesToCopy.  | 
1091  |  |   Cord& AssignLargeString(std::string&& src);  | 
1092  |  |  | 
1093  |  |   // Helper for AbslHashValue().  | 
1094  |  |   template <typename H>  | 
1095  | 0  |   H HashFragmented(H hash_state) const { | 
1096  | 0  |     typename H::AbslInternalPiecewiseCombiner combiner;  | 
1097  | 0  |     ForEachChunk([&combiner, &hash_state](absl::string_view chunk) { | 
1098  | 0  |       hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),  | 
1099  | 0  |                                        chunk.size());  | 
1100  | 0  |     });  | 
1101  | 0  |     return combiner.finalize(std::move(hash_state));  | 
1102  | 0  |   }  | 
1103  |  |  | 
1104  |  |   friend class CrcCord;  | 
1105  |  |   void SetCrcCordState(crc_internal::CrcCordState state);  | 
1106  |  |   const crc_internal::CrcCordState* absl_nullable MaybeGetCrcCordState() const;  | 
1107  |  |  | 
1108  |  |   CharIterator FindImpl(CharIterator it, absl::string_view needle) const;  | 
1109  |  |  | 
1110  |  |   void CopyToArrayImpl(char* absl_nonnull dst) const;  | 
1111  |  | };  | 
1112  |  |  | 
1113  |  | ABSL_NAMESPACE_END  | 
1114  |  | }  // namespace absl  | 
1115  |  |  | 
1116  |  | namespace absl { | 
1117  |  | ABSL_NAMESPACE_BEGIN  | 
1118  |  |  | 
1119  |  | // allow a Cord to be logged  | 
1120  |  | extern std::ostream& operator<<(std::ostream& out, const Cord& cord);  | 
1121  |  |  | 
1122  |  | // ------------------------------------------------------------------  | 
1123  |  | // Internal details follow.  Clients should ignore.  | 
1124  |  |  | 
1125  |  | namespace cord_internal { | 
1126  |  |  | 
1127  |  | // Does non-template-specific `CordRepExternal` initialization.  | 
1128  |  | // Requires `data` to be non-empty.  | 
1129  |  | void InitializeCordRepExternal(absl::string_view data,  | 
1130  |  |                                CordRepExternal* absl_nonnull rep);  | 
1131  |  |  | 
1132  |  | // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer  | 
1133  |  | // to it. Requires `data` to be non-empty.  | 
1134  |  | template <typename Releaser>  | 
1135  |  | // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.  | 
1136  |  | CordRep* absl_nonnull NewExternalRep(absl::string_view data,  | 
1137  | 0  |                                      Releaser&& releaser) { | 
1138  | 0  |   assert(!data.empty());  | 
1139  | 0  |   using ReleaserType = absl::decay_t<Releaser>;  | 
1140  | 0  |   CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(  | 
1141  | 0  |       std::forward<Releaser>(releaser), 0);  | 
1142  | 0  |   InitializeCordRepExternal(data, rep);  | 
1143  | 0  |   return rep;  | 
1144  | 0  | }  | 
1145  |  |  | 
1146  |  | // Overload for function reference types that dispatches using a function  | 
1147  |  | // pointer because there are no `alignof()` or `sizeof()` a function reference.  | 
1148  |  | // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.  | 
1149  |  | inline CordRep* absl_nonnull NewExternalRep(  | 
1150  | 0  |     absl::string_view data, void (&releaser)(absl::string_view)) { | 
1151  | 0  |   return NewExternalRep(data, &releaser);  | 
1152  | 0  | }  | 
1153  |  |  | 
1154  |  | }  // namespace cord_internal  | 
1155  |  |  | 
1156  |  | template <typename Releaser>  | 
1157  |  | Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) { | 
1158  |  |   Cord cord;  | 
1159  |  |   if (ABSL_PREDICT_TRUE(!data.empty())) { | 
1160  |  |     cord.contents_.EmplaceTree(::absl::cord_internal::NewExternalRep(  | 
1161  |  |                                    data, std::forward<Releaser>(releaser)),  | 
1162  |  |                                Cord::MethodIdentifier::kMakeCordFromExternal);  | 
1163  |  |   } else { | 
1164  |  |     using ReleaserType = absl::decay_t<Releaser>;  | 
1165  |  |     cord_internal::InvokeReleaser(  | 
1166  |  |         cord_internal::Rank1{}, ReleaserType(std::forward<Releaser>(releaser)), | 
1167  |  |         data);  | 
1168  |  |   }  | 
1169  |  |   return cord;  | 
1170  |  | }  | 
1171  |  |  | 
1172  |  | constexpr Cord::InlineRep::InlineRep(absl::string_view sv,  | 
1173  |  |                                      CordRep* absl_nullable rep)  | 
1174  |  |     : data_(sv, rep) {} | 
1175  |  |  | 
1176  |  | inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)  | 
1177  |  |     : data_(InlineData::kDefaultInit) { | 
1178  |  |   if (CordRep* tree = src.tree()) { | 
1179  |  |     EmplaceTree(CordRep::Ref(tree), src.data_,  | 
1180  |  |                 CordzUpdateTracker::kConstructorCord);  | 
1181  |  |   } else { | 
1182  |  |     data_ = src.data_;  | 
1183  |  |   }  | 
1184  |  | }  | 
1185  |  |  | 
1186  |  | inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) { | 
1187  |  |   src.ResetToEmpty();  | 
1188  |  | }  | 
1189  |  |  | 
1190  | 0  | inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) { | 
1191  | 0  |   if (this == &src) { | 
1192  | 0  |     return *this;  | 
1193  | 0  |   }  | 
1194  | 0  |   if (!is_tree() && !src.is_tree()) { | 
1195  | 0  |     data_ = src.data_;  | 
1196  | 0  |     return *this;  | 
1197  | 0  |   }  | 
1198  | 0  |   AssignSlow(src);  | 
1199  | 0  |   return *this;  | 
1200  | 0  | }  | 
1201  |  |  | 
1202  |  | inline Cord::InlineRep& Cord::InlineRep::operator=(  | 
1203  | 0  |     Cord::InlineRep&& src) noexcept { | 
1204  | 0  |   if (is_tree()) { | 
1205  | 0  |     UnrefTree();  | 
1206  | 0  |   }  | 
1207  | 0  |   data_ = src.data_;  | 
1208  | 0  |   src.ResetToEmpty();  | 
1209  | 0  |   return *this;  | 
1210  | 0  | }  | 
1211  |  |  | 
1212  | 0  | inline void Cord::InlineRep::Swap(Cord::InlineRep* absl_nonnull rhs) { | 
1213  | 0  |   if (rhs == this) { | 
1214  | 0  |     return;  | 
1215  | 0  |   }  | 
1216  | 0  |   using std::swap;  | 
1217  | 0  |   swap(data_, rhs->data_);  | 
1218  | 0  | }  | 
1219  |  |  | 
1220  | 0  | inline const char* absl_nullable Cord::InlineRep::data() const { | 
1221  | 0  |   return is_tree() ? nullptr : data_.as_chars();  | 
1222  | 0  | }  | 
1223  |  |  | 
1224  | 0  | inline const char* absl_nonnull Cord::InlineRep::as_chars() const { | 
1225  | 0  |   assert(!data_.is_tree());  | 
1226  | 0  |   return data_.as_chars();  | 
1227  | 0  | }  | 
1228  |  |  | 
1229  |  | inline absl::cord_internal::CordRep* absl_nonnull Cord::InlineRep::as_tree()  | 
1230  | 0  |     const { | 
1231  | 0  |   assert(data_.is_tree());  | 
1232  | 0  |   return data_.as_tree();  | 
1233  | 0  | }  | 
1234  |  |  | 
1235  |  | inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::tree()  | 
1236  | 0  |     const { | 
1237  | 0  |   if (is_tree()) { | 
1238  | 0  |     return as_tree();  | 
1239  | 0  |   } else { | 
1240  | 0  |     return nullptr;  | 
1241  | 0  |   }  | 
1242  | 0  | }  | 
1243  |  |  | 
1244  | 0  | inline size_t Cord::InlineRep::size() const { | 
1245  | 0  |   return is_tree() ? as_tree()->length : inline_size();  | 
1246  | 0  | }  | 
1247  |  |  | 
1248  |  | inline cord_internal::CordRepFlat* absl_nonnull  | 
1249  | 0  | Cord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) { | 
1250  | 0  |   static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");  | 
1251  | 0  |   size_t len = data_.inline_size();  | 
1252  | 0  |   auto* result = CordRepFlat::New(len + extra);  | 
1253  | 0  |   result->length = len;  | 
1254  | 0  |   data_.copy_max_inline_to(result->Data());  | 
1255  | 0  |   return result;  | 
1256  | 0  | }  | 
1257  |  |  | 
1258  |  | inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,  | 
1259  | 0  |                                          MethodIdentifier method) { | 
1260  | 0  |   assert(rep);  | 
1261  | 0  |   data_.make_tree(rep);  | 
1262  | 0  |   CordzInfo::MaybeTrackCord(data_, method);  | 
1263  | 0  | }  | 
1264  |  |  | 
1265  |  | inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,  | 
1266  |  |                                          const InlineData& parent,  | 
1267  | 0  |                                          MethodIdentifier method) { | 
1268  | 0  |   data_.make_tree(rep);  | 
1269  | 0  |   CordzInfo::MaybeTrackCord(data_, parent, method);  | 
1270  | 0  | }  | 
1271  |  |  | 
1272  |  | inline void Cord::InlineRep::SetTree(CordRep* absl_nonnull rep,  | 
1273  | 0  |                                      const CordzUpdateScope& scope) { | 
1274  | 0  |   assert(rep);  | 
1275  | 0  |   assert(data_.is_tree());  | 
1276  | 0  |   data_.set_tree(rep);  | 
1277  | 0  |   scope.SetCordRep(rep);  | 
1278  | 0  | }  | 
1279  |  |  | 
1280  |  | inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* absl_nullable rep,  | 
1281  | 0  |                                             const CordzUpdateScope& scope) { | 
1282  | 0  |   assert(data_.is_tree());  | 
1283  | 0  |   if (rep) { | 
1284  | 0  |     data_.set_tree(rep);  | 
1285  | 0  |   } else { | 
1286  | 0  |     data_ = {}; | 
1287  | 0  |   }  | 
1288  | 0  |   scope.SetCordRep(rep);  | 
1289  | 0  | }  | 
1290  |  |  | 
1291  |  | inline void Cord::InlineRep::CommitTree(const CordRep* absl_nullable old_rep,  | 
1292  |  |                                         CordRep* absl_nonnull rep,  | 
1293  |  |                                         const CordzUpdateScope& scope,  | 
1294  | 0  |                                         MethodIdentifier method) { | 
1295  | 0  |   if (old_rep) { | 
1296  | 0  |     SetTree(rep, scope);  | 
1297  | 0  |   } else { | 
1298  | 0  |     EmplaceTree(rep, method);  | 
1299  | 0  |   }  | 
1300  | 0  | }  | 
1301  |  |  | 
1302  | 0  | inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::clear() { | 
1303  | 0  |   if (is_tree()) { | 
1304  | 0  |     CordzInfo::MaybeUntrackCord(cordz_info());  | 
1305  | 0  |   }  | 
1306  | 0  |   absl::cord_internal::CordRep* result = tree();  | 
1307  | 0  |   ResetToEmpty();  | 
1308  | 0  |   return result;  | 
1309  | 0  | }  | 
1310  |  |  | 
1311  | 0  | inline void Cord::InlineRep::CopyToArray(char* absl_nonnull dst) const { | 
1312  | 0  |   assert(!is_tree());  | 
1313  | 0  |   size_t n = inline_size();  | 
1314  | 0  |   assert(n != 0);  | 
1315  | 0  |   cord_internal::SmallMemmove(dst, data_.as_chars(), n);  | 
1316  | 0  | }  | 
1317  |  |  | 
1318  | 0  | inline void Cord::InlineRep::MaybeRemoveEmptyCrcNode() { | 
1319  | 0  |   CordRep* rep = tree();  | 
1320  | 0  |   if (rep == nullptr || ABSL_PREDICT_TRUE(rep->length > 0)) { | 
1321  | 0  |     return;  | 
1322  | 0  |   }  | 
1323  | 0  |   assert(rep->IsCrc());  | 
1324  | 0  |   assert(rep->crc()->child == nullptr);  | 
1325  | 0  |   CordzInfo::MaybeUntrackCord(cordz_info());  | 
1326  | 0  |   CordRep::Unref(rep);  | 
1327  | 0  |   ResetToEmpty();  | 
1328  | 0  | }  | 
1329  |  |  | 
1330  |  | constexpr inline Cord::Cord() noexcept {} | 
1331  |  |  | 
1332  |  | inline Cord::Cord(absl::string_view src)  | 
1333  |  |     : Cord(src, CordzUpdateTracker::kConstructorString) {} | 
1334  |  |  | 
1335  |  | template <typename T>  | 
1336  |  | constexpr Cord::Cord(strings_internal::StringConstant<T>)  | 
1337  |  |     : contents_(strings_internal::StringConstant<T>::value,  | 
1338  |  |                 strings_internal::StringConstant<T>::value.size() <=  | 
1339  |  |                         cord_internal::kMaxInline  | 
1340  |  |                     ? nullptr  | 
1341  |  |                     : &cord_internal::ConstInitExternalStorage<  | 
1342  |  |                           strings_internal::StringConstant<T>>::value) {} | 
1343  |  |  | 
1344  | 0  | inline Cord& Cord::operator=(const Cord& x) { | 
1345  | 0  |   contents_ = x.contents_;  | 
1346  | 0  |   return *this;  | 
1347  | 0  | }  | 
1348  |  |  | 
1349  |  | template <typename T, Cord::EnableIfString<T>>  | 
1350  |  | Cord& Cord::operator=(T&& src) { | 
1351  |  |   if (src.size() <= cord_internal::kMaxBytesToCopy) { | 
1352  |  |     return operator=(absl::string_view(src));  | 
1353  |  |   } else { | 
1354  |  |     return AssignLargeString(std::forward<T>(src));  | 
1355  |  |   }  | 
1356  |  | }  | 
1357  |  |  | 
1358  |  | inline Cord::Cord(const Cord& src) : contents_(src.contents_) {} | 
1359  |  |  | 
1360  |  | inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {} | 
1361  |  |  | 
1362  | 0  | inline void Cord::swap(Cord& other) noexcept { | 
1363  | 0  |   contents_.Swap(&other.contents_);  | 
1364  | 0  | }  | 
1365  |  |  | 
1366  | 0  | inline Cord& Cord::operator=(Cord&& x) noexcept { | 
1367  | 0  |   contents_ = std::move(x.contents_);  | 
1368  | 0  |   return *this;  | 
1369  | 0  | }  | 
1370  |  |  | 
1371  |  | extern template Cord::Cord(std::string&& src);  | 
1372  |  |  | 
1373  | 0  | inline size_t Cord::size() const { | 
1374  | 0  |   // Length is 1st field in str.rep_  | 
1375  | 0  |   return contents_.size();  | 
1376  | 0  | }  | 
1377  |  |  | 
1378  | 0  | inline bool Cord::empty() const { return size() == 0; } | 
1379  |  |  | 
1380  |  | inline size_t Cord::EstimatedMemoryUsage(  | 
1381  | 0  |     CordMemoryAccounting accounting_method) const { | 
1382  | 0  |   size_t result = sizeof(Cord);  | 
1383  | 0  |   if (const absl::cord_internal::CordRep* rep = contents_.tree()) { | 
1384  | 0  |     switch (accounting_method) { | 
1385  | 0  |       case CordMemoryAccounting::kFairShare:  | 
1386  | 0  |         result += cord_internal::GetEstimatedFairShareMemoryUsage(rep);  | 
1387  | 0  |         break;  | 
1388  | 0  |       case CordMemoryAccounting::kTotalMorePrecise:  | 
1389  | 0  |         result += cord_internal::GetMorePreciseMemoryUsage(rep);  | 
1390  | 0  |         break;  | 
1391  | 0  |       case CordMemoryAccounting::kTotal:  | 
1392  | 0  |         result += cord_internal::GetEstimatedMemoryUsage(rep);  | 
1393  | 0  |         break;  | 
1394  | 0  |     }  | 
1395  | 0  |   }  | 
1396  | 0  |   return result;  | 
1397  | 0  | }  | 
1398  |  |  | 
1399  |  | inline absl::optional<absl::string_view> Cord::TryFlat() const  | 
1400  | 0  |     ABSL_ATTRIBUTE_LIFETIME_BOUND { | 
1401  | 0  |   absl::cord_internal::CordRep* rep = contents_.tree();  | 
1402  | 0  |   if (rep == nullptr) { | 
1403  | 0  |     return absl::string_view(contents_.data(), contents_.size());  | 
1404  | 0  |   }  | 
1405  | 0  |   absl::string_view fragment;  | 
1406  | 0  |   if (GetFlatAux(rep, &fragment)) { | 
1407  | 0  |     return fragment;  | 
1408  | 0  |   }  | 
1409  | 0  |   return absl::nullopt;  | 
1410  | 0  | }  | 
1411  |  |  | 
1412  | 0  | inline absl::string_view Cord::Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND { | 
1413  | 0  |   absl::cord_internal::CordRep* rep = contents_.tree();  | 
1414  | 0  |   if (rep == nullptr) { | 
1415  | 0  |     return absl::string_view(contents_.data(), contents_.size());  | 
1416  | 0  |   } else { | 
1417  | 0  |     absl::string_view already_flat_contents;  | 
1418  | 0  |     if (GetFlatAux(rep, &already_flat_contents)) { | 
1419  | 0  |       return already_flat_contents;  | 
1420  | 0  |     }  | 
1421  | 0  |   }  | 
1422  | 0  |   return FlattenSlowPath();  | 
1423  | 0  | }  | 
1424  |  |  | 
1425  | 0  | inline void Cord::Append(absl::string_view src) { | 
1426  | 0  |   contents_.AppendArray(src, CordzUpdateTracker::kAppendString);  | 
1427  | 0  | }  | 
1428  |  |  | 
1429  | 0  | inline void Cord::Prepend(absl::string_view src) { | 
1430  | 0  |   PrependArray(src, CordzUpdateTracker::kPrependString);  | 
1431  | 0  | }  | 
1432  |  |  | 
1433  | 0  | inline void Cord::Append(CordBuffer buffer) { | 
1434  | 0  |   if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;  | 
1435  | 0  |   contents_.MaybeRemoveEmptyCrcNode();  | 
1436  | 0  |   absl::string_view short_value;  | 
1437  | 0  |   if (CordRep* rep = buffer.ConsumeValue(short_value)) { | 
1438  | 0  |     contents_.AppendTree(rep, CordzUpdateTracker::kAppendCordBuffer);  | 
1439  | 0  |   } else { | 
1440  | 0  |     AppendPrecise(short_value, CordzUpdateTracker::kAppendCordBuffer);  | 
1441  | 0  |   }  | 
1442  | 0  | }  | 
1443  |  |  | 
1444  | 0  | inline void Cord::Prepend(CordBuffer buffer) { | 
1445  | 0  |   if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;  | 
1446  | 0  |   contents_.MaybeRemoveEmptyCrcNode();  | 
1447  | 0  |   absl::string_view short_value;  | 
1448  | 0  |   if (CordRep* rep = buffer.ConsumeValue(short_value)) { | 
1449  | 0  |     contents_.PrependTree(rep, CordzUpdateTracker::kPrependCordBuffer);  | 
1450  | 0  |   } else { | 
1451  | 0  |     PrependPrecise(short_value, CordzUpdateTracker::kPrependCordBuffer);  | 
1452  | 0  |   }  | 
1453  | 0  | }  | 
1454  |  |  | 
1455  | 0  | inline CordBuffer Cord::GetAppendBuffer(size_t capacity, size_t min_capacity) { | 
1456  | 0  |   if (empty()) return CordBuffer::CreateWithDefaultLimit(capacity);  | 
1457  | 0  |   return GetAppendBufferSlowPath(0, capacity, min_capacity);  | 
1458  | 0  | }  | 
1459  |  |  | 
1460  |  | inline CordBuffer Cord::GetCustomAppendBuffer(size_t block_size,  | 
1461  |  |                                               size_t capacity,  | 
1462  | 0  |                                               size_t min_capacity) { | 
1463  | 0  |   if (empty()) { | 
1464  | 0  |     return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)  | 
1465  | 0  |                       : CordBuffer::CreateWithDefaultLimit(capacity);  | 
1466  | 0  |   }  | 
1467  | 0  |   return GetAppendBufferSlowPath(block_size, capacity, min_capacity);  | 
1468  | 0  | }  | 
1469  |  |  | 
1470  |  | extern template void Cord::Append(std::string&& src);  | 
1471  |  | extern template void Cord::Prepend(std::string&& src);  | 
1472  |  |  | 
1473  | 0  | inline int Cord::Compare(const Cord& rhs) const { | 
1474  | 0  |   if (!contents_.is_tree() && !rhs.contents_.is_tree()) { | 
1475  | 0  |     return contents_.data_.Compare(rhs.contents_.data_);  | 
1476  | 0  |   }  | 
1477  | 0  | 
  | 
1478  | 0  |   return CompareImpl(rhs);  | 
1479  | 0  | }  | 
1480  |  |  | 
1481  |  | // Does 'this' cord start/end with rhs  | 
1482  | 0  | inline bool Cord::StartsWith(const Cord& rhs) const { | 
1483  | 0  |   if (contents_.IsSame(rhs.contents_)) return true;  | 
1484  | 0  |   size_t rhs_size = rhs.size();  | 
1485  | 0  |   if (size() < rhs_size) return false;  | 
1486  | 0  |   return EqualsImpl(rhs, rhs_size);  | 
1487  | 0  | }  | 
1488  |  |  | 
1489  | 0  | inline bool Cord::StartsWith(absl::string_view rhs) const { | 
1490  | 0  |   size_t rhs_size = rhs.size();  | 
1491  | 0  |   if (size() < rhs_size) return false;  | 
1492  | 0  |   return EqualsImpl(rhs, rhs_size);  | 
1493  | 0  | }  | 
1494  |  |  | 
1495  | 0  | inline void Cord::CopyToArrayImpl(char* absl_nonnull dst) const { | 
1496  | 0  |   if (!contents_.is_tree()) { | 
1497  | 0  |     if (!empty()) contents_.CopyToArray(dst);  | 
1498  | 0  |   } else { | 
1499  | 0  |     CopyToArraySlowPath(dst);  | 
1500  | 0  |   }  | 
1501  | 0  | }  | 
1502  |  |  | 
1503  |  | inline void Cord::ChunkIterator::InitTree(  | 
1504  | 0  |     cord_internal::CordRep* absl_nonnull tree) { | 
1505  | 0  |   tree = cord_internal::SkipCrcNode(tree);  | 
1506  | 0  |   if (tree->tag == cord_internal::BTREE) { | 
1507  | 0  |     current_chunk_ = btree_reader_.Init(tree->btree());  | 
1508  | 0  |   } else { | 
1509  | 0  |     current_leaf_ = tree;  | 
1510  | 0  |     current_chunk_ = cord_internal::EdgeData(tree);  | 
1511  | 0  |   }  | 
1512  | 0  | }  | 
1513  |  |  | 
1514  |  | inline Cord::ChunkIterator::ChunkIterator(  | 
1515  |  |     cord_internal::CordRep* absl_nonnull tree) { | 
1516  |  |   bytes_remaining_ = tree->length;  | 
1517  |  |   InitTree(tree);  | 
1518  |  | }  | 
1519  |  |  | 
1520  |  | inline Cord::ChunkIterator::ChunkIterator(const Cord* absl_nonnull cord) { | 
1521  |  |   if (CordRep* tree = cord->contents_.tree()) { | 
1522  |  |     bytes_remaining_ = tree->length;  | 
1523  |  |     if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) { | 
1524  |  |       InitTree(tree);  | 
1525  |  |     } else { | 
1526  |  |       current_chunk_ = {}; | 
1527  |  |     }  | 
1528  |  |   } else { | 
1529  |  |     bytes_remaining_ = cord->contents_.inline_size();  | 
1530  |  |     current_chunk_ = {cord->contents_.data(), bytes_remaining_}; | 
1531  |  |   }  | 
1532  |  | }  | 
1533  |  |  | 
1534  | 0  | inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() { | 
1535  | 0  |   current_chunk_ = btree_reader_.Next();  | 
1536  | 0  |   return *this;  | 
1537  | 0  | }  | 
1538  |  |  | 
1539  | 0  | inline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) { | 
1540  | 0  |   assert(n >= current_chunk_.size());  | 
1541  | 0  |   bytes_remaining_ -= n;  | 
1542  | 0  |   if (bytes_remaining_) { | 
1543  | 0  |     if (n == current_chunk_.size()) { | 
1544  | 0  |       current_chunk_ = btree_reader_.Next();  | 
1545  | 0  |     } else { | 
1546  | 0  |       size_t offset = btree_reader_.length() - bytes_remaining_;  | 
1547  | 0  |       current_chunk_ = btree_reader_.Seek(offset);  | 
1548  | 0  |     }  | 
1549  | 0  |   } else { | 
1550  | 0  |     current_chunk_ = {}; | 
1551  | 0  |   }  | 
1552  | 0  | }  | 
1553  |  |  | 
1554  | 0  | inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() { | 
1555  | 0  |   ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&  | 
1556  | 0  |                         "Attempted to iterate past `end()`");  | 
1557  | 0  |   assert(bytes_remaining_ >= current_chunk_.size());  | 
1558  | 0  |   bytes_remaining_ -= current_chunk_.size();  | 
1559  | 0  |   if (bytes_remaining_ > 0) { | 
1560  | 0  |     if (btree_reader_) { | 
1561  | 0  |       return AdvanceBtree();  | 
1562  | 0  |     } else { | 
1563  | 0  |       assert(!current_chunk_.empty());  // Called on invalid iterator.  | 
1564  | 0  |     }  | 
1565  | 0  |     current_chunk_ = {}; | 
1566  | 0  |   }  | 
1567  | 0  |   return *this;  | 
1568  | 0  | }  | 
1569  |  |  | 
1570  | 0  | inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) { | 
1571  | 0  |   ChunkIterator tmp(*this);  | 
1572  | 0  |   operator++();  | 
1573  | 0  |   return tmp;  | 
1574  | 0  | }  | 
1575  |  |  | 
1576  | 0  | inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const { | 
1577  | 0  |   return bytes_remaining_ == other.bytes_remaining_;  | 
1578  | 0  | }  | 
1579  |  |  | 
1580  | 0  | inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const { | 
1581  | 0  |   return !(*this == other);  | 
1582  | 0  | }  | 
1583  |  |  | 
1584  | 0  | inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const { | 
1585  | 0  |   ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);  | 
1586  | 0  |   return current_chunk_;  | 
1587  | 0  | }  | 
1588  |  |  | 
1589  | 0  | inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const { | 
1590  | 0  |   ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);  | 
1591  | 0  |   return ¤t_chunk_;  | 
1592  | 0  | }  | 
1593  |  |  | 
1594  | 0  | inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) { | 
1595  | 0  |   assert(n < current_chunk_.size());  | 
1596  | 0  |   current_chunk_.remove_prefix(n);  | 
1597  | 0  |   bytes_remaining_ -= n;  | 
1598  | 0  | }  | 
1599  |  |  | 
1600  | 0  | inline void Cord::ChunkIterator::AdvanceBytes(size_t n) { | 
1601  | 0  |   assert(bytes_remaining_ >= n);  | 
1602  | 0  |   if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) { | 
1603  | 0  |     RemoveChunkPrefix(n);  | 
1604  | 0  |   } else if (n != 0) { | 
1605  | 0  |     if (btree_reader_) { | 
1606  | 0  |       AdvanceBytesBtree(n);  | 
1607  | 0  |     } else { | 
1608  | 0  |       bytes_remaining_ = 0;  | 
1609  | 0  |     }  | 
1610  | 0  |   }  | 
1611  | 0  | }  | 
1612  |  |  | 
1613  | 0  | inline Cord::ChunkIterator Cord::chunk_begin() const { | 
1614  | 0  |   return ChunkIterator(this);  | 
1615  | 0  | }  | 
1616  |  |  | 
1617  | 0  | inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); } | 
1618  |  |  | 
1619  | 0  | inline Cord::ChunkIterator Cord::ChunkRange::begin() const { | 
1620  | 0  |   return cord_->chunk_begin();  | 
1621  | 0  | }  | 
1622  |  |  | 
1623  | 0  | inline Cord::ChunkIterator Cord::ChunkRange::end() const { | 
1624  | 0  |   return cord_->chunk_end();  | 
1625  | 0  | }  | 
1626  |  |  | 
1627  | 0  | inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); } | 
1628  |  |  | 
1629  | 0  | inline Cord::CharIterator& Cord::CharIterator::operator++() { | 
1630  | 0  |   if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) { | 
1631  | 0  |     chunk_iterator_.RemoveChunkPrefix(1);  | 
1632  | 0  |   } else { | 
1633  | 0  |     ++chunk_iterator_;  | 
1634  | 0  |   }  | 
1635  | 0  |   return *this;  | 
1636  | 0  | }  | 
1637  |  |  | 
1638  | 0  | inline Cord::CharIterator Cord::CharIterator::operator++(int) { | 
1639  | 0  |   CharIterator tmp(*this);  | 
1640  | 0  |   operator++();  | 
1641  | 0  |   return tmp;  | 
1642  | 0  | }  | 
1643  |  |  | 
1644  | 0  | inline bool Cord::CharIterator::operator==(const CharIterator& other) const { | 
1645  | 0  |   return chunk_iterator_ == other.chunk_iterator_;  | 
1646  | 0  | }  | 
1647  |  |  | 
1648  | 0  | inline bool Cord::CharIterator::operator!=(const CharIterator& other) const { | 
1649  | 0  |   return !(*this == other);  | 
1650  | 0  | }  | 
1651  |  |  | 
1652  | 0  | inline Cord::CharIterator::reference Cord::CharIterator::operator*() const { | 
1653  | 0  |   return *chunk_iterator_->data();  | 
1654  | 0  | }  | 
1655  |  |  | 
1656  |  | inline Cord Cord::AdvanceAndRead(CharIterator* absl_nonnull it,  | 
1657  | 0  |                                  size_t n_bytes) { | 
1658  | 0  |   assert(it != nullptr);  | 
1659  | 0  |   return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);  | 
1660  | 0  | }  | 
1661  |  |  | 
1662  | 0  | inline void Cord::Advance(CharIterator* absl_nonnull it, size_t n_bytes) { | 
1663  | 0  |   assert(it != nullptr);  | 
1664  | 0  |   it->chunk_iterator_.AdvanceBytes(n_bytes);  | 
1665  | 0  | }  | 
1666  |  |  | 
1667  | 0  | inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) { | 
1668  | 0  |   return *it.chunk_iterator_;  | 
1669  | 0  | }  | 
1670  |  |  | 
1671  |  | inline ptrdiff_t Cord::Distance(const CharIterator& first,  | 
1672  | 0  |                                 const CharIterator& last) { | 
1673  | 0  |   return static_cast<ptrdiff_t>(first.chunk_iterator_.bytes_remaining_ -  | 
1674  | 0  |                                 last.chunk_iterator_.bytes_remaining_);  | 
1675  | 0  | }  | 
1676  |  |  | 
1677  | 0  | inline Cord::CharIterator Cord::char_begin() const { | 
1678  | 0  |   return CharIterator(this);  | 
1679  | 0  | }  | 
1680  |  |  | 
1681  | 0  | inline Cord::CharIterator Cord::char_end() const { return CharIterator(); } | 
1682  |  |  | 
1683  | 0  | inline Cord::CharIterator Cord::CharRange::begin() const { | 
1684  | 0  |   return cord_->char_begin();  | 
1685  | 0  | }  | 
1686  |  |  | 
1687  | 0  | inline Cord::CharIterator Cord::CharRange::end() const { | 
1688  | 0  |   return cord_->char_end();  | 
1689  | 0  | }  | 
1690  |  |  | 
1691  | 0  | inline Cord::CharRange Cord::Chars() const { return CharRange(this); } | 
1692  |  |  | 
1693  |  | inline void Cord::ForEachChunk(  | 
1694  | 0  |     absl::FunctionRef<void(absl::string_view)> callback) const { | 
1695  | 0  |   absl::cord_internal::CordRep* rep = contents_.tree();  | 
1696  | 0  |   if (rep == nullptr) { | 
1697  | 0  |     callback(absl::string_view(contents_.data(), contents_.size()));  | 
1698  | 0  |   } else { | 
1699  | 0  |     ForEachChunkAux(rep, callback);  | 
1700  | 0  |   }  | 
1701  | 0  | }  | 
1702  |  |  | 
1703  |  | // Nonmember Cord-to-Cord relational operators.  | 
1704  | 0  | inline bool operator==(const Cord& lhs, const Cord& rhs) { | 
1705  | 0  |   if (lhs.contents_.IsSame(rhs.contents_)) return true;  | 
1706  | 0  |   size_t rhs_size = rhs.size();  | 
1707  | 0  |   if (lhs.size() != rhs_size) return false;  | 
1708  | 0  |   return lhs.EqualsImpl(rhs, rhs_size);  | 
1709  | 0  | }  | 
1710  |  |  | 
1711  | 0  | inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); } | 
1712  | 0  | inline bool operator<(const Cord& x, const Cord& y) { return x.Compare(y) < 0; } | 
1713  | 0  | inline bool operator>(const Cord& x, const Cord& y) { return x.Compare(y) > 0; } | 
1714  | 0  | inline bool operator<=(const Cord& x, const Cord& y) { | 
1715  | 0  |   return x.Compare(y) <= 0;  | 
1716  | 0  | }  | 
1717  | 0  | inline bool operator>=(const Cord& x, const Cord& y) { | 
1718  | 0  |   return x.Compare(y) >= 0;  | 
1719  | 0  | }  | 
1720  |  |  | 
1721  |  | // Nonmember Cord-to-absl::string_view relational operators.  | 
1722  |  | //  | 
1723  |  | // Due to implicit conversions, these also enable comparisons of Cord with  | 
1724  |  | // std::string and const char*.  | 
1725  | 0  | inline bool operator==(const Cord& lhs, absl::string_view rhs) { | 
1726  | 0  |   size_t lhs_size = lhs.size();  | 
1727  | 0  |   size_t rhs_size = rhs.size();  | 
1728  | 0  |   if (lhs_size != rhs_size) return false;  | 
1729  | 0  |   return lhs.EqualsImpl(rhs, rhs_size);  | 
1730  | 0  | }  | 
1731  |  |  | 
1732  | 0  | inline bool operator==(absl::string_view x, const Cord& y) { return y == x; } | 
1733  | 0  | inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); } | 
1734  | 0  | inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); } | 
1735  | 0  | inline bool operator<(const Cord& x, absl::string_view y) { | 
1736  | 0  |   return x.Compare(y) < 0;  | 
1737  | 0  | }  | 
1738  | 0  | inline bool operator<(absl::string_view x, const Cord& y) { | 
1739  | 0  |   return y.Compare(x) > 0;  | 
1740  | 0  | }  | 
1741  | 0  | inline bool operator>(const Cord& x, absl::string_view y) { return y < x; } | 
1742  | 0  | inline bool operator>(absl::string_view x, const Cord& y) { return y < x; } | 
1743  | 0  | inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); } | 
1744  | 0  | inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); } | 
1745  | 0  | inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); } | 
1746  | 0  | inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); } | 
1747  |  |  | 
1748  |  | // Some internals exposed to test code.  | 
1749  |  | namespace strings_internal { | 
1750  |  | class CordTestAccess { | 
1751  |  |  public:  | 
1752  |  |   static size_t FlatOverhead();  | 
1753  |  |   static size_t MaxFlatLength();  | 
1754  |  |   static size_t SizeofCordRepExternal();  | 
1755  |  |   static size_t SizeofCordRepSubstring();  | 
1756  |  |   static size_t FlatTagToLength(uint8_t tag);  | 
1757  |  |   static uint8_t LengthToTag(size_t s);  | 
1758  |  | };  | 
1759  |  | }  // namespace strings_internal  | 
1760  |  | ABSL_NAMESPACE_END  | 
1761  |  | }  // namespace absl  | 
1762  |  |  | 
1763  |  | #endif  // ABSL_STRINGS_CORD_H_  |