mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
166 lines
3.0 KiB
Go
166 lines
3.0 KiB
Go
package btree
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
"unsafe"
|
|
)
|
|
|
|
func assert(cond bool) {
|
|
if !cond {
|
|
panic("assert failed!")
|
|
}
|
|
}
|
|
|
|
// power2 returns a value that is greater or equal to 'val' and is power-of-two.
|
|
func power2(val int) int {
|
|
i := 1
|
|
for i < val {
|
|
i <<= 1
|
|
}
|
|
return i
|
|
}
|
|
|
|
// helpers for sha1
|
|
|
|
func cmp(a, b *byte) int64 {
|
|
pa, pb := unsafe.Pointer(a), unsafe.Pointer(b)
|
|
if *(*uint64)(pa) != *(*uint64)(pb) {
|
|
return int64(*(*uint64)(pa) - *(*uint64)(pb))
|
|
}
|
|
pa, pb = unsafe.Add(pa, 8), unsafe.Add(pb, 8)
|
|
if *(*uint64)(pa) != *(*uint64)(pb) {
|
|
return int64(*(*uint64)(pa) - *(*uint64)(pb))
|
|
}
|
|
return int64(*(*uint32)(unsafe.Add(pa, 8)) - *(*uint32)(unsafe.Add(pa, 8)))
|
|
}
|
|
|
|
func copysha1(dst *byte, src *byte) {
|
|
pa, pb := unsafe.Pointer(dst), unsafe.Pointer(src)
|
|
*(*[sha1Size]byte)(pa) = *(*[sha1Size]byte)(pb)
|
|
}
|
|
|
|
func resetsha1(sha1 *byte) {
|
|
p := unsafe.Pointer(sha1)
|
|
*(*[sha1Size]byte)(p) = [sha1Size]byte{}
|
|
}
|
|
|
|
// reading table
|
|
|
|
func read64(r io.Reader) (int64, error) {
|
|
var b = make([]byte, 8)
|
|
_, err := r.Read(b)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int64(binary.LittleEndian.Uint64(b)), nil
|
|
}
|
|
|
|
func read32(r io.Reader) (int32, error) {
|
|
var b = make([]byte, 4)
|
|
_, err := r.Read(b)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int32(binary.LittleEndian.Uint32(b)), nil
|
|
}
|
|
|
|
func readTable(r io.Reader, t *table) error {
|
|
for i := 0; i < tableSize; i++ {
|
|
err := readItem(r, &t.items[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
switch unsafe.Sizeof(0) {
|
|
case 8:
|
|
i, err := read64(r)
|
|
t.size = int(i)
|
|
return err
|
|
case 4:
|
|
i, err := read32(r)
|
|
t.size = int(i)
|
|
return err
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|
|
|
|
func readItem(r io.Reader, i *item) error {
|
|
_, err := r.Read(i.sha1[:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
i.offset, err = read64(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
i.child, err = read64(r)
|
|
return err
|
|
}
|
|
|
|
func readSuper(r io.Reader, s *super) error {
|
|
var err error
|
|
if s.top, err = read64(r); err != nil {
|
|
return err
|
|
}
|
|
if s.freeTop, err = read64(r); err != nil {
|
|
return err
|
|
}
|
|
s.alloc, err = read64(r)
|
|
return err
|
|
}
|
|
|
|
// write table
|
|
|
|
func write64(w io.Writer, i int64) error {
|
|
var b = make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(b, uint64(i))
|
|
_, err := w.Write(b)
|
|
return err
|
|
}
|
|
|
|
func write32(w io.Writer, i int32) error {
|
|
var b = make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(b, uint32(i))
|
|
_, err := w.Write(b)
|
|
return err
|
|
}
|
|
|
|
func writeTable(w io.Writer, t *table) error {
|
|
for i := 0; i < tableSize; i++ {
|
|
err := writeItem(w, &t.items[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
switch unsafe.Sizeof(0) {
|
|
case 8:
|
|
return write64(w, int64(t.size))
|
|
case 4:
|
|
return write32(w, int32(t.size))
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|
|
|
|
func writeItem(w io.Writer, i *item) error {
|
|
if _, err := w.Write(i.sha1[:]); err != nil {
|
|
return err
|
|
}
|
|
if err := write64(w, i.offset); err != nil {
|
|
return err
|
|
}
|
|
return write64(w, i.child)
|
|
}
|
|
|
|
func writeSuper(w io.Writer, s *super) error {
|
|
if err := write64(w, s.top); err != nil {
|
|
return err
|
|
}
|
|
if err := write64(w, s.freeTop); err != nil {
|
|
return err
|
|
}
|
|
return write64(w, s.alloc)
|
|
}
|