From c7c65f54afa6e0927c1a9a5ee818a79de337151a Mon Sep 17 00:00:00 2001 From: Giuseppe Ottaviano Date: Thu, 12 Feb 2015 17:46:14 -0800 Subject: [PATCH] Fix EliasFanoReader position() when past-the-end Summary: `EliasFanoReader::position()` used to return `size() - 1` both when the reader is positioned on the last element, and after `next()` is called after that (and it return `false`). Now in the latter case `position()` returns `size()` (consistently with the usual behaviour of past-the-end iterators). Also fix the return type of `jumpTo`. Test Plan: fbconfig folly/experimental/test:eliasfano_test && fbmake runtests_opt Reviewed By: philipp@fb.com Subscribers: trunkagent, folly-diffs@, yfeldblum FB internal diff: D1846275 Signature: t1:1846275:1423790264:151f5d2e1e09d4e24dfb758473dfb9cd52c070bd --- folly/experimental/EliasFanoCoding.h | 29 ++++++++++------------- folly/experimental/test/CodingTestUtils.h | 12 +++++----- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/folly/experimental/EliasFanoCoding.h b/folly/experimental/EliasFanoCoding.h index 61335819..7f83b0e8 100644 --- a/folly/experimental/EliasFanoCoding.h +++ b/folly/experimental/EliasFanoCoding.h @@ -542,9 +542,8 @@ class EliasFanoReader : private boost::noncopyable { } bool next() { - if (UNLIKELY(progress_ == list_.size)) { - value_ = std::numeric_limits::max(); - return false; + if (UNLIKELY(progress_ >= list_.size)) { + return setDone(); } value_ = readLowerPart(progress_) | (upper_.next() << list_.numLowerBits); @@ -567,9 +566,7 @@ class EliasFanoReader : private boost::noncopyable { return true; } - progress_ = list_.size; - value_ = std::numeric_limits::max(); - return false; + return setDone(); } bool skipTo(ValueType value) { @@ -577,9 +574,7 @@ class EliasFanoReader : private boost::noncopyable { if (value <= value_) { return true; } else if (value > lastValue_) { - progress_ = list_.size; - value_ = std::numeric_limits::max(); - return false; + return setDone(); } size_t upperValue = (value >> list_.numLowerBits); @@ -607,19 +602,15 @@ class EliasFanoReader : private boost::noncopyable { reset(); return true; } - progress_ = list_.size; - value_ = std::numeric_limits::max(); - return false; + return setDone(); } - ValueType jumpTo(ValueType value) { + bool jumpTo(ValueType value) { if (value <= 0) { reset(); return true; } else if (value > lastValue_) { - progress_ = list_.size; - value_ = std::numeric_limits::max(); - return false; + return setDone(); } upper_.jumpToNext(value >> list_.numLowerBits); @@ -633,6 +624,12 @@ class EliasFanoReader : private boost::noncopyable { ValueType value() const { return value_; } private: + bool setDone() { + value_ = std::numeric_limits::max(); + progress_ = list_.size + 1; + return false; + } + ValueType readLowerPart(size_t i) const { DCHECK_LT(i, list_.size); const size_t pos = i * list_.numLowerBits; diff --git a/folly/experimental/test/CodingTestUtils.h b/folly/experimental/test/CodingTestUtils.h index 2d686b95..1c53121f 100644 --- a/folly/experimental/test/CodingTestUtils.h +++ b/folly/experimental/test/CodingTestUtils.h @@ -84,7 +84,7 @@ void testNext(const std::vector& data, const List& list) { } EXPECT_FALSE(reader.next()); EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); } template @@ -100,7 +100,7 @@ void testSkip(const std::vector& data, const List& list, } EXPECT_FALSE(reader.skip(skipStep)); EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); EXPECT_FALSE(reader.next()); } @@ -136,7 +136,7 @@ void testSkipTo(const std::vector& data, const List& list, value = reader.value() + delta; } EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); EXPECT_FALSE(reader.next()); } @@ -153,7 +153,7 @@ void testSkipTo(const std::vector& data, const List& list) { Reader reader(list); EXPECT_FALSE(reader.skipTo(data.back() + 1)); EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); EXPECT_FALSE(reader.next()); } } @@ -180,7 +180,7 @@ void testJump(const std::vector& data, const List& list) { } EXPECT_FALSE(reader.jump(data.size() + 1)); EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); } template @@ -217,7 +217,7 @@ void testJumpTo(const std::vector& data, const List& list) { EXPECT_FALSE(reader.jumpTo(data.back() + 1)); EXPECT_EQ(reader.value(), std::numeric_limits::max()); - EXPECT_EQ(reader.position(), reader.size() - 1); + EXPECT_EQ(reader.position(), reader.size()); } template -- 2.34.1