From 102cd8748ed6fd31d24eaa82c6974242fb5a05fe Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Sat, 21 Jan 2017 23:22:38 +0800 Subject: [PATCH] fix write int --- feature_stream_int.go | 587 +++++++++++++++++++----------------------- jsoniter_int_test.go | 8 +- 2 files changed, 262 insertions(+), 333 deletions(-) diff --git a/feature_stream_int.go b/feature_stream_int.go index f15e531..bb7dbf7 100644 --- a/feature_stream_int.go +++ b/feature_stream_int.go @@ -3,6 +3,7 @@ package jsoniter var digits []uint8 var digitTens []uint8 var digitOnes []uint8 +var DIGITS []uint32 func init() { digits = []uint8{ @@ -37,390 +38,318 @@ func init() { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', } -} -func (stream *Stream) WriteUint8(val uint8) { - if stream.Available() < 3 { - stream.Flush() - } - charPos := stream.n - if val <= 9 { - charPos += 1; - } else { - if val <= 99 { - charPos += 2; - } else { - charPos += 3; - } - } - stream.n = charPos - var q uint8 - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break + 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 } } } -func (stream *Stream) WriteInt8(val int8) { +func writeFirstBuf(buf []byte, v uint32, n int) int { + start := v >> 24 + if start == 0 { + buf[n] = byte(v >> 16) + n++ + buf[n] = byte(v >> 8) + n++ + } else if start == 1 { + buf[n] = byte(v >> 8) + n++ + } + buf[n] = byte(v) + n++ + return n +} + +func writeBuf(buf []byte, v uint32, n int) { + buf[n] = byte(v >> 16) + buf[n + 1] = byte(v >> 8) + buf[n + 2] = byte(v) +} + +func (stream *Stream) WriteUint8(val uint8) { + if stream.Available() < 3 { + stream.Flush() + } + stream.n = writeFirstBuf(stream.buf, DIGITS[val], stream.n) +} + +func (stream *Stream) WriteInt8(nval int8) { if stream.Available() < 4 { stream.Flush() } - charPos := stream.n - if (val < 0) { - charPos += 1 - val = -val - stream.buf[stream.n] = '-' - } - if val <= 9 { - charPos += 1; + n := stream.n + var val uint8 + if (nval < 0) { + val = uint8(-nval) + stream.buf[n] = '-' + n++ } else { - if val <= 99 { - charPos += 2; - } else { - charPos += 3; - } - } - stream.n = charPos - var q int8 - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + val = uint8(nval) } + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) } func (stream *Stream) WriteUint16(val uint16) { if stream.Available() < 5 { stream.Flush() } - charPos := stream.n - if val <= 99 { - if val <= 9 { - charPos += 1; - } else { - charPos += 2; - } - } else { - if val <= 999 { - charPos += 3; - } else { - if val <= 9999 { - charPos += 4; - } else { - charPos += 5; - } - } - } - stream.n = charPos - var q uint16 - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], stream.n) + return } + r1 := val - q1 * 1000; + n := writeFirstBuf(stream.buf, DIGITS[q1], stream.n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return } -func (stream *Stream) WriteInt16(val int16) { +func (stream *Stream) WriteInt16(nval int16) { if stream.Available() < 6 { stream.Flush() } - charPos := stream.n - if (val < 0) { - charPos += 1 - val = -val - stream.buf[stream.n] = '-' - } - if val <= 99 { - if val <= 9 { - charPos += 1; - } else { - charPos += 2; - } + n := stream.n + var val uint16 + if (nval < 0) { + val = uint16(-nval) + stream.buf[n] = '-' + n++ } else { - if val <= 999 { - charPos += 3; - } else { - if val <= 9999 { - charPos += 4; - } else { - charPos += 5; - } - } + val = uint16(nval) } - stream.n = charPos - var q int16 - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) + return } + r1 := val - q1 * 1000; + n = writeFirstBuf(stream.buf, DIGITS[q1], n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return } func (stream *Stream) WriteUint32(val uint32) { if stream.Available() < 10 { stream.Flush() } - charPos := stream.n - if val <= 99999 { - if val <= 999 { - if val <= 9 { - charPos += 1; - } else { - if val <= 99 { - charPos += 2; - } else { - charPos += 3; - } - } - } else { - if val <= 9999 { - charPos += 4; - } else { - charPos += 5; - } - } + n := stream.n + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) + return + } + r1 := val - q1 * 1000; + q2 := q1 / 1000 + if q2 == 0 { + n := writeFirstBuf(stream.buf, DIGITS[q1], n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return + } + r2 := q1 - q2 * 1000 + q3 := q2 / 1000 + if q3 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q2], n) } else { - if val < 99999999 { - if val <= 999999 { - charPos += 6; - } else { - if val <= 9999999 { - charPos += 7; - } else { - charPos += 8; - } - } - } else { - if val <= 999999999 { - charPos += 9; - } else { - charPos += 10; - } - } - } - stream.n = charPos - - var q uint32 - for val >= 65536 { - q = val / 100; - // really: r = i - (q * 100); - r := val - ((q << 6) + (q << 5) + (q << 2)); - val = q; - charPos-- - stream.buf[charPos] = digitOnes[r]; - charPos-- - stream.buf[charPos] = digitTens[r]; - } - - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + r3 := q2 - q3 * 1000 + stream.buf[n] = byte(q3 + '0') + n++ + writeBuf(stream.buf, DIGITS[r3], n) + n += 3 } + writeBuf(stream.buf, DIGITS[r2], n) + writeBuf(stream.buf, DIGITS[r1], n + 3) + stream.n = n + 6 } -func (stream *Stream) WriteInt32(val int32) { +func (stream *Stream) WriteInt32(nval int32) { if stream.Available() < 11 { stream.Flush() } - charPos := stream.n - if (val < 0) { - charPos += 1 - val = -val - stream.buf[stream.n] = '-' - } - if val <= 99999 { - if val <= 999 { - if val <= 9 { - charPos += 1; - } else { - if val <= 99 { - charPos += 2; - } else { - charPos += 3; - } - } - } else { - if val <= 9999 { - charPos += 4; - } else { - charPos += 5; - } - } + n := stream.n + var val uint32 + if (nval < 0) { + val = uint32(-nval) + stream.buf[n] = '-' + n++ } else { - if val < 99999999 { - if val <= 999999 { - charPos += 6; - } else { - if val <= 9999999 { - charPos += 7; - } else { - charPos += 8; - } - } - } else { - if val <= 999999999 { - charPos += 9; - } else { - charPos += 10; - } - } + val = uint32(nval) } - stream.n = charPos - - var q int32 - for val >= 65536 { - q = val / 100; - // really: r = i - (q * 100); - r := val - ((q << 6) + (q << 5) + (q << 2)); - val = q; - charPos-- - stream.buf[charPos] = digitOnes[r]; - charPos-- - stream.buf[charPos] = digitTens[r]; + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) + return } - - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + r1 := val - q1 * 1000; + q2 := q1 / 1000 + if q2 == 0 { + n := writeFirstBuf(stream.buf, DIGITS[q1], n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return } + r2 := q1 - q2 * 1000 + q3 := q2 / 1000 + if q3 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q2], n) + } else { + r3 := q2 - q3 * 1000 + stream.buf[n] = byte(q3 + '0') + n++ + writeBuf(stream.buf, DIGITS[r3], n) + n += 3 + } + writeBuf(stream.buf, DIGITS[r2], n) + writeBuf(stream.buf, DIGITS[r1], n + 3) + stream.n = n + 6 } func (stream *Stream) WriteUint64(val uint64) { - if stream.Available() < 10 { + if stream.Available() < 20 { stream.Flush() } - charPos := stream.n - if val <= 99999 { - if val <= 999 { - if val <= 9 { - charPos += 1; - } else { - if val <= 99 { - charPos += 2; - } else { - charPos += 3; - } - } - } else { - if val <= 9999 { - charPos += 4; - } else { - charPos += 5; - } - } - } else if val < 9999999999 { - if val < 99999999 { - if val <= 999999 { - charPos += 6; - } else { - if val <= 9999999 { - charPos += 7; - } else { - charPos += 8; - } - } - } else { - if val <= 999999999 { - charPos += 9; - } else { - charPos += 10; - } - } - } else { - stream.writeUint64SlowPath(val) + n := stream.n + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) return } - stream.n = charPos - var q uint64 - for val >= 65536 { - q = val / 100; - // really: r = i - (q * 100); - r := val - ((q << 6) + (q << 5) + (q << 2)); - val = q; - charPos-- - stream.buf[charPos] = digitOnes[r]; - charPos-- - stream.buf[charPos] = digitTens[r]; + r1 := val - q1 * 1000; + q2 := q1 / 1000 + if q2 == 0 { + n := writeFirstBuf(stream.buf, DIGITS[q1], n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return } - - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - stream.buf[charPos] = digits[r] - val = q; - if val == 0 { - break - } + r2 := q1 - q2 * 1000 + q3 := q2 / 1000 + if q3 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q2], n) + writeBuf(stream.buf, DIGITS[r2], n) + writeBuf(stream.buf, DIGITS[r1], n + 3) + stream.n = n + 6 + return } + r3 := q2 - q3 * 1000 + q4 := q3 / 1000 + if q4 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q3], n) + writeBuf(stream.buf, DIGITS[r3], n) + writeBuf(stream.buf, DIGITS[r2], n + 3) + writeBuf(stream.buf, DIGITS[r1], n + 6) + stream.n = n + 9 + return + } + r4 := q3 - q4 * 1000 + q5 := q4 / 1000 + if q5 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q4], n) + writeBuf(stream.buf, DIGITS[r4], n) + writeBuf(stream.buf, DIGITS[r3], n + 3) + writeBuf(stream.buf, DIGITS[r2], n + 6) + writeBuf(stream.buf, DIGITS[r1], n + 9) + stream.n = n + 12 + return + } + r5 := q4 - q5 * 1000 + q6 := q5 / 1000 + if q6 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q5], n) + } else { + n = writeFirstBuf(stream.buf, DIGITS[q6], n) + r6 := q5 - q6 * 1000 + writeBuf(stream.buf, DIGITS[r6], n) + n += 3 + } + writeBuf(stream.buf, DIGITS[r5], n) + writeBuf(stream.buf, DIGITS[r4], n + 3) + writeBuf(stream.buf, DIGITS[r3], n + 6) + writeBuf(stream.buf, DIGITS[r2], n + 9) + writeBuf(stream.buf, DIGITS[r1], n + 12) + stream.n = n + 15 } -func (stream *Stream) WriteInt64(val int64) { - if (val < 0) { - val = -val - stream.writeByte('-') +func (stream *Stream) WriteInt64(nval int64) { + if stream.Available() < 20 { + stream.Flush() } - stream.WriteUint64(uint64(val)) -} - -func (stream *Stream) writeUint64SlowPath(val uint64) { - var temp [20]byte - charPos := 20 - var q uint64 - for val >= 65536 { - q = val / 100; - // really: r = i - (q * 100); - r := val - ((q << 6) + (q << 5) + (q << 2)); - val = q; - charPos-- - temp[charPos] = digitOnes[r]; - charPos-- - temp[charPos] = digitTens[r]; + n := stream.n + var val uint64 + if (nval < 0) { + val = uint64(-nval) + stream.buf[n] = '-' + n++ + } else { + val = uint64(nval) } - - for { - q = val / 10 - r := val - ((q << 3) + (q << 1)) // r = i-(q*10) ... - charPos-- - temp[charPos] = digits[r] - val = q; - if val == 0 { - break - } + q1 := val / 1000 + if q1 == 0 { + stream.n = writeFirstBuf(stream.buf, DIGITS[val], n) + return } - stream.Write(temp[charPos:]) + r1 := val - q1 * 1000; + q2 := q1 / 1000 + if q2 == 0 { + n := writeFirstBuf(stream.buf, DIGITS[q1], n) + writeBuf(stream.buf, DIGITS[r1], n) + stream.n = n + 3 + return + } + r2 := q1 - q2 * 1000 + q3 := q2 / 1000 + if q3 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q2], n) + writeBuf(stream.buf, DIGITS[r2], n) + writeBuf(stream.buf, DIGITS[r1], n + 3) + stream.n = n + 6 + return + } + r3 := q2 - q3 * 1000 + q4 := q3 / 1000 + if q4 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q3], n) + writeBuf(stream.buf, DIGITS[r3], n) + writeBuf(stream.buf, DIGITS[r2], n + 3) + writeBuf(stream.buf, DIGITS[r1], n + 6) + stream.n = n + 9 + return + } + r4 := q3 - q4 * 1000 + q5 := q4 / 1000 + if q5 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q4], n) + writeBuf(stream.buf, DIGITS[r4], n) + writeBuf(stream.buf, DIGITS[r3], n + 3) + writeBuf(stream.buf, DIGITS[r2], n + 6) + writeBuf(stream.buf, DIGITS[r1], n + 9) + stream.n = n + 12 + return + } + r5 := q4 - q5 * 1000 + q6 := q5 / 1000 + if q6 == 0 { + n = writeFirstBuf(stream.buf, DIGITS[q5], n) + } else { + stream.buf[n] = byte(q6 + '0') + n++ + r6 := q5 - q6 * 1000 + writeBuf(stream.buf, DIGITS[r6], n) + n += 3 + } + writeBuf(stream.buf, DIGITS[r5], n) + writeBuf(stream.buf, DIGITS[r4], n + 3) + writeBuf(stream.buf, DIGITS[r3], n + 6) + writeBuf(stream.buf, DIGITS[r2], n + 9) + writeBuf(stream.buf, DIGITS[r1], n + 12) + stream.n = n + 15 } func (stream *Stream) WriteInt(val int) { diff --git a/jsoniter_int_test.go b/jsoniter_int_test.go index fa36e43..b1114e5 100644 --- a/jsoniter_int_test.go +++ b/jsoniter_int_test.go @@ -132,7 +132,7 @@ func Test_write_uint8(t *testing.T) { } func Test_write_int8(t *testing.T) { - vals := []int8{0, 1, -1, 99, 0x7f, -0x7f} + vals := []int8{0, 1, -1, 99, 0x7f, -0x80} for _, val := range vals { t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { should := require.New(t) @@ -196,7 +196,7 @@ func Test_write_uint16(t *testing.T) { } func Test_write_int16(t *testing.T) { - vals := []int16{0, 1, 11, 111, 255, 0xfff, 0x7fff, -0x7fff} + vals := []int16{0, 1, 11, 111, 255, 0xfff, 0x7fff, -0x8000} for _, val := range vals { t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { should := require.New(t) @@ -260,7 +260,7 @@ func Test_write_uint32(t *testing.T) { } func Test_write_int32(t *testing.T) { - vals := []int32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0x7fffffff, -0x7fffffff} + vals := []int32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0x7fffffff, -0x80000000} for _, val := range vals { t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { should := require.New(t) @@ -328,7 +328,7 @@ func Test_write_uint64(t *testing.T) { func Test_write_int64(t *testing.T) { vals := []int64{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff, 0xfffffffff, 0xffffffffff, 0xfffffffffff, 0xffffffffffff, 0xfffffffffffff, 0xffffffffffffff, - 0xfffffffffffffff, 0x7fffffffffffffff, -0x7fffffffffffffff} + 0xfffffffffffffff, 0x7fffffffffffffff, -0x8000000000000000} for _, val := range vals { t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { should := require.New(t)