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 { ...@@ -1028,21 +1028,24 @@ size_t IOBufHash::operator()(const IOBuf& buf) const {
return h1; 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 ca(&a);
io::Cursor cb(&b); io::Cursor cb(&b);
for (;;) { for (;;) {
auto ba = ca.peekBytes(); auto ba = ca.peekBytes();
auto bb = cb.peekBytes(); auto bb = cb.peekBytes();
if (ba.empty() && bb.empty()) { if (ba.empty() && bb.empty()) {
return true; return ordering::eq;
} else if (ba.empty() || bb.empty()) { } else if (ba.empty()) {
return false; 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); DCHECK_GT(n, 0u);
if (memcmp(ba.data(), bb.data(), n)) { const ordering r = to_ordering(std::memcmp(ba.data(), bb.data(), n));
return false; if (r != ordering::eq) {
return r;
} }
ca.skip(n); ca.skip(n);
cb.skip(n); cb.skip(n);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <folly/FBVector.h> #include <folly/FBVector.h>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/lang/Ordering.h>
#include <folly/portability/SysUio.h> #include <folly/portability/SysUio.h>
// Ignore shadowing warnings within this file, so includers can use -Wshadow. // Ignore shadowing warnings within this file, so includers can use -Wshadow.
...@@ -1422,22 +1423,53 @@ struct IOBufHash { ...@@ -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 { struct IOBufCompare {
bool operator()(const IOBuf& a, const IOBuf& b) const; ordering operator()(const IOBuf& a, const IOBuf& b) const;
bool operator()(const std::unique_ptr<IOBuf>& a, ordering operator()(
const std::unique_ptr<IOBuf>& a,
const std::unique_ptr<IOBuf>& b) const { const std::unique_ptr<IOBuf>& b) const {
if (!a && !b) { // clang-format off
return true; return
} else if (!a || !b) { !a && !b ? ordering::eq :
return false; !a && b ? ordering::lt :
} else { a && !b ? ordering::gt :
return (*this)(*a, *b); 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> template <class UniquePtr>
typename std::enable_if<detail::IsUniquePtrToSL<UniquePtr>::value, typename std::enable_if<detail::IsUniquePtrToSL<UniquePtr>::value,
std::unique_ptr<IOBuf>>::type std::unique_ptr<IOBuf>>::type
......
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
#include <folly/memory/Malloc.h> #include <folly/memory/Malloc.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
using folly::ByteRange;
using folly::fbstring; using folly::fbstring;
using folly::fbvector; using folly::fbvector;
using folly::IOBuf; using folly::IOBuf;
using folly::TypedIOBuf; using folly::ordering;
using folly::StringPiece; using folly::StringPiece;
using folly::ByteRange; using folly::TypedIOBuf;
using std::unique_ptr; using std::unique_ptr;
void append(std::unique_ptr<IOBuf>& buf, StringPiece str) { void append(std::unique_ptr<IOBuf>& buf, StringPiece str) {
...@@ -1041,6 +1042,14 @@ namespace { ...@@ -1041,6 +1042,14 @@ namespace {
std::unique_ptr<IOBuf> fromStr(StringPiece sp) { std::unique_ptr<IOBuf> fromStr(StringPiece sp) {
return IOBuf::copyBuffer(ByteRange(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 } // namespace
TEST(IOBuf, HashAndEqual) { TEST(IOBuf, HashAndEqual) {
...@@ -1098,6 +1107,30 @@ TEST(IOBuf, HashAndEqual) { ...@@ -1098,6 +1107,30 @@ TEST(IOBuf, HashAndEqual) {
EXPECT_EQ(hash(e), hash(f)); 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 // 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 // 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 // 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