cord_buffer.h
Go to the documentation of this file.
1 // Copyright 2021 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_buffer.h
17 // -----------------------------------------------------------------------------
18 //
19 // This file defines an `absl::CordBuffer` data structure to hold data for
20 // eventual inclusion within an existing `Cord` data structure. Cord buffers are
21 // useful for building large Cords that may require custom allocation of its
22 // associated memory.
23 //
24 #ifndef ABSL_STRINGS_CORD_BUFFER_H_
25 #define ABSL_STRINGS_CORD_BUFFER_H_
26 
27 #include <algorithm>
28 #include <cassert>
29 #include <cstddef>
30 #include <cstdint>
31 #include <memory>
32 #include <utility>
33 
34 #include "absl/base/config.h"
35 #include "absl/base/macros.h"
36 #include "absl/numeric/bits.h"
37 #include "absl/strings/internal/cord_internal.h"
38 #include "absl/strings/internal/cord_rep_flat.h"
39 #include "absl/types/span.h"
40 
41 namespace absl {
43 
44 class Cord;
45 class CordBufferTestPeer;
46 
47 // CordBuffer
48 //
49 // CordBuffer manages memory buffers for purposes such as zero-copy APIs as well
50 // as applications building cords with large data requiring granular control
51 // over the allocation and size of cord data. For example, a function creating
52 // a cord of random data could use a CordBuffer as follows:
53 //
54 // absl::Cord CreateRandomCord(size_t length) {
55 // absl::Cord cord;
56 // while (length > 0) {
57 // CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(length);
58 // absl::Span<char> data = buffer.available_up_to(length);
59 // FillRandomValues(data.data(), data.size());
60 // buffer.IncreaseLengthBy(data.size());
61 // cord.Append(std::move(buffer));
62 // length -= data.size();
63 // }
64 // return cord;
65 // }
66 //
67 // CordBuffer instances are by default limited to a capacity of `kDefaultLimit`
68 // bytes. `kDefaultLimit` is currently just under 4KiB, but this default may
69 // change in the future and/or for specific architectures. The default limit is
70 // aimed to provide a good trade-off between performance and memory overhead.
71 // Smaller buffers typically incur more compute cost while larger buffers are
72 // more CPU efficient but create significant memory overhead because of such
73 // allocations being less granular. Using larger buffers may also increase the
74 // risk of memory fragmentation.
75 //
76 // Applications create a buffer using one of the `CreateWithDefaultLimit()` or
77 // `CreateWithCustomLimit()` methods. The returned instance will have a non-zero
78 // capacity and a zero length. Applications use the `data()` method to set the
79 // contents of the managed memory, and once done filling the buffer, use the
80 // `IncreaseLengthBy()` or 'SetLength()' method to specify the length of the
81 // initialized data before adding the buffer to a Cord.
82 //
83 // The `CreateWithCustomLimit()` method is intended for applications needing
84 // larger buffers than the default memory limit, allowing the allocation of up
85 // to a capacity of `kCustomLimit` bytes minus some minimum internal overhead.
86 // The usage of `CreateWithCustomLimit()` should be limited to only those use
87 // cases where the distribution of the input is relatively well known, and/or
88 // where the trade-off between the efficiency gains outweigh the risk of memory
89 // fragmentation. See the documentation for `CreateWithCustomLimit()` for more
90 // information on using larger custom limits.
91 //
92 // The capacity of a `CordBuffer` returned by one of the `Create` methods may
93 // be larger than the requested capacity due to rounding, alignment and
94 // granularity of the memory allocator. Applications should use the `capacity`
95 // method to obtain the effective capacity of the returned instance as
96 // demonstrated in the provided example above.
97 //
98 // CordBuffer is a move-only class. All references into the managed memory are
99 // invalidated when an instance is moved into either another CordBuffer instance
100 // or a Cord. Writing to a location obtained by a previous call to `data()`
101 // after an instance was moved will lead to undefined behavior.
102 //
103 // A `moved from` CordBuffer instance will have a valid, but empty state.
104 // CordBuffer is thread compatible.
105 class CordBuffer {
106  public:
107  // kDefaultLimit
108  //
109  // Default capacity limits of allocated CordBuffers.
110  // See the class comments for more information on allocation limits.
111  static constexpr size_t kDefaultLimit = cord_internal::kMaxFlatLength;
112 
113  // kCustomLimit
114  //
115  // Maximum size for CreateWithCustomLimit() allocated buffers.
116  // Note that the effective capacity may be slightly less
117  // because of internal overhead of internal cord buffers.
118  static constexpr size_t kCustomLimit = 64U << 10;
119 
120  // Constructors, Destructors and Assignment Operators
121 
122  // Creates an empty CordBuffer.
123  CordBuffer() = default;
124 
125  // Destroys this CordBuffer instance and, if not empty, releases any memory
126  // managed by this instance, invalidating previously returned references.
127  ~CordBuffer();
128 
129  // CordBuffer is move-only
130  CordBuffer(CordBuffer&& rhs) noexcept;
131  CordBuffer& operator=(CordBuffer&&) noexcept;
133  CordBuffer& operator=(const CordBuffer&) = delete;
134 
135  // CordBuffer::MaximumPayload()
136  //
137  // Returns the guaranteed maximum payload for a CordBuffer returned by the
138  // `CreateWithDefaultLimit()` method. While small, each internal buffer inside
139  // a Cord incurs an overhead to manage the length, type and reference count
140  // for the buffer managed inside the cord tree. Applications can use this
141  // method to get approximate number of buffers required for a given byte
142  // size, etc.
143  //
144  // For example:
145  // const size_t payload = absl::CordBuffer::MaximumPayload();
146  // const size_t buffer_count = (total_size + payload - 1) / payload;
147  // buffers.reserve(buffer_count);
148  static constexpr size_t MaximumPayload();
149 
150  // Overload to the above `MaximumPayload()` except that it returns the
151  // maximum payload for a CordBuffer returned by the `CreateWithCustomLimit()`
152  // method given the provided `block_size`.
153  static constexpr size_t MaximumPayload(size_t block_size);
154 
155  // CordBuffer::CreateWithDefaultLimit()
156  //
157  // Creates a CordBuffer instance of the desired `capacity`, capped at the
158  // default limit `kDefaultLimit`. The returned buffer has a guaranteed
159  // capacity of at least `min(kDefaultLimit, capacity)`. See the class comments
160  // for more information on buffer capacities and intended usage.
162 
163 
164  // CordBuffer::CreateWithCustomLimit()
165  //
166  // Creates a CordBuffer instance of the desired `capacity` rounded to an
167  // appropriate power of 2 size less than, or equal to `block_size`.
168  // Requires `block_size` to be a power of 2.
169  //
170  // If `capacity` is less than or equal to `kDefaultLimit`, then this method
171  // behaves identical to `CreateWithDefaultLimit`, which means that the caller
172  // is guaranteed to get a buffer of at least the requested capacity.
173  //
174  // If `capacity` is greater than or equal to `block_size`, then this method
175  // returns a buffer with an `allocated size` of `block_size` bytes. Otherwise,
176  // this methods returns a buffer with a suitable smaller power of 2 block size
177  // to satisfy the request. The actual size depends on a number of factors, and
178  // is typically (but not necessarily) the highest or second highest power of 2
179  // value less than or equal to `capacity`.
180  //
181  // The 'allocated size' includes a small amount of overhead required for
182  // internal state, which is currently 13 bytes on 64-bit platforms. For
183  // example: a buffer created with `block_size` and `capacity' set to 8KiB
184  // will have an allocated size of 8KiB, and an effective internal `capacity`
185  // of 8KiB - 13 = 8179 bytes.
186  //
187  // To demonstrate this in practice, let's assume we want to read data from
188  // somewhat larger files using approximately 64KiB buffers:
189  //
190  // absl::Cord ReadFromFile(int fd, size_t n) {
191  // absl::Cord cord;
192  // while (n > 0) {
193  // CordBuffer buffer = CordBuffer::CreateWithCustomLimit(64 << 10, n);
194  // absl::Span<char> data = buffer.available_up_to(n);
195  // ReadFileDataOrDie(fd, data.data(), data.size());
196  // buffer.IncreaseLengthBy(data.size());
197  // cord.Append(std::move(buffer));
198  // n -= data.size();
199  // }
200  // return cord;
201  // }
202  //
203  // If we'd use this function to read a file of 659KiB, we may get the
204  // following pattern of allocated cord buffer sizes:
205  //
206  // CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
207  // CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
208  // ...
209  // CreateWithCustomLimit(64KiB, 19586) --> ~16KiB (16371)
210  // CreateWithCustomLimit(64KiB, 3215) --> 3215 (at least 3215)
211  //
212  // The reason the method returns a 16K buffer instead of a roughly 19K buffer
213  // is to reduce memory overhead and fragmentation risks. Using carefully
214  // chosen power of 2 values reduces the entropy of allocated memory sizes.
215  //
216  // Additionally, let's assume we'd use the above function on files that are
217  // generally smaller than 64K. If we'd use 'precise' sized buffers for such
218  // files, than we'd get a very wide distribution of allocated memory sizes
219  // rounded to 4K page sizes, and we'd end up with a lot of unused capacity.
220  //
221  // In general, application should only use custom sizes if the data they are
222  // consuming or storing is expected to be many times the chosen block size,
223  // and be based on objective data and performance metrics. For example, a
224  // compress function may work faster and consume less CPU when using larger
225  // buffers. Such an application should pick a size offering a reasonable
226  // trade-off between expected data size, compute savings with larger buffers,
227  // and the cost or fragmentation effect of larger buffers.
228  // Applications must pick a reasonable spot on that curve, and make sure their
229  // data meets their expectations in size distributions such as "mostly large".
230  static CordBuffer CreateWithCustomLimit(size_t block_size, size_t capacity);
231 
232  // CordBuffer::available()
233  //
234  // Returns the span delineating the available capacity in this buffer
235  // which is defined as `{ data() + length(), capacity() - length() }`.
236  absl::Span<char> available();
237 
238  // CordBuffer::available_up_to()
239  //
240  // Returns the span delineating the available capacity in this buffer limited
241  // to `size` bytes. This is equivalent to `available().subspan(0, size)`.
242  absl::Span<char> available_up_to(size_t size);
243 
244  // CordBuffer::data()
245  //
246  // Returns a non-null reference to the data managed by this instance.
247  // Applications are allowed to write up to `capacity` bytes of instance data.
248  // CordBuffer data is uninitialized by default. Reading data from an instance
249  // that has not yet been initialized will lead to undefined behavior.
250  char* data();
251  const char* data() const;
252 
253  // CordBuffer::length()
254  //
255  // Returns the length of this instance. The default length of a CordBuffer is
256  // 0, indicating an 'empty' CordBuffer. Applications must specify the length
257  // of the data in a CordBuffer before adding it to a Cord.
258  size_t length() const;
259 
260  // CordBuffer::capacity()
261  //
262  // Returns the capacity of this instance. All instances have a non-zero
263  // capacity: default and `moved from` instances have a small internal buffer.
264  size_t capacity() const;
265 
266  // CordBuffer::IncreaseLengthBy()
267  //
268  // Increases the length of this buffer by the specified 'n' bytes.
269  // Applications must make sure all data in this buffer up to the new length
270  // has been initialized before adding a CordBuffer to a Cord: failure to do so
271  // will lead to undefined behavior. Requires `length() + n <= capacity()`.
272  // Typically, applications will use 'available_up_to()` to get a span of the
273  // desired capacity, and use `span.size()` to increase the length as in:
274  // absl::Span<char> span = buffer.available_up_to(desired);
275  // buffer.IncreaseLengthBy(span.size());
276  // memcpy(span.data(), src, span.size());
277  // etc...
278  void IncreaseLengthBy(size_t n);
279 
280  // CordBuffer::SetLength()
281  //
282  // Sets the data length of this instance. Applications must make sure all data
283  // of the specified length has been initialized before adding a CordBuffer to
284  // a Cord: failure to do so will lead to undefined behavior.
285  // Setting the length to a small value or zero does not release any memory
286  // held by this CordBuffer instance. Requires `length <= capacity()`.
287  // Applications should preferably use the `IncreaseLengthBy()` method above
288  // in combination with the 'available()` or `available_up_to()` methods.
289  void SetLength(size_t length);
290 
291  private:
292  // Make sure we don't accidentally over promise.
293  static_assert(kCustomLimit <= cord_internal::kMaxLargeFlatSize, "");
294 
295  // Assume the cost of an 'uprounded' allocation to CeilPow2(size) versus
296  // the cost of allocating at least 1 extra flat <= 4KB:
297  // - Flat overhead = 13 bytes
298  // - Btree amortized cost / node =~ 13 bytes
299  // - 64 byte granularity of tcmalloc at 4K =~ 32 byte average
300  // CPU cost and efficiency requires we should at least 'save' something by
301  // splitting, as a poor man's measure, we say the slop needs to be
302  // at least double the cost offset to make it worth splitting: ~128 bytes.
303  static constexpr size_t kMaxPageSlop = 128;
304 
305  // Overhead for allocation a flat.
306  static constexpr size_t kOverhead = cord_internal::kFlatOverhead;
307 
308  using CordRepFlat = cord_internal::CordRepFlat;
309 
310  // `Rep` is the internal data representation of a CordBuffer. The internal
311  // representation has an internal small size optimization similar to
312  // std::string (SSO).
314  // Inline SSO size of a CordBuffer
315  static constexpr size_t kInlineCapacity = sizeof(intptr_t) * 2 - 1;
316 
317  // Creates a default instance with kInlineCapacity.
318  Rep() : short_rep{} {}
319 
320  // Creates an instance managing an allocated non zero CordRep.
321  explicit Rep(cord_internal::CordRepFlat* rep) : long_rep{rep} {
322  assert(rep != nullptr);
323  }
324 
325  // Returns true if this instance manages the SSO internal buffer.
326  bool is_short() const {
327  constexpr size_t offset = offsetof(Short, raw_size);
328  return (reinterpret_cast<const char*>(this)[offset] & 1) != 0;
329  }
330 
331  // Returns the available area of the internal SSO data
333  assert(is_short());
334  const size_t length = (short_rep.raw_size >> 1);
335  return absl::Span<char>(short_rep.data + length,
336  kInlineCapacity - length);
337  }
338 
339  // Returns the available area of the internal SSO data
341  assert(!is_short());
342  const size_t length = long_rep.rep->length;
343  return absl::Span<char>(long_rep.rep->Data() + length,
344  long_rep.rep->Capacity() - length);
345  }
346 
347  // Returns the length of the internal SSO data.
348  size_t short_length() const {
349  assert(is_short());
350  return short_rep.raw_size >> 1;
351  }
352 
353  // Sets the length of the internal SSO data.
354  // Disregards any previously set CordRep instance.
355  void set_short_length(size_t length) {
356  short_rep.raw_size = static_cast<char>((length << 1) + 1);
357  }
358 
359  // Adds `n` to the current short length.
360  void add_short_length(size_t n) {
361  assert(is_short());
362  short_rep.raw_size += static_cast<char>(n << 1);
363  }
364 
365  // Returns reference to the internal SSO data buffer.
366  char* data() {
367  assert(is_short());
368  return short_rep.data;
369  }
370  const char* data() const {
371  assert(is_short());
372  return short_rep.data;
373  }
374 
375  // Returns a pointer the external CordRep managed by this instance.
377  assert(!is_short());
378  return long_rep.rep;
379  }
380 
381  // The internal representation takes advantage of the fact that allocated
382  // memory is always on an even address, and uses the least significant bit
383  // of the first or last byte (depending on endianness) as the inline size
384  // indicator overlapping with the least significant byte of the CordRep*.
385 #if defined(ABSL_IS_BIG_ENDIAN)
386  struct Long {
387  explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
388  void* padding;
390  };
391  struct Short {
392  char data[sizeof(Long) - 1];
393  char raw_size = 1;
394  };
395 #else
396  struct Long {
397  explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
399  void* padding;
400  };
401  struct Short {
402  char raw_size = 1;
403  char data[sizeof(Long) - 1];
404  };
405 #endif
406 
407  union {
410  };
411  };
412 
413  // Power2 functions
414  static bool IsPow2(size_t size) { return absl::has_single_bit(size); }
415  static size_t Log2Floor(size_t size) { return absl::bit_width(size) - 1; }
416  static size_t Log2Ceil(size_t size) { return absl::bit_width(size - 1); }
417 
418  // Implementation of `CreateWithCustomLimit()`.
419  // This implementation allows for future memory allocation hints to
420  // be passed down into the CordRepFlat allocation function.
421  template <typename... AllocationHints>
422  static CordBuffer CreateWithCustomLimitImpl(size_t block_size,
423  size_t capacity,
424  AllocationHints... hints);
425 
426  // Consumes the value contained in this instance and resets the instance.
427  // This method returns a non-null Cordrep* if the current instances manages a
428  // CordRep*, and resets the instance to an empty SSO instance. If the current
429  // instance is an SSO instance, then this method returns nullptr and sets
430  // `short_value` to the inlined data value. In either case, the current
431  // instance length is reset to zero.
432  // This method is intended to be used by Cord internal functions only.
434  cord_internal::CordRep* rep = nullptr;
435  if (rep_.is_short()) {
436  short_value = absl::string_view(rep_.data(), rep_.short_length());
437  } else {
438  rep = rep_.rep();
439  }
441  return rep;
442  }
443 
444  // Internal constructor.
446  assert(rep != nullptr);
447  }
448 
450 
451  friend class Cord;
452  friend class CordBufferTestPeer;
453 };
454 
455 inline constexpr size_t CordBuffer::MaximumPayload() {
457 }
458 
459 inline constexpr size_t CordBuffer::MaximumPayload(size_t block_size) {
460  // TODO(absl-team): Use std::min when C++11 support is dropped.
461  return (kCustomLimit < block_size ? kCustomLimit : block_size) -
463 }
464 
468  rep->length = 0;
469  return CordBuffer(rep);
470  }
471  return CordBuffer();
472 }
473 
474 template <typename... AllocationHints>
476  size_t block_size, size_t capacity, AllocationHints... hints) {
477  assert(IsPow2(block_size));
479  block_size = (std::min)(block_size, kCustomLimit);
480  if (capacity + kOverhead >= block_size) {
481  capacity = block_size;
482  } else if (capacity <= kDefaultLimit) {
484  } else if (!IsPow2(capacity)) {
485  // Check if rounded up to next power 2 is a good enough fit
486  // with limited waste making it an acceptable direct fit.
487  const size_t rounded_up = size_t{1} << Log2Ceil(capacity);
488  const size_t slop = rounded_up - capacity;
489  if (slop >= kOverhead && slop <= kMaxPageSlop + kOverhead) {
490  capacity = rounded_up;
491  } else {
492  // Round down to highest power of 2 <= capacity.
493  // Consider a more aggressive step down if that may reduce the
494  // risk of fragmentation where 'people are holding it wrong'.
495  const size_t rounded_down = size_t{1} << Log2Floor(capacity);
496  capacity = rounded_down;
497  }
498  }
499  const size_t length = capacity - kOverhead;
500  auto* rep = CordRepFlat::New(CordRepFlat::Large(), length, hints...);
501  rep->length = 0;
502  return CordBuffer(rep);
503 }
504 
506  size_t capacity) {
507  return CreateWithCustomLimitImpl(block_size, capacity);
508 }
509 
511  if (!rep_.is_short()) {
513  }
514 }
515 
516 inline CordBuffer::CordBuffer(CordBuffer&& rhs) noexcept : rep_(rhs.rep_) {
517  rhs.rep_.set_short_length(0);
518 }
519 
520 inline CordBuffer& CordBuffer::operator=(CordBuffer&& rhs) noexcept {
521  if (!rep_.is_short()) cord_internal::CordRepFlat::Delete(rep_.rep());
522  rep_ = rhs.rep_;
523  rhs.rep_.set_short_length(0);
524  return *this;
525 }
526 
529 }
530 
532  return available().subspan(0, size);
533 }
534 
535 inline char* CordBuffer::data() {
536  return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
537 }
538 
539 inline const char* CordBuffer::data() const {
540  return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
541 }
542 
543 inline size_t CordBuffer::capacity() const {
545 }
546 
547 inline size_t CordBuffer::length() const {
548  return rep_.is_short() ? rep_.short_length() : rep_.rep()->length;
549 }
550 
551 inline void CordBuffer::SetLength(size_t length) {
553  if (rep_.is_short()) {
555  } else {
556  rep_.rep()->length = length;
557  }
558 }
559 
560 inline void CordBuffer::IncreaseLengthBy(size_t n) {
561  ABSL_HARDENING_ASSERT(n <= capacity() && length() + n <= capacity());
562  if (rep_.is_short()) {
564  } else {
565  rep_.rep()->length += n;
566  }
567 }
568 
570 } // namespace absl
571 
572 #endif // ABSL_STRINGS_CORD_BUFFER_H_
absl::cord_internal::kMaxLargeFlatSize
static constexpr size_t kMaxLargeFlatSize
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:47
absl::Cord
Definition: abseil-cpp/absl/strings/cord.h:150
absl::CordBuffer::Rep::long_available
absl::Span< char > long_available()
Definition: cord_buffer.h:340
absl::CordBuffer::Log2Ceil
static size_t Log2Ceil(size_t size)
Definition: cord_buffer.h:416
absl::cord_internal::CordRepFlat::Large
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:109
absl::CordBuffer::Rep::short_available
absl::Span< char > short_available()
Definition: cord_buffer.h:332
absl::CordBuffer::CordBuffer
CordBuffer()=default
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
absl::CordBuffer::available_up_to
absl::Span< char > available_up_to(size_t size)
Definition: cord_buffer.h:531
absl::CordBuffer::Rep::data
char * data()
Definition: cord_buffer.h:366
absl::CordBuffer::Rep::Long
Definition: cord_buffer.h:396
absl::CordBuffer::length
size_t length() const
Definition: cord_buffer.h:547
capacity
uint16_t capacity
Definition: protobuf/src/google/protobuf/descriptor.cc:948
absl::CordBuffer::Rep::rep
cord_internal::CordRepFlat * rep() const
Definition: cord_buffer.h:376
absl::CordBuffer::available
absl::Span< char > available()
Definition: cord_buffer.h:527
absl::cord_internal::CordRepFlat::New
static CordRepFlat * New(size_t len)
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:128
absl::CordBuffer::data
char * data()
Definition: cord_buffer.h:535
absl::CordBuffer::CreateWithCustomLimit
static CordBuffer CreateWithCustomLimit(size_t block_size, size_t capacity)
Definition: cord_buffer.h:505
absl::Span
Definition: abseil-cpp/absl/types/span.h:152
absl::cord_internal::CordRepFlat::Delete
static void Delete(CordRep *rep)
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:137
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
absl::cord_internal::CordRepFlat::Capacity
size_t Capacity() const
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:166
absl::cord_internal::kMaxFlatLength
static constexpr size_t kMaxFlatLength
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:45
absl::CordBuffer::MaximumPayload
static constexpr size_t MaximumPayload()
Definition: cord_buffer.h:455
absl::CordBuffer::capacity
size_t capacity() const
Definition: cord_buffer.h:543
absl::CordBuffer::ConsumeValue
cord_internal::CordRep * ConsumeValue(absl::string_view &short_value)
Definition: cord_buffer.h:433
run_xds_tests.delete
delete
Definition: run_xds_tests.py:3329
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::cord_internal::CordRep
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:209
absl::CordBuffer::SetLength
void SetLength(size_t length)
Definition: cord_buffer.h:551
ABSL_HARDENING_ASSERT
#define ABSL_HARDENING_ASSERT(expr)
Definition: abseil-cpp/absl/base/macros.h:134
absl::CordBuffer::Rep::Long::rep
cord_internal::CordRepFlat * rep
Definition: cord_buffer.h:398
absl::CordBuffer::kCustomLimit
static constexpr size_t kCustomLimit
Definition: cord_buffer.h:118
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
absl::CordBuffer::CordBuffer
CordBuffer(cord_internal::CordRepFlat *rep)
Definition: cord_buffer.h:445
absl::CordBuffer::Rep::data
const char * data() const
Definition: cord_buffer.h:370
absl::CordBuffer::Rep::Long::padding
void * padding
Definition: cord_buffer.h:399
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::CordBuffer::Log2Floor
static size_t Log2Floor(size_t size)
Definition: cord_buffer.h:415
absl::CordBuffer::kOverhead
static constexpr size_t kOverhead
Definition: cord_buffer.h:306
absl::CordBuffer::Rep::Short
Definition: cord_buffer.h:401
absl::CordBuffer::operator=
CordBuffer & operator=(CordBuffer &&) noexcept
Definition: cord_buffer.h:520
absl::CordBuffer::Rep::add_short_length
void add_short_length(size_t n)
Definition: cord_buffer.h:360
absl::CordBuffer::Rep::kInlineCapacity
static constexpr size_t kInlineCapacity
Definition: cord_buffer.h:315
absl::cord_internal::kFlatOverhead
static constexpr size_t kFlatOverhead
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:42
absl::CordBuffer::Rep::short_rep
Short short_rep
Definition: cord_buffer.h:409
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
absl::has_single_bit
constexpr std::enable_if< std::is_unsigned< T >::value, bool >::type has_single_bit(T x) noexcept
Definition: abseil-cpp/absl/numeric/bits.h:126
absl::CordBuffer::IncreaseLengthBy
void IncreaseLengthBy(size_t n)
Definition: cord_buffer.h:560
min
#define min(a, b)
Definition: qsort.h:83
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
absl::bit_width
ABSL_INTERNAL_CONSTEXPR_CLZ std::enable_if< std::is_unsigned< T >::value, T >::type bit_width(T x) noexcept
Definition: abseil-cpp/absl/numeric/bits.h:135
absl::cord_internal::CordRep::length
size_t length
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:228
absl::CordBuffer::CreateWithDefaultLimit
static CordBuffer CreateWithDefaultLimit(size_t capacity)
Definition: cord_buffer.h:465
absl::CordBuffer::Rep::short_length
size_t short_length() const
Definition: cord_buffer.h:348
absl::CordBuffer::Rep::Long::Long
Long(cord_internal::CordRepFlat *rep_arg)
Definition: cord_buffer.h:397
absl::CordBuffer::~CordBuffer
~CordBuffer()
Definition: cord_buffer.h:510
absl::CordBuffer::IsPow2
static bool IsPow2(size_t size)
Definition: cord_buffer.h:414
absl::CordBuffer::Rep
Definition: cord_buffer.h:313
absl::CordBuffer::kMaxPageSlop
static constexpr size_t kMaxPageSlop
Definition: cord_buffer.h:303
absl::cord_internal::CordRepFlat::Data
char * Data()
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:162
string_view
absl::string_view string_view
Definition: attr.cc:22
absl::CordBuffer::rep_
Rep rep_
Definition: cord_buffer.h:449
rep
const CordRep * rep
Definition: cord_analysis.cc:53
absl::CordBuffer::kDefaultLimit
static constexpr size_t kDefaultLimit
Definition: cord_buffer.h:111
absl::CordBuffer::Rep::Rep
Rep(cord_internal::CordRepFlat *rep)
Definition: cord_buffer.h:321
absl::CordBuffer::Rep::is_short
bool is_short() const
Definition: cord_buffer.h:326
absl::CordBuffer
Definition: cord_buffer.h:105
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::CordBufferTestPeer
Definition: cord_buffer_test.cc:39
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
length
std::size_t length
Definition: abseil-cpp/absl/time/internal/test_util.cc:57
absl::CordBuffer::Rep::long_rep
Long long_rep
Definition: cord_buffer.h:408
testing::gmock_generated_actions_test::Short
short Short(short n)
Definition: bloaty/third_party/googletest/googlemock/test/gmock-generated-actions_test.cc:62
absl::cord_internal::CordRepFlat
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:107
absl::CordBuffer::Rep::Rep
Rep()
Definition: cord_buffer.h:318
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
absl::CordBuffer::Rep::set_short_length
void set_short_length(size_t length)
Definition: cord_buffer.h:355
absl::CordBuffer::CreateWithCustomLimitImpl
static CordBuffer CreateWithCustomLimitImpl(size_t block_size, size_t capacity, AllocationHints... hints)
Definition: cord_buffer.h:475


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:56