Reverse iterators (#224)

with passing tests
This commit is contained in:
Jeremiah Andrews
2018-06-24 19:37:32 -07:00
committed by Jae Kwon
parent fb7ec62b29
commit cb08d28d40
6 changed files with 151 additions and 24 deletions

View File

@ -190,7 +190,8 @@ func (db *CLevelDB) Iterator(start, end []byte) Iterator {
}
func (db *CLevelDB) ReverseIterator(start, end []byte) Iterator {
panic("not implemented yet") // XXX
itr := db.db.NewIterator(db.ro)
return newCLevelDBIterator(itr, start, end, true)
}
var _ Iterator = (*cLevelDBIterator)(nil)
@ -204,12 +205,25 @@ type cLevelDBIterator struct {
func newCLevelDBIterator(source *levigo.Iterator, start, end []byte, isReverse bool) *cLevelDBIterator {
if isReverse {
panic("not implemented yet") // XXX
}
if start != nil {
source.Seek(start)
if start == nil {
source.SeekToLast()
} else {
source.Seek(start)
if source.Valid() {
soakey := source.Key() // start or after key
if bytes.Compare(start, soakey) < 0 {
source.Prev()
}
} else {
source.SeekToLast()
}
}
} else {
source.SeekToFirst()
if start == nil {
source.SeekToFirst()
} else {
source.Seek(start)
}
}
return &cLevelDBIterator{
source: source,
@ -243,9 +257,16 @@ func (itr cLevelDBIterator) Valid() bool {
// If key is end or past it, invalid.
var end = itr.end
var key = itr.source.Key()
if end != nil && bytes.Compare(end, key) <= 0 {
itr.isInvalid = true
return false
if itr.isReverse {
if end != nil && bytes.Compare(key, end) <= 0 {
itr.isInvalid = true
return false
}
} else {
if end != nil && bytes.Compare(end, key) <= 0 {
itr.isInvalid = true
return false
}
}
// It's valid.
@ -267,7 +288,11 @@ func (itr cLevelDBIterator) Value() []byte {
func (itr cLevelDBIterator) Next() {
itr.assertNoError()
itr.assertIsValid()
itr.source.Next()
if itr.isReverse {
itr.source.Prev()
} else {
itr.source.Next()
}
}
func (itr cLevelDBIterator) Close() {