Commit 9547cef8 authored by Peter Griess's avatar Peter Griess Committed by Jordan DeLong

Add some CursorBase::operator-() implementations

Summary:
- Add CursorBase::operator-() implementations for Cursor and BufType;
useful for figuring out the distance between two objects

Test Plan: - Used in some other code

Reviewed By: simpkins@fb.com

FB internal diff: D690046
parent 2a80dba7
......@@ -216,6 +216,57 @@ class CursorBase {
}
}
/**
* Return the distance between two cursors.
*/
size_t operator-(const CursorBase& other) const {
BufType *otherBuf = other.crtBuf_;
size_t len = 0;
if (otherBuf != crtBuf_) {
len += otherBuf->length() - other.offset_;
for (otherBuf = otherBuf->next();
otherBuf != crtBuf_ && otherBuf != other.buffer_;
otherBuf = otherBuf->next()) {
len += otherBuf->length();
}
if (otherBuf == other.buffer_) {
throw std::out_of_range("wrap-around");
}
len += offset_;
} else {
if (offset_ < other.offset_) {
throw std::out_of_range("underflow");
}
len += offset_ - other.offset_;
}
return len;
}
/**
* Return the distance from the given IOBuf to the this cursor.
*/
size_t operator-(const BufType* buf) const {
size_t len = 0;
BufType *curBuf = buf;
while (curBuf != crtBuf_) {
len += curBuf->length();
curBuf = curBuf->next();
if (curBuf == buf || curBuf == buffer_) {
throw std::out_of_range("wrap-around");
}
}
len += offset_;
return len;
}
protected:
BufType* crtBuf_;
size_t offset_;
......
......@@ -326,6 +326,63 @@ TEST(IOBuf, Appender) {
EXPECT_EQ("hello world", toString(*head));
}
TEST(IOBuf, CursorOperators) {
// Test operators on a single-item chain
{
std::unique_ptr<IOBuf> chain1(IOBuf::create(20));
chain1->append(10);
Cursor curs1(chain1.get());
EXPECT_EQ(0, curs1 - chain1.get());
curs1.skip(3);
EXPECT_EQ(3, curs1 - chain1.get());
curs1.skip(7);
EXPECT_EQ(10, curs1 - chain1.get());
Cursor curs2(chain1.get());
EXPECT_EQ(0, curs2 - chain1.get());
EXPECT_EQ(10, curs1 - curs2);
EXPECT_THROW(curs2 - curs1, std::out_of_range);
}
// Test cross-chain operations
{
std::unique_ptr<IOBuf> chain1(IOBuf::create(20));
chain1->append(10);
std::unique_ptr<IOBuf> chain2 = chain1->clone();
Cursor curs1(chain1.get());
Cursor curs2(chain2.get());
EXPECT_THROW(curs1 - curs2, std::out_of_range);
EXPECT_THROW(curs1 - chain2.get(), std::out_of_range);
}
// Test operations on multi-item chains
{
std::unique_ptr<IOBuf> chain(IOBuf::create(20));
chain->append(10);
chain->appendChain(chain->clone());
EXPECT_EQ(20, chain->computeChainDataLength());
Cursor curs1(chain.get());
curs1.skip(5);
Cursor curs2(chain.get());
curs2.skip(3);
EXPECT_EQ(2, curs1 - curs2);
EXPECT_EQ(5, curs1 - chain.get());
EXPECT_THROW(curs2 - curs1, std::out_of_range);
curs1.skip(7);
EXPECT_EQ(9, curs1 - curs2);
EXPECT_EQ(12, curs1 - chain.get());
EXPECT_THROW(curs2 - curs1, std::out_of_range);
curs2.skip(7);
EXPECT_EQ(2, curs1 - curs2);
EXPECT_THROW(curs2 - curs1, std::out_of_range);
}
}
int benchmark_size = 1000;
unique_ptr<IOBuf> iobuf_benchmark;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment