add Cursor::peekBytes()
[folly.git] / folly / io / IOBuf.cpp
index 35c4e102bf49d85f01dd08af97a65acdbc864df9..763522b74abc1b2134c9d20966a522f69f0641af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#ifndef __STDC_LIMIT_MACROS
 #define __STDC_LIMIT_MACROS
+#endif
 
 #include <folly/io/IOBuf.h>
 
@@ -143,9 +145,7 @@ void* IOBuf::operator new(size_t size) {
   return &(storage->buf);
 }
 
-void* IOBuf::operator new(size_t size, void* ptr) {
-  return ptr;
-}
+void* IOBuf::operator new(size_t /* size */, void* ptr) { return ptr; }
 
 void IOBuf::operator delete(void* ptr) {
   auto* storageAddr = static_cast<uint8_t*>(ptr) - offsetof(HeapStorage, buf);
@@ -186,7 +186,7 @@ void IOBuf::releaseStorage(HeapStorage* storage, uint16_t freeFlags) {
   }
 }
 
-void IOBuf::freeInternalBuf(void* buf, void* userData) {
+void IOBuf::freeInternalBuf(void* /* buf */, void* userData) {
   auto* storage = static_cast<HeapStorage*>(userData);
   releaseStorage(storage, kDataInUse);
 }
@@ -203,9 +203,12 @@ IOBuf::IOBuf(CreateOp, uint64_t capacity)
   data_ = buf_;
 }
 
-IOBuf::IOBuf(CopyBufferOp op, const void* buf, uint64_t size,
-             uint64_t headroom, uint64_t minTailroom)
-  : IOBuf(CREATE, headroom + size + minTailroom) {
+IOBuf::IOBuf(CopyBufferOp /* op */,
+             const void* buf,
+             uint64_t size,
+             uint64_t headroom,
+             uint64_t minTailroom)
+    : IOBuf(CREATE, headroom + size + minTailroom) {
   advance(headroom);
   memcpy(writableData(), buf, size);
   append(size);
@@ -329,15 +332,45 @@ unique_ptr<IOBuf> IOBuf::wrapBuffer(const void* buf, uint64_t capacity) {
   return make_unique<IOBuf>(WRAP_BUFFER, buf, capacity);
 }
 
+IOBuf IOBuf::wrapBufferAsValue(const void* buf, uint64_t capacity) {
+  return IOBuf(WrapBufferOp::WRAP_BUFFER, buf, capacity);
+}
+
 IOBuf::IOBuf() noexcept {
 }
 
-IOBuf::IOBuf(IOBuf&& other) noexcept {
-  *this = std::move(other);
+IOBuf::IOBuf(IOBuf&& other) noexcept
+    : data_(other.data_),
+      buf_(other.buf_),
+      length_(other.length_),
+      capacity_(other.capacity_),
+      flagsAndSharedInfo_(other.flagsAndSharedInfo_) {
+  // Reset other so it is a clean state to be destroyed.
+  other.data_ = nullptr;
+  other.buf_ = nullptr;
+  other.length_ = 0;
+  other.capacity_ = 0;
+  other.flagsAndSharedInfo_ = 0;
+
+  // If other was part of the chain, assume ownership of the rest of its chain.
+  // (It's only valid to perform move assignment on the head of a chain.)
+  if (other.next_ != &other) {
+    next_ = other.next_;
+    next_->prev_ = this;
+    other.next_ = &other;
+
+    prev_ = other.prev_;
+    prev_->next_ = this;
+    other.prev_ = &other;
+  }
+
+  // Sanity check to make sure that other is in a valid state to be destroyed.
+  DCHECK_EQ(other.prev_, &other);
+  DCHECK_EQ(other.next_, &other);
 }
 
 IOBuf::IOBuf(const IOBuf& other) {
-  other.cloneInto(*this);
+  *this = other.cloneAsValue();
 }
 
 IOBuf::IOBuf(InternalConstructor,
@@ -470,39 +503,35 @@ void IOBuf::prependChain(unique_ptr<IOBuf>&& iobuf) {
 }
 
 unique_ptr<IOBuf> IOBuf::clone() const {
-  unique_ptr<IOBuf> ret = make_unique<IOBuf>();
-  cloneInto(*ret);
-  return ret;
+  return make_unique<IOBuf>(cloneAsValue());
 }
 
 unique_ptr<IOBuf> IOBuf::cloneOne() const {
-  unique_ptr<IOBuf> ret = make_unique<IOBuf>();
-  cloneOneInto(*ret);
-  return ret;
+  return make_unique<IOBuf>(cloneOneAsValue());
 }
 
-void IOBuf::cloneInto(IOBuf& other) const {
-  IOBuf tmp;
-  cloneOneInto(tmp);
+IOBuf IOBuf::cloneAsValue() const {
+  auto tmp = cloneOneAsValue();
 
   for (IOBuf* current = next_; current != this; current = current->next_) {
     tmp.prependChain(current->cloneOne());
   }
 
-  other = std::move(tmp);
+  return tmp;
 }
 
-void IOBuf::cloneOneInto(IOBuf& other) const {
-  SharedInfo* info = sharedInfo();
-  if (info) {
+IOBuf IOBuf::cloneOneAsValue() const {
+  if (SharedInfo* info = sharedInfo()) {
     setFlags(kFlagMaybeShared);
-  }
-  other = IOBuf(InternalConstructor(),
-                flagsAndSharedInfo_, buf_, capacity_,
-                data_, length_);
-  if (info) {
     info->refcount.fetch_add(1, std::memory_order_acq_rel);
   }
+  return IOBuf(
+      InternalConstructor(),
+      flagsAndSharedInfo_,
+      buf_,
+      capacity_,
+      data_,
+      length_);
 }
 
 void IOBuf::unshareOneSlow() {
@@ -933,12 +962,12 @@ size_t IOBufHash::operator()(const IOBuf& buf) const {
   hasher.Init(0, 0);
   io::Cursor cursor(&buf);
   for (;;) {
-    auto p = cursor.peek();
-    if (p.second == 0) {
+    auto b = cursor.peekBytes();
+    if (b.empty()) {
       break;
     }
-    hasher.Update(p.first, p.second);
-    cursor.skip(p.second);
+    hasher.Update(b.data(), b.size());
+    cursor.skip(b.size());
   }
   uint64_t h1;
   uint64_t h2;
@@ -950,16 +979,16 @@ bool IOBufEqual::operator()(const IOBuf& a, const IOBuf& b) const {
   io::Cursor ca(&a);
   io::Cursor cb(&b);
   for (;;) {
-    auto pa = ca.peek();
-    auto pb = cb.peek();
-    if (pa.second == 0 && pb.second == 0) {
+    auto ba = ca.peekBytes();
+    auto bb = cb.peekBytes();
+    if (ba.empty() && bb.empty()) {
       return true;
-    } else if (pa.second == 0 || pb.second == 0) {
+    } else if (ba.empty() || bb.empty()) {
       return false;
     }
-    size_t n = std::min(pa.second, pb.second);
+    size_t n = std::min(ba.size(), bb.size());
     DCHECK_GT(n, 0);
-    if (memcmp(pa.first, pb.first, n)) {
+    if (memcmp(ba.data(), bb.data(), n)) {
       return false;
     }
     ca.skip(n);