Files
bin/bin.go

1487 lines
32 KiB
Go
Raw Normal View History

2022-12-24 17:48:08 +02:00
package bin
// ВАЖНО!
// Игры с битами для int* лучше всего делать в аналогичном uint* типе, а затем в конце
// приводить, например int32(uint32).
// Битовое представление отрицательного числа - все 0 заменяются на единицы.
import (
"bytes"
"errors"
"fmt"
"io"
"log"
"math"
"time"
)
// ByteOrder - порядок байт
type ByteOrder string
const (
maxReadAttempts = 5
// LH - low to high byte order
LH ByteOrder = "LH"
// HL - high to low byte order
HL ByteOrder = "HL"
Int32SignBit uint32 = 1 << 31
Int64SignBit uint64 = 1 << 63
)
var (
// ErrReadOverflow shows 100% bug in the source reader
ErrReadOverflow = errors.New("bin: reader returned 'n' > bufsize")
// ErrNegativeReadCount shows 100% bug in the source reader
ErrNegativeReadCount = errors.New("bin: reader returned negative 'n'")
unknownByteOrder = "bin: unknown byteOrder %q"
wrongArraySize = "bin: array size %d is not enough"
offsets24HL = []uint{24, 16, 8}
offsets24LH = []uint{0, 8, 16}
offsets32HL = []uint{24, 16, 8, 0}
offsets32LH = []uint{0, 8, 16, 24}
offsets48HL = []uint{56, 48, 40, 32, 24, 16}
offsets48LH = []uint{0, 8, 16, 24, 32, 40}
offsets64HL = []uint{56, 48, 40, 32, 24, 16, 8, 0}
offsets64LH = []uint{0, 8, 16, 24, 32, 40, 48, 56}
)
func ReadByteAsInt(r io.ByteReader) (i int, err error) {
b, err := r.ReadByte()
if err != nil {
return
}
return int(b), nil
}
func ReadUint32AsInt64(r io.ByteReader, byteOrder ByteOrder) (_ int64, err error) {
u32, err := ReadUint32(r, byteOrder)
if err != nil {
return
}
return int64(u32), nil
}
2022-12-24 17:48:08 +02:00
// ReadN - безопасно читаем n байт. Обрабатывает все возможные ситуации, в том числе
// баги Reader
func ReadN(r io.Reader, n int) (_ []byte, err error) {
if n == 0 {
return
}
if n < 0 {
err = fmt.Errorf("Wrong n=%d", n)
}
buf := make([]byte, n)
var q, total, readAttempts int
// Избегаем вечного цикла из-за неправильной реализации ридера
for readAttempts < maxReadAttempts {
bufsize := n - total
q, err = r.Read(buf[total:])
// Если буфер заполнен - успех, возвращаем буфер, err игнорируем
if q == bufsize {
return buf, nil
}
// Если ошибка - выходим с ошибкой
if err != nil {
return
}
// Если прочитали больше чем размер буфера. Баг в Reader
if q > bufsize {
err = ErrReadOverflow
return
}
// Если прочитали < 0. Баг в Reader
if q < 0 {
err = ErrNegativeReadCount
return
}
// Если ошибки нет, а прочитали 0 байт - чтобы не войти в бесконечный цикл
// увеличиваем readAttempts
if q == 0 {
readAttempts++
} else {
// Что-то прочитали, но меньше чем нужно - увеличиваем счетчик
// суммарно прочитанного
total += q
}
}
err = io.ErrNoProgress
return
}
func ReadString(r io.Reader, n int) (_ string, err error) {
buf, err := ReadN(r, n)
if err != nil {
return
}
return string(buf), nil
}
// GetInt16 - читает из массива arr 2 байта и декодирует их в int16.
func GetInt16(arr []byte, byteOrder ByteOrder) (num int16, err error) {
if len(arr) < 2 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = int16(arr[0]) | (int16(arr[1]) << 8)
case HL:
num = int16(arr[1]) | (int16(arr[0]) << 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetInt32 - читает из массива arr 4 байта и декодирует их в int32.
func GetInt32(arr []byte, byteOrder ByteOrder) (num int32, err error) {
if len(arr) < 4 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = int32(arr[0]) | (int32(arr[1]) << 8) |
(int32(arr[2]) << 16) | (int32(arr[3]) << 24)
case HL:
num = int32(arr[3]) | (int32(arr[2]) << 8) |
(int32(arr[1]) << 16) | (int32(arr[0]) << 24)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetInt64 - читает из массива arr 8 байт и декодирует их в int64.
func GetInt64(arr []byte, byteOrder ByteOrder) (num int64, err error) {
if len(arr) < 8 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = int64(arr[0]) | (int64(arr[1]) << 8) |
(int64(arr[2]) << 16) | (int64(arr[3]) << 24) |
(int64(arr[4]) << 32) | (int64(arr[5]) << 40) |
(int64(arr[6]) << 48) | (int64(arr[7]) << 56)
case HL:
num = int64(arr[7]) | (int64(arr[6]) << 8) |
(int64(arr[5]) << 16) | (int64(arr[4]) << 24) |
(int64(arr[3]) << 32) | (int64(arr[2]) << 40) |
(int64(arr[1]) << 48) | (int64(arr[0]) << 56)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetUint16 - читает из массива arr 2 байта и декодирует их в uint16.
func GetUint16(arr []byte, byteOrder ByteOrder) (num uint16, err error) {
if len(arr) < 2 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = uint16(arr[0]) | (uint16(arr[1]) << 8)
case HL:
num = uint16(arr[1]) | (uint16(arr[0]) << 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetUint32 - читает из массива arr 4 байта и декодирует их в uint32.
func GetUint32(arr []byte, byteOrder ByteOrder) (num uint32, err error) {
if len(arr) < 4 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = uint32(arr[0]) | (uint32(arr[1]) << 8) |
(uint32(arr[2]) << 16) | (uint32(arr[3]) << 24)
case HL:
num = uint32(arr[3]) | (uint32(arr[2]) << 8) |
(uint32(arr[1]) << 16) | (uint32(arr[0]) << 24)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetUint64 - читает из массива arr 8 байт и декодирует их в uint64.
func GetUint64(arr []byte, byteOrder ByteOrder) (num uint64, err error) {
if len(arr) < 8 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
num = uint64(arr[0]) | (uint64(arr[1]) << 8) |
(uint64(arr[2]) << 16) | (uint64(arr[3]) << 24) |
(uint64(arr[4]) << 32) | (uint64(arr[5]) << 40) |
(uint64(arr[6]) << 48) | (uint64(arr[7]) << 56)
case HL:
num = uint64(arr[7]) | (uint64(arr[6]) << 8) |
(uint64(arr[5]) << 16) | (uint64(arr[4]) << 24) |
(uint64(arr[3]) << 32) | (uint64(arr[2]) << 40) |
(uint64(arr[1]) << 48) | (uint64(arr[0]) << 56)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// GetFloat32 - записывает 4 байта в массив arr
func GetFloat32(arr []byte, byteOrder ByteOrder) (_ float32, err error) {
tmp, err := GetUint32(arr, byteOrder)
if err != nil {
return
}
return math.Float32frombits(tmp), nil
}
// GetFloat64 - записывает 4 байта в массив arr
func GetFloat64(arr []byte, byteOrder ByteOrder) (_ float64, err error) {
tmp, err := GetUint64(arr, byteOrder)
if err != nil {
return
}
return math.Float64frombits(tmp), nil
}
// PutInt16 - записывает 2 байта в массив arr
func PutInt16(arr []byte, num int16, byteOrder ByteOrder) (err error) {
if len(arr) < 2 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
case HL:
arr[1] = byte(num)
arr[0] = byte(num >> 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutInt32 - записывает 4 байта в массив arr
func PutInt32(arr []byte, num int32, byteOrder ByteOrder) (err error) {
if len(arr) < 4 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
arr[2] = byte(num >> 16)
arr[3] = byte(num >> 24)
case HL:
arr[3] = byte(num)
arr[2] = byte(num >> 8)
arr[1] = byte(num >> 16)
arr[0] = byte(num >> 24)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutInt64 - записывает 8 байт в массив arr
func PutInt64(arr []byte, num int64, byteOrder ByteOrder) (err error) {
if len(arr) < 8 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
arr[2] = byte(num >> 16)
arr[3] = byte(num >> 24)
arr[4] = byte(num >> 32)
arr[5] = byte(num >> 40)
arr[6] = byte(num >> 48)
arr[7] = byte(num >> 56)
case HL:
arr[7] = byte(num)
arr[6] = byte(num >> 8)
arr[5] = byte(num >> 16)
arr[4] = byte(num >> 24)
arr[3] = byte(num >> 32)
arr[2] = byte(num >> 40)
arr[1] = byte(num >> 48)
arr[0] = byte(num >> 56)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutUint16 - записывает 2 байта в массив arr
func PutUint16(arr []byte, num uint16, byteOrder ByteOrder) (err error) {
if len(arr) < 2 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
case HL:
arr[1] = byte(num)
arr[0] = byte(num >> 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutUint32 - записывает 4 байта в массив arr
func PutUint32(arr []byte, num uint32, byteOrder ByteOrder) (err error) {
if len(arr) < 4 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
arr[2] = byte(num >> 16)
arr[3] = byte(num >> 24)
case HL:
arr[3] = byte(num)
arr[2] = byte(num >> 8)
arr[1] = byte(num >> 16)
arr[0] = byte(num >> 24)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutUint64 - записывает 8 байт в массив arr
func PutUint64(arr []byte, num uint64, byteOrder ByteOrder) (err error) {
if len(arr) < 8 {
err = fmt.Errorf(wrongArraySize, len(arr))
return
}
switch byteOrder {
case LH:
arr[0] = byte(num)
arr[1] = byte(num >> 8)
arr[2] = byte(num >> 16)
arr[3] = byte(num >> 24)
arr[4] = byte(num >> 32)
arr[5] = byte(num >> 40)
arr[6] = byte(num >> 48)
arr[7] = byte(num >> 56)
case HL:
arr[7] = byte(num)
arr[6] = byte(num >> 8)
arr[5] = byte(num >> 16)
arr[4] = byte(num >> 24)
arr[3] = byte(num >> 32)
arr[2] = byte(num >> 40)
arr[1] = byte(num >> 48)
arr[0] = byte(num >> 56)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// PutFloat32 - записывает 4 байта в массив arr
func PutFloat32(arr []byte, num float32, byteOrder ByteOrder) (err error) {
return PutUint32(arr, math.Float32bits(num), byteOrder)
}
// PutFloat64 - записывает 4 байта в массив arr
func PutFloat64(arr []byte, num float64, byteOrder ByteOrder) (err error) {
return PutUint64(arr, math.Float64bits(num), byteOrder)
}
/*
PutVarUint64 - записывает в Writer от 1 до 9 байт, возвращает количество
записанных байт. Порядок байт - от младшего к старшему. В 9м байте все биты
значащие.
*/
func PutVarUint64(arr []byte, num uint64) (_ int, err error) {
for i := 0; i < 8; i++ {
arr[i] = byte(num & 127)
num >>= 7
if num == 0 {
arr[i] |= 128
return i + 1, nil
}
}
// в последнем 9м байте все биты значащие
arr[8] = byte(num)
return 9, nil
}
// WriteInt16 - записывает в Writer 2 байта
func WriteInt16(w io.Writer, num int16, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteInt24 - записывает в Writer 3 байта
func WriteInt24(w io.Writer, num int32, byteOrder ByteOrder) (err error) {
var sign byte
if num < 0 {
sign = 128
}
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte((num>>16)&127) | sign,
})
case HL:
_, err = w.Write([]byte{
byte((num>>16)&127) | sign,
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteInt32 - записывает в Writer 4 байта
func WriteInt32(w io.Writer, num int32, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteInt48 - записывает в Writer 6 байт
func WriteInt48(w io.Writer, num int64, byteOrder ByteOrder) (err error) {
var sign byte
if num < 0 {
sign = 128
}
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte((num>>40)&127) | sign,
})
case HL:
_, err = w.Write([]byte{
byte((num>>40)&127) | sign,
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteInt64 - записывает в Writer 8 байт
func WriteInt64(w io.Writer, num int64, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
byte(num >> 48),
byte(num >> 56),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 56),
byte(num >> 48),
byte(num >> 40),
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteUint16 - записывает в Writer 2 байта
func WriteUint16(w io.Writer, num uint16, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteUint32 - записывает в Writer 4 байта
func WriteUint32(w io.Writer, num uint32, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteUint64 - записывает в Writer 8 байт
func WriteUint64(w io.Writer, num uint64, byteOrder ByteOrder) (err error) {
switch byteOrder {
case LH:
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
byte(num >> 48),
byte(num >> 56),
})
case HL:
_, err = w.Write([]byte{
byte(num >> 56),
byte(num >> 48),
byte(num >> 40),
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
})
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// WriteFloat32 - записывает в Writer 4 байта
func WriteFloat32(w io.Writer, num float32, byteOrder ByteOrder) (err error) {
return WriteUint32(w, math.Float32bits(num), byteOrder)
}
// WriteFloat64 - записывает в Writer 8 байт
func WriteFloat64(w io.Writer, num float64, byteOrder ByteOrder) (err error) {
return WriteUint64(w, math.Float64bits(num), byteOrder)
}
// ReadInt16 - читает из ByteReader arr 2 байта и декодирует их в int16.
func ReadInt16(src io.ByteReader, byteOrder ByteOrder) (num int16, err error) {
b1, err := src.ReadByte()
if err != nil {
return
}
b2, err := src.ReadByte()
if err != nil {
return
}
switch byteOrder {
case LH:
num = int16(b1) | (int16(b2) << 8)
case HL:
num = int16(b2) | (int16(b1) << 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// ReadInt24 - читает из ByteReader arr 3 байта и декодирует их в int32.
// Нужно для протокола mbus.
func ReadInt24(src io.ByteReader, byteOrder ByteOrder) (i int32, err error) {
var (
num uint32
b, high byte
)
if byteOrder == LH {
for _, offset := range []uint{0, 8} {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint32(b) << offset
}
high, err = src.ReadByte()
if err != nil {
return
}
} else {
high, err = src.ReadByte()
if err != nil {
return
}
for _, offset := range []uint{8, 0} {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint32(b) << offset
}
}
num |= uint32(high&127) << 16
if high > 127 {
// заглушка
num |= 255 << 23
num |= Int32SignBit
}
return int32(num), nil
}
// ReadInt32 - читает из ByteReader arr 4 байта и декодирует их в int32.
func ReadInt32(src io.ByteReader, byteOrder ByteOrder) (num int32, err error) {
var (
b byte
offsets []uint
)
switch byteOrder {
case LH:
offsets = offsets32LH
case HL:
offsets = offsets32HL
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
return
}
for _, off := range offsets {
b, err = src.ReadByte()
if err != nil {
return
}
num |= int32(b) << off
}
return
}
// ReadInt48 - читает из ByteReader arr 6 байт и декодирует их в int64.
// Нужно для протокола mbus.
func ReadInt48(src io.ByteReader, byteOrder ByteOrder) (i int64, err error) {
var (
num uint64
b, high byte
)
if byteOrder == LH {
for _, offset := range []uint{0, 8, 16, 24, 32} {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint64(b) << offset
}
high, err = src.ReadByte()
if err != nil {
return
}
} else {
high, err = src.ReadByte()
if err != nil {
return
}
for _, offset := range []uint{32, 24, 16, 8, 0} {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint64(b) << offset
}
}
num |= uint64(high&127) << 40
if high > 127 {
// 2 заглушки
num |= 255 << 47
num |= 255 << 55
num |= Int64SignBit
}
return int64(num), nil
}
// ReadInt64 - читает из ByteReader arr 8 байт и декодирует их в int64.
func ReadInt64(src io.ByteReader, byteOrder ByteOrder) (num int64, err error) {
var (
b byte
offsets []uint
)
switch byteOrder {
case LH:
offsets = offsets64LH
case HL:
offsets = offsets64HL
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
return
}
for _, off := range offsets {
b, err = src.ReadByte()
if err != nil {
return
}
num |= int64(b) << off
}
return
}
// ReadUint16 - читает из ByteReader arr 2 байта и декодирует их в uint16.
func ReadUint16(src io.ByteReader, byteOrder ByteOrder) (num uint16, err error) {
b1, err := src.ReadByte()
if err != nil {
return
}
b2, err := src.ReadByte()
if err != nil {
return
}
switch byteOrder {
case LH:
num = uint16(b1) | (uint16(b2) << 8)
case HL:
num = uint16(b2) | (uint16(b1) << 8)
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
}
return
}
// ReadUint32 - читает из ByteReader arr 4 байта и декодирует их в uint32.
func ReadUint32(src io.ByteReader, byteOrder ByteOrder) (num uint32, err error) {
var (
b byte
offsets []uint
)
switch byteOrder {
case LH:
offsets = offsets32LH
case HL:
offsets = offsets32HL
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
return
}
for _, off := range offsets {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint32(b) << off
}
return
}
// ReadUint64 - читает из ByteReader arr 8 байт и декодирует их в uint64.
func ReadUint64(src io.ByteReader, byteOrder ByteOrder) (num uint64, err error) {
var (
b byte
offsets []uint
)
switch byteOrder {
case LH:
offsets = offsets64LH
case HL:
offsets = offsets64HL
default:
err = fmt.Errorf(unknownByteOrder, byteOrder)
return
}
for _, off := range offsets {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint64(b) << off
}
return
}
// ReadFloat32 - читает из ByteReader arr 4 байта и декодирует их в float32.
func ReadFloat32(src io.ByteReader, byteOrder ByteOrder) (_ float32, err error) {
tmp, err := ReadUint32(src, byteOrder)
if err != nil {
return
}
return math.Float32frombits(tmp), nil
}
// ReadFloat64 - читает из ByteReader arr 8 байт и декодирует их в float64.
func ReadFloat64(src io.ByteReader, byteOrder ByteOrder) (_ float64, err error) {
tmp, err := ReadUint64(src, byteOrder)
if err != nil {
return
}
return math.Float64frombits(tmp), nil
}
/////////////////////////////////// VAR
/*
WriteVarUint32 - записывает в Writer от 1 до 5 байт, возвращает количество
записанных байт. Порядок байт - от младшего к старшему. Значение последнего
байта всегда >= 128, остальных < 128.
*/
func WriteVarUint32(w io.Writer, num uint32) (i int) {
arr := make([]byte, 5)
for ; i < 5; i++ {
arr[i] = byte(num & 127)
num >>= 7
if num == 0 {
break
}
}
arr[i] |= 128
i++
w.Write(arr[:i])
return
}
/*
ReadVarUint32 - читает из ByteReader от 1 до 5 байт, и декодирует их в uint32.
*/
func ReadVarUint32(src io.ByteReader) (num uint32, err error) {
var b byte
for i := 0; i < 5; i++ {
b, err = src.ReadByte()
if err != nil {
return
}
if b >= 128 {
num |= uint32(b&127) << uint(i*7)
return
}
num |= uint32(b) << uint(i*7)
}
err = fmt.Errorf("VarUint32 encoded value not found\n")
return
}
/*
WriteVarUint64 - записывает в Writer от 1 до 9 байт, возвращает количество
записанных байт. Порядок байт - от младшего к старшему. В 9м байте все биты
значащие.
*/
func WriteVarUint64(w io.Writer, num uint64) (_ int, err error) {
arr := make([]byte, 9)
for i := 0; i < 8; i++ {
arr[i] = byte(num & 127)
num >>= 7
if num == 0 {
arr[i] |= 128
i++
return w.Write(arr[:i])
}
}
// в последнем 9м байте все биты значащие
arr[8] = byte(num)
return w.Write(arr)
}
/*
ReadVarUint64 - читает из ByteReader от 1 до 9 байт, и декодирует их в uint64.
*/
func ReadVarUint64(src io.ByteReader) (num uint64, err error) {
var b byte
for i := 0; i < 8; i++ {
b, err = src.ReadByte()
if err != nil {
return
}
if b >= 128 {
num |= uint64(b&127) << uint(i*7)
return
}
num |= uint64(b) << uint(i*7)
}
b, err = src.ReadByte()
if err != nil {
return
}
// в последнем 9м байте все биты значащие
num |= uint64(b) << 56
return
}
///////////////// НУЖНЫ ЛИ ?
/*
WriteMaxUint64 - кодирует число минимально возможным количеством байт (от 1 до 8).
Возвращает количество записанных байт. Порядок байт - от младшего к старшему.
*/
func WriteMaxUint64(w io.Writer, num uint64) (i int) {
arr := make([]byte, 8)
for ; i < 8; i++ {
arr[i] = byte(num)
num >>= 8
if num == 0 {
break
}
}
i++
w.Write(arr[:i])
return
}
/*
ReadMaxUint64 - читает из ByteReader число, закодированное методом MaxUint64.
*/
func ReadMaxUint64(src io.ByteReader, n int) (num uint64, err error) {
if n < 1 || n > 8 {
log.Fatalf("n=%d, allowed values 1-8\n", n)
}
var b byte
for i := 0; i < n; i++ {
b, err = src.ReadByte()
if err != nil {
return
}
num |= uint64(b) << uint(i*8)
}
return
}
/*
func PutVar2b(w io.Writer, num int) int {
if num < 128 {
w.Write([]byte{byte(num)})
return 1
}
w.Write([]byte{
byte(num&127) | 128,
byte(num >> 7),
})
return 2
}
func getVar2b(w io.Writer, num int) int {
if num < 128 {
w.Write([]byte{byte(num)})
return 1
}
w.Write([]byte{
byte(num&127) | 128,
byte(num >> 7),
})
return 2
}
func PutVarInt32(w io.Writer, num int32) (int, error) {
//if num > 2147483647 {
// return 0, fmt.Errorf("num %d overflows int32", num)
//}
arr := make([]byte, 5)
for i := 0; i < 4; i++ {
arr[i] = byte(num & 127)
num >>= 7
if num == 0 {
arr[i] |= 128
return w.Write(arr[:i+1])
}
}
// в последнем 9м байте все биты значащие
arr[5] = byte(num)
return w.Write(arr)
}
func VarInt32(src io.ByteReader) (num int, err error) {
var (
b byte
off uint
)
for ; off < 28; off += 7 {
b, err = src.ReadByte()
if err != nil {
return
}
if b < 128 {
num |= int(b) << off
} else {
num |= int(b&127) << off
return
}
}
b, err = src.ReadByte()
if err != nil {
return
}
// в последнем 9м байте все биты значащие
num |= int(b&7) << 28
return
}
*/
/*
func PackVarUint32(num int) (err error) {
idx := 0
for num > 127 {
s.vint[idx] = byte(num & 127)
num >>= 7
idx++
}
// Даже в последнем байте отсекаем старший бит (знак)
s.vint[idx] = byte(num&127) | 128
_, err = s.dst.Write(s.vint[:idx+1])
return
}
*/
var zeroUnixTime = []byte{0, 0, 0, 0, 0, 0}
func Read6bDateTime(r io.ByteReader) (_ time.Time, err error) {
var arr []byte
for i := 0; i < 6; i++ {
var b byte
b, err = r.ReadByte()
if err != nil {
return
}
arr = append(arr, b)
}
if bytes.Equal(arr, zeroUnixTime) {
return time.Unix(0, 0), nil
}
tm := time.Date(
int(arr[0])+2000,
time.Month(arr[1]),
int(arr[2]),
int(arr[3]),
int(arr[4]),
int(arr[5]),
0,
time.UTC,
)
return tm, nil
}
func Write6bDateTime(w io.Writer, tm time.Time) (err error) {
var arr []byte
// ВАЖНО!
tm = tm.In(time.UTC)
if tm.Unix() == 0 {
arr = zeroUnixTime
} else {
arr = []byte{
byte(tm.Year() - 2000),
byte(tm.Month()),
byte(tm.Day()),
byte(tm.Hour()),
byte(tm.Minute()),
byte(tm.Second()),
}
}
//fmt.Printf("TIME: %v / %v\n", tm.Unix(), arr)
_, err = w.Write(arr)
return
}
const (
MaxUint8 uint64 = 1<<8 - 1
MaxUint16 uint64 = 1<<16 - 1
MaxUint24 uint64 = 1<<24 - 1
MaxUint32 uint64 = 1<<32 - 1
MaxUint40 uint64 = 1<<40 - 1
MaxUint48 uint64 = 1<<48 - 1
MaxUint56 uint64 = 1<<56 - 1
MaxUint64 uint64 = 18446744073709551615
// MaxSafeInt - максимальное целое, которое можно сохранить в переменной
// типа float64 без потери точности
MinSafeInt int64 = -(1 << 53)
MaxSafeInt int64 = 1<<53 - 1
)
// WriteMaxSafeUint - кодирует 2**53-1 // LH
func WriteMaxSafeUint(w io.Writer, num uint64, byteOrder ByteOrder) (n int, err error) {
var arr []byte
if num <= MaxUint8 {
arr = []byte{
byte(num),
}
} else if num <= MaxUint16 {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
}
} else {
arr = []byte{
byte(num >> 8),
byte(num),
}
}
} else if num <= MaxUint24 {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
}
} else {
arr = []byte{
byte(num >> 16),
byte(num >> 8),
byte(num),
}
}
} else if num <= MaxUint32 {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
}
} else {
arr = []byte{
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
}
}
} else if num <= MaxUint40 {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
}
} else {
arr = []byte{
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
}
}
} else if num <= MaxUint48 {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
}
} else {
arr = []byte{
byte(num >> 40),
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
}
}
} else if num <= uint64(MaxSafeInt) {
if byteOrder == LH {
arr = []byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
byte(num >> 48),
}
} else {
arr = []byte{
byte(num >> 48),
byte(num >> 40),
byte(num >> 32),
byte(num >> 24),
byte(num >> 16),
byte(num >> 8),
byte(num),
}
}
} else {
err = fmt.Errorf("num %d > MaxSafeInt %d", num, MaxSafeInt)
return
}
return w.Write(arr)
}
type SplittedFloat struct {
Int int64 // bin.MaxSafeInt
Frac int64 // до 7 разрядов
}
func (s SplittedFloat) AsFloat64(fracDigits int) float64 {
//return float64(s.Int) + float64(s.Frac)/ fracMultipliers[fracDigits]
return float64(s.Int) + float64(s.Frac)/math.Pow10(fracDigits)
}
/*
var fracMultipliers = []float64{
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
}
*/
var prec = []float64{
0.999999999, // 0
0.99999999, // 1
0.9999999, // 2
0.999999, // 3
0.99999, // 4
0.9999, // 5
0.999, // 6
0.99, // 7
//0.99, // 8
}
func SplitFloat(num float64, fracDigits int) SplittedFloat {
var isNegative bool
if num < 0 {
isNegative = true
}
num = math.Abs(num)
//if fracDigits >= len(fracMultipliers) {
// panic(fmt.Sprintf("max fracDigits is %d, not %d\n",
// len(fracMultipliers), fracDigits))
//}
i, f := math.Modf(num)
poweredFrac := f * math.Pow10(fracDigits)
// В этот момент может произойти потеря точности, когда 0.55 превратится
// в 0.5499999999 (в меньшую сторону)
fracAsInt := int64(poweredFrac)
//
dif := poweredFrac - float64(fracAsInt)
//fmt.Printf("DIF %.10f\n\n", dif)
var eps float64
if fracDigits >= len(prec) {
eps = 0.99
} else {
eps = prec[fracDigits]
}
if dif > eps {
fracAsInt++
}
//fmt.Printf("\nSPLIT: %.10f, int = %d, frac = %v, %v, %d\n\n", num, int(i), f, f*fracMultipliers[fracDigits], int(f*fracMultipliers[fracDigits]))
if isNegative {
i *= -1
}
return SplittedFloat{
Int: int64(i),
Frac: fracAsInt,
}
}
/*
if byteOrder == LH {
} else {
}
*/
/*
// Round a float to a specific decimal place or precision
func Round(input float64, places int) (rounded float64, err error) {
// If the float is not a number
if math.IsNaN(input) {
return math.NaN(), fmt.Errorf("fuck")
}
// Find out the actual sign and correct the input for later
sign := 1.0
if input < 0 {
sign = -1
input *= -1
}
// Use the places arg to get the amount of precision wanted
precision := math.Pow(10, float64(places))
// Find the decimal place we are looking to round
digit := input * precision
// Get the actual decimal number as a fraction to be compared
_, decimal := math.Modf(digit)
// If the decimal is less than .5 we round down otherwise up
if decimal >= 0.5 {
rounded = math.Ceil(digit)
} else {
rounded = math.Floor(digit)
}
// Finally we do the math to actually create a rounded number
return rounded / precision * sign, nil
}
*/
func UnsetBit(b byte, idx byte) byte {
if ((b >> idx) & 1) == 1 {
// сбрасываем
var mask byte = ^(1 << idx)
return b & mask
}
return b
}
func SetBit(b byte, idx byte) byte {
if ((b >> idx) & 1) == 0 {
// устанавливаем
return b | (1 << idx)
}
return b
}
func Float64AsUint64(f float64) uint64 {
arr := make([]byte, 8)
PutFloat64(arr, f, LH)
u, _ := GetUint64(arr, LH)
return u
}
func Uint64AsFloat64(u uint64) float64 {
arr := make([]byte, 8)
PutUint64(arr, u, LH)
f, _ := GetFloat64(arr, LH)
return f
}
func Int64AsUint64(i int64) uint64 {
arr := make([]byte, 8)
PutInt64(arr, i, LH)
u, _ := GetUint64(arr, LH)
return u
}
func Uint64AsInt64(u uint64) int64 {
arr := make([]byte, 8)
PutUint64(arr, u, LH)
i, _ := GetInt64(arr, LH)
return i
}