Apply clang-format to folly/io/ (namespace)
[folly.git] / folly / io / Cursor.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <assert.h>
20 #include <cstdarg>
21 #include <stdexcept>
22 #include <string.h>
23 #include <type_traits>
24 #include <memory>
25
26 #include <folly/Bits.h>
27 #include <folly/Likely.h>
28 #include <folly/Memory.h>
29 #include <folly/Portability.h>
30 #include <folly/Range.h>
31 #include <folly/io/IOBuf.h>
32 #include <folly/io/IOBufQueue.h>
33 #include <folly/portability/BitsFunctexcept.h>
34
35 /**
36  * Cursor class for fast iteration over IOBuf chains.
37  *
38  * Cursor - Read-only access
39  *
40  * RWPrivateCursor - Read-write access, assumes private access to IOBuf chain
41  * RWUnshareCursor - Read-write access, calls unshare on write (COW)
42  * Appender        - Write access, assumes private access to IOBuf chian
43  *
44  * Note that RW cursors write in the preallocated part of buffers (that is,
45  * between the buffer's data() and tail()), while Appenders append to the end
46  * of the buffer (between the buffer's tail() and bufferEnd()).  Appenders
47  * automatically adjust the buffer pointers, so you may only use one
48  * Appender with a buffer chain; for this reason, Appenders assume private
49  * access to the buffer (you need to call unshare() yourself if necessary).
50  **/
51 namespace folly {
52 namespace io {
53
54 namespace detail {
55
56 template <class Derived, class BufType>
57 class CursorBase {
58   // Make all the templated classes friends for copy constructor.
59   template <class D, typename B> friend class CursorBase;
60  public:
61   explicit CursorBase(BufType* buf) : crtBuf_(buf), buffer_(buf) { }
62
63   /**
64    * Copy constructor.
65    *
66    * This also allows constructing a CursorBase from other derived types.
67    * For instance, this allows constructing a Cursor from an RWPrivateCursor.
68    */
69   template <class OtherDerived, class OtherBuf>
70   explicit CursorBase(const CursorBase<OtherDerived, OtherBuf>& cursor)
71     : crtBuf_(cursor.crtBuf_),
72       offset_(cursor.offset_),
73       buffer_(cursor.buffer_) { }
74
75   /**
76    * Reset cursor to point to a new buffer.
77    */
78   void reset(BufType* buf) {
79     crtBuf_ = buf;
80     buffer_ = buf;
81     offset_ = 0;
82   }
83
84   const uint8_t* data() const {
85     return crtBuf_->data() + offset_;
86   }
87
88   /**
89    * Return the remaining space available in the current IOBuf.
90    *
91    * May return 0 if the cursor is at the end of an IOBuf.  Use peekBytes()
92    * instead if you want to avoid this.  peekBytes() will advance to the next
93    * non-empty IOBuf (up to the end of the chain) if the cursor is currently
94    * pointing at the end of a buffer.
95    */
96   size_t length() const {
97     return crtBuf_->length() - offset_;
98   }
99
100   /**
101    * Return the space available until the end of the entire IOBuf chain.
102    */
103   size_t totalLength() const {
104     if (crtBuf_ == buffer_) {
105       return crtBuf_->computeChainDataLength() - offset_;
106     }
107     CursorBase end(buffer_->prev());
108     end.offset_ = end.buffer_->length();
109     return end - *this;
110   }
111
112   /**
113    * Return true if the cursor could advance the specified number of bytes
114    * from its current position.
115    * This is useful for applications that want to do checked reads instead of
116    * catching exceptions and is more efficient than using totalLength as it
117    * walks the minimal set of buffers in the chain to determine the result.
118    */
119   bool canAdvance(size_t amount) const {
120     const IOBuf* nextBuf = crtBuf_;
121     size_t available = length();
122     do {
123       if (available >= amount) {
124         return true;
125       }
126       amount -= available;
127       nextBuf = nextBuf->next();
128       available = nextBuf->length();
129     } while (nextBuf != buffer_);
130     return false;
131   }
132
133   /*
134    * Return true if the cursor is at the end of the entire IOBuf chain.
135    */
136   bool isAtEnd() const {
137     // Check for the simple cases first.
138     if (offset_ != crtBuf_->length()) {
139       return false;
140     }
141     if (crtBuf_ == buffer_->prev()) {
142       return true;
143     }
144     // We are at the end of a buffer, but it isn't the last buffer.
145     // We might still be at the end if the remaining buffers in the chain are
146     // empty.
147     const IOBuf* buf = crtBuf_->next();;
148     while (buf != buffer_) {
149       if (buf->length() > 0) {
150         return false;
151       }
152       buf = buf->next();
153     }
154     return true;
155   }
156
157   /**
158    * Advances the cursor to the end of the entire IOBuf chain.
159    */
160   void advanceToEnd() {
161     offset_ = buffer_->prev()->length();
162     if (crtBuf_ != buffer_->prev()) {
163       crtBuf_ = buffer_->prev();
164       static_cast<Derived*>(this)->advanceDone();
165     }
166   }
167
168   Derived& operator+=(size_t offset) {
169     Derived* p = static_cast<Derived*>(this);
170     p->skip(offset);
171     return *p;
172   }
173   Derived operator+(size_t offset) const {
174     Derived other(*this);
175     other.skip(offset);
176     return other;
177   }
178
179   Derived& operator-=(size_t offset) {
180     Derived* p = static_cast<Derived*>(this);
181     p->retreat(offset);
182     return *p;
183   }
184   Derived operator-(size_t offset) const {
185     Derived other(*this);
186     other.retreat(offset);
187     return other;
188   }
189
190   /**
191    * Compare cursors for equality/inequality.
192    *
193    * Two cursors are equal if they are pointing to the same location in the
194    * same IOBuf chain.
195    */
196   bool operator==(const Derived& other) const {
197     return (offset_ == other.offset_) && (crtBuf_ == other.crtBuf_);
198   }
199   bool operator!=(const Derived& other) const {
200     return !operator==(other);
201   }
202
203   template <class T>
204   typename std::enable_if<std::is_arithmetic<T>::value, bool>::type tryRead(
205       T& val) {
206     if (LIKELY(length() >= sizeof(T))) {
207       val = loadUnaligned<T>(data());
208       offset_ += sizeof(T);
209       advanceBufferIfEmpty();
210       return true;
211     }
212     return pullAtMostSlow(&val, sizeof(T)) == sizeof(T);
213   }
214
215   template <class T>
216   bool tryReadBE(T& val) {
217     const bool result = tryRead(val);
218     val = Endian::big(val);
219     return result;
220   }
221
222   template <class T>
223   bool tryReadLE(T& val) {
224     const bool result = tryRead(val);
225     val = Endian::little(val);
226     return result;
227   }
228
229   template <class T>
230   T read() {
231     T val{};
232     if (!tryRead(val)) {
233       std::__throw_out_of_range("underflow");
234     }
235     return val;
236   }
237
238   template <class T>
239   T readBE() {
240     return Endian::big(read<T>());
241   }
242
243   template <class T>
244   T readLE() {
245     return Endian::little(read<T>());
246   }
247
248   /**
249    * Read a fixed-length string.
250    *
251    * The std::string-based APIs should probably be avoided unless you
252    * ultimately want the data to live in an std::string. You're better off
253    * using the pull() APIs to copy into a raw buffer otherwise.
254    */
255   std::string readFixedString(size_t len) {
256     std::string str;
257     str.reserve(len);
258     if (LIKELY(length() >= len)) {
259       str.append(reinterpret_cast<const char*>(data()), len);
260       offset_ += len;
261       advanceBufferIfEmpty();
262     } else {
263       readFixedStringSlow(&str, len);
264     }
265     return str;
266   }
267
268   /**
269    * Read a string consisting of bytes until the given terminator character is
270    * seen. Raises an std::length_error if maxLength bytes have been processed
271    * before the terminator is seen.
272    *
273    * See comments in readFixedString() about when it's appropriate to use this
274    * vs. using pull().
275    */
276   std::string readTerminatedString(
277       char termChar = '\0',
278       size_t maxLength = std::numeric_limits<size_t>::max());
279
280   /*
281    * Read all bytes until the specified predicate returns true.
282    *
283    * The predicate will be called on each byte in turn, until it returns false
284    * or until the end of the IOBuf chain is reached.
285    *
286    * Returns the result as a string.
287    */
288   template <typename Predicate>
289   std::string readWhile(const Predicate& predicate);
290
291   /*
292    * Read all bytes until the specified predicate returns true.
293    *
294    * This is a more generic version of readWhile() takes an arbitrary Output
295    * object, and calls Output::append() with each chunk of matching data.
296    */
297   template <typename Predicate, typename Output>
298   void readWhile(const Predicate& predicate, Output& out);
299
300   /*
301    * Skip all bytes until the specified predicate returns true.
302    *
303    * The predicate will be called on each byte in turn, until it returns false
304    * or until the end of the IOBuf chain is reached.
305    */
306   template <typename Predicate>
307   void skipWhile(const Predicate& predicate);
308
309   size_t skipAtMost(size_t len) {
310     if (LIKELY(length() >= len)) {
311       offset_ += len;
312       advanceBufferIfEmpty();
313       return len;
314     }
315     return skipAtMostSlow(len);
316   }
317
318   void skip(size_t len) {
319     if (LIKELY(length() >= len)) {
320       offset_ += len;
321       advanceBufferIfEmpty();
322     } else {
323       skipSlow(len);
324     }
325   }
326
327   size_t retreatAtMost(size_t len) {
328     if (len <= offset_) {
329       offset_ -= len;
330       return len;
331     }
332     return retreatAtMostSlow(len);
333   }
334
335   void retreat(size_t len) {
336     if (len <= offset_) {
337       offset_ -= len;
338     } else {
339       retreatSlow(len);
340     }
341   }
342
343   size_t pullAtMost(void* buf, size_t len) {
344     // Fast path: it all fits in one buffer.
345     if (LIKELY(length() >= len)) {
346       memcpy(buf, data(), len);
347       offset_ += len;
348       advanceBufferIfEmpty();
349       return len;
350     }
351     return pullAtMostSlow(buf, len);
352   }
353
354   void pull(void* buf, size_t len) {
355     if (LIKELY(length() >= len)) {
356       memcpy(buf, data(), len);
357       offset_ += len;
358       advanceBufferIfEmpty();
359     } else {
360       pullSlow(buf, len);
361     }
362   }
363
364   /**
365    * Return the available data in the current buffer.
366    * If you want to gather more data from the chain into a contiguous region
367    * (for hopefully zero-copy access), use gather() before peekBytes().
368    */
369   ByteRange peekBytes() {
370     // Ensure that we're pointing to valid data
371     size_t available = length();
372     while (UNLIKELY(available == 0 && tryAdvanceBuffer())) {
373       available = length();
374     }
375     return ByteRange{data(), available};
376   }
377
378   /**
379    * Alternate version of peekBytes() that returns a std::pair
380    * instead of a ByteRange.  (This method pre-dates ByteRange.)
381    *
382    * This function will eventually be deprecated.
383    */
384   std::pair<const uint8_t*, size_t> peek() {
385     auto bytes = peekBytes();
386     return std::make_pair(bytes.data(), bytes.size());
387   }
388
389   void clone(std::unique_ptr<folly::IOBuf>& buf, size_t len) {
390     if (UNLIKELY(cloneAtMost(buf, len) != len)) {
391       std::__throw_out_of_range("underflow");
392     }
393   }
394
395   void clone(folly::IOBuf& buf, size_t len) {
396     if (UNLIKELY(cloneAtMost(buf, len) != len)) {
397       std::__throw_out_of_range("underflow");
398     }
399   }
400
401   size_t cloneAtMost(folly::IOBuf& buf, size_t len) {
402     std::unique_ptr<folly::IOBuf> tmp;
403     size_t copied = 0;
404     for (int loopCount = 0; true; ++loopCount) {
405       // Fast path: it all fits in one buffer.
406       size_t available = length();
407       if (LIKELY(available >= len)) {
408         if (loopCount == 0) {
409           crtBuf_->cloneOneInto(buf);
410           buf.trimStart(offset_);
411           buf.trimEnd(buf.length() - len);
412         } else {
413           tmp = crtBuf_->cloneOne();
414           tmp->trimStart(offset_);
415           tmp->trimEnd(tmp->length() - len);
416           buf.prependChain(std::move(tmp));
417         }
418
419         offset_ += len;
420         advanceBufferIfEmpty();
421         return copied + len;
422       }
423
424       if (loopCount == 0) {
425         crtBuf_->cloneOneInto(buf);
426         buf.trimStart(offset_);
427       } else {
428         tmp = crtBuf_->cloneOne();
429         tmp->trimStart(offset_);
430         buf.prependChain(std::move(tmp));
431       }
432
433       copied += available;
434       if (UNLIKELY(!tryAdvanceBuffer())) {
435         return copied;
436       }
437       len -= available;
438     }
439   }
440
441   size_t cloneAtMost(std::unique_ptr<folly::IOBuf>& buf, size_t len) {
442     if (!buf) {
443       buf = std::make_unique<folly::IOBuf>();
444     }
445     return cloneAtMost(*buf, len);
446   }
447
448   /**
449    * Return the distance between two cursors.
450    */
451   size_t operator-(const CursorBase& other) const {
452     BufType *otherBuf = other.crtBuf_;
453     size_t len = 0;
454
455     if (otherBuf != crtBuf_) {
456       len += otherBuf->length() - other.offset_;
457
458       for (otherBuf = otherBuf->next();
459            otherBuf != crtBuf_ && otherBuf != other.buffer_;
460            otherBuf = otherBuf->next()) {
461         len += otherBuf->length();
462       }
463
464       if (otherBuf == other.buffer_) {
465         std::__throw_out_of_range("wrap-around");
466       }
467
468       len += offset_;
469     } else {
470       if (offset_ < other.offset_) {
471         std::__throw_out_of_range("underflow");
472       }
473
474       len += offset_ - other.offset_;
475     }
476
477     return len;
478   }
479
480   /**
481    * Return the distance from the given IOBuf to the this cursor.
482    */
483   size_t operator-(const BufType* buf) const {
484     size_t len = 0;
485
486     const BufType* curBuf = buf;
487     while (curBuf != crtBuf_) {
488       len += curBuf->length();
489       curBuf = curBuf->next();
490       if (curBuf == buf || curBuf == buffer_) {
491         std::__throw_out_of_range("wrap-around");
492       }
493     }
494
495     len += offset_;
496     return len;
497   }
498
499  protected:
500   ~CursorBase() { }
501
502   BufType* head() {
503     return buffer_;
504   }
505
506   bool tryAdvanceBuffer() {
507     BufType* nextBuf = crtBuf_->next();
508     if (UNLIKELY(nextBuf == buffer_)) {
509       offset_ = crtBuf_->length();
510       return false;
511     }
512
513     offset_ = 0;
514     crtBuf_ = nextBuf;
515     static_cast<Derived*>(this)->advanceDone();
516     return true;
517   }
518
519   bool tryRetreatBuffer() {
520     if (UNLIKELY(crtBuf_ == buffer_)) {
521       offset_ = 0;
522       return false;
523     }
524     crtBuf_ = crtBuf_->prev();
525     offset_ = crtBuf_->length();
526     static_cast<Derived*>(this)->advanceDone();
527     return true;
528   }
529
530   void advanceBufferIfEmpty() {
531     if (length() == 0) {
532       tryAdvanceBuffer();
533     }
534   }
535
536   BufType* crtBuf_;
537   size_t offset_ = 0;
538
539  private:
540   void readFixedStringSlow(std::string* str, size_t len) {
541     for (size_t available; (available = length()) < len; ) {
542       str->append(reinterpret_cast<const char*>(data()), available);
543       if (UNLIKELY(!tryAdvanceBuffer())) {
544         std::__throw_out_of_range("string underflow");
545       }
546       len -= available;
547     }
548     str->append(reinterpret_cast<const char*>(data()), len);
549     offset_ += len;
550     advanceBufferIfEmpty();
551   }
552
553   size_t pullAtMostSlow(void* buf, size_t len) {
554     uint8_t* p = reinterpret_cast<uint8_t*>(buf);
555     size_t copied = 0;
556     for (size_t available; (available = length()) < len; ) {
557       memcpy(p, data(), available);
558       copied += available;
559       if (UNLIKELY(!tryAdvanceBuffer())) {
560         return copied;
561       }
562       p += available;
563       len -= available;
564     }
565     memcpy(p, data(), len);
566     offset_ += len;
567     advanceBufferIfEmpty();
568     return copied + len;
569   }
570
571   void pullSlow(void* buf, size_t len) {
572     if (UNLIKELY(pullAtMostSlow(buf, len) != len)) {
573       std::__throw_out_of_range("underflow");
574     }
575   }
576
577   size_t skipAtMostSlow(size_t len) {
578     size_t skipped = 0;
579     for (size_t available; (available = length()) < len; ) {
580       skipped += available;
581       if (UNLIKELY(!tryAdvanceBuffer())) {
582         return skipped;
583       }
584       len -= available;
585     }
586     offset_ += len;
587     advanceBufferIfEmpty();
588     return skipped + len;
589   }
590
591   void skipSlow(size_t len) {
592     if (UNLIKELY(skipAtMostSlow(len) != len)) {
593       std::__throw_out_of_range("underflow");
594     }
595   }
596
597   size_t retreatAtMostSlow(size_t len) {
598     size_t retreated = 0;
599     for (size_t available; (available = offset_) < len;) {
600       retreated += available;
601       if (UNLIKELY(!tryRetreatBuffer())) {
602         return retreated;
603       }
604       len -= available;
605     }
606     offset_ -= len;
607     return retreated + len;
608   }
609
610   void retreatSlow(size_t len) {
611     if (UNLIKELY(retreatAtMostSlow(len) != len)) {
612       std::__throw_out_of_range("underflow");
613     }
614   }
615
616   void advanceDone() {
617   }
618
619   BufType* buffer_;
620 };
621
622 } // namespace detail
623
624 class Cursor : public detail::CursorBase<Cursor, const IOBuf> {
625  public:
626   explicit Cursor(const IOBuf* buf)
627     : detail::CursorBase<Cursor, const IOBuf>(buf) {}
628
629   template <class OtherDerived, class OtherBuf>
630   explicit Cursor(const detail::CursorBase<OtherDerived, OtherBuf>& cursor)
631     : detail::CursorBase<Cursor, const IOBuf>(cursor) {}
632 };
633
634 namespace detail {
635
636 template <class Derived>
637 class Writable {
638  public:
639   template <class T>
640   typename std::enable_if<std::is_arithmetic<T>::value>::type
641   write(T value) {
642     const uint8_t* u8 = reinterpret_cast<const uint8_t*>(&value);
643     Derived* d = static_cast<Derived*>(this);
644     d->push(u8, sizeof(T));
645   }
646
647   template <class T>
648   void writeBE(T value) {
649     Derived* d = static_cast<Derived*>(this);
650     d->write(Endian::big(value));
651   }
652
653   template <class T>
654   void writeLE(T value) {
655     Derived* d = static_cast<Derived*>(this);
656     d->write(Endian::little(value));
657   }
658
659   void push(const uint8_t* buf, size_t len) {
660     Derived* d = static_cast<Derived*>(this);
661     if (d->pushAtMost(buf, len) != len) {
662       std::__throw_out_of_range("overflow");
663     }
664   }
665
666   void push(ByteRange buf) {
667     if (this->pushAtMost(buf) != buf.size()) {
668       std::__throw_out_of_range("overflow");
669     }
670   }
671
672   size_t pushAtMost(ByteRange buf) {
673     Derived* d = static_cast<Derived*>(this);
674     return d->pushAtMost(buf.data(), buf.size());
675   }
676
677   /**
678    * push len bytes of data from input cursor, data could be in an IOBuf chain.
679    * If input cursor contains less than len bytes, or this cursor has less than
680    * len bytes writable space, an out_of_range exception will be thrown.
681    */
682   void push(Cursor cursor, size_t len) {
683     if (this->pushAtMost(cursor, len) != len) {
684       std::__throw_out_of_range("overflow");
685     }
686   }
687
688   size_t pushAtMost(Cursor cursor, size_t len) {
689     size_t written = 0;
690     for(;;) {
691       auto currentBuffer = cursor.peekBytes();
692       const uint8_t* crtData = currentBuffer.data();
693       size_t available = currentBuffer.size();
694       if (available == 0) {
695         // end of buffer chain
696         return written;
697       }
698       // all data is in current buffer
699       if (available >= len) {
700         this->push(crtData, len);
701         cursor.skip(len);
702         return written + len;
703       }
704
705       // write the whole current IOBuf
706       this->push(crtData, available);
707       cursor.skip(available);
708       written += available;
709       len -= available;
710     }
711   }
712 };
713
714 } // namespace detail
715
716 enum class CursorAccess {
717   PRIVATE,
718   UNSHARE
719 };
720
721 template <CursorAccess access>
722 class RWCursor
723   : public detail::CursorBase<RWCursor<access>, IOBuf>,
724     public detail::Writable<RWCursor<access>> {
725   friend class detail::CursorBase<RWCursor<access>, IOBuf>;
726  public:
727   explicit RWCursor(IOBuf* buf)
728     : detail::CursorBase<RWCursor<access>, IOBuf>(buf),
729       maybeShared_(true) {}
730
731   template <class OtherDerived, class OtherBuf>
732   explicit RWCursor(const detail::CursorBase<OtherDerived, OtherBuf>& cursor)
733     : detail::CursorBase<RWCursor<access>, IOBuf>(cursor),
734       maybeShared_(true) {}
735   /**
736    * Gather at least n bytes contiguously into the current buffer,
737    * by coalescing subsequent buffers from the chain as necessary.
738    */
739   void gather(size_t n) {
740     // Forbid attempts to gather beyond the end of this IOBuf chain.
741     // Otherwise we could try to coalesce the head of the chain and end up
742     // accidentally freeing it, invalidating the pointer owned by external
743     // code.
744     //
745     // If crtBuf_ == head() then IOBuf::gather() will perform all necessary
746     // checking.  We only have to perform an explicit check here when calling
747     // gather() on a non-head element.
748     if (this->crtBuf_ != this->head() && this->totalLength() < n) {
749       throw std::overflow_error("cannot gather() past the end of the chain");
750     }
751     this->crtBuf_->gather(this->offset_ + n);
752   }
753   void gatherAtMost(size_t n) {
754     size_t size = std::min(n, this->totalLength());
755     return this->crtBuf_->gather(this->offset_ + size);
756   }
757
758   using detail::Writable<RWCursor<access>>::pushAtMost;
759   size_t pushAtMost(const uint8_t* buf, size_t len) {
760     // We have to explicitly check for an input length of 0.
761     // We support buf being nullptr in this case, but we need to avoid calling
762     // memcpy() with a null source pointer, since that is undefined behavior
763     // even if the length is 0.
764     if (len == 0) {
765       return 0;
766     }
767
768     size_t copied = 0;
769     for (;;) {
770       // Fast path: the current buffer is big enough.
771       size_t available = this->length();
772       if (LIKELY(available >= len)) {
773         if (access == CursorAccess::UNSHARE) {
774           maybeUnshare();
775         }
776         memcpy(writableData(), buf, len);
777         this->offset_ += len;
778         return copied + len;
779       }
780
781       if (access == CursorAccess::UNSHARE) {
782         maybeUnshare();
783       }
784       memcpy(writableData(), buf, available);
785       copied += available;
786       if (UNLIKELY(!this->tryAdvanceBuffer())) {
787         return copied;
788       }
789       buf += available;
790       len -= available;
791     }
792   }
793
794   void insert(std::unique_ptr<folly::IOBuf> buf) {
795     folly::IOBuf* nextBuf;
796     if (this->offset_ == 0) {
797       // Can just prepend
798       nextBuf = this->crtBuf_;
799       this->crtBuf_->prependChain(std::move(buf));
800     } else {
801       std::unique_ptr<folly::IOBuf> remaining;
802       if (this->crtBuf_->length() - this->offset_ > 0) {
803         // Need to split current IOBuf in two.
804         remaining = this->crtBuf_->cloneOne();
805         remaining->trimStart(this->offset_);
806         nextBuf = remaining.get();
807         buf->prependChain(std::move(remaining));
808       } else {
809         // Can just append
810         nextBuf = this->crtBuf_->next();
811       }
812       this->crtBuf_->trimEnd(this->length());
813       this->crtBuf_->appendChain(std::move(buf));
814     }
815     // Jump past the new links
816     this->offset_ = 0;
817     this->crtBuf_ = nextBuf;
818   }
819
820   uint8_t* writableData() {
821     return this->crtBuf_->writableData() + this->offset_;
822   }
823
824  private:
825   void maybeUnshare() {
826     if (UNLIKELY(maybeShared_)) {
827       this->crtBuf_->unshareOne();
828       maybeShared_ = false;
829     }
830   }
831
832   void advanceDone() {
833     maybeShared_ = true;
834   }
835
836   bool maybeShared_;
837 };
838
839 typedef RWCursor<CursorAccess::PRIVATE> RWPrivateCursor;
840 typedef RWCursor<CursorAccess::UNSHARE> RWUnshareCursor;
841
842 /**
843  * Append to the end of a buffer chain, growing the chain (by allocating new
844  * buffers) in increments of at least growth bytes every time.  Won't grow
845  * (and push() and ensure() will throw) if growth == 0.
846  *
847  * TODO(tudorb): add a flavor of Appender that reallocates one IOBuf instead
848  * of chaining.
849  */
850 class Appender : public detail::Writable<Appender> {
851  public:
852   Appender(IOBuf* buf, uint64_t growth)
853     : buffer_(buf),
854       crtBuf_(buf->prev()),
855       growth_(growth) {
856   }
857
858   uint8_t* writableData() {
859     return crtBuf_->writableTail();
860   }
861
862   size_t length() const {
863     return crtBuf_->tailroom();
864   }
865
866   /**
867    * Mark n bytes (must be <= length()) as appended, as per the
868    * IOBuf::append() method.
869    */
870   void append(size_t n) {
871     crtBuf_->append(n);
872   }
873
874   /**
875    * Ensure at least n contiguous bytes available to write.
876    * Postcondition: length() >= n.
877    */
878   void ensure(uint64_t n) {
879     if (LIKELY(length() >= n)) {
880       return;
881     }
882
883     // Waste the rest of the current buffer and allocate a new one.
884     // Don't make it too small, either.
885     if (growth_ == 0) {
886       std::__throw_out_of_range("can't grow buffer chain");
887     }
888
889     n = std::max(n, growth_);
890     buffer_->prependChain(IOBuf::create(n));
891     crtBuf_ = buffer_->prev();
892   }
893
894   using detail::Writable<Appender>::pushAtMost;
895   size_t pushAtMost(const uint8_t* buf, size_t len) {
896     // We have to explicitly check for an input length of 0.
897     // We support buf being nullptr in this case, but we need to avoid calling
898     // memcpy() with a null source pointer, since that is undefined behavior
899     // even if the length is 0.
900     if (len == 0) {
901       return 0;
902     }
903
904     size_t copied = 0;
905     for (;;) {
906       // Fast path: it all fits in one buffer.
907       size_t available = length();
908       if (LIKELY(available >= len)) {
909         memcpy(writableData(), buf, len);
910         append(len);
911         return copied + len;
912       }
913
914       memcpy(writableData(), buf, available);
915       append(available);
916       copied += available;
917       if (UNLIKELY(!tryGrowChain())) {
918         return copied;
919       }
920       buf += available;
921       len -= available;
922     }
923   }
924
925   /*
926    * Append to the end of this buffer, using a printf() style
927    * format specifier.
928    *
929    * Note that folly/Format.h provides nicer and more type-safe mechanisms
930    * for formatting strings, which should generally be preferred over
931    * printf-style formatting.  Appender objects can be used directly as an
932    * output argument for Formatter objects.  For example:
933    *
934    *   Appender app(&iobuf);
935    *   format("{} {}", "hello", "world")(app);
936    *
937    * However, printf-style strings are still needed when dealing with existing
938    * third-party code in some cases.
939    *
940    * This will always add a nul-terminating character after the end
941    * of the output.  However, the buffer data length will only be updated to
942    * include the data itself.  The nul terminator will be the first byte in the
943    * buffer tailroom.
944    *
945    * This method may throw exceptions on error.
946    */
947   void printf(FOLLY_PRINTF_FORMAT const char* fmt, ...)
948     FOLLY_PRINTF_FORMAT_ATTR(2, 3);
949
950   void vprintf(const char* fmt, va_list ap);
951
952   /*
953    * Calling an Appender object with a StringPiece will append the string
954    * piece.  This allows Appender objects to be used directly with
955    * Formatter.
956    */
957   void operator()(StringPiece sp) {
958     push(ByteRange(sp));
959   }
960
961  private:
962   bool tryGrowChain() {
963     assert(crtBuf_->next() == buffer_);
964     if (growth_ == 0) {
965       return false;
966     }
967
968     buffer_->prependChain(IOBuf::create(growth_));
969     crtBuf_ = buffer_->prev();
970     return true;
971   }
972
973   IOBuf* buffer_;
974   IOBuf* crtBuf_;
975   uint64_t growth_;
976 };
977
978 class QueueAppender : public detail::Writable<QueueAppender> {
979  public:
980   /**
981    * Create an Appender that writes to a IOBufQueue.  When we allocate
982    * space in the queue, we grow no more than growth bytes at once
983    * (unless you call ensure() with a bigger value yourself).
984    */
985   QueueAppender(IOBufQueue* queue, uint64_t growth) {
986     reset(queue, growth);
987   }
988
989   void reset(IOBufQueue* queue, uint64_t growth) {
990     queue_ = queue;
991     growth_ = growth;
992   }
993
994   uint8_t* writableData() {
995     return static_cast<uint8_t*>(queue_->writableTail());
996   }
997
998   size_t length() const { return queue_->tailroom(); }
999
1000   void append(size_t n) { queue_->postallocate(n); }
1001
1002   // Ensure at least n contiguous; can go above growth_, throws if
1003   // not enough room.
1004   void ensure(uint64_t n) { queue_->preallocate(n, growth_); }
1005
1006   template <class T>
1007   typename std::enable_if<std::is_arithmetic<T>::value>::type
1008   write(T value) {
1009     // We can't fail.
1010     auto p = queue_->preallocate(sizeof(T), growth_);
1011     storeUnaligned(p.first, value);
1012     queue_->postallocate(sizeof(T));
1013   }
1014
1015   using detail::Writable<QueueAppender>::pushAtMost;
1016   size_t pushAtMost(const uint8_t* buf, size_t len) {
1017     // Fill the current buffer
1018     const size_t copyLength = std::min(len, length());
1019     if (copyLength != 0) {
1020       memcpy(writableData(), buf, copyLength);
1021       append(copyLength);
1022       buf += copyLength;
1023     }
1024     // Allocate more buffers as necessary
1025     size_t remaining = len - copyLength;
1026     while (remaining != 0) {
1027       auto p = queue_->preallocate(std::min(remaining, growth_),
1028                                    growth_,
1029                                    remaining);
1030       memcpy(p.first, buf, p.second);
1031       queue_->postallocate(p.second);
1032       buf += p.second;
1033       remaining -= p.second;
1034     }
1035
1036     return len;
1037   }
1038
1039   void insert(std::unique_ptr<folly::IOBuf> buf) {
1040     if (buf) {
1041       queue_->append(std::move(buf), true);
1042     }
1043   }
1044
1045   void insert(const folly::IOBuf& buf) {
1046     insert(buf.clone());
1047   }
1048
1049  private:
1050   folly::IOBufQueue* queue_;
1051   size_t growth_;
1052 };
1053 } // namespace io
1054 } // namespace folly
1055
1056 #include <folly/io/Cursor-inl.h>