114 lines
2.1 KiB
Go
114 lines
2.1 KiB
Go
|
// Copyright (c) 2015 Couchbase, Inc.
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the
|
||
|
// License. You may obtain a copy of the License at
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
// Unless required by applicable law or agreed to in writing,
|
||
|
// software distributed under the License is distributed on an "AS
|
||
|
// IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||
|
// express or implied. See the License for the specific language
|
||
|
// governing permissions and limitations under the License.
|
||
|
|
||
|
// +build go1.4
|
||
|
|
||
|
package cznicb
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
|
||
|
"github.com/cznic/b"
|
||
|
)
|
||
|
|
||
|
var iteratorDoneErr = errors.New("iteratorDoneErr") // A sentinel value.
|
||
|
|
||
|
type Iterator struct { // Assuming that iterators are used single-threaded.
|
||
|
s *Store
|
||
|
e *b.Enumerator
|
||
|
|
||
|
currK interface{}
|
||
|
currV interface{}
|
||
|
currErr error
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) SeekFirst() {
|
||
|
i.currK = nil
|
||
|
i.currV = nil
|
||
|
i.currErr = nil
|
||
|
|
||
|
var err error
|
||
|
i.s.m.RLock()
|
||
|
i.e, err = i.s.t.SeekFirst()
|
||
|
i.s.m.RUnlock() // cannot defer, must unlock before Next
|
||
|
if err != nil {
|
||
|
i.currK = nil
|
||
|
i.currV = nil
|
||
|
i.currErr = iteratorDoneErr
|
||
|
}
|
||
|
|
||
|
i.Next()
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Seek(k []byte) {
|
||
|
i.currK = nil
|
||
|
i.currV = nil
|
||
|
i.currErr = nil
|
||
|
|
||
|
i.s.m.RLock()
|
||
|
i.e, _ = i.s.t.Seek(k)
|
||
|
i.s.m.RUnlock() // cannot defer, must unlock before Next
|
||
|
|
||
|
i.Next()
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Next() {
|
||
|
if i.currErr != nil {
|
||
|
i.currK = nil
|
||
|
i.currV = nil
|
||
|
i.currErr = iteratorDoneErr
|
||
|
return
|
||
|
}
|
||
|
|
||
|
i.s.m.RLock()
|
||
|
defer i.s.m.RUnlock()
|
||
|
i.currK, i.currV, i.currErr = i.e.Next()
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Current() ([]byte, []byte, bool) {
|
||
|
if i.currErr == iteratorDoneErr ||
|
||
|
i.currK == nil ||
|
||
|
i.currV == nil {
|
||
|
return nil, nil, false
|
||
|
}
|
||
|
|
||
|
return i.currK.([]byte), i.currV.([]byte), true
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Key() []byte {
|
||
|
k, _, ok := i.Current()
|
||
|
if !ok {
|
||
|
return nil
|
||
|
}
|
||
|
return k
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Value() []byte {
|
||
|
_, v, ok := i.Current()
|
||
|
if !ok {
|
||
|
return nil
|
||
|
}
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Valid() bool {
|
||
|
_, _, ok := i.Current()
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
func (i *Iterator) Close() error {
|
||
|
if i.e != nil {
|
||
|
i.e.Close()
|
||
|
}
|
||
|
i.e = nil
|
||
|
return nil
|
||
|
}
|