mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-27 01:24:54 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			328 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package store
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 
 | |
| 	"github.com/lunny/nodb/store/driver"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	IteratorForward  uint8 = 0
 | |
| 	IteratorBackward uint8 = 1
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	RangeClose uint8 = 0x00
 | |
| 	RangeLOpen uint8 = 0x01
 | |
| 	RangeROpen uint8 = 0x10
 | |
| 	RangeOpen  uint8 = 0x11
 | |
| )
 | |
| 
 | |
| // min must less or equal than max
 | |
| //
 | |
| // range type:
 | |
| //
 | |
| //  close: [min, max]
 | |
| //  open: (min, max)
 | |
| //  lopen: (min, max]
 | |
| //  ropen: [min, max)
 | |
| //
 | |
| type Range struct {
 | |
| 	Min []byte
 | |
| 	Max []byte
 | |
| 
 | |
| 	Type uint8
 | |
| }
 | |
| 
 | |
| type Limit struct {
 | |
| 	Offset int
 | |
| 	Count  int
 | |
| }
 | |
| 
 | |
| type Iterator struct {
 | |
| 	it driver.IIterator
 | |
| }
 | |
| 
 | |
| // Returns a copy of key.
 | |
| func (it *Iterator) Key() []byte {
 | |
| 	k := it.it.Key()
 | |
| 	if k == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return append([]byte{}, k...)
 | |
| }
 | |
| 
 | |
| // Returns a copy of value.
 | |
| func (it *Iterator) Value() []byte {
 | |
| 	v := it.it.Value()
 | |
| 	if v == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return append([]byte{}, v...)
 | |
| }
 | |
| 
 | |
| // Returns a reference of key.
 | |
| // you must be careful that it will be changed after next iterate.
 | |
| func (it *Iterator) RawKey() []byte {
 | |
| 	return it.it.Key()
 | |
| }
 | |
| 
 | |
| // Returns a reference of value.
 | |
| // you must be careful that it will be changed after next iterate.
 | |
| func (it *Iterator) RawValue() []byte {
 | |
| 	return it.it.Value()
 | |
| }
 | |
| 
 | |
| // Copy key to b, if b len is small or nil, returns a new one.
 | |
| func (it *Iterator) BufKey(b []byte) []byte {
 | |
| 	k := it.RawKey()
 | |
| 	if k == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if b == nil {
 | |
| 		b = []byte{}
 | |
| 	}
 | |
| 
 | |
| 	b = b[0:0]
 | |
| 	return append(b, k...)
 | |
| }
 | |
| 
 | |
| // Copy value to b, if b len is small or nil, returns a new one.
 | |
| func (it *Iterator) BufValue(b []byte) []byte {
 | |
| 	v := it.RawValue()
 | |
| 	if v == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	if b == nil {
 | |
| 		b = []byte{}
 | |
| 	}
 | |
| 
 | |
| 	b = b[0:0]
 | |
| 	return append(b, v...)
 | |
| }
 | |
| 
 | |
