Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:15

0001 // Copyright 2021 The Abseil Authors
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //     https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // -----------------------------------------------------------------------------
0016 // File: cord_buffer.h
0017 // -----------------------------------------------------------------------------
0018 //
0019 // This file defines an `absl::CordBuffer` data structure to hold data for
0020 // eventual inclusion within an existing `Cord` data structure. Cord buffers are
0021 // useful for building large Cords that may require custom allocation of its
0022 // associated memory.
0023 //
0024 #ifndef ABSL_STRINGS_CORD_BUFFER_H_
0025 #define ABSL_STRINGS_CORD_BUFFER_H_
0026 
0027 #include <algorithm>
0028 #include <cassert>
0029 #include <cstddef>
0030 #include <cstdint>
0031 #include <memory>
0032 #include <utility>
0033 
0034 #include "absl/base/config.h"
0035 #include "absl/base/macros.h"
0036 #include "absl/numeric/bits.h"
0037 #include "absl/strings/internal/cord_internal.h"
0038 #include "absl/strings/internal/cord_rep_flat.h"
0039 #include "absl/types/span.h"
0040 
0041 namespace absl {
0042 ABSL_NAMESPACE_BEGIN
0043 
0044 class Cord;
0045 class CordBufferTestPeer;
0046 
0047 // CordBuffer
0048 //
0049 // CordBuffer manages memory buffers for purposes such as zero-copy APIs as well
0050 // as applications building cords with large data requiring granular control
0051 // over the allocation and size of cord data. For example, a function creating
0052 // a cord of random data could use a CordBuffer as follows:
0053 //
0054 //   absl::Cord CreateRandomCord(size_t length) {
0055 //     absl::Cord cord;
0056 //     while (length > 0) {
0057 //       CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(length);
0058 //       absl::Span<char> data = buffer.available_up_to(length);
0059 //       FillRandomValues(data.data(), data.size());
0060 //       buffer.IncreaseLengthBy(data.size());
0061 //       cord.Append(std::move(buffer));
0062 //       length -= data.size();
0063 //     }
0064 //     return cord;
0065 //   }
0066 //
0067 // CordBuffer instances are by default limited to a capacity of `kDefaultLimit`
0068 // bytes. `kDefaultLimit` is currently just under 4KiB, but this default may
0069 // change in the future and/or for specific architectures. The default limit is
0070 // aimed to provide a good trade-off between performance and memory overhead.
0071 // Smaller buffers typically incur more compute cost while larger buffers are
0072 // more CPU efficient but create significant memory overhead because of such
0073 // allocations being less granular. Using larger buffers may also increase the
0074 // risk of memory fragmentation.
0075 //
0076 // Applications create a buffer using one of the `CreateWithDefaultLimit()` or
0077 // `CreateWithCustomLimit()` methods. The returned instance will have a non-zero
0078 // capacity and a zero length. Applications use the `data()` method to set the
0079 // contents of the managed memory, and once done filling the buffer, use the
0080 // `IncreaseLengthBy()` or 'SetLength()' method to specify the length of the
0081 // initialized data before adding the buffer to a Cord.
0082 //
0083 // The `CreateWithCustomLimit()` method is intended for applications needing
0084 // larger buffers than the default memory limit, allowing the allocation of up
0085 // to a capacity of `kCustomLimit` bytes minus some minimum internal overhead.
0086 // The usage of `CreateWithCustomLimit()` should be limited to only those use
0087 // cases where the distribution of the input is relatively well known, and/or
0088 // where the trade-off between the efficiency gains outweigh the risk of memory
0089 // fragmentation. See the documentation for `CreateWithCustomLimit()` for more
0090 // information on using larger custom limits.
0091 //
0092 // The capacity of a `CordBuffer` returned by one of the `Create` methods may
0093 // be larger than the requested capacity due to rounding, alignment and
0094 // granularity of the memory allocator. Applications should use the `capacity`
0095 // method to obtain the effective capacity of the returned instance as
0096 // demonstrated in the provided example above.
0097 //
0098 // CordBuffer is a move-only class. All references into the managed memory are
0099 // invalidated when an instance is moved into either another CordBuffer instance
0100 // or a Cord. Writing to a location obtained by a previous call to `data()`
0101 // after an instance was moved will lead to undefined behavior.
0102 //
0103 // A `moved from` CordBuffer instance will have a valid, but empty state.
0104 // CordBuffer is thread compatible.
0105 class CordBuffer {
0106  public:
0107   // kDefaultLimit
0108   //
0109   // Default capacity limits of allocated CordBuffers.
0110   // See the class comments for more information on allocation limits.
0111   static constexpr size_t kDefaultLimit = cord_internal::kMaxFlatLength;
0112 
0113   // kCustomLimit
0114   //
0115   // Maximum size for CreateWithCustomLimit() allocated buffers.
0116   // Note that the effective capacity may be slightly less
0117   // because of internal overhead of internal cord buffers.
0118   static constexpr size_t kCustomLimit = 64U << 10;
0119 
0120   // Constructors, Destructors and Assignment Operators
0121 
0122   // Creates an empty CordBuffer.
0123   CordBuffer() = default;
0124 
0125   // Destroys this CordBuffer instance and, if not empty, releases any memory
0126   // managed by this instance, invalidating previously returned references.
0127   ~CordBuffer();
0128 
0129   // CordBuffer is move-only
0130   CordBuffer(CordBuffer&& rhs) noexcept;
0131   CordBuffer& operator=(CordBuffer&&) noexcept;
0132   CordBuffer(const CordBuffer&) = delete;
0133   CordBuffer& operator=(const CordBuffer&) = delete;
0134 
0135   // CordBuffer::MaximumPayload()
0136   //
0137   // Returns the guaranteed maximum payload for a CordBuffer returned by the
0138   // `CreateWithDefaultLimit()` method. While small, each internal buffer inside
0139   // a Cord incurs an overhead to manage the length, type and reference count
0140   // for the buffer managed inside the cord tree. Applications can use this
0141   // method to get approximate number of buffers required for a given byte
0142   // size, etc.
0143   //
0144   // For example:
0145   //   const size_t payload = absl::CordBuffer::MaximumPayload();
0146   //   const size_t buffer_count = (total_size + payload - 1) / payload;
0147   //   buffers.reserve(buffer_count);
0148   static constexpr size_t MaximumPayload();
0149 
0150   // Overload to the above `MaximumPayload()` except that it returns the
0151   // maximum payload for a CordBuffer returned by the `CreateWithCustomLimit()`
0152   // method given the provided `block_size`.
0153   static constexpr size_t MaximumPayload(size_t block_size);
0154 
0155   // CordBuffer::CreateWithDefaultLimit()
0156   //
0157   // Creates a CordBuffer instance of the desired `capacity`, capped at the
0158   // default limit `kDefaultLimit`. The returned buffer has a guaranteed
0159   // capacity of at least `min(kDefaultLimit, capacity)`. See the class comments
0160   // for more information on buffer capacities and intended usage.
0161   static CordBuffer CreateWithDefaultLimit(size_t capacity);
0162 
0163   // CordBuffer::CreateWithCustomLimit()
0164   //
0165   // Creates a CordBuffer instance of the desired `capacity` rounded to an
0166   // appropriate power of 2 size less than, or equal to `block_size`.
0167   // Requires `block_size` to be a power of 2.
0168   //
0169   // If `capacity` is less than or equal to `kDefaultLimit`, then this method
0170   // behaves identical to `CreateWithDefaultLimit`, which means that the caller
0171   // is guaranteed to get a buffer of at least the requested capacity.
0172   //
0173   // If `capacity` is greater than or equal to `block_size`, then this method
0174   // returns a buffer with an `allocated size` of `block_size` bytes. Otherwise,
0175   // this methods returns a buffer with a suitable smaller power of 2 block size
0176   // to satisfy the request. The actual size depends on a number of factors, and
0177   // is typically (but not necessarily) the highest or second highest power of 2
0178   // value less than or equal to `capacity`.
0179   //
0180   // The 'allocated size' includes a small amount of overhead required for
0181   // internal state, which is currently 13 bytes on 64-bit platforms. For
0182   // example: a buffer created with `block_size` and `capacity' set to 8KiB
0183   // will have an allocated size of 8KiB, and an effective internal `capacity`
0184   // of 8KiB - 13 = 8179 bytes.
0185   //
0186   // To demonstrate this in practice, let's assume we want to read data from
0187   // somewhat larger files using approximately 64KiB buffers:
0188   //
0189   //   absl::Cord ReadFromFile(int fd, size_t n) {
0190   //     absl::Cord cord;
0191   //     while (n > 0) {
0192   //       CordBuffer buffer = CordBuffer::CreateWithCustomLimit(64 << 10, n);
0193   //       absl::Span<char> data = buffer.available_up_to(n);
0194   //       ReadFileDataOrDie(fd, data.data(), data.size());
0195   //       buffer.IncreaseLengthBy(data.size());
0196   //       cord.Append(std::move(buffer));
0197   //       n -= data.size();
0198   //     }
0199   //     return cord;
0200   //   }
0201   //
0202   // If we'd use this function to read a file of 659KiB, we may get the
0203   // following pattern of allocated cord buffer sizes:
0204   //
0205   //   CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
0206   //   CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
0207   //   ...
0208   //   CreateWithCustomLimit(64KiB,  19586) --> ~16KiB (16371)
0209   //   CreateWithCustomLimit(64KiB,   3215) -->   3215 (at least 3215)
0210   //
0211   // The reason the method returns a 16K buffer instead of a roughly 19K buffer
0212   // is to reduce memory overhead and fragmentation risks. Using carefully
0213   // chosen power of 2 values reduces the entropy of allocated memory sizes.
0214   //
0215   // Additionally, let's assume we'd use the above function on files that are
0216   // generally smaller than 64K. If we'd use 'precise' sized buffers for such
0217   // files, than we'd get a very wide distribution of allocated memory sizes
0218   // rounded to 4K page sizes, and we'd end up with a lot of unused capacity.
0219   //
0220   // In general, application should only use custom sizes if the data they are
0221   // consuming or storing is expected to be many times the chosen block size,
0222   // and be based on objective data and performance metrics. For example, a
0223   // compress function may work faster and consume less CPU when using larger
0224   // buffers. Such an application should pick a size offering a reasonable
0225   // trade-off between expected data size, compute savings with larger buffers,
0226   // and the cost or fragmentation effect of larger buffers.
0227   // Applications must pick a reasonable spot on that curve, and make sure their
0228   // data meets their expectations in size distributions such as "mostly large".
0229   static CordBuffer CreateWithCustomLimit(size_t block_size, size_t capacity);
0230 
0231   // CordBuffer::available()
0232   //
0233   // Returns the span delineating the available capacity in this buffer
0234   // which is defined as `{ data() + length(), capacity() - length() }`.
0235   absl::Span<char> available();
0236 
0237   // CordBuffer::available_up_to()
0238   //
0239   // Returns the span delineating the available capacity in this buffer limited
0240   // to `size` bytes. This is equivalent to `available().subspan(0, size)`.
0241   absl::Span<char> available_up_to(size_t size);
0242 
0243   // CordBuffer::data()
0244   //
0245   // Returns a non-null reference to the data managed by this instance.
0246   // Applications are allowed to write up to `capacity` bytes of instance data.
0247   // CordBuffer data is uninitialized by default. Reading data from an instance
0248   // that has not yet been initialized will lead to undefined behavior.
0249   char* data();
0250   const char* data() const;
0251 
0252   // CordBuffer::length()
0253   //
0254   // Returns the length of this instance. The default length of a CordBuffer is
0255   // 0, indicating an 'empty' CordBuffer. Applications must specify the length
0256   // of the data in a CordBuffer before adding it to a Cord.
0257   size_t length() const;
0258 
0259   // CordBuffer::capacity()
0260   //
0261   // Returns the capacity of this instance. All instances have a non-zero
0262   // capacity: default and `moved from` instances have a small internal buffer.
0263   size_t capacity() const;
0264 
0265   // CordBuffer::IncreaseLengthBy()
0266   //
0267   // Increases the length of this buffer by the specified 'n' bytes.
0268   // Applications must make sure all data in this buffer up to the new length
0269   // has been initialized before adding a CordBuffer to a Cord: failure to do so
0270   // will lead to undefined behavior.  Requires `length() + n <= capacity()`.
0271   // Typically, applications will use 'available_up_to()` to get a span of the
0272   // desired capacity, and use `span.size()` to increase the length as in:
0273   //   absl::Span<char> span = buffer.available_up_to(desired);
0274   //   buffer.IncreaseLengthBy(span.size());
0275   //   memcpy(span.data(), src, span.size());
0276   //   etc...
0277   void IncreaseLengthBy(size_t n);
0278 
0279   // CordBuffer::SetLength()
0280   //
0281   // Sets the data length of this instance. Applications must make sure all data
0282   // of the specified length has been initialized before adding a CordBuffer to
0283   // a Cord: failure to do so will lead to undefined behavior.
0284   // Setting the length to a small value or zero does not release any memory
0285   // held by this CordBuffer instance. Requires `length <= capacity()`.
0286   // Applications should preferably use the `IncreaseLengthBy()` method above
0287   // in combination with the 'available()` or `available_up_to()` methods.
0288   void SetLength(size_t length);
0289 
0290  private:
0291   // Make sure we don't accidentally over promise.
0292   static_assert(kCustomLimit <= cord_internal::kMaxLargeFlatSize, "");
0293 
0294   // Assume the cost of an 'uprounded' allocation to CeilPow2(size) versus
0295   // the cost of allocating at least 1 extra flat <= 4KB:
0296   // - Flat overhead = 13 bytes
0297   // - Btree amortized cost / node =~ 13 bytes
0298   // - 64 byte granularity of tcmalloc at 4K =~ 32 byte average
0299   // CPU cost and efficiency requires we should at least 'save' something by
0300   // splitting, as a poor man's measure, we say the slop needs to be
0301   // at least double the cost offset to make it worth splitting: ~128 bytes.
0302   static constexpr size_t kMaxPageSlop = 128;
0303 
0304   // Overhead for allocation a flat.
0305   static constexpr size_t kOverhead = cord_internal::kFlatOverhead;
0306 
0307   using CordRepFlat = cord_internal::CordRepFlat;
0308 
0309   // `Rep` is the internal data representation of a CordBuffer. The internal
0310   // representation has an internal small size optimization similar to
0311   // std::string (SSO).
0312   struct Rep {
0313     // Inline SSO size of a CordBuffer
0314     static constexpr size_t kInlineCapacity = sizeof(intptr_t) * 2 - 1;
0315 
0316     // Creates a default instance with kInlineCapacity.
0317     Rep() : short_rep{} {}
0318 
0319     // Creates an instance managing an allocated non zero CordRep.
0320     explicit Rep(cord_internal::CordRepFlat* rep) : long_rep{rep} {
0321       assert(rep != nullptr);
0322     }
0323 
0324     // Returns true if this instance manages the SSO internal buffer.
0325     bool is_short() const {
0326       constexpr size_t offset = offsetof(Short, raw_size);
0327       return (reinterpret_cast<const char*>(this)[offset] & 1) != 0;
0328     }
0329 
0330     // Returns the available area of the internal SSO data
0331     absl::Span<char> short_available() {
0332       const size_t length = short_length();
0333       return absl::Span<char>(short_rep.data + length,
0334                               kInlineCapacity - length);
0335     }
0336 
0337     // Returns the available area of the internal SSO data
0338     absl::Span<char> long_available() const {
0339       assert(!is_short());
0340       const size_t length = long_rep.rep->length;
0341       return absl::Span<char>(long_rep.rep->Data() + length,
0342                               long_rep.rep->Capacity() - length);
0343     }
0344 
0345     // Returns the length of the internal SSO data.
0346     size_t short_length() const {
0347       assert(is_short());
0348       return static_cast<size_t>(short_rep.raw_size >> 1);
0349     }
0350 
0351     // Sets the length of the internal SSO data.
0352     // Disregards any previously set CordRep instance.
0353     void set_short_length(size_t length) {
0354       short_rep.raw_size = static_cast<char>((length << 1) + 1);
0355     }
0356 
0357     // Adds `n` to the current short length.
0358     void add_short_length(size_t n) {
0359       assert(is_short());
0360       short_rep.raw_size += static_cast<char>(n << 1);
0361     }
0362 
0363     // Returns reference to the internal SSO data buffer.
0364     char* data() {
0365       assert(is_short());
0366       return short_rep.data;
0367     }
0368     const char* data() const {
0369       assert(is_short());
0370       return short_rep.data;
0371     }
0372 
0373     // Returns a pointer the external CordRep managed by this instance.
0374     cord_internal::CordRepFlat* rep() const {
0375       assert(!is_short());
0376       return long_rep.rep;
0377     }
0378 
0379     // The internal representation takes advantage of the fact that allocated
0380     // memory is always on an even address, and uses the least significant bit
0381     // of the first or last byte (depending on endianness) as the inline size
0382     // indicator overlapping with the least significant byte of the CordRep*.
0383 #if defined(ABSL_IS_BIG_ENDIAN)
0384     struct Long {
0385       explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
0386       void* padding;
0387       cord_internal::CordRepFlat* rep;
0388     };
0389     struct Short {
0390       char data[sizeof(Long) - 1];
0391       char raw_size = 1;
0392     };
0393 #else
0394     struct Long {
0395       explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
0396       cord_internal::CordRepFlat* rep;
0397       void* padding;
0398     };
0399     struct Short {
0400       char raw_size = 1;
0401       char data[sizeof(Long) - 1];
0402     };
0403 #endif
0404 
0405     union {
0406       Long long_rep;
0407       Short short_rep;
0408     };
0409   };
0410 
0411   // Power2 functions
0412   static bool IsPow2(size_t size) { return absl::has_single_bit(size); }
0413   static size_t Log2Floor(size_t size) {
0414     return static_cast<size_t>(absl::bit_width(size) - 1);
0415   }
0416   static size_t Log2Ceil(size_t size) {
0417     return static_cast<size_t>(absl::bit_width(size - 1));
0418   }
0419 
0420   // Implementation of `CreateWithCustomLimit()`.
0421   // This implementation allows for future memory allocation hints to
0422   // be passed down into the CordRepFlat allocation function.
0423   template <typename... AllocationHints>
0424   static CordBuffer CreateWithCustomLimitImpl(size_t block_size,
0425                                               size_t capacity,
0426                                               AllocationHints... hints);
0427 
0428   // Consumes the value contained in this instance and resets the instance.
0429   // This method returns a non-null Cordrep* if the current instances manages a
0430   // CordRep*, and resets the instance to an empty SSO instance. If the current
0431   // instance is an SSO instance, then this method returns nullptr and sets
0432   // `short_value` to the inlined data value. In either case, the current
0433   // instance length is reset to zero.
0434   // This method is intended to be used by Cord internal functions only.
0435   cord_internal::CordRep* ConsumeValue(absl::string_view& short_value) {
0436     cord_internal::CordRep* rep = nullptr;
0437     if (rep_.is_short()) {
0438       short_value = absl::string_view(rep_.data(), rep_.short_length());
0439     } else {
0440       rep = rep_.rep();
0441     }
0442     rep_.set_short_length(0);
0443     return rep;
0444   }
0445 
0446   // Internal constructor.
0447   explicit CordBuffer(cord_internal::CordRepFlat* rep) : rep_(rep) {
0448     assert(rep != nullptr);
0449   }
0450 
0451   Rep rep_;
0452 
0453   friend class Cord;
0454   friend class CordBufferTestPeer;
0455 };
0456 
0457 inline constexpr size_t CordBuffer::MaximumPayload() {
0458   return cord_internal::kMaxFlatLength;
0459 }
0460 
0461 inline constexpr size_t CordBuffer::MaximumPayload(size_t block_size) {
0462   return (std::min)(kCustomLimit, block_size) - cord_internal::kFlatOverhead;
0463 }
0464 
0465 inline CordBuffer CordBuffer::CreateWithDefaultLimit(size_t capacity) {
0466   if (capacity > Rep::kInlineCapacity) {
0467     auto* rep = cord_internal::CordRepFlat::New(capacity);
0468     rep->length = 0;
0469     return CordBuffer(rep);
0470   }
0471   return CordBuffer();
0472 }
0473 
0474 template <typename... AllocationHints>
0475 inline CordBuffer CordBuffer::CreateWithCustomLimitImpl(
0476     size_t block_size, size_t capacity, AllocationHints... hints) {
0477   assert(IsPow2(block_size));
0478   capacity = (std::min)(capacity, kCustomLimit);
0479   block_size = (std::min)(block_size, kCustomLimit);
0480   if (capacity + kOverhead >= block_size) {
0481     capacity = block_size;
0482   } else if (capacity <= kDefaultLimit) {
0483     capacity = capacity + kOverhead;
0484   } else if (!IsPow2(capacity)) {
0485     // Check if rounded up to next power 2 is a good enough fit
0486     // with limited waste making it an acceptable direct fit.
0487     const size_t rounded_up = size_t{1} << Log2Ceil(capacity);
0488     const size_t slop = rounded_up - capacity;
0489     if (slop >= kOverhead && slop <= kMaxPageSlop + kOverhead) {
0490       capacity = rounded_up;
0491     } else {
0492       // Round down to highest power of 2 <= capacity.
0493       // Consider a more aggressive step down if that may reduce the
0494       // risk of fragmentation where 'people are holding it wrong'.
0495       const size_t rounded_down = size_t{1} << Log2Floor(capacity);
0496       capacity = rounded_down;
0497     }
0498   }
0499   const size_t length = capacity - kOverhead;
0500   auto* rep = CordRepFlat::New(CordRepFlat::Large(), length, hints...);
0501   rep->length = 0;
0502   return CordBuffer(rep);
0503 }
0504 
0505 inline CordBuffer CordBuffer::CreateWithCustomLimit(size_t block_size,
0506                                                     size_t capacity) {
0507   return CreateWithCustomLimitImpl(block_size, capacity);
0508 }
0509 
0510 inline CordBuffer::~CordBuffer() {
0511   if (!rep_.is_short()) {
0512     cord_internal::CordRepFlat::Delete(rep_.rep());
0513   }
0514 }
0515 
0516 inline CordBuffer::CordBuffer(CordBuffer&& rhs) noexcept : rep_(rhs.rep_) {
0517   rhs.rep_.set_short_length(0);
0518 }
0519 
0520 inline CordBuffer& CordBuffer::operator=(CordBuffer&& rhs) noexcept {
0521   if (!rep_.is_short()) cord_internal::CordRepFlat::Delete(rep_.rep());
0522   rep_ = rhs.rep_;
0523   rhs.rep_.set_short_length(0);
0524   return *this;
0525 }
0526 
0527 inline absl::Span<char> CordBuffer::available() {
0528   return rep_.is_short() ? rep_.short_available() : rep_.long_available();
0529 }
0530 
0531 inline absl::Span<char> CordBuffer::available_up_to(size_t size) {
0532   return available().subspan(0, size);
0533 }
0534 
0535 inline char* CordBuffer::data() {
0536   return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
0537 }
0538 
0539 inline const char* CordBuffer::data() const {
0540   return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
0541 }
0542 
0543 inline size_t CordBuffer::capacity() const {
0544   return rep_.is_short() ? Rep::kInlineCapacity : rep_.rep()->Capacity();
0545 }
0546 
0547 inline size_t CordBuffer::length() const {
0548   return rep_.is_short() ? rep_.short_length() : rep_.rep()->length;
0549 }
0550 
0551 inline void CordBuffer::SetLength(size_t length) {
0552   ABSL_HARDENING_ASSERT(length <= capacity());
0553   if (rep_.is_short()) {
0554     rep_.set_short_length(length);
0555   } else {
0556     rep_.rep()->length = length;
0557   }
0558 }
0559 
0560 inline void CordBuffer::IncreaseLengthBy(size_t n) {
0561   ABSL_HARDENING_ASSERT(n <= capacity() && length() + n <= capacity());
0562   if (rep_.is_short()) {
0563     rep_.add_short_length(n);
0564   } else {
0565     rep_.rep()->length += n;
0566   }
0567 }
0568 
0569 ABSL_NAMESPACE_END
0570 }  // namespace absl
0571 
0572 #endif  // ABSL_STRINGS_CORD_BUFFER_H_