return end - *this;
}
+ /**
+ * Return true if the cursor could advance the specified number of bytes
+ * from its current position.
+ * This is useful for applications that want to do checked reads instead of
+ * catching exceptions and is more efficient than using totalLength as it
+ * walks the minimal set of buffers in the chain to determine the result.
+ */
+ bool canAdvance(size_t amount) const {
+ const IOBuf* nextBuf = crtBuf_;
+ size_t available = length();
+ do {
+ if (available >= amount) {
+ return true;
+ }
+ amount -= available;
+ nextBuf = nextBuf->next();
+ available = nextBuf->length();
+ } while (nextBuf != buffer_);
+ return false;
+ }
+
/*
* Return true if the cursor is at the end of the entire IOBuf chain.
*/
c.skip(5);
EXPECT_TRUE(c.isAtEnd());
}
+
+ // Test canAdvance with a chain of items
+ {
+ auto chain = IOBuf::create(10);
+ chain->append(10);
+ chain->appendChain(chain->clone());
+ EXPECT_EQ(2, chain->countChainElements());
+ EXPECT_EQ(20, chain->computeChainDataLength());
+
+ Cursor c(chain.get());
+ for (size_t i = 0; i <= 20; ++i) {
+ EXPECT_TRUE(c.canAdvance(i));
+ }
+ EXPECT_FALSE(c.canAdvance(21));
+ c.skip(10);
+ EXPECT_TRUE(c.canAdvance(10));
+ EXPECT_FALSE(c.canAdvance(11));
+ }
}
TEST(IOBuf, StringOperations) {