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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:02