mirror of
https://github.com/json-iterator/go.git
synced 2024-11-27 08:30:57 +02:00
int lazy any
This commit is contained in:
parent
9df37bbd68
commit
ba410b045b
@ -13,9 +13,24 @@ func Unmarshal(data []byte, v interface{}) error {
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func UnmarshalAny(data []byte) (Any, error) {
|
||||
iter := ParseBytes(data)
|
||||
any := iter.ReadAny()
|
||||
if iter.Error == io.EOF {
|
||||
return any, nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
|
||||
}
|
||||
return any, iter.Error
|
||||
}
|
||||
|
||||
func UnmarshalFromString(str string, v interface{}) error {
|
||||
// safe to do the unsafe cast here, as str is always referenced in this scope
|
||||
data := *(*[]byte)(unsafe.Pointer(&str))
|
||||
@ -24,9 +39,26 @@ func UnmarshalFromString(str string, v interface{}) error {
|
||||
if iter.Error == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
func UnmarshalAnyFromString(str string) (Any, error) {
|
||||
// safe to do the unsafe cast here, as str is always referenced in this scope
|
||||
data := *(*[]byte)(unsafe.Pointer(&str))
|
||||
iter := ParseBytes(data)
|
||||
any := iter.ReadAny()
|
||||
if iter.Error == io.EOF {
|
||||
return any, nil
|
||||
}
|
||||
if iter.Error == nil {
|
||||
iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
|
||||
}
|
||||
return nil, iter.Error
|
||||
}
|
||||
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
stream := NewStream(buf, 4096)
|
||||
|
57
feature_any.go
Normal file
57
feature_any.go
Normal file
@ -0,0 +1,57 @@
|
||||
package jsoniter
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Any interface {
|
||||
LastError() error
|
||||
ToBool() bool
|
||||
ToInt() int
|
||||
ToInt32() int32
|
||||
ToInt64() int64
|
||||
ToFloat32() float32
|
||||
ToFloat64() float64
|
||||
ToString() string
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReadAny() Any {
|
||||
valueType := iter.WhatIsNext()
|
||||
switch valueType {
|
||||
case Nil:
|
||||
iter.skipFixedBytes(4)
|
||||
return &nilAny{}
|
||||
case Number:
|
||||
dotFound, lazyBuf := iter.skipNumber()
|
||||
if dotFound {
|
||||
return &floatLazyAny{lazyBuf, nil, nil}
|
||||
} else {
|
||||
return &intLazyAny{lazyBuf, nil, nil, 0}
|
||||
}
|
||||
}
|
||||
iter.reportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iter *Iterator) skipNumber() (bool, []byte) {
|
||||
dotFound := false
|
||||
var lazyBuf []byte
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
c := iter.buf[i]
|
||||
if c == '.' {
|
||||
dotFound = true
|
||||
continue
|
||||
}
|
||||
switch c {
|
||||
case ' ', '\n', '\r', '\t', ',', '}', ']':
|
||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:i]...)
|
||||
iter.head = i
|
||||
return dotFound, lazyBuf
|
||||
}
|
||||
}
|
||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
|
||||
if !iter.loadMore() {
|
||||
iter.head = iter.tail;
|
||||
return dotFound, lazyBuf
|
||||
}
|
||||
}
|
||||
}
|
39
feature_any_float.go
Normal file
39
feature_any_float.go
Normal file
@ -0,0 +1,39 @@
|
||||
package jsoniter
|
||||
|
||||
type floatLazyAny struct {
|
||||
buf []byte
|
||||
iter *Iterator
|
||||
err error
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) LastError() error {
|
||||
return any.err
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToBool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToInt() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToInt32() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToInt64() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToFloat32() float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToFloat64() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *floatLazyAny) ToString() string {
|
||||
return ""
|
||||
}
|
66
feature_any_int.go
Normal file
66
feature_any_int.go
Normal file
@ -0,0 +1,66 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type intLazyAny struct {
|
||||
buf []byte
|
||||
iter *Iterator
|
||||
err error
|
||||
cache int64
|
||||
}
|
||||
|
||||
func (any *intLazyAny) fillCache() {
|
||||
if any.err != nil {
|
||||
return
|
||||
}
|
||||
iter := any.iter
|
||||
if iter == nil {
|
||||
iter = NewIterator()
|
||||
}
|
||||
iter.ResetBytes(any.buf)
|
||||
any.cache = iter.ReadInt64()
|
||||
if iter.Error != io.EOF {
|
||||
iter.reportError("intLazyAny", "there are bytes left")
|
||||
}
|
||||
any.err = iter.Error
|
||||
}
|
||||
|
||||
func (any *intLazyAny) LastError() error {
|
||||
return any.err
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToBool() bool {
|
||||
return any.ToInt64() != 0
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToInt() int {
|
||||
any.fillCache()
|
||||
return int(any.cache)
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToInt32() int32 {
|
||||
any.fillCache()
|
||||
return int32(any.cache)
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToInt64() int64 {
|
||||
any.fillCache()
|
||||
return any.cache
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToFloat32() float32 {
|
||||
any.fillCache()
|
||||
return float32(any.cache)
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToFloat64() float64 {
|
||||
any.fillCache()
|
||||
return float64(any.cache)
|
||||
}
|
||||
|
||||
func (any *intLazyAny) ToString() string {
|
||||
return *(*string)(unsafe.Pointer(&any.buf))
|
||||
}
|
36
feature_any_nil.go
Normal file
36
feature_any_nil.go
Normal file
@ -0,0 +1,36 @@
|
||||
package jsoniter
|
||||
|
||||
type nilAny struct {
|
||||
}
|
||||
|
||||
func (any *nilAny) LastError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (any *nilAny) ToBool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (any *nilAny) ToInt() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *nilAny) ToInt32() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *nilAny) ToInt64() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *nilAny) ToFloat32() float32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *nilAny) ToFloat64() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (any *nilAny) ToString() string {
|
||||
return ""
|
||||
}
|
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
)
|
||||
|
||||
func Test_read_uint64_invalid(t *testing.T) {
|
||||
@ -99,6 +100,16 @@ func Test_read_int64_overflow(t *testing.T) {
|
||||
should.NotNil(iter.Error)
|
||||
}
|
||||
|
||||
func Test_read_int64_as_any(t *testing.T) {
|
||||
should := require.New(t)
|
||||
any, err := UnmarshalAnyFromString("1234")
|
||||
should.Nil(err)
|
||||
should.Equal(1234, any.ToInt())
|
||||
should.Equal(io.EOF, any.LastError())
|
||||
should.Equal("1234", any.ToString())
|
||||
should.True(any.ToBool())
|
||||
}
|
||||
|
||||
func Test_write_uint8(t *testing.T) {
|
||||
vals := []uint8{0, 1, 11, 111, 255}
|
||||
for _, val := range vals {
|
||||
|
@ -12,6 +12,13 @@ func Test_read_null(t *testing.T) {
|
||||
should.True(iter.ReadNil())
|
||||
iter = ParseString(`null`)
|
||||
should.Nil(iter.Read())
|
||||
iter = ParseString(`null`)
|
||||
any, err := UnmarshalAnyFromString(`null`)
|
||||
should.Nil(err)
|
||||
should.Equal(0, any.ToInt())
|
||||
should.Equal(float64(0), any.ToFloat64())
|
||||
should.Equal("", any.ToString())
|
||||
should.False(any.ToBool())
|
||||
}
|
||||
|
||||
func Test_write_null(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user