cord.h 65 KB

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