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