Files
bin/bin.go

1487 lines
32 KiB
Go
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
// 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
}