Commit f35c91c0 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

All comparison predicates for IOBuf

Summary: [Folly] All comparison predicates for `IOBuf`, not just `EqualTo`.

Reviewed By: djwatson, stevegury

Differential Revision: D7596700

fbshipit-source-id: 2d5cef2797dc75d4fb76c2d13e4a938f738da163
parent 1bd8b4f5
......@@ -1028,21 +1028,24 @@ size_t IOBufHash::operator()(const IOBuf& buf) const {
return h1;
}
bool IOBufEqualTo::operator()(const IOBuf& a, const IOBuf& b) const {
ordering IOBufCompare::operator()(const IOBuf& a, const IOBuf& b) const {
io::Cursor ca(&a);
io::Cursor cb(&b);
for (;;) {
auto ba = ca.peekBytes();
auto bb = cb.peekBytes();
if (ba.empty() && bb.empty()) {
return true;
} else if (ba.empty() || bb.empty()) {
return false;
return ordering::eq;
} else if (ba.empty()) {
return ordering::lt;
} else if (bb.empty()) {
return ordering::gt;
}
size_t n = std::min(ba.size(), bb.size());
const size_t n = std::min(ba.size(), bb.size());
DCHECK_GT(n, 0u);
if (memcmp(ba.data(), bb.data(), n)) {
return false;
const ordering r = to_ordering(std::memcmp(ba.data(), bb.data(), n));
if (r != ordering::eq) {
return r;
}
ca.skip(n);
cb.skip(n);
......
......@@ -31,6 +31,7 @@
#include <folly/FBVector.h>
#include <folly/Portability.h>
#include <folly/Range.h>
#include <folly/lang/Ordering.h>
#include <folly/portability/SysUio.h>
// Ignore shadowing warnings within this file, so includers can use -Wshadow.
......@@ -1422,22 +1423,53 @@ struct IOBufHash {
};
/**
* Equality predicate for IOBuf objects. Compares data in the entire chain.
* Ordering for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufEqualTo {
bool operator()(const IOBuf& a, const IOBuf& b) const;
bool operator()(const std::unique_ptr<IOBuf>& a,
const std::unique_ptr<IOBuf>& b) const {
if (!a && !b) {
return true;
} else if (!a || !b) {
return false;
} else {
return (*this)(*a, *b);
}
struct IOBufCompare {
ordering operator()(const IOBuf& a, const IOBuf& b) const;
ordering operator()(
const std::unique_ptr<IOBuf>& a,
const std::unique_ptr<IOBuf>& b) const {
// clang-format off
return
!a && !b ? ordering::eq :
!a && b ? ordering::lt :
a && !b ? ordering::gt :
operator()(*a, *b);
// clang-format on
}
};
/**
* Equality predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufEqualTo : compare_equal_to<IOBufCompare> {};
/**
* Inequality predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufNotEqualTo : compare_not_equal_to<IOBufCompare> {};
/**
* Less predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufLess : compare_less<IOBufCompare> {};
/**
* At-most predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufLessEqual : compare_less_equal<IOBufCompare> {};
/**
* Greater predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufGreater : compare_greater<IOBufCompare> {};
/**
* At-least predicate for IOBuf objects. Compares data in the entire chain.
*/
struct IOBufGreaterEqual : compare_greater_equal<IOBufCompare> {};
template <class UniquePtr>
typename std::enable_if<detail::IsUniquePtrToSL<UniquePtr>::value,
std::unique_ptr<IOBuf>>::type
......
......@@ -25,12 +25,13 @@
#include <folly/memory/Malloc.h>
#include <folly/portability/GTest.h>
using folly::ByteRange;
using folly::fbstring;
using folly::fbvector;
using folly::IOBuf;
using folly::TypedIOBuf;
using folly::ordering;
using folly::StringPiece;
using folly::ByteRange;
using folly::TypedIOBuf;
using std::unique_ptr;
void append(std::unique_ptr<IOBuf>& buf, StringPiece str) {
......@@ -1041,6 +1042,14 @@ namespace {
std::unique_ptr<IOBuf> fromStr(StringPiece sp) {
return IOBuf::copyBuffer(ByteRange(sp));
}
std::unique_ptr<IOBuf> seq(std::initializer_list<StringPiece> sps) {
auto ret = IOBuf::create(0);
for (auto sp : sps) {
ret->prependChain(IOBuf::copyBuffer(ByteRange(sp)));
}
return ret;
}
} // namespace
TEST(IOBuf, HashAndEqual) {
......@@ -1098,6 +1107,30 @@ TEST(IOBuf, HashAndEqual) {
EXPECT_EQ(hash(e), hash(f));
}
TEST(IOBuf, IOBufCompare) {
folly::IOBufCompare op;
auto n = std::unique_ptr<IOBuf>{};
auto e = IOBuf::create(0);
auto hello1 = seq({"hello"});
auto hello2 = seq({"hel", "lo"});
auto hello3 = seq({"he", "ll", "o"});
auto hellow = seq({"hellow"});
auto hellox = seq({"hellox"});
EXPECT_EQ(ordering::eq, op(n, n));
EXPECT_EQ(ordering::lt, op(n, e));
EXPECT_EQ(ordering::gt, op(e, n));
EXPECT_EQ(ordering::lt, op(e, hello1));
EXPECT_EQ(ordering::gt, op(hello1, e));
EXPECT_EQ(ordering::eq, op(hello1, hello1));
EXPECT_EQ(ordering::eq, op(hello1, hello2));
EXPECT_EQ(ordering::eq, op(hello1, hello3));
EXPECT_EQ(ordering::lt, op(hello1, hellow));
EXPECT_EQ(ordering::gt, op(hellow, hello1));
EXPECT_EQ(ordering::lt, op(hellow, hellox));
EXPECT_EQ(ordering::gt, op(hellox, hellow));
}
// reserveSlow() had a bug when reallocating the buffer in place. It would
// preserve old headroom if it's not too much (heuristically) but wouldn't
// adjust the requested amount of memory to account for that; the end result
......
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