diff --git a/Facade.h b/Facade.h index 4e16c15..175b839 100644 --- a/Facade.h +++ b/Facade.h @@ -19,12 +19,20 @@ struct Facade { int limit, bool reverse) const { std::vector> result; + if (begin >= end) { + return result; + } + weaselab::VersionedMap::Iterator versionedIter[2]; const weaselab::VersionedMap::Key key[] = { {begin.data(), int(begin.size())}, {end.data(), int(end.size())}}; const int64_t v[] = {version, version}; facade->versioned.firstGeq(key, v, versionedIter, 2); + if (versionedIter[0] == versionedIter[1]) { + return result; + } + static const uint8_t zero_[] = {0}; static const String zero{zero_, 1}; @@ -32,7 +40,10 @@ struct Facade { weaselab::VersionedMap::Iterator iter = versionedIter[1]; weaselab::VersionedMap::Iterator endIter = versionedIter[0]; String readUntil = end; - for (; iter != endIter; --iter) { + if (iter == facade->versioned.end(version)) { + --iter; + } + for (;; --iter) { auto m = *iter; const auto mEnd = m.type == weaselab::VersionedMap::Set || m.param2Len == 0 @@ -56,6 +67,9 @@ struct Facade { readUntil = String(m.param1, m.param1Len); break; } + if (iter == endIter) { + break; + } } facade->unversionedRead(begin, readUntil, limit, true, result); return result; diff --git a/VersionedMap.cpp b/VersionedMap.cpp index df3aae1..c10df89 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -1015,6 +1015,8 @@ void materializeMutations(VersionedMap::Iterator::Impl *impl, const Entry *prev, } VersionedMap::Iterator &VersionedMap::Iterator::operator++() { + impl->cmp = 1; + if (impl->mutationIndex < impl->mutationCount - 1) { ++impl->mutationIndex; return *this; @@ -1040,19 +1042,46 @@ VersionedMap::Iterator VersionedMap::Iterator::operator++(int) { } VersionedMap::Iterator &VersionedMap::Iterator::operator--() { + impl->cmp = -1; + if (impl->mutationIndex > 0) { --impl->mutationIndex; return *this; } - // TODO support decrementing end + // Handle decrementing end + if (impl->finger.searchPathSize() == 0) { + bool ignored; + impl->finger.push( + impl->map->roots.getThreadSafeHandle().rootForVersion(impl->version), + ignored); + assert(impl->finger.backNode() != 0); + uint32_t c; + while ((c = impl->map->child( + impl->finger.backNode(), true, impl->version)) != 0) { + impl->finger.push(c, true); + } + + const Entry *next = nullptr; + for (;;) { + materializeMutations(impl, nullptr, next); + if (impl->mutationCount > 0) { + break; + } + next = impl->map->mm.base[impl->finger.backNode()].entry; + impl->map->move(impl->finger, impl->version, + false); + } + impl->mutationIndex = impl->mutationCount - 1; + return *this; + } do { - const auto &entry = *impl->map->mm.base[impl->finger.backNode()].entry; + const Entry *entry = impl->map->mm.base[impl->finger.backNode()].entry; impl->map->move(impl->finger, impl->version, false); if (impl->finger.searchPathSize() > 0) { - materializeMutations(impl, nullptr, &entry); + materializeMutations(impl, nullptr, entry); } } while (impl->mutationCount == 0); impl->mutationIndex = impl->mutationCount - 1;