forked from mirror/go-json
Fix double pointer
This commit is contained in:
parent
5a8383f0d2
commit
ee52d7f0ae
|
@ -8,12 +8,8 @@ import (
|
||||||
|
|
||||||
func (d *Decoder) compileHead(typ *rtype) (decoder, error) {
|
func (d *Decoder) compileHead(typ *rtype) (decoder, error) {
|
||||||
switch {
|
switch {
|
||||||
case typ.Implements(unmarshalJSONType):
|
|
||||||
return newUnmarshalJSONDecoder(typ, "", ""), nil
|
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
|
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||||
case typ.Implements(unmarshalTextType):
|
|
||||||
return newUnmarshalTextDecoder(typ, "", ""), nil
|
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
|
return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil
|
||||||
}
|
}
|
||||||
|
@ -22,12 +18,8 @@ func (d *Decoder) compileHead(typ *rtype) (decoder, error) {
|
||||||
|
|
||||||
func (d *Decoder) compile(typ *rtype, structName, fieldName string) (decoder, error) {
|
func (d *Decoder) compile(typ *rtype, structName, fieldName string) (decoder, error) {
|
||||||
switch {
|
switch {
|
||||||
case typ.Implements(unmarshalJSONType):
|
|
||||||
return newUnmarshalJSONDecoder(typ, structName, fieldName), nil
|
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
case rtype_ptrTo(typ).Implements(unmarshalJSONType):
|
||||||
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||||
case typ.Implements(unmarshalTextType):
|
|
||||||
return newUnmarshalTextDecoder(typ, structName, fieldName), nil
|
|
||||||
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
case rtype_ptrTo(typ).Implements(unmarshalTextType):
|
||||||
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,18 +38,7 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
|
||||||
src := s.buf[start:s.cursor]
|
src := s.buf[start:s.cursor]
|
||||||
dst := make([]byte, len(src))
|
dst := make([]byte, len(src))
|
||||||
copy(dst, src)
|
copy(dst, src)
|
||||||
if d.isDoublePointer {
|
|
||||||
newptr := unsafe_New(d.typ.Elem())
|
|
||||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
|
||||||
typ: d.typ,
|
|
||||||
ptr: newptr,
|
|
||||||
}))
|
|
||||||
if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil {
|
|
||||||
d.annotateError(s.cursor, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*(*unsafe.Pointer)(p) = newptr
|
|
||||||
} else {
|
|
||||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: p,
|
ptr: p,
|
||||||
|
@ -58,7 +47,6 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
|
||||||
d.annotateError(s.cursor, err)
|
d.annotateError(s.cursor, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,16 +45,14 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
|
||||||
if b, ok := unquoteBytes(dst); ok {
|
if b, ok := unquoteBytes(dst); ok {
|
||||||
dst = b
|
dst = b
|
||||||
}
|
}
|
||||||
newptr := unsafe_New(d.typ.Elem())
|
|
||||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
|
||||||
typ: d.typ,
|
typ: d.typ,
|
||||||
ptr: newptr,
|
ptr: p,
|
||||||
}))
|
}))
|
||||||
if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil {
|
if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil {
|
||||||
d.annotateError(s.cursor, err)
|
d.annotateError(s.cursor, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*(*unsafe.Pointer)(p) = newptr
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1298,7 +1298,7 @@ func TestNilMarshal(t *testing.T) {
|
||||||
{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
|
{v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
|
||||||
{v: struct{ M json.Marshaler }{}, want: `{"M":null}`},
|
{v: struct{ M json.Marshaler }{}, want: `{"M":null}`},
|
||||||
{v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
|
{v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
|
||||||
{v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, // doesn't compatible with encoding/json
|
{v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
|
||||||
{v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
|
{v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
|
||||||
{v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
|
{v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
|
||||||
{v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
|
{v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
|
||||||
|
|
28
encode_vm.go
28
encode_vm.go
|
@ -226,25 +226,16 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
||||||
}
|
}
|
||||||
vv := rv.Interface()
|
vv := rv.Interface()
|
||||||
header := (*interfaceHeader)(unsafe.Pointer(&vv))
|
header := (*interfaceHeader)(unsafe.Pointer(&vv))
|
||||||
typ := header.typ
|
if header.typ.Kind() == reflect.Ptr {
|
||||||
if typ.Kind() == reflect.Ptr {
|
if rv.Elem().IsNil() {
|
||||||
typ = typ.Elem()
|
e.encodeNull()
|
||||||
|
e.encodeByte(',')
|
||||||
|
code = code.next
|
||||||
|
break
|
||||||
}
|
}
|
||||||
var c *opcode
|
|
||||||
if typ.Kind() == reflect.Map {
|
|
||||||
code, err := e.compileMap(&encodeCompileContext{
|
|
||||||
typ: typ,
|
|
||||||
root: code.root,
|
|
||||||
withIndent: e.enabledIndent,
|
|
||||||
indent: code.indent,
|
|
||||||
}, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
c = code
|
c, err := e.compileHead(&encodeCompileContext{
|
||||||
} else {
|
typ: header.typ,
|
||||||
code, err := e.compile(&encodeCompileContext{
|
|
||||||
typ: typ,
|
|
||||||
root: code.root,
|
root: code.root,
|
||||||
withIndent: e.enabledIndent,
|
withIndent: e.enabledIndent,
|
||||||
indent: code.indent,
|
indent: code.indent,
|
||||||
|
@ -252,9 +243,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c = code
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeLastCode := c.beforeLastCode()
|
beforeLastCode := c.beforeLastCode()
|
||||||
lastCode := beforeLastCode.next
|
lastCode := beforeLastCode.next
|
||||||
lastCode.idx = beforeLastCode.idx + uintptrSize
|
lastCode.idx = beforeLastCode.idx + uintptrSize
|
||||||
|
|
Loading…
Reference in New Issue