add IOBuf::maybeCopyBuffer()
authorAdam Simpkins <simpkins@fb.com>
Wed, 14 Nov 2012 04:58:10 +0000 (20:58 -0800)
committerJordan DeLong <jdelong@fb.com>
Sun, 16 Dec 2012 22:45:22 +0000 (14:45 -0800)
Summary:
Add a version of IOBuf::copyBuffer() which accepts a std::string, as
well as a maybeCopyBuffer() function which returns a null pointer if the
input string is empty.

In proxygen we have a few places where we construct an IOBuf from a
string configuration parameter, and we almost always want a null pointer
rather than an empty IOBuf chain if the string is empty.

Test Plan: Included unit tests for these new functions.

Reviewed By: tudorb@fb.com

FB internal diff: D630547

folly/experimental/io/IOBuf.h
folly/experimental/io/test/IOBufTest.cpp

index e48650a..3a0abb8 100644 (file)
@@ -299,6 +299,29 @@ class IOBuf {
                                            uint32_t headroom=0,
                                            uint32_t minTailroom=0);
 
+  /**
+   * Convenience function to create a new IOBuf object that copies data from a
+   * user-supplied string, optionally allocating a given amount of
+   * headroom and tailroom.
+   *
+   * Beware when attempting to invoke this function with a constant string
+   * literal and a headroom argument: you will likely end up invoking the
+   * version of copyBuffer() above.  IOBuf::copyBuffer("hello", 3) will treat
+   * the first argument as a const void*, and will invoke the version of
+   * copyBuffer() above, with the size argument of 3.
+   */
+  static std::unique_ptr<IOBuf> copyBuffer(const std::string& buf,
+                                           uint32_t headroom=0,
+                                           uint32_t minTailroom=0);
+
+  /**
+   * A version of copyBuffer() that returns a null pointer if the input string
+   * is empty.
+   */
+  static std::unique_ptr<IOBuf> maybeCopyBuffer(const std::string& buf,
+                                                uint32_t headroom=0,
+                                                uint32_t minTailroom=0);
+
   /**
    * Convenience function to free a chain of IOBufs held by a unique_ptr.
    */
@@ -1076,6 +1099,21 @@ inline std::unique_ptr<IOBuf> IOBuf::copyBuffer(
   return buf;
 }
 
+inline std::unique_ptr<IOBuf> IOBuf::copyBuffer(const std::string& buf,
+                                                uint32_t headroom,
+                                                uint32_t minTailroom) {
+  return copyBuffer(buf.data(), buf.size(), headroom, minTailroom);
+}
+
+inline std::unique_ptr<IOBuf> IOBuf::maybeCopyBuffer(const std::string& buf,
+                                                     uint32_t headroom,
+                                                     uint32_t minTailroom) {
+  if (buf.empty()) {
+    return nullptr;
+  }
+  return copyBuffer(buf.data(), buf.size(), headroom, minTailroom);
+}
+
 } // folly
 
 #endif // FOLLY_IO_IOBUF_H_
index b16511a..f6f6fe2 100644 (file)
@@ -550,6 +550,34 @@ TEST(IOBuf, copyBuffer) {
   EXPECT_EQ(s, std::string(reinterpret_cast<const char*>(buf->data()),
                            buf->length()));
   EXPECT_LE(2, buf->tailroom());
+
+  buf = IOBuf::copyBuffer(s, 5, 7);
+  EXPECT_EQ(5, buf->headroom());
+  EXPECT_EQ(s, std::string(reinterpret_cast<const char*>(buf->data()),
+                           buf->length()));
+  EXPECT_LE(7, buf->tailroom());
+
+  std::string empty;
+  buf = IOBuf::copyBuffer(empty, 3, 6);
+  EXPECT_EQ(3, buf->headroom());
+  EXPECT_EQ(0, buf->length());
+  EXPECT_LE(6, buf->tailroom());
+}
+
+TEST(IOBuf, maybeCopyBuffer) {
+  std::string s("this is a test");
+  auto buf = IOBuf::maybeCopyBuffer(s, 1, 2);
+  EXPECT_EQ(1, buf->headroom());
+  EXPECT_EQ(s, std::string(reinterpret_cast<const char*>(buf->data()),
+                           buf->length()));
+  EXPECT_LE(2, buf->tailroom());
+
+  std::string empty;
+  buf = IOBuf::maybeCopyBuffer("", 5, 7);
+  EXPECT_EQ(nullptr, buf.get());
+
+  buf = IOBuf::maybeCopyBuffer("");
+  EXPECT_EQ(nullptr, buf.get());
 }
 
 namespace {