-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbisearch.go
More file actions
50 lines (40 loc) · 1 KB
/
bisearch.go
File metadata and controls
50 lines (40 loc) · 1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package bisearch
import (
"bytes"
"errors"
"io"
)
var (
ErrIncorrectLength = errors.New("incorrect length")
ErrOperationIsNotCompleted = errors.New("operation is not completed")
ErrNotExist = errors.New("key does not exist")
)
func Search(f io.ReadSeeker, from, count uint64, length int, key []byte) ([]byte, error) {
if length < len(key) {
return nil, ErrIncorrectLength
}
l, r := uint64(0), count-1
record := make([]byte, length)
for r <= count && l >= 0 && r >= l {
m := l + (r-l)/2
pos := int64(from + m*uint64(length))
if n, err := f.Seek(pos, io.SeekStart); err != nil {
return nil, err
} else if n != pos {
return nil, ErrOperationIsNotCompleted
}
if n, err := f.Read(record); err != nil {
return nil, err
} else if n != length {
return nil, ErrOperationIsNotCompleted
}
if cmp := bytes.Compare(key, record[:len(key)]); cmp == 0 {
return record, nil
} else if cmp > 0 {
l = m + 1
} else {
r = m - 1
}
}
return nil, ErrNotExist
}