| func (it *Iterator) Close() {
 | |
| 	if it.it != nil {
 | |
| 		it.it.Close()
 | |
| 		it.it = nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (it *Iterator) Valid() bool {
 | |
| 	return it.it.Valid()
 | |
| }
 | |
| 
 | |
| func (it *Iterator) Next() {
 | |
| 	it.it.Next()
 | |
| }
 | |
| 
 | |
| func (it *Iterator) Prev() {
 | |
| 	it.it.Prev()
 | |
| }
 | |
| 
 | |
| func (it *Iterator) SeekToFirst() {
 | |
| 	it.it.First()
 | |
| }
 | |
| 
 | |
| func (it *Iterator) SeekToLast() {
 | |
| 	it.it.Last()
 | |
| }
 | |
| 
 | |
| func (it *Iterator) Seek(key []byte) {
 | |
| 	it.it.Seek(key)
 | |
| }
 | |
| 
 | |
| // Finds by key, if not found, nil returns.
 | |
| func (it *Iterator) Find(key []byte) []byte {
 | |
| 	it.Seek(key)
 | |
| 	if it.Valid() {
 | |
| 		k := it.RawKey()
 | |
| 		if k == nil {
 | |
| 			return nil
 | |
| 		} else if bytes.Equal(k, key) {
 | |
| 			return it.Value()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Finds by key, if not found, nil returns, else a reference of value returns.
 | |
| // you must be careful that it will be changed after next iterate.
 | |
| func (it *Iterator) RawFind(key []byte) []byte {
 | |
| 	it.Seek(key)
 | |
| 	if it.Valid() {
 | |
| 		k := it.RawKey()
 | |
| 		if k == nil {
 | |
| 			return nil
 | |
| 		} else if bytes.Equal(k, key) {
 | |
| 			return it.RawValue()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type RangeLimitIterator struct {
 | |
| 	it *Iterator
 | |
| 
 | |
| 	r *Range
 | |
| 	l *Limit
 | |
| 
 | |
| 	step int
 | |
| 
 | |
| 	//0 for IteratorForward, 1 for IteratorBackward
 | |
| 	direction uint8
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) Key() []byte {
 | |
| 	return it.it.Key()
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) Value() []byte {
 | |
| 	return it.it.Value()
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) RawKey() []byte {
 | |
| 	return it.it.RawKey()
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) RawValue() []byte {
 | |
| 	return it.it.RawValue()
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) BufKey(b []byte) []byte {
 | |
| 	return it.it.BufKey(b)
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) BufValue(b []byte) []byte {
 | |
| 	return it.it.BufValue(b)
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) Valid() bool {
 | |
| 	if it.l.Offset < 0 {
 | |
| 		return false
 | |
| 	} else if !it.it.Valid() {
 | |
| 		return false
 | |
| 	} else if it.l.Count >= 0 && it.step >= it.l.Count {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	if it.direction == IteratorForward {
 | |
| 		if it.r.Max != nil {
 | |
| 			r := bytes.Compare(it.it.RawKey(), it.r.Max)
 | |
| 			if it.r.Type&RangeROpen > 0 {
 | |
| 				return !(r >= 0)
 | |
| 			} else {
 | |
| 				return !(r > 0)
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		if it.r.Min != nil {
 | |
| 			r := bytes.Compare(it.it.RawKey(), it.r.Min)
 | |
| 			if it.r.Type&RangeLOpen > 0 {
 | |
| 				return !(r <= 0)
 | |
| 			} else {
 | |
| 				return !(r < 0)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) Next() {
 | |
| 	it.step++
 | |
| 
 | |
| 	if it.direction == IteratorForward {
 | |
| 		it.it.Next()
 | |
| 	} else {
 | |
| 		it.it.Prev()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (it *RangeLimitIterator) Close() {
 | |
| 	it.it.Close()
 | |
| }
 | |
| 
 | |
| func NewRangeLimitIterator(i *Iterator, r *Range, l *Limit) *RangeLimitIterator {
 | |
| 	return rangeLimitIterator(i, r, l, IteratorForward)
 | |
| }
 | |
| 
 | |
| func NewRevRangeLimitIterator(i *Iterator, r *Range, l *Limit) *RangeLimitIterator {
 | |
| 	return rangeLimitIterator(i, r, l, IteratorBackward)
 | |
| }
 | |
| 
 | |
| func NewRangeIterator(i *Iterator, r *Range) *RangeLimitIterator {
 | |
| 	return rangeLimitIterator(i, r, &Limit{0, -1}, IteratorForward)
 | |
| }
 | |
| 
 | |
| func NewRevRangeIterator(i *Iterator, r *Range) *RangeLimitIterator {
 | |
| 	return rangeLimitIterator(i, r, &Limit{0, -1}, IteratorBackward)
 | |
| }
 | |
| 
 | |
| func rangeLimitIterator(i *Iterator, r *Range, l *Limit, direction uint8) *RangeLimitIterator {
 | |
| 	it := new(RangeLimitIterator)
 | |
| 
 | |
| 	it.it = i
 | |
| 
 | |
| 	it.r = r
 | |
| 	it.l = l
 | |
| 	it.direction = direction
 | |
| 
 | |
| 	it.step = 0
 | |
| 
 | |
| 	if l.Offset < 0 {
 | |
| 		return it
 | |
| 	}
 | |
| 
 | |
| 	if direction == IteratorForward {
 | |
| 		if r.Min == nil {
 | |
| 			it.it.SeekToFirst()
 | |
| 		} else {
 | |
| 			it.it.Seek(r.Min)
 | |
| 
 | |
| 			if r.Type&RangeLOpen > 0 {
 | |
| 				if it.it.Valid() && bytes.Equal(it.it.RawKey(), r.Min) {
 | |
| 					it.it.Next()
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		if r.Max == nil {
 | |
| 			it.it.SeekToLast()
 | |
| 		} else {
 | |
| 			it.it.Seek(r.Max)
 | |
| 
 | |
| 			if !it.it.Valid() {
 | |
| 				it.it.SeekToLast()
 | |
| 			} else {
 | |
| 				if !bytes.Equal(it.it.RawKey(), r.Max) {
 | |
| 					it.it.Prev()
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if r.Type&RangeROpen > 0 {
 | |
| 				if it.it.Valid() && bytes.Equal(it.it.RawKey(), r.Max) {
 | |
| 					it.it.Prev()
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for i := 0; i < l.Offset; i++ {
 | |
| 		if it.it.Valid() {
 | |
| 			if it.direction == IteratorForward {
 | |
| 				it.it.Next()
 | |
| 			} else {
 | |
| 				it.it.Prev()
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return it
 | |
| }
 |