package db
|
|
|
|
import "bytes"
|
|
|
|
// A wrapper around itr that tries to keep the iterator
|
|
// within the bounds as defined by `prefix`
|
|
type prefixIterator struct {
|
|
itr Iterator
|
|
prefix []byte
|
|
invalid bool
|
|
}
|
|
|
|
func (pi *prefixIterator) Seek(key []byte) {
|
|
if !bytes.HasPrefix(key, pi.prefix) {
|
|
pi.invalid = true
|
|
return
|
|
}
|
|
pi.itr.Seek(key)
|
|
pi.checkInvalid()
|
|
}
|
|
|
|
func (pi *prefixIterator) checkInvalid() {
|
|
if !pi.itr.Valid() {
|
|
pi.invalid = true
|
|
}
|
|
}
|
|
|
|
func (pi *prefixIterator) Valid() bool {
|
|
if pi.invalid {
|
|
return false
|
|
}
|
|
key := pi.itr.Key()
|
|
ok := bytes.HasPrefix(key, pi.prefix)
|
|
if !ok {
|
|
pi.invalid = true
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (pi *prefixIterator) Next() {
|
|
if pi.invalid {
|
|
panic("prefixIterator Next() called when invalid")
|
|
}
|
|
pi.itr.Next()
|
|
pi.checkInvalid()
|
|
}
|
|
|
|
func (pi *prefixIterator) Prev() {
|
|
if pi.invalid {
|
|
panic("prefixIterator Prev() called when invalid")
|
|
}
|
|
pi.itr.Prev()
|
|
pi.checkInvalid()
|
|
}
|
|
|
|
func (pi *prefixIterator) Key() []byte {
|
|
if pi.invalid {
|
|
panic("prefixIterator Key() called when invalid")
|
|
}
|
|
return pi.itr.Key()
|
|
}
|
|
|
|
func (pi *prefixIterator) Value() []byte {
|
|
if pi.invalid {
|
|
panic("prefixIterator Value() called when invalid")
|
|
}
|
|
return pi.itr.Value()
|
|
}
|
|
|
|
func (pi *prefixIterator) Close() { pi.itr.Close() }
|
|
func (pi *prefixIterator) GetError() error { return pi.itr.GetError() }
|
|
|
|
func IteratePrefix(db DB, prefix []byte) Iterator {
|
|
itr := db.Iterator()
|
|
pi := &prefixIterator{
|
|
itr: itr,
|
|
prefix: prefix,
|
|
}
|
|
pi.Seek(prefix)
|
|
return pi
|
|
}
|