544 lines
12 KiB
Go
544 lines
12 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
"strconv"
|
|
)
|
|
|
|
var digits []uint32
|
|
var intDigits []int8
|
|
|
|
const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1
|
|
const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1
|
|
const maxFloat64 = 1<<53 - 1
|
|
|
|
func init() {
|
|
digits = make([]uint32, 1000)
|
|
for i := uint32(0); i < 1000; i++ {
|
|
digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0'
|
|
if i < 10 {
|
|
digits[i] += 2 << 24
|
|
} else if i < 100 {
|
|
digits[i] += 1 << 24
|
|
}
|
|
}
|
|
|
|
intDigits = make([]int8, 256)
|
|
for i := 0; i < len(intDigits); i++ {
|
|
intDigits[i] = invalidCharForNumber
|
|
}
|
|
for i := int8('0'); i <= int8('9'); i++ {
|
|
intDigits[i] = i - int8('0')
|
|
}
|
|
}
|
|
|
|
//Read Int For String--------------------------------------------------------------------------------------------------------------------------------
|
|
func ReadInt8ForString(buf []byte) (ret int8, n int, err error) {
|
|
var (
|
|
val uint32
|
|
)
|
|
c := buf[0]
|
|
if c == '-' {
|
|
val, n, err = ReadUint32ForString(buf[1:])
|
|
if val > math.MaxInt8+1 {
|
|
err = errors.New("ReadInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = -int8(val)
|
|
return
|
|
}
|
|
val, n, err = ReadUint32ForString(buf)
|
|
if val > math.MaxInt8 {
|
|
err = errors.New("ReadInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = int8(val)
|
|
return
|
|
}
|
|
|
|
func ReadInt16ForString(buf []byte) (ret int16, n int, err error) {
|
|
var (
|
|
val uint32
|
|
)
|
|
c := buf[0]
|
|
if c == '-' {
|
|
val, n, err = ReadUint32ForString(buf[1:])
|
|
if val > math.MaxInt16+1 {
|
|
err = errors.New("ReadInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = -int16(val)
|
|
return
|
|
}
|
|
val, n, err = ReadUint32ForString(buf)
|
|
if val > math.MaxInt16 {
|
|
err = errors.New("ReadInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = int16(val)
|
|
return
|
|
}
|
|
|
|
func ReadInt32ForString(buf []byte) (ret int32, n int, err error) {
|
|
var (
|
|
val uint32
|
|
)
|
|
c := buf[0]
|
|
if c == '-' {
|
|
val, n, err = ReadUint32ForString(buf[1:])
|
|
if val > math.MaxInt32+1 {
|
|
err = errors.New("ReadInt32ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = -int32(val)
|
|
return
|
|
}
|
|
val, n, err = ReadUint32ForString(buf)
|
|
if val > math.MaxInt32 {
|
|
err = errors.New("ReadInt32ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = int32(val)
|
|
return
|
|
}
|
|
|
|
func ReadInt64ForString(buf []byte) (ret int64, n int, err error) {
|
|
var (
|
|
val uint64
|
|
)
|
|
c := buf[0]
|
|
if c == '-' {
|
|
val, n, err = ReadUint64ForString(buf[1:])
|
|
if val > math.MaxInt64+1 {
|
|
err = errors.New("ReadInt64ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = -int64(val)
|
|
return
|
|
}
|
|
val, n, err = ReadUint64ForString(buf)
|
|
if val > math.MaxInt64 {
|
|
err = errors.New("ReadInt64ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = int64(val)
|
|
return
|
|
}
|
|
|
|
func ReadUint8ForString(buf []byte) (ret uint8, n int, err error) {
|
|
var (
|
|
val uint32
|
|
)
|
|
val, n, err = ReadUint32ForString(buf)
|
|
if val > math.MaxUint8 {
|
|
err = errors.New("ReadUInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = uint8(val)
|
|
return
|
|
}
|
|
|
|
func ReadUint16ForString(buf []byte) (ret uint16, n int, err error) {
|
|
var (
|
|
val uint32
|
|
)
|
|
val, n, err = ReadUint32ForString(buf)
|
|
if val > math.MaxUint16 {
|
|
err = errors.New("ReadUInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
|
|
return
|
|
}
|
|
ret = uint16(val)
|
|
return
|
|
}
|
|
|
|
func ReadUint32ForString(buf []byte) (ret uint32, n int, err error) {
|
|
ind := intDigits[buf[0]]
|
|
if ind == 0 {
|
|
err = assertInteger(buf[1:])
|
|
return
|
|
}
|
|
if ind == invalidCharForNumber {
|
|
err = errors.New("ReadUint32ForString unexpected character: " + string([]byte{byte(ind)}))
|
|
return
|
|
}
|
|
ret = uint32(ind)
|
|
if len(buf) > 10 {
|
|
i := 0
|
|
ind2 := intDigits[buf[i]]
|
|
if ind2 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
i++
|
|
ind3 := intDigits[buf[i]]
|
|
if ind3 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*10 + uint32(ind2)
|
|
return
|
|
}
|
|
i++
|
|
ind4 := intDigits[buf[i]]
|
|
if ind4 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*100 + uint32(ind2)*10 + uint32(ind3)
|
|
return
|
|
}
|
|
i++
|
|
ind5 := intDigits[buf[i]]
|
|
if ind5 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4)
|
|
return
|
|
}
|
|
i++
|
|
ind6 := intDigits[buf[i]]
|
|
if ind6 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5)
|
|
return
|
|
}
|
|
i++
|
|
ind7 := intDigits[buf[i]]
|
|
if ind7 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6)
|
|
return
|
|
}
|
|
i++
|
|
ind8 := intDigits[buf[i]]
|
|
if ind8 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7)
|
|
return
|
|
}
|
|
i++
|
|
ind9 := intDigits[buf[i]]
|
|
ret = ret*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8)
|
|
n = i
|
|
if ind9 == invalidCharForNumber {
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
}
|
|
for i := 1; i < len(buf); i++ {
|
|
ind = intDigits[buf[i]]
|
|
if ind == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
if ret > uint32SafeToMultiply10 {
|
|
value2 := (ret << 3) + (ret << 1) + uint32(ind)
|
|
if value2 < ret {
|
|
err = errors.New("ReadUint32ForString overflow")
|
|
return
|
|
}
|
|
ret = value2
|
|
continue
|
|
}
|
|
ret = (ret << 3) + (ret << 1) + uint32(ind)
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadUint64ForString(buf []byte) (ret uint64, n int, err error) {
|
|
ind := intDigits[buf[0]]
|
|
if ind == 0 {
|
|
err = assertInteger(buf[1:])
|
|
return
|
|
}
|
|
if ind == invalidCharForNumber {
|
|
err = errors.New("ReadUint64ForString unexpected character: " + string([]byte{byte(ind)}))
|
|
return
|
|
}
|
|
ret = uint64(ind)
|
|
if len(buf) > 10 {
|
|
i := 0
|
|
ind2 := intDigits[buf[i]]
|
|
if ind2 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
i++
|
|
ind3 := intDigits[buf[i]]
|
|
if ind3 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*10 + uint64(ind2)
|
|
return
|
|
}
|
|
i++
|
|
ind4 := intDigits[buf[i]]
|
|
if ind4 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*100 + uint64(ind2)*10 + uint64(ind3)
|
|
return
|
|
}
|
|
i++
|
|
ind5 := intDigits[buf[i]]
|
|
if ind5 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4)
|
|
return
|
|
}
|
|
i++
|
|
ind6 := intDigits[buf[i]]
|
|
if ind6 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5)
|
|
return
|
|
}
|
|
i++
|
|
ind7 := intDigits[buf[i]]
|
|
if ind7 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6)
|
|
return
|
|
}
|
|
i++
|
|
ind8 := intDigits[buf[i]]
|
|
if ind8 == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
ret = ret*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7)
|
|
return
|
|
}
|
|
i++
|
|
ind9 := intDigits[buf[i]]
|
|
ret = ret*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8)
|
|
n = i
|
|
if ind9 == invalidCharForNumber {
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
}
|
|
for i := 1; i < len(buf); i++ {
|
|
ind = intDigits[buf[i]]
|
|
if ind == invalidCharForNumber {
|
|
n = i
|
|
err = assertInteger(buf[i:])
|
|
return
|
|
}
|
|
if ret > uint64SafeToMultiple10 {
|
|
value2 := (ret << 3) + (ret << 1) + uint64(ind)
|
|
if value2 < ret {
|
|
err = errors.New("ReadUint64ForString overflow")
|
|
return
|
|
}
|
|
ret = value2
|
|
continue
|
|
}
|
|
ret = (ret << 3) + (ret << 1) + uint64(ind)
|
|
}
|
|
return
|
|
}
|
|
|
|
func assertInteger(buf []byte) (err error) {
|
|
if len(buf) > 0 && buf[0] == '.' {
|
|
err = errors.New("assertInteger can not decode float as int")
|
|
}
|
|
return
|
|
}
|
|
|
|
//Write Int To String--------------------------------------------------------------------------------------------------------------------------------
|
|
func WriteChar(buff *[]byte, c byte) {
|
|
*buff = append(*buff, c)
|
|
}
|
|
|
|
// WriteUint8 write uint8 to stream
|
|
func WriteUint8ToString(buf *[]byte, val uint8) {
|
|
*buf = writeFirstBuf(*buf, digits[val])
|
|
return
|
|
}
|
|
|
|
// WriteInt8 write int8 to stream
|
|
func WriteInt8ToString(buf *[]byte, nval int8) {
|
|
var val uint8
|
|
if nval < 0 {
|
|
val = uint8(-nval)
|
|
*buf = append(*buf, '-')
|
|
} else {
|
|
val = uint8(nval)
|
|
}
|
|
*buf = writeFirstBuf(*buf, digits[val])
|
|
return
|
|
}
|
|
|
|
// WriteUint16 write uint16 to stream
|
|
func WriteUint16ToString(buf *[]byte, val uint16) {
|
|
q1 := val / 1000
|
|
if q1 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[val])
|
|
return
|
|
}
|
|
r1 := val - q1*1000
|
|
*buf = writeFirstBuf(*buf, digits[q1])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
|
|
// WriteInt16 write int16 to stream
|
|
func WriteInt16ToString(buf *[]byte, nval int16) {
|
|
var val uint16
|
|
if nval < 0 {
|
|
val = uint16(-nval)
|
|
*buf = append(*buf, '-')
|
|
} else {
|
|
val = uint16(nval)
|
|
}
|
|
WriteUint16ToString(buf, val)
|
|
return
|
|
}
|
|
|
|
// WriteUint32 write uint32 to stream
|
|
func WriteUint32ToString(buf *[]byte, val uint32) {
|
|
q1 := val / 1000
|
|
if q1 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[val])
|
|
return
|
|
}
|
|
r1 := val - q1*1000
|
|
q2 := q1 / 1000
|
|
if q2 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q1])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
r2 := q1 - q2*1000
|
|
q3 := q2 / 1000
|
|
if q3 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q2])
|
|
} else {
|
|
r3 := q2 - q3*1000
|
|
*buf = append(*buf, byte(q3+'0'))
|
|
*buf = writeBuf(*buf, digits[r3])
|
|
}
|
|
*buf = writeBuf(*buf, digits[r2])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
|
|
// WriteInt32 write int32 to stream
|
|
func WriteInt32ToString(buf *[]byte, nval int32) {
|
|
var val uint32
|
|
if nval < 0 {
|
|
val = uint32(-nval)
|
|
*buf = append(*buf, '-')
|
|
} else {
|
|
val = uint32(nval)
|
|
}
|
|
WriteUint32ToString(buf, val)
|
|
return
|
|
}
|
|
|
|
// WriteUint64 write uint64 to stream
|
|
func WriteUint64ToString(buf *[]byte, val uint64) {
|
|
q1 := val / 1000
|
|
if q1 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[val])
|
|
return
|
|
}
|
|
r1 := val - q1*1000
|
|
q2 := q1 / 1000
|
|
if q2 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q1])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
r2 := q1 - q2*1000
|
|
q3 := q2 / 1000
|
|
if q3 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q2])
|
|
*buf = writeBuf(*buf, digits[r2])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
r3 := q2 - q3*1000
|
|
q4 := q3 / 1000
|
|
if q4 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q3])
|
|
*buf = writeBuf(*buf, digits[r3])
|
|
*buf = writeBuf(*buf, digits[r2])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
r4 := q3 - q4*1000
|
|
q5 := q4 / 1000
|
|
if q5 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q4])
|
|
*buf = writeBuf(*buf, digits[r4])
|
|
*buf = writeBuf(*buf, digits[r3])
|
|
*buf = writeBuf(*buf, digits[r2])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
r5 := q4 - q5*1000
|
|
q6 := q5 / 1000
|
|
if q6 == 0 {
|
|
*buf = writeFirstBuf(*buf, digits[q5])
|
|
} else {
|
|
*buf = writeFirstBuf(*buf, digits[q6])
|
|
r6 := q5 - q6*1000
|
|
*buf = writeBuf(*buf, digits[r6])
|
|
}
|
|
*buf = writeBuf(*buf, digits[r5])
|
|
*buf = writeBuf(*buf, digits[r4])
|
|
*buf = writeBuf(*buf, digits[r3])
|
|
*buf = writeBuf(*buf, digits[r2])
|
|
*buf = writeBuf(*buf, digits[r1])
|
|
return
|
|
}
|
|
|
|
// WriteInt64 write int64 to stream
|
|
func WriteInt64ToString(buf *[]byte, nval int64) {
|
|
var val uint64
|
|
if nval < 0 {
|
|
val = uint64(-nval)
|
|
*buf = append(*buf, '-')
|
|
} else {
|
|
val = uint64(nval)
|
|
}
|
|
WriteUint64ToString(buf, val)
|
|
return
|
|
}
|
|
|
|
// WriteInt write int to stream
|
|
func WriteIntToString(buf *[]byte, val int) {
|
|
WriteInt64ToString(buf, int64(val))
|
|
return
|
|
}
|
|
|
|
// WriteUint write uint to stream
|
|
func WriteUint(buf *[]byte, val uint) {
|
|
WriteUint64ToString(buf, uint64(val))
|
|
return
|
|
}
|
|
|
|
func writeFirstBuf(space []byte, v uint32) []byte {
|
|
start := v >> 24
|
|
if start == 0 {
|
|
space = append(space, byte(v>>16), byte(v>>8))
|
|
} else if start == 1 {
|
|
space = append(space, byte(v>>8))
|
|
}
|
|
space = append(space, byte(v))
|
|
return space
|
|
}
|
|
|
|
func writeBuf(buf []byte, v uint32) []byte {
|
|
return append(buf, byte(v>>16), byte(v>>8), byte(v))
|
|
}
|