Cursor.h 33 KB

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