gitroast/vendor/github.com/pingcap/go-hbase/iohelper/utils.go

178 lines
3.0 KiB
Go

package iohelper
import (
"bytes"
"encoding/binary"
"io"
"github.com/juju/errors"
)
var (
cachedItob [][]byte
)
func init() {
cachedItob = make([][]byte, 1024)
for i := 0; i < len(cachedItob); i++ {
var b bytes.Buffer
writeVLong(&b, int64(i))
cachedItob[i] = b.Bytes()
}
}
func itob(i int) ([]byte, error) {
if i >= 0 && i < len(cachedItob) {
return cachedItob[i], nil
}
var b bytes.Buffer
err := binary.Write(&b, binary.BigEndian, i)
if err != nil {
return nil, errors.Trace(err)
}
return b.Bytes(), nil
}
func decodeVIntSize(value byte) int32 {
if int32(value) >= -112 {
return int32(1)
}
if int32(value) < -120 {
return -119 - int32(value)
}
return -111 - int32(value)
}
func isNegativeVInt(value byte) bool {
return int32(value) < -120 || int32(value) >= -112 && int32(value) < 0
}
func readVLong(r io.Reader) (int64, error) {
var firstByte byte
err := binary.Read(r, binary.BigEndian, &firstByte)
if err != nil {
return 0, errors.Trace(err)
}
l := decodeVIntSize(firstByte)
if l == 1 {
return int64(firstByte), nil
}
var (
i int64
idx int32
)
for idx = 0; idx < l-1; idx++ {
var b byte
err = binary.Read(r, binary.BigEndian, &b)
if err != nil {
return 0, errors.Trace(err)
}
i <<= 8
i |= int64(b & 255)
}
if isNegativeVInt(firstByte) {
return ^i, nil
}
return i, nil
}
func writeVLong(w io.Writer, i int64) error {
var err error
if i >= -112 && i <= 127 {
err = binary.Write(w, binary.BigEndian, byte(i))
if err != nil {
return errors.Trace(err)
}
} else {
var l int32 = -112
if i < 0 {
i = ^i
l = -120
}
var tmp int64
for tmp = i; tmp != 0; l-- {
tmp >>= 8
}
err = binary.Write(w, binary.BigEndian, byte(l))
if err != nil {
return errors.Trace(err)
}
if l < -120 {
l = -(l + 120)
} else {
l = -(l + 112)
}
for idx := l; idx != 0; idx-- {
var mask int64
shiftbits := uint((idx - 1) * 8)
mask = int64(255) << shiftbits
err = binary.Write(w, binary.BigEndian, byte((i&mask)>>shiftbits))
if err != nil {
return errors.Trace(err)
}
}
}
return nil
}
func ReadVarBytes(r ByteMultiReader) ([]byte, error) {
sz, err := readVLong(r)
if err != nil {
return nil, errors.Trace(err)
}
b := make([]byte, sz)
_, err = r.Read(b)
if err != nil {
return nil, errors.Trace(err)
}
return b, nil
}
func WriteVarBytes(w io.Writer, b []byte) error {
lenb, err := itob(len(b))
if err != nil {
return errors.Trace(err)
}
_, err = w.Write(lenb)
if err != nil {
return errors.Trace(err)
}
_, err = w.Write(b)
return errors.Trace(err)
}
func ReadInt32(r io.Reader) (int32, error) {
var n int32
err := binary.Read(r, binary.BigEndian, &n)
return n, errors.Trace(err)
}
func ReadN(r io.Reader, n int32) ([]byte, error) {
b := make([]byte, n)
_, err := io.ReadFull(r, b)
return b, errors.Trace(err)
}
func ReadUint64(r io.Reader) (uint64, error) {
var n uint64
err := binary.Read(r, binary.BigEndian, &n)
return n, errors.Trace(err)
}