first commit
This commit is contained in:
198
arr.go
Normal file
198
arr.go
Normal file
@@ -0,0 +1,198 @@
|
||||
package bin
|
||||
|
||||
func DeleteArrElem(arr []byte, qty int, elemSize int, idx int) {
|
||||
dstIdx := elemSize * idx
|
||||
srcIdx := dstIdx + elemSize
|
||||
|
||||
end := qty * elemSize
|
||||
|
||||
for ; srcIdx < end; srcIdx++ {
|
||||
arr[dstIdx] = arr[srcIdx]
|
||||
dstIdx++
|
||||
}
|
||||
|
||||
for i := elemSize * (qty - 1); i < end; i++ {
|
||||
arr[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func InsertArrElem(arr []byte, qty int, elem []byte, idx int) {
|
||||
elemSize := len(elem)
|
||||
|
||||
srcIdx := qty*elemSize - 1 // last byte
|
||||
dstIdx := srcIdx + elemSize
|
||||
|
||||
end := elemSize * idx
|
||||
|
||||
for ; srcIdx >= end; srcIdx-- {
|
||||
arr[dstIdx] = arr[srcIdx]
|
||||
dstIdx--
|
||||
}
|
||||
|
||||
// Вставляем элемент
|
||||
for _, b := range elem {
|
||||
arr[end] = b
|
||||
end++
|
||||
}
|
||||
}
|
||||
|
||||
// Для массивов, которые начинаются с конца arr и движутся к началу
|
||||
func DeleteReverseArrElem(arr []byte, qty int, elemSize int, idx int) {
|
||||
dstIdx := len(arr) - idx*elemSize - 1
|
||||
srcIdx := dstIdx - elemSize
|
||||
|
||||
end := len(arr) - qty*elemSize
|
||||
|
||||
for ; srcIdx >= end; srcIdx-- {
|
||||
arr[dstIdx] = arr[srcIdx]
|
||||
dstIdx--
|
||||
}
|
||||
|
||||
for i := end; i < end+elemSize; i++ {
|
||||
arr[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// qty = 2
|
||||
// 0 0 3 3 1 1
|
||||
// 3 3 3 3 1 1
|
||||
func InsertReverseArrElem(arr []byte, qty int, elem []byte, idx int) {
|
||||
elemSize := len(elem)
|
||||
|
||||
srcIdx := len(arr) - qty*elemSize
|
||||
dstIdx := srcIdx - elemSize
|
||||
|
||||
end := len(arr) - elemSize*idx
|
||||
|
||||
for ; srcIdx < end; srcIdx++ {
|
||||
arr[dstIdx] = arr[srcIdx]
|
||||
dstIdx++
|
||||
}
|
||||
|
||||
// Вставляем элемент
|
||||
i := end - elemSize
|
||||
for _, b := range elem {
|
||||
arr[i] = b
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// Предполагается что значения отсортированы ASC
|
||||
func FindArrElem(arr []byte, qty int, elem []byte, byteOrder ByteOrder) (elemIdx int, isFound bool) {
|
||||
if qty == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Границы (индексы элементов массива)
|
||||
a := 0
|
||||
b := qty - 1
|
||||
|
||||
for {
|
||||
elemIdx = (b-a)/2 + a
|
||||
|
||||
code := compareToArrElem(arr, elem, elemIdx, byteOrder)
|
||||
|
||||
if code == 1 {
|
||||
a = elemIdx + 1
|
||||
if a > b {
|
||||
return elemIdx + 1, false
|
||||
}
|
||||
} else if code == -1 {
|
||||
b = elemIdx - 1
|
||||
if b < a {
|
||||
return elemIdx, false
|
||||
}
|
||||
} else {
|
||||
return elemIdx, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -1, меньше
|
||||
// 1, больше
|
||||
// 0, равны
|
||||
func compareToArrElem(arr []byte, elem []byte, elemIdx int, byteOrder ByteOrder) int {
|
||||
if byteOrder == HL {
|
||||
// индекс первого байта
|
||||
idx := elemIdx * len(elem)
|
||||
|
||||
for _, b := range elem {
|
||||
if b > arr[idx] {
|
||||
return 1
|
||||
} else if b < arr[idx] {
|
||||
return -1
|
||||
}
|
||||
idx++
|
||||
}
|
||||
} else {
|
||||
// индекс последнего байта
|
||||
idx := (elemIdx+1)*len(elem) - 1
|
||||
|
||||
for bIdx := len(elem) - 1; bIdx >= 0; bIdx-- {
|
||||
b := elem[bIdx]
|
||||
if b > arr[idx] {
|
||||
return 1
|
||||
} else if b < arr[idx] {
|
||||
return -1
|
||||
}
|
||||
idx--
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// func find(arr []int, num int) (int, bool) {
|
||||
// var a, b, i int
|
||||
// b = len(arr) - 1
|
||||
// for {
|
||||
// i = (b-a)/2 + a
|
||||
// if num > arr[i] {
|
||||
// a = i + 1
|
||||
// if a > b {
|
||||
// return i + 1, false
|
||||
// }
|
||||
// } else if num < arr[i] {
|
||||
// b = i - 1
|
||||
// if b < a {
|
||||
// return i, false
|
||||
// }
|
||||
// } else {
|
||||
// return i, true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
type KeyComparator interface {
|
||||
CompareTo(int) int
|
||||
}
|
||||
|
||||
// Предполагается что значения отсортированы ASC
|
||||
func BinarySearch(qty int, keyComparator KeyComparator) (elemIdx int, isFound bool) {
|
||||
if qty == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Границы (индексы элементов массива)
|
||||
a := 0
|
||||
b := qty - 1
|
||||
|
||||
for {
|
||||
elemIdx = (b-a)/2 + a
|
||||
|
||||
code := keyComparator.CompareTo(elemIdx)
|
||||
|
||||
if code == 1 {
|
||||
a = elemIdx + 1
|
||||
if a > b {
|
||||
return elemIdx + 1, false
|
||||
}
|
||||
} else if code == -1 {
|
||||
b = elemIdx - 1
|
||||
if b < a {
|
||||
return elemIdx, false
|
||||
}
|
||||
} else {
|
||||
return elemIdx, true
|
||||
}
|
||||
}
|
||||
}
|
||||
108
bin.sgo
Executable file
108
bin.sgo
Executable file
@@ -0,0 +1,108 @@
|
||||
package bin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func PutVarInt32(w io.Writer, num int) (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 PutVarUint(arr []byte, num uint64) int {
|
||||
for i := 0; i < 8; i++ {
|
||||
arr[i] = byte(num & 127)
|
||||
num >>= 7
|
||||
if num == 0 {
|
||||
arr[i] |= 128
|
||||
return i + 1
|
||||
}
|
||||
}
|
||||
// в последнем 9м байте все биты значащие
|
||||
arr[8] = byte(num)
|
||||
return 9
|
||||
}
|
||||
|
||||
func VarUint(src io.ByteReader) (num uint64, err error) {
|
||||
var (
|
||||
b byte
|
||||
off uint
|
||||
)
|
||||
for ; off < 56; off += 7 {
|
||||
b, err = src.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if b < 128 {
|
||||
num |= uint64(b) << off
|
||||
} else {
|
||||
num |= uint64(b&127) << off
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
b, err = src.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// в последнем 9м байте все биты значащие
|
||||
num |= uint64(b) << 56
|
||||
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
|
||||
}
|
||||
*/
|
||||
663
bin_test.go
Executable file
663
bin_test.go
Executable file
@@ -0,0 +1,663 @@
|
||||
package bin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"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
|
||||
|
||||
n := SplitFloat(f, 4)
|
||||
x := SplitFloat(total, 4)
|
||||
|
||||
fmt.Printf("int: %d, frac: %d\n", n.Int, n.Frac)
|
||||
fmt.Printf("total int: %d, frac: %d\n", x.Int, x.Frac)
|
||||
}
|
||||
|
||||
func TestSplitFloat2(t *testing.T) {
|
||||
//prev := 65032252.8724999875 // округляет вниз .6985
|
||||
//total := 9.2449999973 // округляет вверх 8.2292
|
||||
|
||||
fracDigits := 4
|
||||
|
||||
floatPrev := 65000005.499980002
|
||||
|
||||
floatTotal := 3.5000800019
|
||||
|
||||
prev := SplitFloat(floatPrev, fracDigits)
|
||||
total := SplitFloat(floatTotal, fracDigits)
|
||||
|
||||
fmt.Printf("prev: i=%d, f=%d\n", prev.Int, prev.Frac)
|
||||
fmt.Printf("total i=%d, f=%d\n", total.Int, total.Frac)
|
||||
|
||||
value := SplitFloat(floatPrev+floatTotal, fracDigits)
|
||||
|
||||
fmt.Printf("real i=%d, f=%d\n", value.Int, value.Frac)
|
||||
|
||||
calcInt := prev.Int + total.Int
|
||||
calcFrac := prev.Frac + total.Frac
|
||||
|
||||
if calcFrac >= 10000 {
|
||||
calcFrac -= 10000
|
||||
calcInt += 1
|
||||
}
|
||||
|
||||
fmt.Printf("calc i=%d, f=%d\n", calcInt, calcFrac)
|
||||
|
||||
fmt.Printf("\n%.9f\n", 10000000.999999999)
|
||||
|
||||
}
|
||||
|
||||
func TestBitOps(t *testing.T) {
|
||||
var b byte = 255
|
||||
|
||||
var bitNo byte = 7
|
||||
|
||||
fmt.Printf("%08b\n", UnsetBit(b, bitNo))
|
||||
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). Из массива
|
||||
// нужно удалять элементы по индексу, либо в массив вставлять по индексу (чтобы другие
|
||||
// элементы "подвинулись").
|
||||
|
||||
type _DeleteArrElemTestCase struct {
|
||||
Arr []byte
|
||||
Qty int
|
||||
ElemSize int
|
||||
Idx int
|
||||
Result []byte
|
||||
}
|
||||
|
||||
type _InsertArrElemTestCase struct {
|
||||
Arr []byte
|
||||
Qty int
|
||||
Elem []byte
|
||||
Idx int
|
||||
Result []byte
|
||||
}
|
||||
|
||||
func TestDeleteArrElem(t *testing.T) {
|
||||
originArr := []byte{1, 1, 2, 2, 3, 3, 255, 0, 0, 0}
|
||||
|
||||
testCases := []_DeleteArrElemTestCase{
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 0,
|
||||
Result: []byte{2, 2, 3, 3, 0, 0, 255, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 1,
|
||||
Result: []byte{1, 1, 3, 3, 0, 0, 255, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 2,
|
||||
Result: []byte{1, 1, 2, 2, 0, 0, 255, 0, 0, 0},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
arrcopy := make([]byte, len(testCase.Arr))
|
||||
|
||||
copy(arrcopy, testCase.Arr)
|
||||
|
||||
DeleteArrElem(arrcopy, testCase.Qty, testCase.ElemSize, testCase.Idx)
|
||||
|
||||
if !bytes.Equal(arrcopy, testCase.Result) {
|
||||
t.Fatalf(`
|
||||
Source: %v
|
||||
Estimate: %v
|
||||
Real: %v`,
|
||||
testCase.Arr, testCase.Result, arrcopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertArrElem(t *testing.T) {
|
||||
originArr := []byte{1, 1, 2, 2, 0, 0, 255, 0}
|
||||
elem := []byte{7, 7}
|
||||
|
||||
testCases := []_InsertArrElemTestCase{
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 0,
|
||||
Result: []byte{7, 7, 1, 1, 2, 2, 255, 0},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 1,
|
||||
Result: []byte{1, 1, 7, 7, 2, 2, 255, 0},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 2,
|
||||
Result: []byte{1, 1, 2, 2, 7, 7, 255, 0},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
arrcopy := make([]byte, len(testCase.Arr))
|
||||
|
||||
copy(arrcopy, testCase.Arr)
|
||||
|
||||
InsertArrElem(arrcopy, testCase.Qty, testCase.Elem, testCase.Idx)
|
||||
|
||||
if !bytes.Equal(arrcopy, testCase.Result) {
|
||||
t.Fatalf(`
|
||||
Source: %v
|
||||
Estimate: %v
|
||||
Real: %v`,
|
||||
testCase.Arr, testCase.Result, arrcopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteReverseArrElem(t *testing.T) {
|
||||
originArr := []byte{0, 0, 255, 3, 3, 2, 2, 1, 1}
|
||||
|
||||
testCases := []_DeleteArrElemTestCase{
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 0,
|
||||
Result: []byte{0, 0, 255, 0, 0, 3, 3, 2, 2},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 1,
|
||||
Result: []byte{0, 0, 255, 0, 0, 3, 3, 1, 1},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 3,
|
||||
ElemSize: 2,
|
||||
Idx: 2,
|
||||
Result: []byte{0, 0, 255, 0, 0, 2, 2, 1, 1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
arrcopy := make([]byte, len(testCase.Arr))
|
||||
|
||||
copy(arrcopy, testCase.Arr)
|
||||
|
||||
DeleteReverseArrElem(arrcopy, testCase.Qty, testCase.ElemSize, testCase.Idx)
|
||||
|
||||
if !bytes.Equal(arrcopy, testCase.Result) {
|
||||
t.Fatalf(`
|
||||
Source: %v
|
||||
Estimate: %v
|
||||
Real: %v`,
|
||||
testCase.Arr, testCase.Result, arrcopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertReverseArrElem(t *testing.T) {
|
||||
originArr := []byte{0, 255, 0, 0, 2, 2, 1, 1}
|
||||
elem := []byte{7, 7}
|
||||
|
||||
testCases := []_InsertArrElemTestCase{
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 0,
|
||||
Result: []byte{0, 255, 2, 2, 1, 1, 7, 7},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 1,
|
||||
Result: []byte{0, 255, 2, 2, 7, 7, 1, 1},
|
||||
},
|
||||
{
|
||||
Arr: originArr,
|
||||
Qty: 2,
|
||||
Elem: elem,
|
||||
Idx: 2,
|
||||
Result: []byte{0, 255, 7, 7, 2, 2, 1, 1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
arrcopy := make([]byte, len(testCase.Arr))
|
||||
|
||||
copy(arrcopy, testCase.Arr)
|
||||
|
||||
InsertReverseArrElem(arrcopy, testCase.Qty, testCase.Elem, testCase.Idx)
|
||||
|
||||
if !bytes.Equal(arrcopy, testCase.Result) {
|
||||
t.Fatalf(`
|
||||
Source: %v
|
||||
Estimate: %v
|
||||
Real: %v`,
|
||||
testCase.Arr, testCase.Result, arrcopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareToArrElem(t *testing.T) {
|
||||
arr := []byte{1, 2, 3, 4}
|
||||
elem := []byte{5, 2}
|
||||
|
||||
code := compareToArrElem(arr, elem, 1, HL)
|
||||
|
||||
fmt.Printf("code: %d\n", code)
|
||||
}
|
||||
|
||||
type _FindArrElemTestCase struct {
|
||||
Elem []byte // элемент, который будем искать в массиве
|
||||
// Результат поиска - индекс и флаг
|
||||
Idx int
|
||||
Found bool
|
||||
}
|
||||
|
||||
func TestFindArrElem(t *testing.T) {
|
||||
arr := []byte{2, 2, 5, 5, 7, 7, 0, 0}
|
||||
|
||||
testCases := []_FindArrElemTestCase{
|
||||
{
|
||||
Elem: []byte{1, 1},
|
||||
Idx: 0,
|
||||
Found: false,
|
||||
},
|
||||
{
|
||||
Elem: []byte{2, 2},
|
||||
Idx: 0,
|
||||
Found: true,
|
||||
},
|
||||
{
|
||||
Elem: []byte{3, 3},
|
||||
Idx: 1,
|
||||
Found: false,
|
||||
},
|
||||
{
|
||||
Elem: []byte{5, 5},
|
||||
Idx: 1,
|
||||
Found: true,
|
||||
},
|
||||
{
|
||||
Elem: []byte{6, 6},
|
||||
Idx: 2,
|
||||
Found: false,
|
||||
},
|
||||
{
|
||||
Elem: []byte{7, 7},
|
||||
Idx: 2,
|
||||
Found: true,
|
||||
},
|
||||
{
|
||||
Elem: []byte{8, 8},
|
||||
Idx: 3,
|
||||
Found: false,
|
||||
},
|
||||
}
|
||||
|
||||
errorPattern := `Case:
|
||||
byteOrder: %s
|
||||
elem: %v
|
||||
idx: %d
|
||||
found: %t
|
||||
|
||||
Result:
|
||||
idx: %d
|
||||
found: %t
|
||||
`
|
||||
|
||||
var (
|
||||
idx int
|
||||
found bool
|
||||
)
|
||||
|
||||
for _, testCase := range testCases {
|
||||
idx, found = FindArrElem(arr, 3, testCase.Elem, LH)
|
||||
if idx != testCase.Idx || found != testCase.Found {
|
||||
t.Fatalf(errorPattern,
|
||||
LH, testCase.Elem, testCase.Idx, testCase.Found, idx, found)
|
||||
}
|
||||
|
||||
// Тоже самое, но с другим порядком байт
|
||||
idx, found = FindArrElem(arr, 3, testCase.Elem, HL)
|
||||
if idx != testCase.Idx || found != testCase.Found {
|
||||
t.Fatalf(errorPattern,
|
||||
HL, testCase.Elem, testCase.Idx, testCase.Found, idx, found)
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
err := WriteInt32(buf, ^math.MaxInt32, 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)
|
||||
}
|
||||
47
buffer.go
Normal file
47
buffer.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package bin
|
||||
|
||||
type Buffer struct {
|
||||
arr []byte
|
||||
}
|
||||
|
||||
func NewBuffer(arr []byte) *Buffer {
|
||||
s := new(Buffer)
|
||||
s.arr = arr
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Buffer) WriteByte(b byte) (err error) {
|
||||
s.arr = append(s.arr, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Buffer) Write(data []byte) (int, error) {
|
||||
s.arr = append(s.arr, data...)
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (s *Buffer) ByteAt(idx int) byte {
|
||||
return s.arr[idx]
|
||||
}
|
||||
|
||||
func (s *Buffer) WriteByteAt(b byte, idx int) {
|
||||
s.arr[idx] = b
|
||||
}
|
||||
|
||||
func (s *Buffer) Len() int {
|
||||
return len(s.arr)
|
||||
}
|
||||
|
||||
func (s *Buffer) Bytes() []byte {
|
||||
return s.arr[:]
|
||||
}
|
||||
|
||||
func (s *Buffer) CopyBytes() []byte {
|
||||
dst := make([]byte, len(s.arr))
|
||||
copy(dst, s.arr)
|
||||
return dst
|
||||
}
|
||||
|
||||
func (s *Buffer) Reset() {
|
||||
s.arr = s.arr[:0]
|
||||
}
|
||||
27
buffer_test.go
Normal file
27
buffer_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package bin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBuffer(t *testing.T) {
|
||||
arr := make([]byte, 0)
|
||||
|
||||
buf := NewBuffer(arr)
|
||||
buf.WriteByte(100)
|
||||
|
||||
fmt.Println(buf.ByteAt(0))
|
||||
|
||||
buf.Write([]byte{1, 2, 3})
|
||||
buf.WriteByteAt(200, 0)
|
||||
|
||||
fmt.Println(buf.ByteAt(0))
|
||||
|
||||
fmt.Println(buf.Bytes())
|
||||
|
||||
buf.Reset()
|
||||
|
||||
fmt.Println(buf.Bytes())
|
||||
fmt.Println(buf.Len())
|
||||
}
|
||||
Reference in New Issue
Block a user