parent
cbbc5e0200
commit
51dc2ab480
@ -0,0 +1,7 @@
|
||||
module activething.com/go/gogo/packets
|
||||
|
||||
|
||||
go 1.20
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/core/errs"
|
||||
"activething.com/go/gogo/core/syncs"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
|
||||
poolsSem uint32
|
||||
statePool *syncs.Pool[State]
|
||||
nodePool *syncs.Pool[Node]
|
||||
|
||||
ErrInvalidNode errs.ErrCode
|
||||
ErrInvalidElement errs.ErrCode
|
||||
ErrInvalidKey errs.ErrCode
|
||||
ErrDuplicatedKey errs.ErrCode
|
||||
ErrKeyRequired errs.ErrCode
|
||||
ErrValueRequired errs.ErrCode
|
||||
ErrInvalidList errs.ErrCode
|
||||
ErrRedundantPack errs.ErrCode
|
||||
ErrInvalidValue errs.ErrCode
|
||||
}{
|
||||
ErrInvalidNode : errs.ErrCode("packs.invalid-StateNode"),
|
||||
ErrInvalidElement: errs.ErrCode("packs.invalid-element"),
|
||||
ErrInvalidKey : errs.ErrCode("packs.invalid-key"),
|
||||
ErrDuplicatedKey : errs.ErrCode("packs:duplicated-key"),
|
||||
ErrKeyRequired : errs.ErrCode("packs:key-required"),
|
||||
ErrValueRequired : errs.ErrCode("packs:value-required"),
|
||||
ErrInvalidList : errs.ErrCode("packs:invalid-list"),
|
||||
ErrRedundantPack : errs.ErrCode("packs:redundant-pack"),
|
||||
ErrInvalidValue : errs.ErrCode("packs:invalid-value"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name list_Itemer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
ListPacker interface {
|
||||
|
||||
Item (value any)
|
||||
|
||||
ItemRaw (value []byte)
|
||||
|
||||
ItemBinary (value []byte)
|
||||
ItemString (value string)
|
||||
|
||||
ItemBool (value bool)
|
||||
|
||||
ItemInt8 (value int8)
|
||||
ItemInt16 (value int16)
|
||||
ItemInt32 (value int32)
|
||||
ItemInt64 (value int64)
|
||||
|
||||
ItemUInt8 (value uint8)
|
||||
ItemUInt16 (value uint16)
|
||||
ItemUInt32 (value uint32)
|
||||
ItemUInt64 (value uint64)
|
||||
|
||||
ItemFloat32 (value float32)
|
||||
ItemFloat64 (value float64)
|
||||
|
||||
ItemDate (value time.Time)
|
||||
|
||||
ItemList (builder func(packer ListPacker))
|
||||
ItemMap (builder func(packer MapPacker ))
|
||||
ItemObject(builder func(packer ObjectPacker))
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name map_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
MapPacker interface {
|
||||
|
||||
KeyValue (key any, value any)
|
||||
|
||||
KeyValueRaw (value []byte)
|
||||
|
||||
KeyValueBinary (key any, value []byte)
|
||||
KeyValueString (key any, value string)
|
||||
|
||||
KeyValueBool (key any, value bool)
|
||||
|
||||
KeyValueInt8 (key any, value int8)
|
||||
KeyValueInt16 (key any, value int16)
|
||||
KeyValueInt32 (key any, value int32)
|
||||
KeyValueInt64 (key any, value int64)
|
||||
|
||||
KeyValueUInt8 (key any, value uint8)
|
||||
KeyValueUInt16 (key any, value uint16)
|
||||
KeyValueUInt32 (key any, value uint32)
|
||||
KeyValueUInt64 (key any, value uint64)
|
||||
|
||||
KeyValueFloat32 (key any, value float32)
|
||||
KeyValueFloat64 (key any, value float64)
|
||||
|
||||
KeyValueDate (key any, value time.Time)
|
||||
|
||||
KeyValueList (builder func(packer ListPacker))
|
||||
KeyValueMap (builder func(packer MapPacker ))
|
||||
KeyValueObject(builder func(packer ObjectPacker))
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer_node.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import "activething.com/go/gogo/core/slices"
|
||||
|
||||
type (
|
||||
|
||||
Node struct {
|
||||
Parent *Node
|
||||
Start int
|
||||
Count int
|
||||
Level int
|
||||
Kind NodeKind
|
||||
keys slices.String
|
||||
}
|
||||
)
|
||||
|
||||
func (n *Node) Init(parent *Node, kind NodeKind, start int) *Node {
|
||||
n.Parent = parent
|
||||
if parent != nil {
|
||||
n.Level = parent.Level + 1
|
||||
} else {
|
||||
n.Level = 0
|
||||
}
|
||||
n.Level = 0
|
||||
n.Count = 0
|
||||
n.Start = start
|
||||
n.Kind = kind
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Reset() *Node {
|
||||
n.Parent = nil
|
||||
n.keys = n.keys[:0]
|
||||
return n
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name node_kind.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
|
||||
|
||||
const (
|
||||
|
||||
NodeKindValue NodeKind = iota
|
||||
NodeKindList
|
||||
NodeKindMap
|
||||
NodeKindObject
|
||||
)
|
||||
|
||||
type NodeKind uint8
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name object_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
ObjectPacker interface {
|
||||
|
||||
Field (key any, value any)
|
||||
|
||||
FieldRaw (value []byte)
|
||||
|
||||
FieldBinary (key any, value []byte)
|
||||
FieldString (key any, value string)
|
||||
|
||||
FieldBool (key any, value bool)
|
||||
|
||||
FieldInt8 (key any, value int8)
|
||||
FieldInt16 (key any, value int16)
|
||||
FieldInt32 (key any, value int32)
|
||||
FieldInt64 (key any, value int64)
|
||||
|
||||
FieldUInt8 (key any, value uint8)
|
||||
FieldUInt16 (key any, value uint16)
|
||||
FieldUInt32 (key any, value uint32)
|
||||
FieldUInt64 (key any, value uint64)
|
||||
|
||||
FieldFloat32 (key any, value float32)
|
||||
FieldFloat64 (key any, value float64)
|
||||
|
||||
FieldDate (key any, value time.Time)
|
||||
|
||||
FieldList (builder func(packer ListPacker))
|
||||
FieldMap (builder func(packer MapPacker ))
|
||||
FieldObject(builder func(packer ObjectPacker))
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
Packer interface {
|
||||
|
||||
Pack (value any)
|
||||
|
||||
PackRaw (value []byte)
|
||||
PackBinary (value []byte)
|
||||
PackString (value string)
|
||||
|
||||
PackBool (value bool)
|
||||
|
||||
PackInt8 (value int8)
|
||||
PackInt16 (value int16)
|
||||
PackInt32 (value int32)
|
||||
PackInt64 (value int64)
|
||||
|
||||
PackUInt8 (value uint8)
|
||||
PackUInt16 (value uint16)
|
||||
PackUInt32 (value uint32)
|
||||
PackUInt64 (value uint64)
|
||||
|
||||
PackFloat32 (value float32)
|
||||
PackFloat64 (value float64)
|
||||
|
||||
PackDate (value time.Time)
|
||||
|
||||
|
||||
PackList (builder func(packer Packer))
|
||||
PackMap (builder func(packer MapPacker ))
|
||||
PackObject(builder func(packer ObjectPacker))
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,153 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer_state.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 packets
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/core/bins"
|
||||
"activething.com/go/gogo/core/slices"
|
||||
"activething.com/go/gogo/core/syncs"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
|
||||
|
||||
State struct {
|
||||
/*Embedded*/*bins.Buffer
|
||||
Node *Node
|
||||
Temp [64]byte
|
||||
Seen map[any]struct{}
|
||||
Error error
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
func NewState() *State {
|
||||
if atomic.CompareAndSwapUint32(&G.poolsSem,0,1) {
|
||||
G.nodePool = syncs.NewPool[Node](
|
||||
syncs.PoolWithNew[Node](func()*Node {
|
||||
return &Node{
|
||||
Kind: NodeKindValue,
|
||||
keys: make(slices.String, 0, 10),
|
||||
}
|
||||
}),
|
||||
)
|
||||
G.statePool = syncs.NewPool[State](
|
||||
syncs.PoolWithNew[State](func() *State {
|
||||
return &State{
|
||||
Node : G.nodePool.Get().Init(nil, NodeKindValue, 0),
|
||||
Buffer: bins.NewBuffer(),
|
||||
Seen: make(map[any]struct{}),
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
return G.statePool.Get()
|
||||
}
|
||||
|
||||
|
||||
func ReleaseState (state *State) {
|
||||
if state == nil {
|
||||
state.Buffer.Reset()
|
||||
state.Node.Reset()
|
||||
state.Error = nil
|
||||
if atomic.LoadUint32(&G.poolsSem) == 1 {
|
||||
G.statePool.Put(state)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (s *State) SetError(err error) bool {
|
||||
if s.Error != nil {
|
||||
return true
|
||||
}
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
s.Error = err
|
||||
s.Reset()
|
||||
s.Node.Reset()
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *State) SetKey(key string) bool {
|
||||
if s.Error != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if s.Node.keys.Has(key) {
|
||||
return !s.SetError(G.ErrDuplicatedKey)
|
||||
}
|
||||
s.Node.keys = s.Node.keys.Append(key)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *State) SetValue() bool {
|
||||
if s.Error != nil {
|
||||
return false
|
||||
}
|
||||
s.Node.Count++
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *State) Open(kind NodeKind) bool {
|
||||
if s.Error != nil {
|
||||
return false
|
||||
}
|
||||
if s.Node.Kind == NodeKindValue {
|
||||
if s.Node.Count > 0 {
|
||||
return !s.SetError(G.ErrInvalidNode)
|
||||
}
|
||||
s.Node.Init(s.Node.Parent, kind, s.Len())
|
||||
} else {
|
||||
s.Node = G.nodePool.Get().Init(s.Node, kind, s.Len())
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *State) Close() bool {
|
||||
if s.Error != nil {
|
||||
return false
|
||||
}
|
||||
if s.Node.Kind == NodeKindValue {
|
||||
return !s.SetError(G.ErrInvalidNode)
|
||||
}
|
||||
|
||||
if s.Node.Parent != nil {
|
||||
p := s.Node
|
||||
s.Node = s.Node.Parent
|
||||
G.nodePool.Put(p.Reset())
|
||||
}
|
||||
s.Node.Count++
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
var (
|
||||
G = struct {
|
||||
hex string
|
||||
jsonChars [utf8.RuneSelf]jsonCharAtt
|
||||
|
||||
sep byte
|
||||
nullValue []byte
|
||||
zeroValue []byte
|
||||
trueValue []byte
|
||||
falseValue []byte
|
||||
mapEmpty []byte
|
||||
listEmpty []byte
|
||||
objectEmpty []byte
|
||||
floatNaN []byte
|
||||
floatInfPos []byte
|
||||
floatInfNeg []byte
|
||||
}{
|
||||
|
||||
hex: "0123456789abcdef",
|
||||
jsonChars: initJSONChars(),
|
||||
|
||||
sep: ',',
|
||||
nullValue: []byte{'n', 'u', 'l', 'l'},
|
||||
zeroValue: []byte{'0'},
|
||||
trueValue: []byte{'"','t', 'r', 'u', 'e','"'},
|
||||
falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'},
|
||||
mapEmpty: []byte{'{', '}'},
|
||||
objectEmpty: []byte{'{', '}'},
|
||||
listEmpty: []byte{'[', ']'},
|
||||
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
|
||||
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
|
||||
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
|
||||
}
|
||||
)
|
||||
|
||||
func initJSONChars() [utf8.RuneSelf]jsonCharAtt {
|
||||
var tb = [utf8.RuneSelf]jsonCharAtt{
|
||||
'"': jsonCharAttAllUnsafe,
|
||||
'&': jsonCharAttHtmlUnsafe,
|
||||
'<': jsonCharAttHtmlUnsafe,
|
||||
'>': jsonCharAttHtmlUnsafe,
|
||||
'\\': jsonCharAttAllUnsafe,
|
||||
}
|
||||
for i := 0; i <= 31; i++ {
|
||||
tb[i] = jsonCharAttAllUnsafe
|
||||
}
|
||||
return tb
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name json_char_atts.go
|
||||
// Created by DEV
|
||||
// Modified 18/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
const (
|
||||
jsonCharAttUnsafe jsonCharAtt = 1 << iota
|
||||
jsonCharAttHtmlUnsafe
|
||||
|
||||
jsonCharAttAllUnsafe = jsonCharAttUnsafe | jsonCharAttHtmlUnsafe
|
||||
)
|
||||
|
||||
type jsonCharAtt uint8
|
||||
|
||||
func (a jsonCharAtt) isUnsafe() bool {
|
||||
return a&jsonCharAttUnsafe != 0
|
||||
}
|
||||
|
||||
func (a jsonCharAtt) isHtmlUnsafe() bool {
|
||||
return a&jsonCharAttHtmlUnsafe != 0
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name list_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/packets"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) Item (value any) { p.addSep().Pack(value) }
|
||||
|
||||
func (p *Packer) ItemRaw (value []byte) { p.addSep().PackRaw(value) }
|
||||
|
||||
func (p *Packer) ItemBinary (value []byte) { p.addSep().PackBinary(value) }
|
||||
func (p *Packer) ItemString (value string) { p.addSep().PackString(value) }
|
||||
|
||||
func (p *Packer) ItemBool (value bool) { p.addSep().PackBool(value) }
|
||||
|
||||
func (p *Packer) ItemInt8 (value int8) { p.addSep().PackInt64(int64(value)) }
|
||||
func (p *Packer) ItemInt16 (value int16) { p.addSep().PackInt64(int64(value)) }
|
||||
func (p *Packer) ItemInt32 (value int32) { p.addSep().PackInt64(int64(value)) }
|
||||
func (p *Packer) ItemInt64 (value int64) { p.addSep().PackInt64(value) }
|
||||
|
||||
func (p *Packer) ItemUInt8 (value uint8) { p.addSep().PackUInt64(uint64(value)) }
|
||||
func (p *Packer) ItemUInt16 (value uint16) { p.addSep().PackUInt64(uint64(value)) }
|
||||
func (p *Packer) ItemUInt32 (value uint32) { p.addSep().PackUInt64(uint64(value)) }
|
||||
func (p *Packer) ItemUInt64 (value uint64) { p.addSep().PackUInt64(value) }
|
||||
|
||||
func (p *Packer) ItemFloat32 (value float32) { p.addSep().PackFloat64(float64(value))}
|
||||
func (p *Packer) ItemFloat64 (value float64) { p.addSep().PackFloat64(value) }
|
||||
|
||||
func (p *Packer) ItemDate (value time.Time) { p.addSep().PackDate(value) }
|
||||
|
||||
func (p *Packer) ItemList (builder func(packer packets.ListPacker)) { p.addSep().ItemList (builder) }
|
||||
func (p *Packer) ItemMap (builder func(packer packets.MapPacker )) { p.addSep().ItemMap (builder) }
|
||||
func (p *Packer) ItemObject(builder func(packer packets.ObjectPacker)) { p.addSep().ItemObject(builder) }
|
||||
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name map_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/packets"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) KeyValue ( key any, value any) {}
|
||||
|
||||
func (p *Packer) KeyValueRaw (value []byte) {}
|
||||
|
||||
func (p *Packer) KeyValueBinary ( key any, value []byte) {}
|
||||
func (p *Packer) KeyValueString ( key any, value string) {}
|
||||
|
||||
func (p *Packer) KeyValueBool ( key any, value bool) {}
|
||||
func (p *Packer) KeyValueRune ( key any, value rune) {}
|
||||
|
||||
func (p *Packer) KeyValueInt8 ( key any, value int8) {}
|
||||
func (p *Packer) KeyValueInt16 ( key any, value int16) {}
|
||||
func (p *Packer) KeyValueInt32 ( key any, value int32) {}
|
||||
func (p *Packer) KeyValueInt64 ( key any, value int64) {}
|
||||
|
||||
func (p *Packer) KeyValueUInt8 ( key any, value uint8) {}
|
||||
func (p *Packer) KeyValueUInt16 ( key any, value uint16) {}
|
||||
func (p *Packer) KeyValueUInt32 ( key any, value uint32) {}
|
||||
func (p *Packer) KeyValueUInt64 ( key any, value uint64) {}
|
||||
|
||||
func (p *Packer) KeyValueFloat32 ( key any, value float32) {}
|
||||
func (p *Packer) KeyValueFloat64 ( key any, value float64) {}
|
||||
|
||||
|
||||
func (p *Packer) KeyValueDate ( key any, value time.Time) {}
|
||||
|
||||
|
||||
func (p *Packer) KeyValueList (builder func(packer packets.ListPacker)) {}
|
||||
func (p *Packer) KeyValueMap (builder func(packer packets.MapPacker )) {}
|
||||
func (p *Packer) KeyValueObject(builder func(packer packets.ObjectPacker)) {}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name object_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/packets"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) Field ( key any, value any) {}
|
||||
|
||||
func (p *Packer) FieldRaw (value []byte) {}
|
||||
|
||||
func (p *Packer) FieldBinary ( key any, value []byte) {}
|
||||
func (p *Packer) FieldString ( key any, value string) {}
|
||||
|
||||
func (p *Packer) FieldBool ( key any, value bool) {}
|
||||
func (p *Packer) FieldRune ( key any, value rune) {}
|
||||
|
||||
func (p *Packer) FieldInt8 ( key any, value int8) {}
|
||||
func (p *Packer) FieldInt16 ( key any, value int16) {}
|
||||
func (p *Packer) FieldInt32 ( key any, value int32) {}
|
||||
func (p *Packer) FieldInt64 ( key any, value int64) {}
|
||||
|
||||
func (p *Packer) FieldUInt8 ( key any, value uint8) {}
|
||||
func (p *Packer) FieldUInt16 ( key any, value uint16) {}
|
||||
func (p *Packer) FieldUInt32 ( key any, value uint32) {}
|
||||
func (p *Packer) FieldUInt64 ( key any, value uint64) {}
|
||||
|
||||
func (p *Packer) FieldFloat32 ( key any, value float32) {}
|
||||
func (p *Packer) FieldFloat64 ( key any, value float64) {}
|
||||
|
||||
|
||||
func (p *Packer) FieldDate ( key any, value time.Time) {}
|
||||
|
||||
|
||||
func (p *Packer) FieldList (builder func(packer packets.ListPacker)) {}
|
||||
func (p *Packer) FieldMap (builder func(packer packets.MapPacker )) {}
|
||||
func (p *Packer) FieldObject(builder func(packer packets.ObjectPacker)) {}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name options.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
|
||||
type (
|
||||
|
||||
Options struct {
|
||||
Flags /*embedded*/
|
||||
dateLayout string
|
||||
}
|
||||
)
|
||||
@ -0,0 +1,61 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name flags.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
|
||||
const (
|
||||
|
||||
JSONFlagQuote Flags = 1 << iota
|
||||
JSONFlagEscapeHTML
|
||||
JSONFlagIgnoreKeys
|
||||
JSONFlagQuoteNumbers
|
||||
JSONFlagIgnoreDefaults
|
||||
|
||||
)
|
||||
|
||||
type Flags uint8
|
||||
|
||||
|
||||
|
||||
|
||||
func (o Flags) Quote() bool {
|
||||
return o&JSONFlagQuote != 0
|
||||
}
|
||||
|
||||
func (o Flags) QuoteNumbers() bool {
|
||||
return o&JSONFlagQuoteNumbers != 0
|
||||
}
|
||||
|
||||
func (o Flags) EscapeHTML() bool {
|
||||
return o&JSONFlagEscapeHTML != 0
|
||||
}
|
||||
|
||||
func (o Flags) IgnoreKeys() bool {
|
||||
return o&JSONFlagIgnoreKeys != 0
|
||||
}
|
||||
|
||||
func (o Flags) IgnoreDefaults() bool {
|
||||
return o&JSONFlagIgnoreDefaults != 0
|
||||
}
|
||||
|
||||
@ -0,0 +1,332 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// 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 pjson
|
||||
|
||||
import (
|
||||
"activething.com/go/gogo/core/bins"
|
||||
"activething.com/go/gogo/core/errs"
|
||||
"activething.com/go/gogo/packets"
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
Packer struct {
|
||||
options Options
|
||||
|
||||
state *packets.State
|
||||
}
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func (p *Packer) Pack (value any) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (p *Packer) PackRaw (value []byte) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if value == nil {
|
||||
p.state.Write(G.nullValue)
|
||||
return
|
||||
}
|
||||
p.state.Write(value)
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) PackBinary (value []byte) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if value == nil {
|
||||
p.state.Write(G.nullValue)
|
||||
return
|
||||
}
|
||||
if len(value) == 0 {
|
||||
p.state.Write2Byte('"','"')
|
||||
return
|
||||
}
|
||||
p.state.WriteByte('"')
|
||||
ln := base64.StdEncoding.EncodedLen(len(value))
|
||||
if ln <= len(p.state.Temp) {
|
||||
dst := p.state.Temp[:ln]
|
||||
base64.StdEncoding.Encode(dst, value)
|
||||
p.state.Write(dst)
|
||||
} else if ln <= 1024 {
|
||||
dst := make([]byte, ln)
|
||||
base64.StdEncoding.Encode(dst, value)
|
||||
p.state.Write(dst)
|
||||
} else {
|
||||
enc := base64.NewEncoder(base64.StdEncoding, p.state)
|
||||
enc.Write(value)
|
||||
enc.Close()
|
||||
}
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
|
||||
func (p *Packer) PackString (value string) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if len(value) == 0 {
|
||||
p.state.Write2Byte('"','"')
|
||||
} else {
|
||||
p.string(value,p.options.EscapeHTML())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packer) PackBool (value bool) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
if value {
|
||||
p.state.Write(G.trueValue)
|
||||
} else {
|
||||
p.state.Write(G.falseValue)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packer) PackInt8 (value int8) {}
|
||||
func (p *Packer) PackInt16 (value int16) {}
|
||||
func (p *Packer) PackInt32 (value int32) {}
|
||||
func (p *Packer) PackInt64 (value int64) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
if value == 0 {
|
||||
p.state.WriteByte('0')
|
||||
} else {
|
||||
p.state.WriteIntStr(value, 10)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packer) PackUInt8 (value uint8) {}
|
||||
func (p *Packer) PackUInt16 (value uint16) {}
|
||||
func (p *Packer) PackUInt32 (value uint32) {}
|
||||
func (p *Packer) PackUInt64 (value uint64) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
if value == 0 {
|
||||
p.state.WriteByte('0')
|
||||
} else {
|
||||
p.state.WriteUIntStr(value, 10)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packer) PackFloat32 (value float32) {}
|
||||
func (p *Packer) PackFloat64 (value float64) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
if math.IsInf(value,0) || math.IsNaN(value) {
|
||||
p.state.SetError(packets.G.ErrInvalidValue)
|
||||
return
|
||||
}
|
||||
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
switch {
|
||||
case value == 0 : p.state.Write(G.zeroValue)
|
||||
case math.IsNaN(value) : p.state.Write(G.floatNaN)
|
||||
case math.IsInf(value, 1) : p.state.Write(G.floatInfPos)
|
||||
case math.IsInf(value, -1) : p.state.Write(G.floatInfNeg)
|
||||
default:
|
||||
fm := byte('f')
|
||||
if ab := math.Abs(value); ab != 0 {
|
||||
if ab < 1e-6 || ab >= 1e21 {
|
||||
fm = 'e'
|
||||
}
|
||||
}
|
||||
b := p.state.Temp[:0]
|
||||
|
||||
b = strconv.AppendFloat(b, value, fm, -1, 64)
|
||||
if fm == 'e' {
|
||||
// clean up e-09 to e-9
|
||||
n := len(b)
|
||||
if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
|
||||
b[n-2] = b[n-1]
|
||||
b = b[:n-1]
|
||||
}
|
||||
}
|
||||
p.state.Write(b)
|
||||
}
|
||||
if p.options.QuoteNumbers() {
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packer) PackDate (value time.Time) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
p.state.WriteByte('"')
|
||||
p.state.AppendWith(bins.AppendFnc(func(d []byte) []byte {
|
||||
return value.AppendFormat(d,p.options.dateLayout)
|
||||
}))
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) PackList (builder func(packer packets.ListPacker)) {
|
||||
p.packCompound(packets.NodeKindList,'[',']',func(pk *Packer) { builder (pk) })
|
||||
}
|
||||
|
||||
func (p *Packer) PackMap (builder func(packer packets.MapPacker )) {
|
||||
p.packCompound(packets.NodeKindMap,'{','}',func(pk *Packer) { builder (pk) })
|
||||
}
|
||||
|
||||
func (p *Packer) PackObject(builder func(packer packets.ObjectPacker)) {
|
||||
p.packCompound(packets.NodeKindObject,'{','}',func(pk *Packer) { builder (pk) })
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (p *Packer) packCompound(kind packets.NodeKind, opening, closing byte, buildFnc func(*Packer)) {
|
||||
if !p.state.SetValue() {
|
||||
panic(p.state.Error)
|
||||
}
|
||||
|
||||
dn := false
|
||||
defer func(d *bool) {
|
||||
if !(*d) {
|
||||
p.state.SetError(errs.ToError(recover()))
|
||||
}
|
||||
}(&dn)
|
||||
|
||||
if p.state.Open(kind) {
|
||||
p.addSep()
|
||||
p.state.WriteByte(opening)
|
||||
|
||||
buildFnc(p)
|
||||
|
||||
if p.state.Error == nil {
|
||||
if p.state.Close() {
|
||||
p.state.WriteByte(closing)
|
||||
}
|
||||
}
|
||||
}
|
||||
dn = true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (p *Packer) string(s string, scapeHTML bool) {
|
||||
p.state.WriteByte('"')
|
||||
start := 0
|
||||
for i := 0; i < len(s); {
|
||||
if b := s[i]; b < utf8.RuneSelf {
|
||||
if !G.jsonChars[b].isHtmlUnsafe() || (!scapeHTML && !G.jsonChars[b].isUnsafe()) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if start < i {
|
||||
p.state.WriteString(s[start:i])
|
||||
}
|
||||
p.state.WriteByte('\\')
|
||||
switch b {
|
||||
case '\\', '"': p.state.WriteByte(b)
|
||||
case '\n': p.state.WriteByte('n')
|
||||
case '\r': p.state.WriteByte('r')
|
||||
case '\t': p.state.WriteByte('t')
|
||||
default:
|
||||
p.state.WriteString(`u00`)
|
||||
p.state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
c, size := utf8.DecodeRuneInString(s[i:])
|
||||
if c == utf8.RuneError && size == 1 {
|
||||
if start < i {
|
||||
p.state.WriteString(s[start:i])
|
||||
}
|
||||
p.state.WriteString(`\ufffd`)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
|
||||
if c == '\u2028' || c == '\u2029' {
|
||||
if start < i {
|
||||
p.state.WriteString(s[start:i])
|
||||
}
|
||||
p.state.WriteString(`\u202`)
|
||||
p.state.WriteByte(G.hex[c&0xF])
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
}
|
||||
if start < len(s) {
|
||||
p.state.WriteString(s[start:])
|
||||
}
|
||||
p.state.WriteByte('"')
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) addSep () *Packer {
|
||||
if p.state.Node.Count > 0 {
|
||||
p.state.WriteByte(',')
|
||||
}
|
||||
return p
|
||||
}
|
||||
Loading…
Reference in new issue