diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index cad7657..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "cmake.configureOnOpen": false -} \ No newline at end of file diff --git a/bin.go b/bin.go index baad344..388e7d0 100644 --- a/bin.go +++ b/bin.go @@ -1,32 +1,25 @@ 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 + // Int32SignBit uint32 = 1 << 31 + // Int64SignBit uint64 = 1 << 63 + maxReadAttempts = 5 ) var ( @@ -34,39 +27,8 @@ var ( 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) { @@ -125,1207 +87,58 @@ func ReadNInto(r io.Reader, buf []byte) (err error) { 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 -} - -func GetUint48(arr []byte, byteOrder ByteOrder) (num uint64, err error) { - if len(arr) < 6 { - 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) - case HL: - num = uint64(arr[5]) | (uint64(arr[4]) << 8) | - (uint64(arr[3]) << 16) | (uint64(arr[2]) << 24) | - (uint64(arr[1]) << 32) | (uint64(arr[0]) << 40) - 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 -} - -func PutUint48(arr []byte, num uint64, byteOrder ByteOrder) (err error) { - if len(arr) < 6 { - 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) - case HL: - arr[5] = byte(num) - arr[4] = byte(num >> 8) - arr[3] = byte(num >> 16) - arr[2] = byte(num >> 24) - arr[1] = byte(num >> 32) - arr[0] = byte(num >> 40) - 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 -} - -// WriteUint48 - записывает в Writer 6 байт -func WriteUint48(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), - }) - case HL: - _, err = w.Write([]byte{ - byte(num >> 40), - byte(num >> 32), - 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 -} - -// ReadUint48 - читает из ByteReader arr 6 байт и декодирует их в uint64. -func ReadUint48(src io.ByteReader, byteOrder ByteOrder) (num uint64, err error) { - var ( - b byte - offsets []uint - ) - switch byteOrder { - case LH: - offsets = offsets48LH - case HL: - offsets = offsets48HL - default: - err = fmt.Errorf(unknownByteOrder, byteOrder) - return - } - for _, off := range offsets { - b, err = src.ReadByte() - if err != nil { - return - } - num |= uint64(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 -} - -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 - } - - if b >= 128 { - num |= uint64(b&127) << uint(i*7) - return int(num), nil - } - num |= uint64(b) << uint(i*7) - } - b, err = src.ReadByte() - if err != nil { - return - } - // в последнем 9м байте все биты значащие - num |= uint64(b) << 56 - return int(num), nil -} - -///////////////// НУЖНЫ ЛИ ? -/* -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 -} +// 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()), +// } +// } +// _, err = w.Write(arr) +// return +// } const ( MaxUint8 uint64 = 1<<8 - 1 @@ -1341,8 +154,6 @@ const ( // типа float64 без потери точности MinSafeInt int64 = -(1 << 53) MaxSafeInt int64 = 1<<53 - 1 - - //x math.MaxUint64 ) // WriteMaxSafeUint - кодирует 2**53-1 // LH @@ -1547,14 +358,6 @@ func SplitFloat(num float64, fracDigits int) SplittedFloat { } /* - if byteOrder == LH { - - } else { - - } -*/ - -/* // Round a float to a specific decimal place or precision func Round(input float64, places int) (rounded float64, err error) { @@ -1592,6 +395,20 @@ func Round(input float64, places int) (rounded float64, err error) { */ +// FLAGS + +func IsSetFlag(flags byte, flag byte) bool { + return (flags & flag) == flag +} + +func SetFlag(flags byte, flag byte) byte { + return flags | flag +} + +func UnsetFlag(flags byte, flag byte) byte { + return flags & ^flag +} + func UnsetBit(b byte, idx byte) byte { if ((b >> idx) & 1) == 1 { // сбрасываем @@ -1608,45 +425,3 @@ func SetBit(b byte, idx byte) byte { } 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 -} - -// FLAGS - -func IsSetFlag(flags byte, flag byte) bool { - return (flags & flag) == flag -} - -func SetFlag(flags byte, flag byte) byte { - return flags | flag -} - -func UnsetFlag(flags byte, flag byte) byte { - return flags & ^flag -} diff --git a/bin_test.go b/bin_test.go index 8b623bb..fb4d17a 100644 --- a/bin_test.go +++ b/bin_test.go @@ -3,205 +3,9 @@ package bin import ( "bytes" "fmt" - "strconv" "testing" - "time" ) -const ( - max7b uint64 = 127 - max14b uint64 = 16383 - max21b uint64 = 2097151 - max28b uint64 = 268435455 - max35b uint64 = 34359738367 - max42b uint64 = 4398046511103 - max49b uint64 = 562949953421311 - max56b uint64 = 72057594037927935 - - max24b uint64 = 16777215 - max40b uint64 = 1099511627775 - max48b uint64 = 281474976710655 -) - -type UintAndSize struct { - Value uint64 - Size int -} - -/* -func TestVarUint64(t *testing.T) { - // числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи - // плюс предыдущее число. Например: 2**7-1, 2**7 - var nums = []UintAndSize{ - {0, 1}, - {1, 1}, - {max7b, 1}, - {max7b + 1, 2}, - {max14b, 2}, - {max14b + 1, 3}, - {max21b, 3}, - {max21b + 1, 4}, - {max28b, 4}, - {max28b + 1, 5}, - {max35b, 5}, - {max35b + 1, 6}, - {max42b, 6}, - {max42b + 1, 7}, - {max49b, 7}, - {max49b + 1, 8}, - {max56b, 8}, - {max56b + 1, 9}, - {math.MaxUint64, 9}, - } - - buf := bytes.NewBuffer(nil) - - for _, num := range nums { - buf.Reset() - n := PutVarUint64(buf, num.Value) - if n != num.Size { - t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, num.Value) - } - encoded := buf.Bytes() - x, err := GetVarUint64(bytes.NewBuffer(encoded)) - if err != nil { - t.Fatalf("GetVarUint64 error: %s\n", err) - } - if x != num.Value { - t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", num.Value, x, encoded) - } - } -} - -func TestVarUint32(t *testing.T) { - // числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи - // плюс предыдущее число. Например: 2**7-1, 2**7 - var nums = []UintAndSize{ - {0, 1}, - {1, 1}, - {max7b, 1}, - {max7b + 1, 2}, - {max14b, 2}, - {max14b + 1, 3}, - {max21b, 3}, - {max21b + 1, 4}, - {max28b, 4}, - {max28b + 1, 5}, - {math.MaxUint32, 5}, - } - - buf := bytes.NewBuffer(nil) - - for _, num := range nums { - buf.Reset() - origin := uint32(num.Value) - n := PutVarUint32(buf, origin) - if n != num.Size { - t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, origin) - } - encoded := buf.Bytes() - x, err := GetVarUint32(bytes.NewBuffer(encoded)) - if err != nil { - t.Fatalf("GetVarUint32 error: %s\n", err) - } - if x != origin { - t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", origin, x, encoded) - } - } -} -*/ -/* -func TestMaxUint64(t *testing.T) { - // числа между 0, 1 и MaxUint64 - это 2 в степени кратной семи - // плюс предыдущее число. Например: 2**7-1, 2**7 - var nums = []UintAndSize{ - {0, 1}, - {1, 1}, - {math.MaxUint8, 1}, - {math.MaxUint8 + 1, 2}, - {math.MaxUint16, 2}, - {math.MaxUint16 + 1, 3}, - {max24b, 3}, - {max24b + 1, 4}, - {math.MaxUint32, 4}, - {math.MaxUint32 + 1, 5}, - {max40b, 5}, - {max40b + 1, 6}, - {max48b, 6}, - {max48b + 1, 7}, - {max56b, 7}, - {max56b + 1, 8}, - {math.MaxUint64, 8}, - } - - buf := bytes.NewBuffer(nil) - - for _, num := range nums { - buf.Reset() - n := PutMaxUint64(buf, num.Value) - if n != num.Size { - t.Fatalf("Encoded size %d != estimated size %d for num %d\n", n, num.Size, num.Value) - } - encoded := buf.Bytes() - x, err := GetMaxUint64(bytes.NewBuffer(encoded), n) - if err != nil { - t.Fatalf("GetMaxUint64 error: %s\n", err) - } - if x != num.Value { - t.Fatalf("Origin num %d != decoded num %d. Buffer: %v\n", num.Value, x, encoded) - } - } -} -*/ - -func TestFloat32(t *testing.T) { - buf := []byte{234, 171, 234, 171, 234, 171, 234, 171, 234, 171} - - r := bytes.NewBuffer(buf) - - num, err := ReadFloat32(r, HL) - if err != nil { - t.Fatal(err) - } - - fmt.Printf("float32: %f\n", num) - - x := float64(num) - - fmt.Printf("float64: %f\n", x*4) - fmt.Printf("int64: %d\n", int64(x)+10) - - mid := make([]byte, 4) - - err = PutFloat32(mid, num, HL) - if err != nil { - t.Fatal(err) - } - - fmt.Printf("%d\n", mid) -} - -func Test6bDateTime(t *testing.T) { - // - now := time.Now() - - now = now.In(time.UTC) - - w := bytes.NewBuffer(nil) - - Write6bDateTime(w, now) - - arr := w.Bytes() - - fmt.Printf("%s: %v, %d\n", now, arr, now.Unix()) - - r := bytes.NewBuffer(arr) - - tm, _ := Read6bDateTime(r) - - fmt.Printf("%s: %d\n", tm, tm.Unix()) -} - func TestSplitFloat(t *testing.T) { f := 650179.6985999999 // округляет вниз .6985 total := 8.2291999999 // округляет вверх 8.2292 @@ -264,35 +68,6 @@ func TestBitOps(t *testing.T) { fmt.Printf("%08b\n", SetBit(UnsetBit(b, bitNo), bitNo)) } -func TestDecodeFloat(t *testing.T) { - var buf = []byte{0xCE, 0x6E, 0x6B, 0x28} - - f1, err := GetFloat32(buf, LH) - if err != nil { - panic(err) - } - - f2, err := GetFloat32(buf, HL) - if err != nil { - panic(err) - } - - fmt.Printf("LH: %v\nHL: %v\nBIN: %08b\n\n", f1, f2, buf) - - n, err := strconv.ParseFloat("-1e9", 32) - if err != nil { - panic(err) - } - - f := float32(n) - - var arr = []byte{0, 0, 0, 0} - - PutFloat32(arr, f, HL) - - fmt.Printf("%v\nBIN: %08b\n", f, arr) -} - // Тесты массивов (для написания СУБД). Когда в байтовом виде записан массив из N элементов, // фиксированного размера (например 4-байтовый uint32 или 2-байтовый uint16). Из массива // нужно удалять элементы по индексу, либо в массив вставлять по индексу (чтобы другие @@ -582,139 +357,3 @@ Result: //fmt.Printf("idx: %d, found: %t\n", idx, found) } - -func TestFloatToUint(t *testing.T) { - //f = -} - -func TestIntToUint(t *testing.T) { - var i int64 = 20 //-math.MaxInt64 - 1 - - u := Int64AsUint64(i) - - fmt.Printf("%v\n", u) - - x := Uint64AsInt64(u) - - fmt.Printf("%v\n", x) -} - -var bytesOrders = []ByteOrder{LH, HL} - -func TestInt24(t *testing.T) { - var nums = []int32{-1, 0, 1, -4915195, 4915195} - - for _, num := range nums { - for _, byteOrder := range bytesOrders { - buf := bytes.NewBuffer(nil) - - err := WriteInt24(buf, num, byteOrder) - if err != nil { - t.Fatalf("%s; num=%d; byteOrder=%s\n", err, num, byteOrder) - } - - unpacked, err := ReadInt24(buf, byteOrder) - if err != nil { - t.Fatal(err) - } - - if unpacked != num { - t.Fatalf("num %d != unpacked %d (byteOrder=%s)\n", num, unpacked, byteOrder) - } - } - } -} - -func TestInt48(t *testing.T) { - var nums = []int64{-1, 0, 1, -4915195, 4915195} - - for _, num := range nums { - for _, byteOrder := range bytesOrders { - buf := bytes.NewBuffer(nil) - - err := WriteInt48(buf, num, byteOrder) - if err != nil { - t.Fatalf("%s; num=%d; byteOrder=%s\n", err, num, byteOrder) - } - - unpacked, err := ReadInt48(buf, byteOrder) - if err != nil { - t.Fatal(err) - } - - if unpacked != num { - t.Fatalf("num %d != unpacked %d (byteOrder=%s)\n", num, unpacked, byteOrder) - } - } - } -} - -func TestInt32(t *testing.T) { - buf := bytes.NewBuffer(nil) - - byteOrder := HL - - //var origin int32 = -2147483648 - //var origin int32 = math.MaxInt32 - var origin int32 = 12141132 - - err := WriteInt32(buf, origin, byteOrder) - if err != nil { - t.Fatal(err) - } - - fmt.Printf("%08b\n", buf.Bytes()) - - num, err := ReadInt32(buf, byteOrder) - if err != nil { - t.Fatal(err) - } - - fmt.Println(num) -} - -func TestVarSize(t *testing.T) { - var ( - buf = bytes.NewBuffer(nil) - - nums = []int{ - 0, - 1, - 127, // 7 - 16383, // 14 - 2097151, // 21 - 268435455, // 28 - 34359738367, // 35 - 4398046511103, // 42 - 562949953421311, // 49 - 72057594037927935, // 56 - 9223372036854775807, // 63 - } - ) - - for _, num := range nums { - WriteVarSize(buf, num) - - decoded, err := ReadVarSize(buf) - if err != nil { - t.Fatal(err) - } - - if decoded != num { - t.Fatalf("num %d decoded as %d\n", num, decoded) - } - buf.Reset() - } -} - -// func TestSetUnsetFlag(t *testing.T) { -// var ( -// flag byte = 2 -// flags byte = flag -// ) - -// flags &= ^flag - -// fmt.Printf("%b\n", ^flag) -// fmt.Printf("%b\n", UnsetFlag(flags, flag)) -// }