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