mirror of
https://github.com/json-iterator/go.git
synced 2025-06-06 22:36:25 +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 {
|
if iter.Error == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if iter.Error == nil {
|
||||||
|
iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
|
||||||
|
}
|
||||||
return iter.Error
|
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 {
|
func UnmarshalFromString(str string, v interface{}) error {
|
||||||
// safe to do the unsafe cast here, as str is always referenced in this scope
|
// safe to do the unsafe cast here, as str is always referenced in this scope
|
||||||
data := *(*[]byte)(unsafe.Pointer(&str))
|
data := *(*[]byte)(unsafe.Pointer(&str))
|
||||||
@ -24,9 +39,26 @@ func UnmarshalFromString(str string, v interface{}) error {
|
|||||||
if iter.Error == io.EOF {
|
if iter.Error == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if iter.Error == nil {
|
||||||
|
iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
|
||||||
|
}
|
||||||
return iter.Error
|
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) {
|
func Marshal(v interface{}) ([]byte, error) {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
stream := NewStream(buf, 4096)
|
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"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_uint64_invalid(t *testing.T) {
|
func Test_read_uint64_invalid(t *testing.T) {
|
||||||
@ -99,6 +100,16 @@ func Test_read_int64_overflow(t *testing.T) {
|
|||||||
should.NotNil(iter.Error)
|
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) {
|
func Test_write_uint8(t *testing.T) {
|
||||||
vals := []uint8{0, 1, 11, 111, 255}
|
vals := []uint8{0, 1, 11, 111, 255}
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
|
@ -12,6 +12,13 @@ func Test_read_null(t *testing.T) {
|
|||||||
should.True(iter.ReadNil())
|
should.True(iter.ReadNil())
|
||||||
iter = ParseString(`null`)
|
iter = ParseString(`null`)
|
||||||
should.Nil(iter.Read())
|
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) {
|
func Test_write_null(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user