summaryrefslogtreecommitdiffstats
path: root/vendor/gitea.com/lunny/nodb/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gitea.com/lunny/nodb/scan.go')
-rw-r--r--vendor/gitea.com/lunny/nodb/scan.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/vendor/gitea.com/lunny/nodb/scan.go b/vendor/gitea.com/lunny/nodb/scan.go
new file mode 100644
index 0000000000..fc0bdfb113
--- /dev/null
+++ b/vendor/gitea.com/lunny/nodb/scan.go
@@ -0,0 +1,144 @@
+package nodb
+
+import (
+ "bytes"
+ "errors"
+ "regexp"
+
+ "gitea.com/lunny/nodb/store"
+)
+
+var errDataType = errors.New("error data type")
+var errMetaKey = errors.New("error meta key")
+
+// Seek search the prefix key
+func (db *DB) Seek(key []byte) (*store.Iterator, error) {
+ return db.seek(KVType, key)
+}
+
+func (db *DB) seek(dataType byte, key []byte) (*store.Iterator, error) {
+ var minKey []byte
+ var err error
+
+ if len(key) > 0 {
+ if err = checkKeySize(key); err != nil {
+ return nil, err
+ }
+ if minKey, err = db.encodeMetaKey(dataType, key); err != nil {
+ return nil, err
+ }
+
+ } else {
+ if minKey, err = db.encodeMinKey(dataType); err != nil {
+ return nil, err
+ }
+ }
+
+ it := db.bucket.NewIterator()
+ it.Seek(minKey)
+ return it, nil
+}
+
+func (db *DB) MaxKey() ([]byte, error) {
+ return db.encodeMaxKey(KVType)
+}
+
+func (db *DB) Key(it *store.Iterator) ([]byte, error) {
+ return db.decodeMetaKey(KVType, it.Key())
+}
+
+func (db *DB) scan(dataType byte, key []byte, count int, inclusive bool, match string) ([][]byte, error) {
+ var minKey, maxKey []byte
+ var err error
+ var r *regexp.Regexp
+
+ if len(match) > 0 {
+ if r, err = regexp.Compile(match); err != nil {
+ return nil, err
+ }
+ }
+
+ if len(key) > 0 {
+ if err = checkKeySize(key); err != nil {
+ return nil, err
+ }
+ if minKey, err = db.encodeMetaKey(dataType, key); err != nil {
+ return nil, err
+ }
+
+ } else {
+ if minKey, err = db.encodeMinKey(dataType); err != nil {
+ return nil, err
+ }
+ }
+
+ if maxKey, err = db.encodeMaxKey(dataType); err != nil {
+ return nil, err
+ }
+
+ if count <= 0 {
+ count = defaultScanCount
+ }
+
+ v := make([][]byte, 0, count)
+
+ it := db.bucket.NewIterator()
+ it.Seek(minKey)
+
+ if !inclusive {
+ if it.Valid() && bytes.Equal(it.RawKey(), minKey) {
+ it.Next()
+ }
+ }
+
+ for i := 0; it.Valid() && i < count && bytes.Compare(it.RawKey(), maxKey) < 0; it.Next() {
+ if k, err := db.decodeMetaKey(dataType, it.Key()); err != nil {
+ continue
+ } else if r != nil && !r.Match(k) {
+ continue
+ } else {
+ v = append(v, k)
+ i++
+ }
+ }
+ it.Close()
+ return v, nil
+}
+
+func (db *DB) encodeMinKey(dataType byte) ([]byte, error) {
+ return db.encodeMetaKey(dataType, nil)
+}
+
+func (db *DB) encodeMaxKey(dataType byte) ([]byte, error) {
+ k, err := db.encodeMetaKey(dataType, nil)
+ if err != nil {
+ return nil, err
+ }
+ k[len(k)-1] = dataType + 1
+ return k, nil
+}
+
+func (db *DB) encodeMetaKey(dataType byte, key []byte) ([]byte, error) {
+ switch dataType {
+ case KVType:
+ return db.encodeKVKey(key), nil
+ case LMetaType:
+ return db.lEncodeMetaKey(key), nil
+ case HSizeType:
+ return db.hEncodeSizeKey(key), nil
+ case ZSizeType:
+ return db.zEncodeSizeKey(key), nil
+ case BitMetaType:
+ return db.bEncodeMetaKey(key), nil
+ case SSizeType:
+ return db.sEncodeSizeKey(key), nil
+ default:
+ return nil, errDataType
+ }
+}
+func (db *DB) decodeMetaKey(dataType byte, ek []byte) ([]byte, error) {
+ if len(ek) < 2 || ek[0] != db.index || ek[1] != dataType {
+ return nil, errMetaKey
+ }
+ return ek[2:], nil
+}