mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
Compare commits
No commits in common. "dda5da9f64381a317c264c89adc65919f6a077d5" and "78c2ade91308a95abb9c22fdc7f11742e577b1ad" have entirely different histories.
dda5da9f64
...
78c2ade913
18 changed files with 180 additions and 959 deletions
21
README.md
21
README.md
|
|
@ -181,17 +181,16 @@ ret, err := Encode(v, EscapeHTML) // ret == `{"\u0026\u0026":{"X":"\u003c\u003e"
|
|||
### Compact Format
|
||||
Sonic encodes primitive objects (struct/map...) as compact-format JSON by default, except marshaling `json.RawMessage` or `json.Marshaler`: sonic ensures validating their output JSON but **DONOT** compacting them for performance concerns. We provide the option `encoder.CompactMarshaler` to add compacting process.
|
||||
|
||||
### Print Error
|
||||
If there invalid syntax in input JSON, sonic will return `decoder.SyntaxError`, which supports pretty-printing of error position
|
||||
### Print Syntax Error
|
||||
```go
|
||||
import "github.com/bytedance/sonic"
|
||||
import "github.com/bytedance/sonic/decoder"
|
||||
|
||||
var data interface{}
|
||||
err := sonic.UnmarshalString("[[[}]]", &data)
|
||||
err := sonic.Unmarshal("[[[}]]", &data)
|
||||
if err != nil {
|
||||
/*one line by default*/
|
||||
println(e.Error()) // "Syntax error at index 3: invalid char\n\n\t[[[}]]\n\t...^..\n"
|
||||
println(e.Error())) // "Syntax error at index 3: invalid char\n\n\t[[[}]]\n\t...^..\n"
|
||||
/*pretty print*/
|
||||
if e, ok := err.(decoder.SyntaxError); ok {
|
||||
/*Syntax error at index 3: invalid char
|
||||
|
|
@ -200,24 +199,10 @@ if err != nil {
|
|||
...^..
|
||||
*/
|
||||
print(e.Description())
|
||||
}else if me, ok := err.(decoder.MismatchTypeError); ok {
|
||||
print(e.Description()
|
||||
}
|
||||
}
|
||||
```
|
||||
If there a **mismatch-typed** value for a given key, sonic will report `decoder.MismatchTypeError` (if there are many, report the last one), but still skip wrong the value and keep decoding next JSON.
|
||||
```go
|
||||
import "github.com/bytedance/sonic"
|
||||
import "github.com/bytedance/sonic/decoder"
|
||||
|
||||
var data = struct{
|
||||
A int
|
||||
B int
|
||||
}{}
|
||||
err := UnmarshalString(`{"A":"1","B":1}`, &data)
|
||||
println(err.Error()) // Mismatch type int with value string "at index 5: mismatched type with value\n\n\t{\"A\":\"1\",\"B\":1}\n\t.....^.........\n"
|
||||
fmt.Printf("%+v", data) // {A:0 B:1}
|
||||
```
|
||||
### Ast.Node
|
||||
Sonic/ast.Node is a completely self-contained AST for JSON. It implements serialization and deserialization both and provides robust APIs for obtaining and modification of generic data.
|
||||
#### Get/Index
|
||||
|
|
|
|||
|
|
@ -695,14 +695,14 @@ func (self *Node) GetByPath(path ...interface{}) *Node {
|
|||
}
|
||||
var s = self
|
||||
for _, p := range path {
|
||||
switch p := p.(type) {
|
||||
switch p.(type) {
|
||||
case int:
|
||||
s = s.Index(p)
|
||||
s = s.Index(p.(int))
|
||||
if !s.Valid() {
|
||||
return s
|
||||
}
|
||||
case string:
|
||||
s = s.Get(p)
|
||||
s = s.Get(p.(string))
|
||||
if !s.Valid() {
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@ func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
|
|||
|
||||
var err types.ParsingError
|
||||
for _, p := range path {
|
||||
switch p := p.(type) {
|
||||
switch p.(type) {
|
||||
case int:
|
||||
if err = self.parser.searchIndex(p); err != 0 {
|
||||
if err = self.parser.searchIndex(p.(int)); err != 0 {
|
||||
return Node{}, self.parser.ExportError(err)
|
||||
}
|
||||
case string:
|
||||
if err = self.parser.searchKey(p); err != 0 {
|
||||
if err = self.parser.searchKey(p.(string)); err != 0 {
|
||||
return Node{}, self.parser.ExportError(err)
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
14
bench.py
14
bench.py
|
|
@ -19,7 +19,8 @@ import os
|
|||
import subprocess
|
||||
import argparse
|
||||
|
||||
gbench_prefix = "SONIC_NO_ASYNC_GC=1 go test -benchmem -run=none "
|
||||
repeat_time = 100
|
||||
gbench_prefix = "SONIC_NO_ASYNC_GC=1 go test -benchmem -run=none -count=%d "%(repeat_time)
|
||||
|
||||
def run(cmd):
|
||||
print(cmd)
|
||||
|
|
@ -86,8 +87,8 @@ def compare(args):
|
|||
run("%s %s ./... 2>&1 | tee %s" %(gbench_prefix, args, main))
|
||||
|
||||
# diff the result
|
||||
# benchstat = "go get golang.org/x/perf/cmd/benchstat && go install golang.org/x/perf/cmd/benchstat"
|
||||
run( "benchstat -sort=delta %s %s"%(main, target))
|
||||
benchstat = "go get golang.org/x/perf/cmd/benchstat && go install golang.org/x/perf/cmd/benchstat"
|
||||
run( "%s && benchstat -sort=delta %s %s"%(benchstat, main, target))
|
||||
run("git checkout -- .")
|
||||
|
||||
# restore branch
|
||||
|
|
@ -104,8 +105,6 @@ def main():
|
|||
help='Compare with the main benchmarking')
|
||||
argparser.add_argument('-t', '--times', dest='times', required=False,
|
||||
help='benchmark the times')
|
||||
argparser.add_argument('-r', '--repeat_times', dest='count', required=False,
|
||||
help='benchmark the count')
|
||||
args = argparser.parse_args()
|
||||
|
||||
if args.filter:
|
||||
|
|
@ -115,11 +114,6 @@ def main():
|
|||
|
||||
if args.times:
|
||||
gbench_args += " -benchtime=%s"%(args.times)
|
||||
|
||||
if args.count:
|
||||
gbench_args += " -count=%s"%(args.count)
|
||||
else:
|
||||
gbench_args += " -count=10"
|
||||
|
||||
if args.compare:
|
||||
target = compare(gbench_args)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
/*
|
||||
|
|
@ -35,13 +34,12 @@ import (
|
|||
`strings`
|
||||
`testing`
|
||||
`time`
|
||||
`unicode/utf8`
|
||||
`unsafe`
|
||||
`unicode/utf8`
|
||||
|
||||
`github.com/bytedance/sonic/decoder`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/assert`
|
||||
)
|
||||
|
||||
type T struct {
|
||||
|
|
@ -1118,7 +1116,6 @@ func TestMarshalEmbeds(t *testing.T) {
|
|||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
for i, tt := range unmarshalTests {
|
||||
t.Log(i, tt.in)
|
||||
if !json.Valid([]byte(tt.in)) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -1731,21 +1728,17 @@ func TestRefUnmarshal(t *testing.T) {
|
|||
func TestEmptyString(t *testing.T) {
|
||||
type T2 struct {
|
||||
Number1 int `json:",string"`
|
||||
Number2 string `json:",string"`
|
||||
Pass bool `json:",string"`
|
||||
Number2 int `json:",string"`
|
||||
}
|
||||
data := `{"Number1":"1", "Number2":"","Pass":"true"}`
|
||||
var t2, t3 T2
|
||||
t2.Number2 = "a"
|
||||
t3.Number2 = "a"
|
||||
data := `{"Number1":"1", "Number2":""}`
|
||||
var t2 T2
|
||||
err := Unmarshal([]byte(data), &t2)
|
||||
if err == nil {
|
||||
t.Fatal("Decode: did not return error")
|
||||
}
|
||||
println(err.Error())
|
||||
err2 := json.Unmarshal([]byte(data), &t3)
|
||||
assert.Equal(t, err == nil, err2 == nil)
|
||||
assert.Equal(t, t3, t2)
|
||||
if t2.Number1 != 1 {
|
||||
t.Fatal("Decode: did not set Number1")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a null for ,string is not replaced with the previous quoted string (issue 7046).
|
||||
|
|
@ -2012,6 +2005,7 @@ var decodeTypeErrorTests = []struct {
|
|||
dest interface{}
|
||||
src string
|
||||
}{
|
||||
{new(string), `{"user": "name"}`}, // issue 4628.
|
||||
{new(error), `{}`}, // issue 4222
|
||||
{new(error), `[]`},
|
||||
{new(error), `""`},
|
||||
|
|
@ -2031,28 +2025,6 @@ func TestUnmarshalTypeError(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var decodeMismatchErrorTests = []struct {
|
||||
dest interface{}
|
||||
src string
|
||||
}{
|
||||
{new(int), `{}`},
|
||||
{new(string), `{}`},
|
||||
{new(bool), `{}`},
|
||||
{new([]byte), `{}`},
|
||||
}
|
||||
|
||||
func TestMismatchTypeError(t *testing.T) {
|
||||
for _, item := range decodeMismatchErrorTests {
|
||||
err := Unmarshal([]byte(item.src), item.dest)
|
||||
if _, ok := err.(*decoder.MismatchTypeError); !ok {
|
||||
if _, ok = err.(decoder.SyntaxError); !ok {
|
||||
t.Errorf("expected mismatch error for Unmarshal(%q, type %T): got %T",
|
||||
item.src, item.dest, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalSyntaxTests = []string{
|
||||
"tru",
|
||||
"fals",
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ const (
|
|||
_FP_args = 96 // 96 bytes to pass arguments and return values for this function
|
||||
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||
_FP_saves = 40 // 40 bytes for saving the registers before CALL instructions
|
||||
_FP_locals = 144 // 144 bytes for local variables
|
||||
_FP_locals = 120 // 120 bytes for local variables
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -89,10 +89,6 @@ const (
|
|||
_BM_space = (1 << ' ') | (1 << '\t') | (1 << '\r') | (1 << '\n')
|
||||
)
|
||||
|
||||
const (
|
||||
_MODE_JSON = 1 << 3 // base64 mode
|
||||
)
|
||||
|
||||
const (
|
||||
_LB_error = "_error"
|
||||
_LB_im_error = "_im_error"
|
||||
|
|
@ -105,7 +101,6 @@ const (
|
|||
_LB_unquote_error = "_unquote_error"
|
||||
_LB_parsing_error = "_parsing_error"
|
||||
_LB_parsing_error_v = "_parsing_error_v"
|
||||
_LB_mismatch_error = "_mismatch_error"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -118,11 +113,6 @@ const (
|
|||
_LB_char_m3_error = "_char_m3_error"
|
||||
)
|
||||
|
||||
const (
|
||||
_LB_skip_one = "_skip_one"
|
||||
_LB_skip_key_value = "_skip_key_value"
|
||||
)
|
||||
|
||||
var (
|
||||
_AX = jit.Reg("AX")
|
||||
_CX = jit.Reg("CX")
|
||||
|
|
@ -206,12 +196,6 @@ var (
|
|||
|
||||
var _VAR_fl = jit.Ptr(_SP, _FP_fargs + _FP_saves + 112)
|
||||
|
||||
var (
|
||||
_VAR_et = jit.Ptr(_SP, _FP_fargs + _FP_saves + 120) // save dismatched type
|
||||
_VAR_ic = jit.Ptr(_SP, _FP_fargs + _FP_saves + 128) // save dismatched position
|
||||
_VAR_pc = jit.Ptr(_SP, _FP_fargs + _FP_saves + 136) // save skip return pc
|
||||
)
|
||||
|
||||
type _Assembler struct {
|
||||
jit.BaseAssembler
|
||||
p _Program
|
||||
|
|
@ -240,9 +224,6 @@ func (self *_Assembler) compile() {
|
|||
self.copy_string()
|
||||
self.escape_string()
|
||||
self.escape_string_twice()
|
||||
self.skip_one()
|
||||
self.skip_key_value()
|
||||
self.mismatch_error()
|
||||
self.type_error()
|
||||
self.field_error()
|
||||
self.range_error()
|
||||
|
|
@ -314,10 +295,6 @@ var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
|
|||
_OP_recurse : (*_Assembler)._asm_OP_recurse,
|
||||
_OP_goto : (*_Assembler)._asm_OP_goto,
|
||||
_OP_switch : (*_Assembler)._asm_OP_switch,
|
||||
_OP_check_char_0 : (*_Assembler)._asm_OP_check_char_0,
|
||||
_OP_dismatch_err : (*_Assembler)._asm_OP_dismatch_err,
|
||||
_OP_go_skip : (*_Assembler)._asm_OP_go_skip,
|
||||
_OP_add : (*_Assembler)._asm_OP_add,
|
||||
}
|
||||
|
||||
func (self *_Assembler) instr(v *_Instr) {
|
||||
|
|
@ -338,10 +315,8 @@ func (self *_Assembler) instrs() {
|
|||
|
||||
func (self *_Assembler) epilogue() {
|
||||
self.Mark(len(self.p))
|
||||
self.Emit("XORL", _ET, _ET) // XORL ET, ET
|
||||
self.Emit("XORL", _EP, _EP) // XORL EP, EP
|
||||
self.Emit("MOVQ", _VAR_et, _ET) // MOVQ VAR_et, ET
|
||||
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
|
||||
self.Sjmp("JNZ", _LB_mismatch_error) // JNZ _LB_mismatch_error
|
||||
self.Link(_LB_error) // _error:
|
||||
self.Emit("MOVQ", _IC, _RET_rc) // MOVQ IC, rc<>+40(FP)
|
||||
self.Emit("MOVQ", _ET, _RET_et) // MOVQ ET, et<>+48(FP)
|
||||
|
|
@ -364,8 +339,6 @@ func (self *_Assembler) prologue() {
|
|||
self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_st_Dc) // MOVQ $_MaxDigitNums, ss.Dcap
|
||||
self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX
|
||||
self.Emit("MOVQ", _AX, _VAR_st_Db) // MOVQ AX, ss.Dbuf
|
||||
self.Emit("XORL", _AX, _AX) // XORL AX, AX
|
||||
self.Emit("MOVQ", _AX, _VAR_et) // MOVQ AX, ss.Dp
|
||||
}
|
||||
|
||||
/** Function Calling Helpers **/
|
||||
|
|
@ -431,12 +404,11 @@ func (self *_Assembler) call_vf(fn obj.Addr) {
|
|||
/** Assembler Error Handlers **/
|
||||
|
||||
var (
|
||||
_F_convT64 = jit.Func(convT64)
|
||||
_F_error_wrap = jit.Func(error_wrap)
|
||||
_F_error_type = jit.Func(error_type)
|
||||
_F_error_field = jit.Func(error_field)
|
||||
_F_error_value = jit.Func(error_value)
|
||||
_F_error_mismatch = jit.Func(error_mismatch)
|
||||
_F_convT64 = jit.Func(convT64)
|
||||
_F_error_wrap = jit.Func(error_wrap)
|
||||
_F_error_type = jit.Func(error_type)
|
||||
_F_error_field = jit.Func(error_field)
|
||||
_F_error_value = jit.Func(error_value)
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -468,69 +440,6 @@ func (self *_Assembler) type_error() {
|
|||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
|
||||
func (self *_Assembler) mismatch_error() {
|
||||
self.Link(_LB_mismatch_error) // _type_error:
|
||||
self.Emit("MOVQ", _ARG_sp, _AX)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.Emit("MOVQ", _ARG_sl, _CX)
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.Emit("MOVQ", _VAR_ic, _AX)
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) // MOVQ AX, 16(SP)
|
||||
self.Emit("MOVQ", _VAR_et, _CX)
|
||||
self.Emit("MOVQ", _CX, jit.Ptr(_SP, 24)) // MOVQ CX, 24(SP)
|
||||
self.call_go(_F_error_mismatch) // CALL_GO error_type
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 32), _ET) // MOVQ 32(SP), ET
|
||||
self.Emit("MOVQ", jit.Ptr(_SP, 40), _EP) // MOVQ 40(SP), EP
|
||||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_dismatch_err(p *_Instr) {
|
||||
self.Emit("MOVQ", _IC, _VAR_ic)
|
||||
self.Emit("MOVQ", jit.Type(p.vt()), _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_go_skip(p *_Instr) {
|
||||
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Xref(p.vi(), 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one) // JMP _skip_one
|
||||
}
|
||||
|
||||
func (self *_Assembler) skip_one() {
|
||||
self.Link(_LB_skip_one) // _skip:
|
||||
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
|
||||
self.Rjmp("JMP" , _R9) // JMP (R9)
|
||||
}
|
||||
|
||||
|
||||
func (self *_Assembler) skip_key_value() {
|
||||
self.Link(_LB_skip_key_value) // _skip:
|
||||
// skip the key
|
||||
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
// match char ':'
|
||||
self.lspace("_global_1")
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(':'))
|
||||
self.Sjmp("JNE" , _LB_parsing_error_v) // JNE _parse_error_v
|
||||
self.Emit("ADDQ", jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
self.lspace("_global_2")
|
||||
// skip the value
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
// jump back to specified address
|
||||
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
|
||||
self.Rjmp("JMP" , _R9) // JMP (R9)
|
||||
}
|
||||
|
||||
func (self *_Assembler) field_error() {
|
||||
self.Link(_LB_field_error) // _field_error:
|
||||
self.Emit("MOVOU", _VAR_sv, _X0) // MOVOU sv, X0
|
||||
|
|
@ -666,32 +575,10 @@ var (
|
|||
_F_vunsigned = jit.Imm(int64(native.S_vunsigned))
|
||||
)
|
||||
|
||||
func (self *_Assembler) check_err(vt reflect.Type, pin string, pin2 int) {
|
||||
func (self *_Assembler) check_err() {
|
||||
self.Emit("MOVQ" , _VAR_st_Vt, _AX) // MOVQ st.Vt, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // CMPQ AX, ${native.V_STRING}
|
||||
// try to skip the value
|
||||
if vt != nil {
|
||||
self.Sjmp("JNS" , "_check_err_{n}") // JNE _parsing_error_v
|
||||
self.Emit("MOVQ", jit.Type(vt), _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
if pin2 != -1 {
|
||||
self.Emit("SUBQ", jit.Imm(1), _BP)
|
||||
self.Emit("MOVQ", _BP, _VAR_ic)
|
||||
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Xref(pin2, 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_key_value)
|
||||
} else {
|
||||
self.Emit("MOVQ", _BP, _VAR_ic)
|
||||
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Sref(pin, 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
}
|
||||
self.Link("_check_err_{n}")
|
||||
} else {
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v
|
||||
}
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v
|
||||
}
|
||||
|
||||
func (self *_Assembler) check_eof(d int64) {
|
||||
|
|
@ -708,25 +595,22 @@ func (self *_Assembler) check_eof(d int64) {
|
|||
func (self *_Assembler) parse_string() { // parse_string has a validate flag params in the last
|
||||
self.Emit("MOVQ", _ARG_fv, _CX)
|
||||
self.call_vf(_F_vstring)
|
||||
self.check_err(nil, "", -1)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_number(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BP)
|
||||
func (self *_Assembler) parse_number() {
|
||||
self.call_vf(_F_vnumber) // call vnumber
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_signed(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BP)
|
||||
func (self *_Assembler) parse_signed() {
|
||||
self.call_vf(_F_vsigned)
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_unsigned(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BP)
|
||||
func (self *_Assembler) parse_unsigned() {
|
||||
self.call_vf(_F_vunsigned)
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
// Pointer: DI, Size: SI, Return: R9
|
||||
|
|
@ -1235,7 +1119,7 @@ func (self *_Assembler) _asm_OP_bin(_ *_Instr) {
|
|||
self.malloc(_SI, _SI) // MALLOC SI, SI
|
||||
|
||||
// TODO: due to base64x's bug, only use AVX mode now
|
||||
self.Emit("MOVL", jit.Imm(_MODE_JSON), _CX) // MOVL $_MODE_JSON, CX
|
||||
self.Emit("XORL", _CX, _CX) // XORL CX, CX
|
||||
|
||||
/* call the decoder */
|
||||
self.Emit("XORL" , _DX, _DX) // XORL DX, DX
|
||||
|
|
@ -1260,18 +1144,7 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
|||
self.Sjmp("JE" , "_false_{n}") // JE _false_{n}
|
||||
self.Emit("MOVL", jit.Imm(_IM_true), _CX) // MOVL $"true", CX
|
||||
self.Emit("CMPL", _CX, jit.Sib(_IP, _IC, 1, 0)) // CMPL CX, (IP)(IC)
|
||||
self.Sjmp("JE" , "_bool_true_{n}")
|
||||
|
||||
// try to skip the value
|
||||
self.Emit("MOVQ", _IC, _VAR_ic)
|
||||
self.Emit("MOVQ", _T_bool, _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Sref("_end_{n}", 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
|
||||
self.Link("_bool_true_{n}")
|
||||
self.Sjmp("JNE" , _LB_im_error) // JNE _im_error
|
||||
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
|
||||
self.Emit("MOVB", jit.Imm(1), jit.Ptr(_VP, 0)) // MOVB $1, (VP)
|
||||
self.Sjmp("JMP" , "_end_{n}") // JMP _end_{n}
|
||||
|
|
@ -1292,28 +1165,20 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
|||
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||
self.Emit("MOVQ", jit.Imm(0), _VAR_fl)
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||
self.Emit("MOVQ", _IC, _BP)
|
||||
self.Sjmp("JNE", "_skip_number_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(1), _VAR_fl)
|
||||
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||
self.Link("_skip_number_{n}")
|
||||
|
||||
/* call skip_number */
|
||||
self.call_sf(_F_skip_number) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JNS" , "_num_next_{n}")
|
||||
self.Emit("LEAQ", _ARG_s, _DI) // LEAQ s<>+0(FP), DI
|
||||
self.Emit("MOVQ", _IC, _ARG_ic) // MOVQ IC, ic<>+16(FP)
|
||||
self.Emit("LEAQ", _ARG_ic, _SI) // LEAQ ic<>+16(FP), SI
|
||||
self.call(_F_skip_number) // CALL _F_skip_number
|
||||
self.Emit("MOVQ", _ARG_ic, _IC) // MOVQ ic<>+16(FP), IC
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
|
||||
/* call skip one */
|
||||
self.Emit("MOVQ", _BP, _VAR_ic)
|
||||
self.Emit("MOVQ", _T_number, _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
self.Byte(0x4c, 0x8d, 0x0d)
|
||||
self.Sref("_num_end_{n}", 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
|
||||
/* assgin string */
|
||||
self.Link("_num_next_{n}")
|
||||
self.slice_from_r(_AX, 0)
|
||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
||||
self.Sjmp("JNC", "_num_write_{n}")
|
||||
|
|
@ -1322,9 +1187,7 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
|||
self.Sjmp("JMP", "_copy_string")
|
||||
self.Link("_num_write_{n}")
|
||||
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
||||
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
||||
|
||||
/* check if quoted */
|
||||
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
||||
self.Emit("CMPQ", _VAR_fl, jit.Imm(1))
|
||||
self.Sjmp("JNE", "_num_end_{n}")
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||
|
|
@ -1332,88 +1195,67 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
|||
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||
self.Link("_num_end_{n}")
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i8(ins *_Instr) {
|
||||
var pin = "_i8_end_{n}"
|
||||
self.parse_signed(int8Type, pin, -1) // PARSE int8
|
||||
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
||||
self.parse_signed() // PARSE int8
|
||||
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
||||
self.Emit("MOVB", _AX, jit.Ptr(_VP, 0)) // MOVB AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i16(ins *_Instr) {
|
||||
var pin = "_i16_end_{n}"
|
||||
self.parse_signed(int16Type, pin, -1) // PARSE int16
|
||||
func (self *_Assembler) _asm_OP_i16(_ *_Instr) {
|
||||
self.parse_signed() // PARSE int16
|
||||
self.range_signed(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
|
||||
self.Emit("MOVW", _AX, jit.Ptr(_VP, 0)) // MOVW AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i32(ins *_Instr) {
|
||||
var pin = "_i32_end_{n}"
|
||||
self.parse_signed(int32Type, pin, -1) // PARSE int32
|
||||
func (self *_Assembler) _asm_OP_i32(_ *_Instr) {
|
||||
self.parse_signed() // PARSE int32
|
||||
self.range_signed(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
|
||||
self.Emit("MOVL", _AX, jit.Ptr(_VP, 0)) // MOVL AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i64(ins *_Instr) {
|
||||
var pin = "_i64_end_{n}"
|
||||
self.parse_signed(int64Type, pin, -1) // PARSE int64
|
||||
func (self *_Assembler) _asm_OP_i64(_ *_Instr) {
|
||||
self.parse_signed() // PARSE int64
|
||||
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u8(ins *_Instr) {
|
||||
var pin = "_u8_end_{n}"
|
||||
self.parse_unsigned(uint8Type, pin, -1) // PARSE uint8
|
||||
func (self *_Assembler) _asm_OP_u8(_ *_Instr) {
|
||||
self.parse_unsigned() // PARSE uint8
|
||||
self.range_unsigned(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
|
||||
self.Emit("MOVB", _AX, jit.Ptr(_VP, 0)) // MOVB AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u16(ins *_Instr) {
|
||||
var pin = "_u16_end_{n}"
|
||||
self.parse_unsigned(uint16Type, pin, -1) // PARSE uint16
|
||||
func (self *_Assembler) _asm_OP_u16(_ *_Instr) {
|
||||
self.parse_unsigned() // PARSE uint16
|
||||
self.range_unsigned(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
|
||||
self.Emit("MOVW", _AX, jit.Ptr(_VP, 0)) // MOVW AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u32(ins *_Instr) {
|
||||
var pin = "_u32_end_{n}"
|
||||
self.parse_unsigned(uint32Type, pin, -1) // PARSE uint32
|
||||
func (self *_Assembler) _asm_OP_u32(_ *_Instr) {
|
||||
self.parse_unsigned() // PARSE uint32
|
||||
self.range_unsigned(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
|
||||
self.Emit("MOVL", _AX, jit.Ptr(_VP, 0)) // MOVL AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u64(ins *_Instr) {
|
||||
var pin = "_u64_end_{n}"
|
||||
self.parse_unsigned(uint64Type, pin, -1) // PARSE uint64
|
||||
func (self *_Assembler) _asm_OP_u64(_ *_Instr) {
|
||||
self.parse_unsigned() // PARSE uint64
|
||||
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f32(ins *_Instr) {
|
||||
var pin = "_f32_end_{n}"
|
||||
self.parse_number(float32Type, pin, -1) // PARSE NUMBER
|
||||
func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single() // RANGE float32
|
||||
self.Emit("MOVSS", _X0, jit.Ptr(_VP, 0)) // MOVSS X0, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f64(ins *_Instr) {
|
||||
var pin = "_f64_end_{n}"
|
||||
self.parse_number(float64Type, pin, -1) // PARSE NUMBER
|
||||
func (self *_Assembler) _asm_OP_f64(_ *_Instr) {
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.Emit("MOVSD", _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
|
||||
self.Emit("MOVSD", _X0, jit.Ptr(_VP, 0)) // MOVSD X0, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_unquote(ins *_Instr) {
|
||||
func (self *_Assembler) _asm_OP_unquote(_ *_Instr) {
|
||||
self.check_eof(2)
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('\\')) // CMPB (IP)(IC), $'\\'
|
||||
self.Sjmp("JNE" , _LB_char_0_error) // JNE _char_0_error
|
||||
|
|
@ -1484,19 +1326,19 @@ func (self *_Assembler) _asm_OP_map_init(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i8(p *_Instr) {
|
||||
self.parse_signed(int8Type, "", p.vi()) // PARSE int8
|
||||
self.parse_signed() // PARSE int8
|
||||
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int8, mapassign, st.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i16(p *_Instr) {
|
||||
self.parse_signed(int16Type, "", p.vi()) // PARSE int16
|
||||
self.parse_signed() // PARSE int16
|
||||
self.range_signed(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int16, mapassign, st.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i32(p *_Instr) {
|
||||
self.parse_signed(int32Type, "", p.vi()) // PARSE int32
|
||||
self.parse_signed() // PARSE int32
|
||||
self.range_signed(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int32, mapassign, st.Iv
|
||||
|
|
@ -1506,7 +1348,7 @@ func (self *_Assembler) _asm_OP_map_key_i32(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i64(p *_Instr) {
|
||||
self.parse_signed(int64Type, "", p.vi()) // PARSE int64
|
||||
self.parse_signed() // PARSE int64
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int64, mapassign, st.Iv
|
||||
} else {
|
||||
|
|
@ -1516,19 +1358,19 @@ func (self *_Assembler) _asm_OP_map_key_i64(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u8(p *_Instr) {
|
||||
self.parse_unsigned(uint8Type, "", p.vi()) // PARSE uint8
|
||||
self.parse_unsigned() // PARSE uint8
|
||||
self.range_unsigned(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint8, vt.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u16(p *_Instr) {
|
||||
self.parse_unsigned(uint16Type, "", p.vi()) // PARSE uint16
|
||||
self.parse_unsigned() // PARSE uint16
|
||||
self.range_unsigned(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint16, vt.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u32(p *_Instr) {
|
||||
self.parse_unsigned(uint32Type, "", p.vi()) // PARSE uint32
|
||||
self.parse_unsigned() // PARSE uint32
|
||||
self.range_unsigned(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint32, vt.Iv
|
||||
|
|
@ -1538,7 +1380,7 @@ func (self *_Assembler) _asm_OP_map_key_u32(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
|
||||
self.parse_unsigned(uint64Type, "", p.vi()) // PARSE uint64
|
||||
self.parse_unsigned() // PARSE uint64
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint64, vt.Iv
|
||||
} else {
|
||||
|
|
@ -1548,14 +1390,14 @@ func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_f32(p *_Instr) {
|
||||
self.parse_number(float32Type, "", p.vi()) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single() // RANGE float32
|
||||
self.Emit("MOVSS", _X0, _VAR_st_Dv) // MOVSS X0, st.Dv
|
||||
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_f64(p *_Instr) {
|
||||
self.parse_number(float64Type, "", p.vi()) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
|
||||
}
|
||||
|
||||
|
|
@ -1745,20 +1587,14 @@ func (self *_Assembler) _asm_OP_unmarshal_text_p(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_lspace(_ *_Instr) {
|
||||
self.lspace("_{n}")
|
||||
}
|
||||
|
||||
func (self *_Assembler) lspace(subfix string) {
|
||||
var label = "_lspace" + subfix
|
||||
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , label) // JA _nospace_{n}
|
||||
self.Sjmp("JA" , "_nospace_{n}") // JA _nospace_{n}
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , label) // JNC _nospace_{n}
|
||||
self.Sjmp("JNC" , "_nospace_{n}") // JNC _nospace_{n}
|
||||
|
||||
/* test up to 4 characters */
|
||||
for i := 0; i < 3; i++ {
|
||||
|
|
@ -1767,9 +1603,9 @@ func (self *_Assembler) lspace(subfix string) {
|
|||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , label) // JA _nospace_{n}
|
||||
self.Sjmp("JA" , "_nospace_{n}") // JA _nospace_{n}
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , label) // JNC _nospace_{n}
|
||||
self.Sjmp("JNC" , "_nospace_{n}") // JNC _nospace_{n}
|
||||
}
|
||||
|
||||
/* handle over to the native function */
|
||||
|
|
@ -1782,7 +1618,7 @@ func (self *_Assembler) lspace(subfix string) {
|
|||
self.Emit("CMPQ" , _AX, _IL) // CMPQ AX, IL
|
||||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVQ" , _AX, _IC) // MOVQ AX, IC
|
||||
self.Link(label) // _nospace_{n}:
|
||||
self.Link("_nospace_{n}") // _nospace_{n}:
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_match_char(p *_Instr) {
|
||||
|
|
@ -1800,16 +1636,6 @@ func (self *_Assembler) _asm_OP_check_char(p *_Instr) {
|
|||
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_check_char_0(p *_Instr) {
|
||||
self.check_eof(1)
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(p.vb()))) // CMPB (IP)(IC), ${p.vb()}
|
||||
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_add(p *_Instr) {
|
||||
self.Emit("ADDQ", jit.Imm(int64(p.vi())), _IC) // ADDQ ${p.vi()}, IC
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_load(_ *_Instr) {
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _VP) // MOVQ (ST)(AX), VP
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ const (
|
|||
_FP_args = 72 // 72 bytes to pass and spill register arguements
|
||||
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||
_FP_saves = 48 // 48 bytes for saving the registers before CALL instructions
|
||||
_FP_locals = 144 // 144 bytes for local variables
|
||||
_FP_locals = 120 // 112 bytes for local variables
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -89,10 +89,6 @@ const (
|
|||
_BM_space = (1 << ' ') | (1 << '\t') | (1 << '\r') | (1 << '\n')
|
||||
)
|
||||
|
||||
const (
|
||||
_MODE_JSON = 1 << 3 // base64 mode
|
||||
)
|
||||
|
||||
const (
|
||||
_LB_error = "_error"
|
||||
_LB_im_error = "_im_error"
|
||||
|
|
@ -105,7 +101,6 @@ const (
|
|||
_LB_unquote_error = "_unquote_error"
|
||||
_LB_parsing_error = "_parsing_error"
|
||||
_LB_parsing_error_v = "_parsing_error_v"
|
||||
_LB_mismatch_error = "_mismatch_error"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -118,11 +113,6 @@ const (
|
|||
_LB_char_m3_error = "_char_m3_error"
|
||||
)
|
||||
|
||||
const (
|
||||
_LB_skip_one = "_skip_one"
|
||||
_LB_skip_key_value = "_skip_key_value"
|
||||
)
|
||||
|
||||
var (
|
||||
_AX = jit.Reg("AX")
|
||||
_BX = jit.Reg("BX")
|
||||
|
|
@ -201,12 +191,6 @@ var (
|
|||
|
||||
var _VAR_fl = jit.Ptr(_SP, _FP_fargs + _FP_saves + 112)
|
||||
|
||||
var (
|
||||
_VAR_et = jit.Ptr(_SP, _FP_fargs + _FP_saves + 120) // save dismatched type
|
||||
_VAR_pc = jit.Ptr(_SP, _FP_fargs + _FP_saves + 128) // save skip return pc
|
||||
_VAR_ic = jit.Ptr(_SP, _FP_fargs + _FP_saves + 136) // save dismatched position
|
||||
)
|
||||
|
||||
type _Assembler struct {
|
||||
jit.BaseAssembler
|
||||
p _Program
|
||||
|
|
@ -235,10 +219,7 @@ func (self *_Assembler) compile() {
|
|||
self.copy_string()
|
||||
self.escape_string()
|
||||
self.escape_string_twice()
|
||||
self.skip_one()
|
||||
self.skip_key_value()
|
||||
self.type_error()
|
||||
self.mismatch_error()
|
||||
self.field_error()
|
||||
self.range_error()
|
||||
self.stack_error()
|
||||
|
|
@ -309,15 +290,6 @@ var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
|
|||
_OP_recurse : (*_Assembler)._asm_OP_recurse,
|
||||
_OP_goto : (*_Assembler)._asm_OP_goto,
|
||||
_OP_switch : (*_Assembler)._asm_OP_switch,
|
||||
_OP_check_char_0 : (*_Assembler)._asm_OP_check_char_0,
|
||||
_OP_dismatch_err : (*_Assembler)._asm_OP_dismatch_err,
|
||||
_OP_go_skip : (*_Assembler)._asm_OP_go_skip,
|
||||
_OP_add : (*_Assembler)._asm_OP_add,
|
||||
_OP_debug : (*_Assembler)._asm_OP_debug,
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_debug(_ *_Instr) {
|
||||
self.Byte(0xcc)
|
||||
}
|
||||
|
||||
func (self *_Assembler) instr(v *_Instr) {
|
||||
|
|
@ -338,10 +310,8 @@ func (self *_Assembler) instrs() {
|
|||
|
||||
func (self *_Assembler) epilogue() {
|
||||
self.Mark(len(self.p))
|
||||
self.Emit("XORL", _ET, _ET) // XORL ET, ET
|
||||
self.Emit("XORL", _EP, _EP) // XORL EP, EP
|
||||
self.Emit("MOVQ", _VAR_et, _ET) // MOVQ VAR_et, ET
|
||||
self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET
|
||||
self.Sjmp("JNZ", _LB_mismatch_error) // JNZ _LB_mismatch_error
|
||||
self.Link(_LB_error) // _error:
|
||||
self.Emit("MOVQ", _EP, _CX) // MOVQ BX, CX
|
||||
self.Emit("MOVQ", _ET, _BX) // MOVQ AX, BX
|
||||
|
|
@ -373,7 +343,6 @@ func (self *_Assembler) prologue() {
|
|||
self.Emit("MOVQ", jit.Imm(0), _VAR_sv_p) // MOVQ $0, sv.p<>+48(FP)
|
||||
self.Emit("MOVQ", jit.Imm(0), _VAR_sv_n) // MOVQ $0, sv.n<>+56(FP)
|
||||
self.Emit("MOVQ", jit.Imm(0), _VAR_vk) // MOVQ $0, vk<>+64(FP)
|
||||
self.Emit("MOVQ", jit.Imm(0), _VAR_et) // MOVQ $0, et<>+120(FP)
|
||||
// initialize digital buffer first
|
||||
self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_st_Dc) // MOVQ $_MaxDigitNums, ss.Dcap
|
||||
self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX
|
||||
|
|
@ -452,12 +421,11 @@ func (self *_Assembler) call_vf(fn obj.Addr) {
|
|||
/** Assembler Error Handlers **/
|
||||
|
||||
var (
|
||||
_F_convT64 = jit.Func(convT64)
|
||||
_F_error_wrap = jit.Func(error_wrap)
|
||||
_F_error_type = jit.Func(error_type)
|
||||
_F_error_field = jit.Func(error_field)
|
||||
_F_error_value = jit.Func(error_value)
|
||||
_F_error_mismatch = jit.Func(error_mismatch)
|
||||
_F_convT64 = jit.Func(convT64)
|
||||
_F_error_wrap = jit.Func(error_wrap)
|
||||
_F_error_type = jit.Func(error_type)
|
||||
_F_error_field = jit.Func(error_field)
|
||||
_F_error_value = jit.Func(error_value)
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -486,16 +454,6 @@ func (self *_Assembler) type_error() {
|
|||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) mismatch_error() {
|
||||
self.Link(_LB_mismatch_error) // _type_error:
|
||||
self.Emit("MOVQ", _ARG_sp, _AX)
|
||||
self.Emit("MOVQ", _ARG_sl, _BX)
|
||||
self.Emit("MOVQ", _VAR_ic, _CX)
|
||||
self.Emit("MOVQ", _VAR_et, _DI)
|
||||
self.call_go(_F_error_mismatch) // CALL_GO error_type
|
||||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) field_error() {
|
||||
self.Link(_LB_field_error) // _field_error:
|
||||
self.Emit("MOVQ", _VAR_sv_p, _AX) // MOVQ sv.p, AX
|
||||
|
|
@ -578,54 +536,6 @@ func (self *_Assembler) parsing_error() {
|
|||
self.Sjmp("JMP" , _LB_error) // JMP _error
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_dismatch_err(p *_Instr) {
|
||||
self.Emit("MOVQ", _IC, _VAR_ic)
|
||||
self.Emit("MOVQ", jit.Type(p.vt()), _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_go_skip(p *_Instr) {
|
||||
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Xref(p.vi(), 4)
|
||||
// self.Byte(0xcc)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one) // JMP _skip_one
|
||||
}
|
||||
|
||||
func (self *_Assembler) skip_one() {
|
||||
self.Link(_LB_skip_one) // _skip:
|
||||
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
|
||||
// self.Byte(0xcc)
|
||||
self.Rjmp("JMP" , _R9) // JMP (R9)
|
||||
}
|
||||
|
||||
func (self *_Assembler) skip_key_value() {
|
||||
self.Link(_LB_skip_key_value) // _skip:
|
||||
// skip the key
|
||||
self.Emit("MOVQ", _VAR_ic, _IC) // MOVQ _VAR_ic, IC
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
// match char ':'
|
||||
self.lspace("_global_1")
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(':'))
|
||||
self.Sjmp("JNE" , _LB_parsing_error_v) // JNE _parse_error_v
|
||||
self.Emit("ADDQ", jit.Imm(1), _IC) // ADDQ $1, IC
|
||||
self.lspace("_global_2")
|
||||
// skip the value
|
||||
self.call_sf(_F_skip_one) // CALL_SF skip_one
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
// jump back to specified address
|
||||
self.Emit("MOVQ" , _VAR_pc, _R9) // MOVQ pc, R9
|
||||
self.Rjmp("JMP" , _R9) // JMP (R9)
|
||||
}
|
||||
|
||||
|
||||
/** Memory Management Routines **/
|
||||
|
||||
var (
|
||||
|
|
@ -675,32 +585,10 @@ var (
|
|||
_F_vunsigned = jit.Imm(int64(native.S_vunsigned))
|
||||
)
|
||||
|
||||
func (self *_Assembler) check_err(vt reflect.Type, pin string, pin2 int) {
|
||||
func (self *_Assembler) check_err() {
|
||||
self.Emit("MOVQ" , _VAR_st_Vt, _AX) // MOVQ st.Vt, AX
|
||||
self.Emit("TESTQ", _AX, _AX) // CMPQ AX, ${native.V_STRING}
|
||||
// try to skip the value
|
||||
if vt != nil {
|
||||
self.Sjmp("JNS" , "_check_err_{n}") // JNE _parsing_error_v
|
||||
self.Emit("MOVQ", jit.Type(vt), _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
if pin2 != -1 {
|
||||
self.Emit("SUBQ", jit.Imm(1), _BX)
|
||||
self.Emit("MOVQ", _BX, _VAR_ic)
|
||||
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Xref(pin2, 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_key_value)
|
||||
} else {
|
||||
self.Emit("MOVQ", _BX, _VAR_ic)
|
||||
self.Byte(0x4c , 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Sref(pin, 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
}
|
||||
self.Link("_check_err_{n}")
|
||||
} else {
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v
|
||||
}
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v
|
||||
}
|
||||
|
||||
func (self *_Assembler) check_eof(d int64) {
|
||||
|
|
@ -714,29 +602,25 @@ func (self *_Assembler) check_eof(d int64) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func (self *_Assembler) parse_string() {
|
||||
self.Emit("MOVQ", _ARG_fv, _CX)
|
||||
self.call_vf(_F_vstring)
|
||||
self.check_err(nil, "", -1)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_number(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BX) // save ic when call native func
|
||||
func (self *_Assembler) parse_number() {
|
||||
self.call_vf(_F_vnumber)
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_signed(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BX) // save ic when call native func
|
||||
func (self *_Assembler) parse_signed() {
|
||||
self.call_vf(_F_vsigned)
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
func (self *_Assembler) parse_unsigned(vt reflect.Type, pin string, pin2 int) {
|
||||
self.Emit("MOVQ", _IC, _BX) // save ic when call native func
|
||||
func (self *_Assembler) parse_unsigned() {
|
||||
self.call_vf(_F_vunsigned)
|
||||
self.check_err(vt, pin, pin2)
|
||||
self.check_err()
|
||||
}
|
||||
|
||||
// Pointer: DI, Size: SI, Return: R9
|
||||
|
|
@ -1229,7 +1113,7 @@ func (self *_Assembler) _asm_OP_bin(_ *_Instr) {
|
|||
self.malloc_AX(_SI, _SI) // MALLOC SI, SI
|
||||
|
||||
// TODO: due to base64x's bug, only use AVX mode now
|
||||
self.Emit("MOVL", jit.Imm(_MODE_JSON), _CX) // MOVL $_MODE_JSON, CX
|
||||
self.Emit("XORL", _CX, _CX) // XORL CX, CX
|
||||
|
||||
/* call the decoder */
|
||||
self.Emit("XORL" , _DX, _DX) // XORL DX, DX
|
||||
|
|
@ -1254,17 +1138,7 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
|||
self.Sjmp("JE" , "_false_{n}") // JE _false_{n}
|
||||
self.Emit("MOVL", jit.Imm(_IM_true), _CX) // MOVL $"true", CX
|
||||
self.Emit("CMPL", _CX, jit.Sib(_IP, _IC, 1, 0)) // CMPL CX, (IP)(IC)
|
||||
self.Sjmp("JE" , "_bool_true_{n}")
|
||||
// try to skip the value
|
||||
self.Emit("MOVQ", _IC, _VAR_ic)
|
||||
self.Emit("MOVQ", _T_bool, _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
self.Byte(0x4c, 0x8d, 0x0d) // LEAQ (PC), R9
|
||||
self.Sref("_end_{n}", 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
|
||||
self.Link("_bool_true_{n}")
|
||||
self.Sjmp("JNE" , _LB_im_error) // JNE _im_error
|
||||
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
|
||||
self.Emit("MOVB", jit.Imm(1), jit.Ptr(_VP, 0)) // MOVB $1, (VP)
|
||||
self.Sjmp("JMP" , "_end_{n}") // JMP _end_{n}
|
||||
|
|
@ -1285,7 +1159,6 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
|||
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||
self.Emit("MOVQ", jit.Imm(0), _VAR_fl)
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||
self.Emit("MOVQ", _IC, _BX)
|
||||
self.Sjmp("JNE", "_skip_number_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(1), _VAR_fl)
|
||||
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||
|
|
@ -1298,19 +1171,8 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
|||
self.callc(_F_skip_number) // CALL _F_skip_number
|
||||
self.Emit("MOVQ", _ARG_ic, _IC) // MOVQ ic<>+16(FP), IC
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JNS" , "_num_next_{n}")
|
||||
self.Sjmp("JS" , _LB_parsing_error_v) // JS _parse_error_v
|
||||
|
||||
/* call skip one */
|
||||
self.Emit("MOVQ", _BX, _VAR_ic)
|
||||
self.Emit("MOVQ", _T_number, _ET)
|
||||
self.Emit("MOVQ", _ET, _VAR_et)
|
||||
self.Byte(0x4c, 0x8d, 0x0d)
|
||||
self.Sref("_num_end_{n}", 4)
|
||||
self.Emit("MOVQ", _R9, _VAR_pc)
|
||||
self.Sjmp("JMP" , _LB_skip_one)
|
||||
|
||||
/* assgin string */
|
||||
self.Link("_num_next_{n}")
|
||||
self.slice_from_r(_AX, 0)
|
||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
||||
self.Sjmp("JNC", "_num_write_{n}")
|
||||
|
|
@ -1329,83 +1191,63 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
||||
var pin = "_i8_end_{n}"
|
||||
self.parse_signed(int8Type, pin, -1) // PARSE int8
|
||||
self.parse_signed() // PARSE int8
|
||||
self.range_signed_CX(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
||||
self.Emit("MOVB", _CX, jit.Ptr(_VP, 0)) // MOVB CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i16(_ *_Instr) {
|
||||
var pin = "_i16_end_{n}"
|
||||
self.parse_signed(int16Type, pin, -1) // PARSE int16
|
||||
self.parse_signed() // PARSE int16
|
||||
self.range_signed_CX(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
|
||||
self.Emit("MOVW", _CX, jit.Ptr(_VP, 0)) // MOVW CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i32(_ *_Instr) {
|
||||
var pin = "_i32_end_{n}"
|
||||
self.parse_signed(int32Type, pin, -1) // PARSE int32
|
||||
self.parse_signed() // PARSE int32
|
||||
self.range_signed_CX(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
|
||||
self.Emit("MOVL", _CX, jit.Ptr(_VP, 0)) // MOVL CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_i64(_ *_Instr) {
|
||||
var pin = "_i64_end_{n}"
|
||||
self.parse_signed(int64Type, pin, -1) // PARSE int64
|
||||
self.parse_signed() // PARSE int64
|
||||
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u8(_ *_Instr) {
|
||||
var pin = "_u8_end_{n}"
|
||||
self.parse_unsigned(uint8Type, pin, -1) // PARSE uint8
|
||||
self.parse_unsigned() // PARSE uint8
|
||||
self.range_unsigned_CX(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
|
||||
self.Emit("MOVB", _CX, jit.Ptr(_VP, 0)) // MOVB CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u16(_ *_Instr) {
|
||||
var pin = "_u16_end_{n}"
|
||||
self.parse_unsigned(uint16Type, pin, -1) // PARSE uint16
|
||||
self.parse_unsigned() // PARSE uint16
|
||||
self.range_unsigned_CX(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
|
||||
self.Emit("MOVW", _CX, jit.Ptr(_VP, 0)) // MOVW CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u32(_ *_Instr) {
|
||||
var pin = "_u32_end_{n}"
|
||||
self.parse_unsigned(uint32Type, pin, -1) // PARSE uint32
|
||||
self.parse_unsigned() // PARSE uint32
|
||||
self.range_unsigned_CX(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
|
||||
self.Emit("MOVL", _CX, jit.Ptr(_VP, 0)) // MOVL CX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_u64(_ *_Instr) {
|
||||
var pin = "_u64_end_{n}"
|
||||
self.parse_unsigned(uint64Type, pin, -1) // PARSE uint64
|
||||
self.parse_unsigned() // PARSE uint64
|
||||
self.Emit("MOVQ", _VAR_st_Iv, _AX) // MOVQ st.Iv, AX
|
||||
self.Emit("MOVQ", _AX, jit.Ptr(_VP, 0)) // MOVQ AX, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
|
||||
var pin = "_f32_end_{n}"
|
||||
self.parse_number(float32Type, pin, -1) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single_X0() // RANGE float32
|
||||
self.Emit("MOVSS", _X0, jit.Ptr(_VP, 0)) // MOVSS X0, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_f64(_ *_Instr) {
|
||||
var pin = "_f64_end_{n}"
|
||||
self.parse_number(float64Type, pin, -1) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.Emit("MOVSD", _VAR_st_Dv, _X0) // MOVSD st.Dv, X0
|
||||
self.Emit("MOVSD", _X0, jit.Ptr(_VP, 0)) // MOVSD X0, (VP)
|
||||
self.Link(pin)
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_unquote(_ *_Instr) {
|
||||
|
|
@ -1478,19 +1320,19 @@ func (self *_Assembler) _asm_OP_map_init(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i8(p *_Instr) {
|
||||
self.parse_signed(int8Type, "", p.vi()) // PARSE int8
|
||||
self.parse_signed() // PARSE int8
|
||||
self.range_signed_CX(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int8, mapassign, st.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i16(p *_Instr) {
|
||||
self.parse_signed(int16Type, "", p.vi()) // PARSE int16
|
||||
self.parse_signed() // PARSE int16
|
||||
self.range_signed_CX(_I_int16, _T_int16, math.MinInt16, math.MaxInt16) // RANGE int16
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN int16, mapassign, st.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i32(p *_Instr) {
|
||||
self.parse_signed(int32Type, "", p.vi()) // PARSE int32
|
||||
self.parse_signed() // PARSE int32
|
||||
self.range_signed_CX(_I_int32, _T_int32, math.MinInt32, math.MaxInt32) // RANGE int32
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int32, mapassign, st.Iv
|
||||
|
|
@ -1501,7 +1343,7 @@ func (self *_Assembler) _asm_OP_map_key_i32(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_i64(p *_Instr) {
|
||||
self.parse_signed(int64Type, "", p.vi()) // PARSE int64
|
||||
self.parse_signed() // PARSE int64
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN int64, mapassign, st.Iv
|
||||
} else {
|
||||
|
|
@ -1511,19 +1353,19 @@ func (self *_Assembler) _asm_OP_map_key_i64(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u8(p *_Instr) {
|
||||
self.parse_unsigned(uint8Type, "", p.vi()) // PARSE uint8
|
||||
self.parse_unsigned() // PARSE uint8
|
||||
self.range_unsigned_CX(_I_uint8, _T_uint8, math.MaxUint8) // RANGE uint8
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint8, vt.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u16(p *_Instr) {
|
||||
self.parse_unsigned(uint16Type, "", p.vi()) // PARSE uint16
|
||||
self.parse_unsigned() // PARSE uint16
|
||||
self.range_unsigned_CX(_I_uint16, _T_uint16, math.MaxUint16) // RANGE uint16
|
||||
self.mapassign_std(p.vt(), _VAR_st_Iv) // MAPASSIGN uint16, vt.Iv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u32(p *_Instr) {
|
||||
self.parse_unsigned(uint32Type, "", p.vi()) // PARSE uint32
|
||||
self.parse_unsigned() // PARSE uint32
|
||||
self.range_unsigned_CX(_I_uint32, _T_uint32, math.MaxUint32) // RANGE uint32
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint32, vt.Iv
|
||||
|
|
@ -1534,7 +1376,7 @@ func (self *_Assembler) _asm_OP_map_key_u32(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
|
||||
self.parse_unsigned(uint64Type, "", p.vi()) // PARSE uint64
|
||||
self.parse_unsigned() // PARSE uint64
|
||||
if vt := p.vt(); !mapfast(vt) {
|
||||
self.mapassign_std(vt, _VAR_st_Iv) // MAPASSIGN uint64, vt.Iv
|
||||
} else {
|
||||
|
|
@ -1544,14 +1386,14 @@ func (self *_Assembler) _asm_OP_map_key_u64(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_f32(p *_Instr) {
|
||||
self.parse_number(float32Type, "", p.vi()) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.range_single_X0() // RANGE float32
|
||||
self.Emit("MOVSS", _X0, _VAR_st_Dv) // MOVSS X0, st.Dv
|
||||
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_map_key_f64(p *_Instr) {
|
||||
self.parse_number(float64Type, "", p.vi()) // PARSE NUMBER
|
||||
self.parse_number() // PARSE NUMBER
|
||||
self.mapassign_std(p.vt(), _VAR_st_Dv) // MAPASSIGN ${p.vt()}, mapassign, st.Dv
|
||||
}
|
||||
|
||||
|
|
@ -1725,19 +1567,14 @@ func (self *_Assembler) _asm_OP_unmarshal_text_p(p *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_lspace(_ *_Instr) {
|
||||
self.lspace("_{n}")
|
||||
}
|
||||
|
||||
func (self *_Assembler) lspace(subfix string) {
|
||||
var label = "_lspace" + subfix
|
||||
self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL
|
||||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , label) // JA _nospace_{n}
|
||||
self.Sjmp("JA" , "_nospace_{n}") // JA _nospace_{n}
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , label) // JNC _nospace_{n}
|
||||
self.Sjmp("JNC" , "_nospace_{n}") // JNC _nospace_{n}
|
||||
|
||||
/* test up to 4 characters */
|
||||
for i := 0; i < 3; i++ {
|
||||
|
|
@ -1746,9 +1583,9 @@ func (self *_Assembler) lspace(subfix string) {
|
|||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX
|
||||
self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '
|
||||
self.Sjmp("JA" , label) // JA _nospace_{n}
|
||||
self.Sjmp("JA" , "_nospace_{n}") // JA _nospace_{n}
|
||||
self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX
|
||||
self.Sjmp("JNC" , label) // JNC _nospace_{n}
|
||||
self.Sjmp("JNC" , "_nospace_{n}") // JNC _nospace_{n}
|
||||
}
|
||||
|
||||
/* handle over to the native function */
|
||||
|
|
@ -1761,7 +1598,7 @@ func (self *_Assembler) lspace(subfix string) {
|
|||
self.Emit("CMPQ" , _AX, _IL) // CMPQ AX, IL
|
||||
self.Sjmp("JAE" , _LB_eof_error) // JAE _eof_error
|
||||
self.Emit("MOVQ" , _AX, _IC) // MOVQ AX, IC
|
||||
self.Link(label) // _nospace_{n}:
|
||||
self.Link("_nospace_{n}") // _nospace_{n}:
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_match_char(p *_Instr) {
|
||||
|
|
@ -1779,16 +1616,6 @@ func (self *_Assembler) _asm_OP_check_char(p *_Instr) {
|
|||
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_check_char_0(p *_Instr) {
|
||||
self.check_eof(1)
|
||||
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(p.vb()))) // CMPB (IP)(IC), ${p.vb()}
|
||||
self.Xjmp("JE" , p.vi()) // JE {p.vi()}
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_add(p *_Instr) {
|
||||
self.Emit("ADDQ", jit.Imm(int64(p.vi())), _IC) // ADDQ ${p.vi()}, IC
|
||||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_load(_ *_Instr) {
|
||||
self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX) // MOVQ (ST), AX
|
||||
self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _VP) // MOVQ (ST)(AX), VP
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
*/
|
||||
|
||||
package decoder
|
||||
|
||||
|
|
@ -230,16 +230,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
src: "true",
|
||||
exp: true,
|
||||
val: new(bool),
|
||||
},
|
||||
{
|
||||
key: "_OP_bool/skip",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: `"true"`,
|
||||
exp: nil,
|
||||
val: new(bool),
|
||||
err: &MismatchTypeError{Src: `"true"`, Pos: 0, Type: reflect.TypeOf(true)},
|
||||
},
|
||||
{
|
||||
}, {
|
||||
key: "_OP_bool/false",
|
||||
ins: []_Instr{newInsOp(_OP_bool)},
|
||||
src: "false",
|
||||
|
|
@ -275,8 +266,7 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
src: "falsx",
|
||||
err: SyntaxError{Src: `falsx`, Pos: 4, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(bool),
|
||||
},
|
||||
{
|
||||
}, {
|
||||
key: "_OP_num/positive",
|
||||
ins: []_Instr{newInsOp(_OP_num)},
|
||||
src: "1.234e5",
|
||||
|
|
@ -292,13 +282,13 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_num/error_eof",
|
||||
ins: []_Instr{newInsOp(_OP_num)},
|
||||
src: "-",
|
||||
err: SyntaxError{Src: `-`, Pos: 1, Code: types.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `-`, Pos: 1, Code: types.ERR_EOF},
|
||||
val: new(json.Number),
|
||||
}, {
|
||||
key: "_OP_num/error_invalid_char",
|
||||
ins: []_Instr{newInsOp(_OP_num)},
|
||||
src: "xxx",
|
||||
err: SyntaxError{Src: `xxx`, Pos: 1, Code: types.ERR_INVALID_CHAR},
|
||||
err: SyntaxError{Src: `xxx`, Pos: 0, Code: types.ERR_INVALID_CHAR},
|
||||
val: new(json.Number),
|
||||
}, {
|
||||
key: "_OP_i8",
|
||||
|
|
@ -312,12 +302,11 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
src: "1234",
|
||||
err: error_value("1234", reflect.TypeOf(int8(0))),
|
||||
val: new(int8),
|
||||
},
|
||||
{
|
||||
}, {
|
||||
key: "_OP_i8/error_wrong_type",
|
||||
ins: []_Instr{newInsOp(_OP_i8)},
|
||||
src: "12.34",
|
||||
err: &MismatchTypeError{Src: `12.34`, Pos: 0, Type: int8Type},
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(int8),
|
||||
}, {
|
||||
key: "_OP_u8",
|
||||
|
|
@ -335,13 +324,13 @@ func TestAssembler_OpCode(t *testing.T) {
|
|||
key: "_OP_u8/error_underflow",
|
||||
ins: []_Instr{newInsOp(_OP_u8)},
|
||||
src: "-123",
|
||||
err: &MismatchTypeError{Src: `-123`, Pos: 0, Type: uint8Type},
|
||||
err: SyntaxError{Src: `-123`, Pos: 0, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(uint8),
|
||||
}, {
|
||||
key: "_OP_u8/error_wrong_type",
|
||||
ins: []_Instr{newInsOp(_OP_u8)},
|
||||
src: "12.34",
|
||||
err: &MismatchTypeError{Src: `12.34`, Pos: 0, Type: uint8Type},
|
||||
err: SyntaxError{Src: `12.34`, Pos: 2, Code: types.ERR_INVALID_NUMBER_FMT},
|
||||
val: new(uint8),
|
||||
}, {
|
||||
key: "_OP_f32",
|
||||
|
|
|
|||
|
|
@ -94,11 +94,6 @@ const (
|
|||
_OP_recurse
|
||||
_OP_goto
|
||||
_OP_switch
|
||||
_OP_check_char_0
|
||||
_OP_dismatch_err
|
||||
_OP_go_skip
|
||||
_OP_add
|
||||
_OP_debug
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -170,9 +165,6 @@ var _OpNames = [256]string {
|
|||
_OP_recurse : "recurse",
|
||||
_OP_goto : "goto",
|
||||
_OP_switch : "switch",
|
||||
_OP_check_char_0 : "check_char_0",
|
||||
_OP_dismatch_err : "dismatch_err",
|
||||
_OP_add : "add",
|
||||
}
|
||||
|
||||
func (self _Op) String() string {
|
||||
|
|
@ -568,26 +560,26 @@ func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) {
|
|||
|
||||
func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
|
||||
switch vt.Kind() {
|
||||
case reflect.Bool : self.compilePrimitive (vt, p, _OP_bool)
|
||||
case reflect.Int : self.compilePrimitive (vt, p, _OP_int())
|
||||
case reflect.Int8 : self.compilePrimitive (vt, p, _OP_i8)
|
||||
case reflect.Int16 : self.compilePrimitive (vt, p, _OP_i16)
|
||||
case reflect.Int32 : self.compilePrimitive (vt, p, _OP_i32)
|
||||
case reflect.Int64 : self.compilePrimitive (vt, p, _OP_i64)
|
||||
case reflect.Uint : self.compilePrimitive (vt, p, _OP_uint())
|
||||
case reflect.Uint8 : self.compilePrimitive (vt, p, _OP_u8)
|
||||
case reflect.Uint16 : self.compilePrimitive (vt, p, _OP_u16)
|
||||
case reflect.Uint32 : self.compilePrimitive (vt, p, _OP_u32)
|
||||
case reflect.Uint64 : self.compilePrimitive (vt, p, _OP_u64)
|
||||
case reflect.Uintptr : self.compilePrimitive (vt, p, _OP_uintptr())
|
||||
case reflect.Float32 : self.compilePrimitive (vt, p, _OP_f32)
|
||||
case reflect.Float64 : self.compilePrimitive (vt, p, _OP_f64)
|
||||
case reflect.Bool : self.compilePrimitive (p, _OP_bool)
|
||||
case reflect.Int : self.compilePrimitive (p, _OP_int())
|
||||
case reflect.Int8 : self.compilePrimitive (p, _OP_i8)
|
||||
case reflect.Int16 : self.compilePrimitive (p, _OP_i16)
|
||||
case reflect.Int32 : self.compilePrimitive (p, _OP_i32)
|
||||
case reflect.Int64 : self.compilePrimitive (p, _OP_i64)
|
||||
case reflect.Uint : self.compilePrimitive (p, _OP_uint())
|
||||
case reflect.Uint8 : self.compilePrimitive (p, _OP_u8)
|
||||
case reflect.Uint16 : self.compilePrimitive (p, _OP_u16)
|
||||
case reflect.Uint32 : self.compilePrimitive (p, _OP_u32)
|
||||
case reflect.Uint64 : self.compilePrimitive (p, _OP_u64)
|
||||
case reflect.Uintptr : self.compilePrimitive (p, _OP_uintptr())
|
||||
case reflect.Float32 : self.compilePrimitive (p, _OP_f32)
|
||||
case reflect.Float64 : self.compilePrimitive (p, _OP_f64)
|
||||
case reflect.String : self.compileString (p, vt)
|
||||
case reflect.Array : self.compileArray (p, sp, vt)
|
||||
case reflect.Interface : self.compileInterface (p, vt)
|
||||
case reflect.Map : self.compileMap (p, sp, vt)
|
||||
case reflect.Ptr : self.compilePtr (p, sp, vt)
|
||||
case reflect.Slice : self.compileSlice (p, sp, vt)
|
||||
case reflect.Slice : self.compileSlice (p, sp, vt.Elem())
|
||||
case reflect.Struct : self.compileStruct (p, sp, vt)
|
||||
default : panic (&json.UnmarshalTypeError{Type: vt})
|
||||
}
|
||||
|
|
@ -627,15 +619,14 @@ func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op
|
|||
i := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
p.tag(sp + 1)
|
||||
skip := self.checkIfSkip(p, vt, '{')
|
||||
p.add(_OP_save)
|
||||
p.chr(_OP_match_char, '{')
|
||||
p.add(_OP_map_init)
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_lspace)
|
||||
j := p.pc()
|
||||
p.chr(_OP_check_char, '}')
|
||||
p.chr(_OP_match_char, '"')
|
||||
skip2 := p.pc()
|
||||
p.rtt(op, vt)
|
||||
|
||||
/* match the closing quote if needed */
|
||||
|
|
@ -647,7 +638,6 @@ func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op
|
|||
p.add(_OP_lspace)
|
||||
p.chr(_OP_match_char, ':')
|
||||
self.compileOne(p, sp + 2, vt.Elem())
|
||||
p.pin(skip2)
|
||||
p.add(_OP_load)
|
||||
k0 := p.pc()
|
||||
p.add(_OP_lspace)
|
||||
|
|
@ -656,7 +646,6 @@ func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op
|
|||
p.chr(_OP_match_char, ',')
|
||||
p.add(_OP_lspace)
|
||||
p.chr(_OP_match_char, '"')
|
||||
skip3 := p.pc()
|
||||
p.rtt(op, vt)
|
||||
|
||||
/* match the closing quote if needed */
|
||||
|
|
@ -668,7 +657,6 @@ func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op
|
|||
p.add(_OP_lspace)
|
||||
p.chr(_OP_match_char, ':')
|
||||
self.compileOne(p, sp + 2, vt.Elem())
|
||||
p.pin(skip3)
|
||||
p.add(_OP_load)
|
||||
p.int(_OP_goto, k0)
|
||||
p.pin(j)
|
||||
|
|
@ -678,7 +666,6 @@ func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op
|
|||
p.add(_OP_goto)
|
||||
p.pin(i)
|
||||
p.add(_OP_nil_1)
|
||||
p.pin(skip)
|
||||
p.pin(x)
|
||||
}
|
||||
|
||||
|
|
@ -705,8 +692,7 @@ func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type) {
|
|||
x := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
p.tag(sp)
|
||||
skip := self.checkIfSkip(p, vt, '[')
|
||||
|
||||
p.chr(_OP_match_char, '[')
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_lspace)
|
||||
v := []int{p.pc()}
|
||||
|
|
@ -739,54 +725,50 @@ func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type) {
|
|||
/* restore the stack */
|
||||
p.pin(w)
|
||||
p.add(_OP_drop)
|
||||
|
||||
p.pin(skip)
|
||||
p.pin(x)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
|
||||
if vt.Elem().Kind() == byteType.Kind() {
|
||||
self.compileSliceBin(p, sp, vt)
|
||||
func (self *_Compiler) compileSlice(p *_Program, sp int, et reflect.Type) {
|
||||
if et.Kind() == byteType.Kind() {
|
||||
self.compileSliceBin(p, sp, et)
|
||||
} else {
|
||||
self.compileSliceList(p, sp, vt)
|
||||
self.compileSliceList(p, sp, et)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSliceBin(p *_Program, sp int, vt reflect.Type) {
|
||||
func (self *_Compiler) compileSliceBin(p *_Program, sp int, et reflect.Type) {
|
||||
i := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
j := p.pc()
|
||||
p.chr(_OP_check_char, '[')
|
||||
skip := self.checkIfSkip(p, vt, '"')
|
||||
p.chr(_OP_match_char, '"')
|
||||
k := p.pc()
|
||||
p.chr(_OP_check_char, '"')
|
||||
p.add(_OP_bin)
|
||||
x := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(j)
|
||||
self.compileSliceBody(p, sp, vt.Elem())
|
||||
self.compileSliceBody(p, sp, et)
|
||||
y := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(i)
|
||||
p.pin(k)
|
||||
p.add(_OP_nil_3)
|
||||
p.pin(x)
|
||||
p.pin(skip)
|
||||
p.pin(y)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSliceList(p *_Program, sp int, vt reflect.Type) {
|
||||
func (self *_Compiler) compileSliceList(p *_Program, sp int, et reflect.Type) {
|
||||
i := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
p.tag(sp)
|
||||
skip := self.checkIfSkip(p, vt, '[')
|
||||
self.compileSliceBody(p, sp, vt.Elem())
|
||||
p.chr(_OP_match_char, '[')
|
||||
self.compileSliceBody(p, sp, et)
|
||||
x := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(i)
|
||||
p.add(_OP_nil_3)
|
||||
p.pin(x)
|
||||
p.pin(skip)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) {
|
||||
|
|
@ -814,19 +796,18 @@ func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) {
|
|||
|
||||
func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
|
||||
if vt == jsonNumberType {
|
||||
self.compilePrimitive(vt, p, _OP_num)
|
||||
self.compilePrimitive(p, _OP_num)
|
||||
} else {
|
||||
self.compileStringBody(vt, p)
|
||||
self.compileStringBody(p)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStringBody(vt reflect.Type, p *_Program) {
|
||||
func (self *_Compiler) compileStringBody(p *_Program) {
|
||||
i := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
skip := self.checkIfSkip(p, vt, '"')
|
||||
p.chr(_OP_match_char, '"')
|
||||
p.add(_OP_str)
|
||||
p.pin(i)
|
||||
p.pin(skip)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
|
||||
|
|
@ -848,9 +829,7 @@ func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
|
|||
p.tag(sp)
|
||||
n := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
|
||||
skip := self.checkIfSkip(p, vt, '{')
|
||||
|
||||
p.chr(_OP_match_char, '{')
|
||||
p.add(_OP_save)
|
||||
p.add(_OP_lspace)
|
||||
x := p.pc()
|
||||
|
|
@ -912,7 +891,6 @@ end_of_object:
|
|||
p.pin(y1)
|
||||
p.add(_OP_drop)
|
||||
p.pin(n)
|
||||
p.pin(skip)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
|
||||
|
|
@ -955,8 +933,7 @@ func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Typ
|
|||
p.add(_OP_lspace)
|
||||
n0 := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
|
||||
skip := self.checkIfSkip(p, stringType, '"')
|
||||
p.chr(_OP_match_char, '"')
|
||||
|
||||
/* also check for inner "null" */
|
||||
n1 = p.pc()
|
||||
|
|
@ -968,9 +945,6 @@ func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Typ
|
|||
p.rtt(_OP_deref, vt)
|
||||
}
|
||||
|
||||
n2 := p.pc()
|
||||
p.chr(_OP_check_char_0, '"')
|
||||
|
||||
/* string opcode selector */
|
||||
_OP_string := func() _Op {
|
||||
if ft == jsonNumberType {
|
||||
|
|
@ -1012,12 +986,6 @@ func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Typ
|
|||
|
||||
/* "null" but not a pointer, act as if the field is not present */
|
||||
if vk != reflect.Ptr {
|
||||
pc2 := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(n2)
|
||||
p.rtt(_OP_dismatch_err, vt)
|
||||
p.int(_OP_add, 1)
|
||||
p.pin(pc2)
|
||||
p.pin(n0)
|
||||
return
|
||||
}
|
||||
|
|
@ -1028,14 +996,7 @@ func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Typ
|
|||
p.pin(n0) // `is_null` jump location
|
||||
p.pin(n1) // `is_null_quote` jump location
|
||||
p.add(_OP_nil_1)
|
||||
pc2 := p.pc()
|
||||
p.add(_OP_goto)
|
||||
p.pin(n2)
|
||||
p.rtt(_OP_dismatch_err, vt)
|
||||
p.int(_OP_add, 1)
|
||||
p.pin(pc)
|
||||
p.pin(pc2)
|
||||
p.pin(skip)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
|
||||
|
|
@ -1057,13 +1018,11 @@ func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
|
|||
p.pin(j)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compilePrimitive(vt reflect.Type, p *_Program, op _Op) {
|
||||
func (self *_Compiler) compilePrimitive(p *_Program, op _Op) {
|
||||
i := p.pc()
|
||||
p.add(_OP_is_null)
|
||||
// skip := self.checkPrimitive(p, vt)
|
||||
p.add(op)
|
||||
p.pin(i)
|
||||
// p.pin(skip)
|
||||
}
|
||||
|
||||
func (self *_Compiler) compileUnmarshalEnd(p *_Program, vt reflect.Type, i int) {
|
||||
|
|
@ -1122,14 +1081,3 @@ func (self *_Compiler) compileUnmarshalTextPtr(p *_Program, vt reflect.Type) {
|
|||
p.rtt(_OP_unmarshal_text_p, vt)
|
||||
p.pin(i)
|
||||
}
|
||||
|
||||
func (self *_Compiler) checkIfSkip(p *_Program, vt reflect.Type, c byte) int {
|
||||
j := p.pc()
|
||||
p.chr(_OP_check_char_0, c)
|
||||
p.rtt(_OP_dismatch_err, vt)
|
||||
s := p.pc()
|
||||
p.add(_OP_go_skip)
|
||||
p.pin(j)
|
||||
p.int(_OP_add, 1)
|
||||
return s
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ import (
|
|||
`encoding/json`
|
||||
`reflect`
|
||||
`runtime`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/native`
|
||||
`github.com/bytedance/sonic/internal/native/types`
|
||||
|
|
@ -96,25 +95,11 @@ func (self *Decoder) Decode(val interface{}) error {
|
|||
if vp == nil || vv.Type.Kind() != reflect.Ptr {
|
||||
return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
|
||||
}
|
||||
initalized := (vv.Type.Pack().Elem().Kind() == reflect.Ptr) && (*(*unsafe.Pointer)(vp) != nil)
|
||||
|
||||
/* create a new stack, and call the decoder */
|
||||
sb, etp := newStack(), rt.PtrElem(vv.Type)
|
||||
nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)
|
||||
|
||||
if err != nil {
|
||||
// clear val memory when decode failed,
|
||||
// not including MismatcheTypeError
|
||||
if _, ok := err.(*MismatchTypeError); !ok {
|
||||
ev := reflect.ValueOf(val).Elem()
|
||||
if initalized {
|
||||
ev.Elem().Set(reflect.Zero(ev.Elem().Type()))
|
||||
} else {
|
||||
ev.Set(reflect.Zero(ev.Type()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return the stack back */
|
||||
self.i = nb
|
||||
freeStack(sb)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
`sync`
|
||||
`testing`
|
||||
`time`
|
||||
`reflect`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
|
|
@ -86,169 +85,6 @@ func init() {
|
|||
_ = json.Unmarshal([]byte(TwitterJson), &_BindingValue)
|
||||
}
|
||||
|
||||
|
||||
func TestSkipMismatchTypeError(t *testing.T) {
|
||||
t.Run("struct", func(t *testing.T) {
|
||||
println("TestSkipError")
|
||||
type skiptype struct {
|
||||
A int `json:"a"`
|
||||
B string `json:"b"`
|
||||
|
||||
Pass *int `json:"pass"`
|
||||
|
||||
C struct{
|
||||
|
||||
Pass4 interface{} `json:"pass4"`
|
||||
|
||||
D struct{
|
||||
E float32 `json:"e"`
|
||||
} `json:"d"`
|
||||
|
||||
Pass2 int `json:"pass2"`
|
||||
|
||||
} `json:"c"`
|
||||
|
||||
E bool `json:"e"`
|
||||
F []int `json:"f"`
|
||||
G map[string]int `json:"g"`
|
||||
H bool `json:"h,string"`
|
||||
|
||||
Pass3 int `json:"pass2"`
|
||||
|
||||
I json.Number `json:"i"`
|
||||
}
|
||||
var obj, obj2 = &skiptype{Pass:new(int)}, &skiptype{Pass:new(int)}
|
||||
var data = `{"a":"","b":1,"c":{"d":true,"pass2":1,"pass4":true},"e":{},"f":"","g":[],"pass":null,"h":"1.0","i":true,"pass3":1}`
|
||||
d := NewDecoder(data)
|
||||
err := d.Decode(obj)
|
||||
err2 := json.Unmarshal([]byte(data), obj2)
|
||||
println(err2.Error())
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
// assert.Equal(t, len(data), d.i)
|
||||
assert.Equal(t, obj2, obj)
|
||||
if te, ok := err.(*MismatchTypeError); ok {
|
||||
assert.Equal(t, reflect.TypeOf(obj.I), te.Type)
|
||||
assert.Equal(t, strings.Index(data, `"i":t`)+4, te.Pos)
|
||||
println(err.Error())
|
||||
} else {
|
||||
t.Fatal("invalid error")
|
||||
}
|
||||
})
|
||||
t.Run("array", func(t *testing.T) {
|
||||
var obj, obj2 = &[]int{}, &[]int{}
|
||||
var data = `["",1,true]`
|
||||
d := NewDecoder(data)
|
||||
err := d.Decode(obj)
|
||||
err2 := json.Unmarshal([]byte(data), obj2)
|
||||
// println(err2.Error())
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
// assert.Equal(t, len(data), d.i)
|
||||
assert.Equal(t, obj2, obj)
|
||||
})
|
||||
t.Run("map", func(t *testing.T) {
|
||||
var obj, obj2 = &map[int]int{}, &map[int]int{}
|
||||
var data = `{"true" : { },"1":1,"2" : true,"3":3}`
|
||||
d := NewDecoder(data)
|
||||
err := d.Decode(obj)
|
||||
err2 := json.Unmarshal([]byte(data), obj2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
// assert.Equal(t, len(data), d.i)
|
||||
assert.Equal(t, obj2, obj)
|
||||
})
|
||||
t.Run("map error", func(t *testing.T) {
|
||||
var obj, obj2 = &map[int]int{}, &map[int]int{}
|
||||
var data = `{"true" : { ],"1":1,"2" : true,"3":3}`
|
||||
d := NewDecoder(data)
|
||||
err := d.Decode(obj)
|
||||
err2 := json.Unmarshal([]byte(data), obj2)
|
||||
println(err.Error())
|
||||
println(err2.Error())
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
// assert.Equal(t, len(data), d.i)
|
||||
// assert.Equal(t, obj2, obj)
|
||||
})
|
||||
}
|
||||
|
||||
type testStruct struct {
|
||||
A int `json:"a"`
|
||||
B string `json:"b"`
|
||||
}
|
||||
|
||||
func TestClearMemWhenError(t *testing.T) {
|
||||
var data = `{"a":1,"b":"1"]`
|
||||
var v, v2 testStruct
|
||||
_, err := decode(data, &v, false)
|
||||
err2 := json.Unmarshal([]byte(data), &v2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, v2, v)
|
||||
|
||||
var z, z2 = new(testStruct), new(testStruct)
|
||||
_, err = decode(data, z, false)
|
||||
err2 = json.Unmarshal([]byte(data), z2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, z2, z)
|
||||
|
||||
var y, y2 *testStruct
|
||||
_, err = decode(data, &y, false)
|
||||
err2 = json.Unmarshal([]byte(data), &y2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, y2, y)
|
||||
|
||||
var x, x2 = new(testStruct), new(testStruct)
|
||||
_, err = decode(data, &x, false)
|
||||
err2 = json.Unmarshal([]byte(data), &x2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, x2, x)
|
||||
|
||||
var a, a2 interface{}
|
||||
_, err = decode(data, &a, false)
|
||||
err2 = json.Unmarshal([]byte(data), &a2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, a2, a)
|
||||
|
||||
var b, b2 = new(interface{}), new(interface{})
|
||||
_, err = decode(data, b, false)
|
||||
err2 = json.Unmarshal([]byte(data), b2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, b2, b)
|
||||
|
||||
var c, c2 *interface{}
|
||||
_, err = decode(data, &c, false)
|
||||
err2 = json.Unmarshal([]byte(data), &c2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, c2, c)
|
||||
|
||||
var d, d2 = new(interface{}), new(interface{})
|
||||
_, err = decode(data, &d, false)
|
||||
err2 = json.Unmarshal([]byte(data), &d2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, d2, d)
|
||||
|
||||
var e, e2 map[string]interface{}
|
||||
_, err = decode(data, &e, false)
|
||||
err2 = json.Unmarshal([]byte(data), &e2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, e2, e)
|
||||
|
||||
var f, f2 = new(map[string]interface{}), new(map[string]interface{})
|
||||
_, err = decode(data, &f, false)
|
||||
err2 = json.Unmarshal([]byte(data), &f2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, f2, f)
|
||||
|
||||
var g, g2 = new(map[string]interface{}), new(map[string]interface{})
|
||||
_, err = decode(data, g, false)
|
||||
err2 = json.Unmarshal([]byte(data), g2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, g2, g)
|
||||
|
||||
var h, h2 *map[string]interface{}
|
||||
_, err = decode(data, &h, false)
|
||||
err2 = json.Unmarshal([]byte(data), &h2)
|
||||
assert.Equal(t, err2 == nil, err == nil)
|
||||
assert.Equal(t, h2, h)
|
||||
}
|
||||
|
||||
func TestDecodeCorrupt(t *testing.T) {
|
||||
var ds = []string{
|
||||
`{,}`,
|
||||
|
|
|
|||
|
|
@ -40,10 +40,6 @@ func (self SyntaxError) Error() string {
|
|||
}
|
||||
|
||||
func (self SyntaxError) Description() string {
|
||||
return "Syntax error " + self.description()
|
||||
}
|
||||
|
||||
func (self SyntaxError) description() string {
|
||||
i := 16
|
||||
p := self.Pos - i
|
||||
q := self.Pos + i
|
||||
|
|
@ -76,7 +72,7 @@ func (self SyntaxError) description() string {
|
|||
|
||||
/* compose the error description */
|
||||
return fmt.Sprintf(
|
||||
"at index %d: %s\n\n\t%s\n\t%s^%s\n",
|
||||
"Syntax error at index %d: %s\n\n\t%s\n\t%s^%s\n",
|
||||
self.Pos,
|
||||
self.Message(),
|
||||
self.Src[p:q],
|
||||
|
|
@ -121,52 +117,6 @@ func error_type(vt *rt.GoType) error {
|
|||
return &json.UnmarshalTypeError{Type: vt.Pack()}
|
||||
}
|
||||
|
||||
type MismatchTypeError struct {
|
||||
Pos int
|
||||
Src string
|
||||
Type reflect.Type
|
||||
}
|
||||
|
||||
func swithchJSONType (src string, pos int) string {
|
||||
var val string
|
||||
switch src[pos] {
|
||||
case 'f': fallthrough
|
||||
case 't': val = "bool"
|
||||
case '"': val = "string"
|
||||
case '{': val = "object"
|
||||
case '[': val = "array"
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': val = "number"
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (self MismatchTypeError) Error() string {
|
||||
se := SyntaxError {
|
||||
Pos : self.Pos,
|
||||
Src : self.Src,
|
||||
Code : types.ERR_MISMATCH,
|
||||
}
|
||||
return fmt.Sprintf("Mismatch type %s with value %s %q", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
|
||||
}
|
||||
|
||||
func (self MismatchTypeError) Description() string {
|
||||
se := SyntaxError {
|
||||
Pos : self.Pos,
|
||||
Src : self.Src,
|
||||
Code : types.ERR_MISMATCH,
|
||||
}
|
||||
return fmt.Sprintf("Mismatch type %s with value %s %s", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_mismatch(src string, pos int, vt *rt.GoType) error {
|
||||
return &MismatchTypeError {
|
||||
Pos : pos,
|
||||
Src : src,
|
||||
Type : vt.Pack(),
|
||||
}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func error_field(name string) error {
|
||||
return errors.New("json: unknown field " + strconv.Quote(name))
|
||||
|
|
|
|||
|
|
@ -28,20 +28,6 @@ import (
|
|||
|
||||
var (
|
||||
byteType = reflect.TypeOf(byte(0))
|
||||
intType = reflect.TypeOf(int(0))
|
||||
int8Type = reflect.TypeOf(int8(0))
|
||||
int16Type = reflect.TypeOf(int16(0))
|
||||
int32Type = reflect.TypeOf(int32(0))
|
||||
int64Type = reflect.TypeOf(int64(0))
|
||||
uintType = reflect.TypeOf(uint(0))
|
||||
uint8Type = reflect.TypeOf(uint8(0))
|
||||
uint16Type = reflect.TypeOf(uint16(0))
|
||||
uint32Type = reflect.TypeOf(uint32(0))
|
||||
uint64Type = reflect.TypeOf(uint64(0))
|
||||
float32Type = reflect.TypeOf(float32(0))
|
||||
float64Type = reflect.TypeOf(float64(0))
|
||||
stringType = reflect.TypeOf("")
|
||||
bytesType = reflect.TypeOf([]byte(nil))
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
base64CorruptInputError = reflect.TypeOf(base64.CorruptInputError(0))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -130,15 +130,9 @@ func TestCompatUnmarshalStd(t *testing.T) {
|
|||
require.Equal(t, jerr, serr)
|
||||
require.Equal(t, jobj, sobj)
|
||||
|
||||
x := struct{
|
||||
A json.Number
|
||||
B json.Number
|
||||
}{}
|
||||
y := struct{
|
||||
A json.Number
|
||||
B json.Number
|
||||
}{}
|
||||
data = []byte(`{"A":"1", "C":-1, "B":1}`)
|
||||
x := struct{A json.Number}{}
|
||||
y := struct{A json.Number}{}
|
||||
data = []byte(`{"A":"1", "B":-1}`)
|
||||
cfg = sonic.Config{
|
||||
DisallowUnknownFields: true,
|
||||
}.Froze()
|
||||
|
|
@ -148,7 +142,7 @@ func TestCompatUnmarshalStd(t *testing.T) {
|
|||
dec.DisallowUnknownFields()
|
||||
jerr = dec.Decode(&y)
|
||||
require.Equal(t, jerr, serr)
|
||||
// require.Equal(t, y, x)
|
||||
require.Equal(t, y, x)
|
||||
}
|
||||
|
||||
func TestCompatEncoderDefault(t *testing.T) {
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -3,10 +3,10 @@ module github.com/bytedance/sonic
|
|||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/klauspost/cpuid/v2 v2.0.9
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670
|
||||
)
|
||||
|
|
|
|||
14
go.sum
14
go.sum
|
|
@ -1,7 +1,5 @@
|
|||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
|
@ -10,20 +8,14 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
|||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ const (
|
|||
ERR_INVALID_NUMBER_FMT ParsingError = 6
|
||||
ERR_RECURSE_EXCEED_MAX ParsingError = 7
|
||||
ERR_FLOAT_INFINITY ParsingError = 8
|
||||
ERR_MISMATCH ParsingError = 9
|
||||
)
|
||||
|
||||
var _ParsingErrors = []string{
|
||||
|
|
@ -87,7 +86,6 @@ var _ParsingErrors = []string{
|
|||
ERR_INVALID_NUMBER_FMT : "invalid number format",
|
||||
ERR_RECURSE_EXCEED_MAX : "recursion exceeded max depth",
|
||||
ERR_FLOAT_INFINITY : "float number is infinity",
|
||||
ERR_MISMATCH : "mismatched type with value",
|
||||
}
|
||||
|
||||
func (self ParsingError) Error() string {
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright 2022 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package issue_test
|
||||
|
||||
import (
|
||||
`testing`
|
||||
|
||||
`encoding/json`
|
||||
. `github.com/bytedance/sonic`
|
||||
`github.com/stretchr/testify/require`
|
||||
)
|
||||
|
||||
func TestIssue_UnmarshalBase64(t *testing.T) {
|
||||
var obj, stdobj []byte
|
||||
tests := []string {
|
||||
`"xy\r\nzu"`,
|
||||
`"xy\/\/"`,
|
||||
`"\/\/=="`,
|
||||
`"\/\/\u003d\u003d"`,
|
||||
`"\u0030\u0030\u0030\u003d"`,
|
||||
}
|
||||
for _, data := range(tests) {
|
||||
stderr := json.Unmarshal([]byte(data), &stdobj)
|
||||
err := Unmarshal([]byte(data), &obj)
|
||||
require.NoError(t, stderr, data)
|
||||
require.NoError(t, err, data)
|
||||
require.Equal(t, stdobj, obj, data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue_UnmarshalBase64Error(t *testing.T) {
|
||||
var obj, stdobj []byte
|
||||
tests := []string {
|
||||
`"xy\r\nzu0==="`,
|
||||
`"xy\/\/`,
|
||||
`"\/\/==`,
|
||||
`"\/\/\u003d0\u003d"`,
|
||||
`"\u0030\u0030\u0030\u003d`,
|
||||
}
|
||||
for _, data := range(tests) {
|
||||
stderr := json.Unmarshal([]byte(data), &stdobj)
|
||||
err := Unmarshal([]byte(data), &obj)
|
||||
require.Equal(t, stderr != nil, err != nil)
|
||||
}
|
||||
var _, _ = obj, stdobj
|
||||
}
|
||||
Loading…
Reference in a new issue