From 6327145300dda5db657b1b650132d0fe1cc49c2e Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Mon, 19 Feb 2018 23:13:33 +0800 Subject: [PATCH] move json number impl --- json_number.go | 31 ------------ reflect.go | 24 +++------ reflect_json_number.go | 112 +++++++++++++++++++++++++++++++++++++++++ reflect_native.go | 56 --------------------- 4 files changed, 120 insertions(+), 103 deletions(-) delete mode 100644 json_number.go create mode 100644 reflect_json_number.go diff --git a/json_number.go b/json_number.go deleted file mode 100644 index e187b20..0000000 --- a/json_number.go +++ /dev/null @@ -1,31 +0,0 @@ -package jsoniter - -import ( - "encoding/json" - "strconv" -) - -type Number string - -// String returns the literal text of the number. -func (n Number) String() string { return string(n) } - -// Float64 returns the number as a float64. -func (n Number) Float64() (float64, error) { - return strconv.ParseFloat(string(n), 64) -} - -// Int64 returns the number as an int64. -func (n Number) Int64() (int64, error) { - return strconv.ParseInt(string(n), 10, 64) -} - -func CastJsonNumber(val interface{}) (string, bool) { - switch typedVal := val.(type) { - case json.Number: - return string(typedVal), true - case Number: - return string(typedVal), true - } - return "", false -} diff --git a/reflect.go b/reflect.go index 5711a5a..5dc6441 100644 --- a/reflect.go +++ b/reflect.go @@ -36,8 +36,6 @@ type checkIsEmpty interface { IsEmpty(ptr unsafe.Pointer) bool } -var jsonNumberType reflect.Type -var jsoniterNumberType reflect.Type var jsonRawMessageType reflect.Type var jsoniterRawMessageType reflect.Type var anyType reflect.Type @@ -47,8 +45,6 @@ var textMarshalerType reflect.Type var textUnmarshalerType reflect.Type func init() { - jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem() - jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem() jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem() jsoniterRawMessageType = reflect.TypeOf((*RawMessage)(nil)).Elem() anyType = reflect.TypeOf((*Any)(nil)).Elem() @@ -116,13 +112,11 @@ func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val if typ == jsoniterRawMessageType { return &jsoniterRawMessageCodec{} } - if typ.AssignableTo(jsonNumberType) { - return &jsonNumberCodec{} + decoder := createDecoderOfJsonNumber(cfg, prefix, typ) + if decoder != nil { + return decoder } - if typ.AssignableTo(jsoniterNumberType) { - return &jsoniterNumberCodec{} - } - decoder := createDecoderOfMarshaler(cfg, prefix, typ) + decoder = createDecoderOfMarshaler(cfg, prefix, typ) if decoder != nil { return decoder } @@ -307,13 +301,11 @@ func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) Val if typ == jsoniterRawMessageType { return &jsoniterRawMessageCodec{} } - if typ.AssignableTo(jsonNumberType) { - return &jsonNumberCodec{} + encoder := createEncoderOfJsonNumber(cfg, prefix, typ) + if encoder != nil { + return encoder } - if typ.AssignableTo(jsoniterNumberType) { - return &jsoniterNumberCodec{} - } - encoder := createEncoderOfMarshaler(cfg, prefix, typ) + encoder = createEncoderOfMarshaler(cfg, prefix, typ) if encoder != nil { return encoder } diff --git a/reflect_json_number.go b/reflect_json_number.go new file mode 100644 index 0000000..e8fdf53 --- /dev/null +++ b/reflect_json_number.go @@ -0,0 +1,112 @@ +package jsoniter + +import ( + "encoding/json" + "strconv" + "unsafe" + "reflect" +) + +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +func CastJsonNumber(val interface{}) (string, bool) { + switch typedVal := val.(type) { + case json.Number: + return string(typedVal), true + case Number: + return string(typedVal), true + } + return "", false +} + +var jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem() +var jsoniterNumberType = reflect.TypeOf((*Number)(nil)).Elem() + +func createDecoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +func createEncoderOfJsonNumber(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +type jsonNumberCodec struct { +} + +func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*json.Number)(ptr)) = json.Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*json.Number)(ptr)) = "" + default: + *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*json.Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.Number)(ptr))) == 0 +} + +type jsoniterNumberCodec struct { +} + +func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*Number)(ptr)) = Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*Number)(ptr)) = "" + default: + *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*Number)(ptr))) == 0 +} \ No newline at end of file diff --git a/reflect_native.go b/reflect_native.go index 97ace76..bc1c969 100644 --- a/reflect_native.go +++ b/reflect_native.go @@ -369,62 +369,6 @@ func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.valType.UnsafeIndirect(ptr) == nil } -type jsonNumberCodec struct { -} - -func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { - switch iter.WhatIsNext() { - case StringValue: - *((*json.Number)(ptr)) = json.Number(iter.ReadString()) - case NilValue: - iter.skipFourBytes('n', 'u', 'l', 'l') - *((*json.Number)(ptr)) = "" - default: - *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) - } -} - -func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { - number := *((*json.Number)(ptr)) - if len(number) == 0 { - stream.writeByte('0') - } else { - stream.WriteRaw(string(number)) - } -} - -func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { - return len(*((*json.Number)(ptr))) == 0 -} - -type jsoniterNumberCodec struct { -} - -func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { - switch iter.WhatIsNext() { - case StringValue: - *((*Number)(ptr)) = Number(iter.ReadString()) - case NilValue: - iter.skipFourBytes('n', 'u', 'l', 'l') - *((*Number)(ptr)) = "" - default: - *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) - } -} - -func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { - number := *((*Number)(ptr)) - if len(number) == 0 { - stream.writeByte('0') - } else { - stream.WriteRaw(string(number)) - } -} - -func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { - return len(*((*Number)(ptr))) == 0 -} - type jsonRawMessageCodec struct { }