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}
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2023-06-11 14:51:02 +03:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-19 18:47:29 +03:00
|
|
|
|
func WriteVarSize(w io.Writer, n int) (_ int, err error) {
|
|
|
|
|
|
num := uint64(n)
|
|
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ReadVarSize(src io.ByteReader) (_ int, err error) {
|
|
|
|
|
|
var (
|
|
|
|
|
|
b byte
|
|
|
|
|
|
num uint64
|
|
|
|
|
|
)
|
|
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
|
|
b, err = src.ReadByte()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2023-12-26 22:22:15 +02:00
|
|
|
|
|
2023-09-19 18:47:29 +03:00
|
|
|
|
if b >= 128 {
|
|
|
|
|
|
num |= uint64(b&127) << uint(i*7)
|
2023-12-26 22:22:15 +02:00
|
|
|
|
return int(num), nil
|
2023-09-19 18:47:29 +03:00
|
|
|
|
}
|
|
|
|
|
|
num |= uint64(b) << uint(i*7)
|
|
|
|
|
|
}
|
|
|
|
|
|
b, err = src.ReadByte()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// в последнем 9м байте все биты значащие
|
|
|
|
|
|
num |= uint64(b) << 56
|
|
|
|
|
|
return int(num), nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-24 17:48:08 +02:00
|
|
|
|
///////////////// НУЖНЫ ЛИ ?
|
|
|
|
|
|
/*
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|