redefiniendo el builder

packs2
DEV 3 years ago
parent 9851697694
commit 8c2c4c1a67

@ -1,372 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name builder.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
import (
"activething.com/go/gogo/core/bins"
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/packs"
"encoding/base64"
"encoding/json"
"math"
"math/cmplx"
"time"
"unicode/utf8"
)
type (
Builder struct {
options Options
encoder *json.Encoder
dateLayout string
scratch [64]byte
state packs.BuilderState
}
)
func NewBuilder (options ...opts.OptionFnc[Builder]) *Builder {
return opts.Apply[Builder](&Builder{
state : *packs.NewBuilderState(),
dateLayout: time.RFC822Z,
options : JSONOptionsQuote | JSONOptionsEscapeHTML,
}, options ...)
}
func (p *Builder) Data () []byte {
return p.state.Bytes()
}
func (p *Builder) Error() error {
return p.state.Error
}
func (p *Builder) SetError (err error) {
p.state.SetError(err)
}
func (p *Builder) Reset() {
p.encoder = nil
p.state.Reset()
}
func (p *Builder) Any (value any) {
switch value.(type) {
case json.Marshaler :
p.state.SetError(p.jsonEncoder().Encode(value))
default:
packs.BuildAny(p ,value,func(v any) error { return p.jsonEncoder().Encode(value) })
}
}
func (p *Builder) Binary (value []byte) {
if value == nil {
p.state.Write(G.nullValue)
return
}
if len(value) == 0{
p.state.Write(G.stringEmpty)
return
}
p.state.WriteByte('"')
ln := base64.StdEncoding.EncodedLen(len(value))
if ln <= len(p.scratch) {
dst := p.scratch[: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 *Builder) String(value string) {
if !p.state.SetValue() {
panic(p.state.Error)
}
if len(value) == 0 {
p.state.Write(G.stringEmpty)
} else {
p.string(value,p.options.EscapeHTML())
}
return
}
func (p *Builder) Bool (value bool) {
if !p.state.SetValue() {
panic(p.state.Error)
}
if value {
p.state.Write(G.trueValue)
} else {
p.state.Write(G.falseValue)
}
}
func (p *Builder) Rune (value rune) {
p.UInt64(uint64(value))
}
func (p *Builder) UInt(value uint) { p.UInt64(uint64(value)) }
func (p *Builder) UInt8(value uint8) { p.UInt64(uint64(value)) }
func (p *Builder) UInt16(value uint16) { p.UInt64(uint64(value)) }
func (p *Builder) UInt32(value uint32) { p.UInt64(uint64(value)) }
func (p *Builder) UInt64(value uint64) {
if !p.state.SetValue() {
panic(p.state.Error)
}
if value == 0 {
p.state.WriteByte('0')
} else {
p.state.WriteUIntStr(value, 10)
}
}
func (p *Builder) Int (value int) { p.Int64(int64(value)) }
func (p *Builder) Int8 (value int8) { p.Int64(int64(value)) }
func (p *Builder) Int16(value int16) { p.Int64(int64(value)) }
func (p *Builder) Int32(value int32) { p.Int64(int64(value)) }
func (p *Builder) Int64(value int64) {
if !p.state.SetValue() {
panic(p.state.Error)
}
if value == 0 {
if p.options.IgnoreDefaults() && p.state.Node.Kind == packs.NodeKindObject {
p.state.Truncate(p.state.Len())
return
}
p.state.WriteByte('0')
} else {
p.state.WriteIntStr(value, 10)
}
}
func (p *Builder) Float32(value float32) { p.Float64(float64(value)) }
func (p *Builder) Float64(value float64) {
if !p.state.SetValue() {
panic(p.state.Error)
}
if p.options.QuoteFloats() {
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:
p.state.WriteFloatStr(value, 'f', -1)
}
if p.options.QuoteFloats() {
p.state.WriteByte('"')
}
}
func (p *Builder) Complex64(value complex64) { p.Complex128(complex128(value)) }
func (p *Builder) Complex128(value complex128){
if !p.state.SetValue() {
panic(p.state.Error)
}
if p.options.QuoteFloats() {
p.state.WriteByte('"')
}
switch {
case value == 0 : p.state.Write(G.zeroValue)
case cmplx.IsInf(value): p.state.Write(G.floatInfPos)
case cmplx.IsNaN(value): p.state.Write(G.floatNaN)
default:
r, i := real(value), imag(value)
p.state.WriteByte('"')
p.state.WriteFloatStr(r, 'f', -1)
p.state.WriteByte('+')
p.state.WriteFloatStr(i, 'f', -1)
p.state.Write2Byte('i', '"')
}
if p.options.QuoteFloats() {
p.state.WriteByte('"')
}
}
func (p *Builder) Date (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.dateLayout)
}))
p.state.WriteByte('"')
}
func (p *Builder) List(buildFnc func(builder packs.BuilderList)) {
p.packCompound(packs.NodeKindList, '[', ']', func() { buildFnc(p) })
}
func (p *Builder) Map(buildFnc func(builder packs.BuilderMap)) {
p.packCompound(packs.NodeKindMap, '{', '}', func() { buildFnc(p) })
}
func (p *Builder) Object(buildFnc func(builder packs.BuilderObject)) {
p.packCompound(packs.NodeKindObject, '{', '}', func() { buildFnc(p) })
}
func (p *Builder) packCompound(kind packs.NodeKind, opening, closing byte, buildFnc func()) {
dn := false
defer func(d *bool) {
if !(*d) {
p.state.SetError(errs.ToError(recover()))
}
}(&dn)
if p.open(kind, opening) {
buildFnc()
p.close(closing)
}
dn = true
}
func (p *Builder) 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 *Builder) throwPanicIfError() {
if p.state.Error != nil {
panic(p.state.Error)
}
}
func (p *Builder) jsonEncoder () *json.Encoder {
if p.encoder == nil {
p.encoder = json.NewEncoder(p.state)
p.encoder.SetEscapeHTML(p.options.EscapeHTML())
}
return p.encoder
}
func (p *Builder) open(kind packs.NodeKind, opening byte) bool {
if p.state.Open(kind) {
p.addSep()
p.state.WriteByte(opening)
return true
}
return false
}
func (p *Builder) close(closing byte) bool {
if p.state.Close() {
p.state.WriteByte(closing)
return true
}
return false
}

@ -1,61 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name builderList.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
import (
"activething.com/go/gogo/packs"
"time"
)
func (p *Builder) ItemAny (value any) { p.addSep(); p.Any(value) }
func (p *Builder) ItemBinary (value []byte){ p.addSep(); p.Binary(value) }
func (p *Builder) ItemString (value string){ p.addSep(); p.String(value) }
func (p *Builder) ItemBool (value bool) { p.addSep(); p.Bool(value) }
func (p *Builder) ItemRune (value rune) { p.addSep(); p.Rune(value) }
func (p *Builder) ItemInt8 (value int8) { p.addSep(); p.Int64(int64(value)) }
func (p *Builder) ItemInt16 (value int16) { p.addSep(); p.Int64(int64(value)) }
func (p *Builder) ItemInt32 (value int32) { p.addSep(); p.Int64(int64(value)) }
func (p *Builder) ItemInt64 (value int64) { p.addSep(); p.Int64(value) }
func (p *Builder) ItemUInt8 (value uint8) { p.addSep(); p.UInt64(uint64(value)) }
func (p *Builder) ItemUInt16 (value uint16){ p.addSep(); p.UInt64(uint64(value)) }
func (p *Builder) ItemUInt32 (value uint32){ p.addSep(); p.UInt64(uint64(value)) }
func (p *Builder) ItemUInt64 (value uint64){ p.addSep(); p.UInt64(value) }
func (p *Builder) ItemFloat32(value float32){ p.addSep(); p.Float64(float64(value)) }
func (p *Builder) ItemFloat64(value float64){ p.addSep(); p.Float64(value) }
func (p *Builder) ItemComplex64 (value complex64) { p.addSep(); p.Complex128(complex128(value)) }
func (p *Builder) ItemComplex128(value complex128) { p.addSep(); p.Complex128(value) }
func (p *Builder) ItemDate (value time.Time) { p.addSep(); p.Date(value) }
func (p *Builder) ItemList (builder func(packer packs.BuilderList)) { p.addSep(); p.ItemList(builder) }
func (p *Builder) ItemMap (builder func(packer packs.BuilderMap)) { p.addSep(); p.ItemMap(builder) }
func (p *Builder) ItemObject(builder func(packer packs.BuilderObject)){ p.addSep(); p.ItemObject(builder) }

@ -1,115 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name BuilderMap.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
import (
"activething.com/go/gogo/packs"
"time"
)
func (p *Builder) ElemAny (key any, value any) {
if p.addKey(key) {
p.Any(value)
}
}
func (p *Builder) ElemBinary (key any, value []byte){
if p.addKey(key) {
p.Binary(value)
}
}
func (p *Builder) ElemString (key any, value string){
if p.addKey(key) {
p.String(value)
}
}
func (p *Builder) ElemBool (key any, value bool ){
if p.addKey(key) {
p.Bool(value)
}
}
func (p *Builder) ElemRune (key any, value rune ){
if p.addKey(key) {
p.Rune(value)
}
}
func (p *Builder) ElemInt8 (key any, value int8 ){ p.ElemInt64(key, int64(value)) }
func (p *Builder) ElemInt16 (key any, value int16 ){ p.ElemInt64(key, int64(value)) }
func (p *Builder) ElemInt32 (key any, value int32 ){ p.ElemInt64(key, int64(value)) }
func (p *Builder) ElemInt64 (key any, value int64 ){
if p.addKey(key) {
p.Int64(value)
}
}
func (p *Builder) ElemUInt8 (key any, value uint8 ){ p.ElemUInt64(key, uint64(value)) }
func (p *Builder) ElemUInt16 (key any, value uint16){ p.ElemUInt64(key, uint64(value)) }
func (p *Builder) ElemUInt32 (key any, value uint32){ p.ElemUInt64(key, uint64(value)) }
func (p *Builder) ElemUInt64 (key any, value uint64){
if p.addKey(key) {
p.UInt64(value)
}
}
func (p *Builder) ElemFloat32(key any, value float32){ p.ElemFloat64(key, float64(value)) }
func (p *Builder) ElemFloat64(key any, value float64){
if p.addKey(key) {
p.Float64(value)
}
}
func (p *Builder) ElemComplex64 (key any, value complex64 ){ p.ElemComplex128(key, complex128(value)) }
func (p *Builder) ElemComplex128(key any, value complex128){
if p.addKey(key) {
p.Complex128(value)
}
}
func (p *Builder) ElemDate (key any, value time.Time) {
if p.addKey(key) {
p.Date(value)
}
}
func (p *Builder) ElemList (key any, builder func(packer packs.BuilderList)) {
if p.addKey(key) {
p.List(builder)
}
}
func (p *Builder) ElemMap (key any, builder func(packer packs.BuilderMap)) {
if p.addKey(key) {
p.Map(builder)
}
}
func (p *Builder) ElemObject(key any, builder func(packer packs.BuilderObject)) {
if p.addKey(key) {
p.Object(builder)
}
}

@ -1,143 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name BuilderObject.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
import (
"activething.com/go/gogo/packs"
"time"
)
func (p *Builder) PropAny (name string, value any) {
if p.addName(name) {
p.Any(value)
}
}
func (p *Builder) PropBinary (name string, value []byte){
if p.options.IgnoreDefaults() && len(value) == 0 {
return
}
if p.addName(name) {
p.Binary(value)
}
}
func (p *Builder) PropString (name string, value string){
if p.options.IgnoreDefaults() && len(value) == 0 {
return
}
if p.addName(name) {
p.String(value)
}
}
func (p *Builder) PropBool (name string, value bool ){
if p.options.IgnoreDefaults() && !value {
return
}
if p.addName(name) {
p.Bool(value)
}
}
func (p *Builder) PropRune (name string, value rune ){
if p.options.IgnoreDefaults() && value == 0 {
return
}
if p.addName(name) {
p.Rune(value)
}
}
func (p *Builder) PropInt8 (name string, value int8 ){ p.PropInt64(name, int64(value)) }
func (p *Builder) PropInt16 (name string, value int16 ){ p.PropInt64(name, int64(value)) }
func (p *Builder) PropInt32 (name string, value int32 ){ p.PropInt64(name, int64(value)) }
func (p *Builder) PropInt64 (name string, value int64 ){
if p.options.IgnoreDefaults() && value == 0 {
return
}
if p.addName(name) {
p.Int64(value)
}
}
func (p *Builder) PropUInt8 (name string, value uint8 ){ p.PropUInt64(name, uint64(value)) }
func (p *Builder) PropUInt16 (name string, value uint16){ p.PropUInt64(name, uint64(value)) }
func (p *Builder) PropUInt32 (name string, value uint32){ p.PropUInt64(name, uint64(value)) }
func (p *Builder) PropUInt64 (name string, value uint64){
if p.options.IgnoreDefaults() && value == 0 {
return
}
if p.addName(name) {
p.UInt64(value)
}
}
func (p *Builder) PropFloat32(name string, value float32){ p.PropFloat64(name, float64(value)) }
func (p *Builder) PropFloat64(name string, value float64){
if p.options.IgnoreDefaults() && value == 0 {
return
}
if p.addName(name) {
p.Float64(value)
}
}
func (p *Builder) PropComplex64 (name string, value complex64 ){ p.PropComplex128(name, complex128(value)) }
func (p *Builder) PropComplex128(name string, value complex128){
if p.options.IgnoreDefaults() && value == (0+0i) {
return
}
if p.addName(name) {
p.Complex128(value)
}
}
func (p *Builder) PropDate (name string, value time.Time) {
if p.options.IgnoreDefaults() && value.IsZero() {
return
}
if p.addName(name) {
p.Date(value)
}
}
func (p *Builder) PropList (name string, builder func(packer packs.BuilderList)) {
if p.addName(name) {
p.List(builder)
}
}
func (p *Builder) PropMap (name string, builder func(packer packs.BuilderMap)) {
if p.addName(name) {
p.Map(builder)
}
}
func (p *Builder) PropObject(name string, builder func(packer packs.BuilderObject)) {
if p.addName(name) {
p.Object(builder)
}
}

@ -1,4 +0,0 @@
module actiovething.com/go/gogo/packs/pjson
go 1.20

@ -1,77 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name gogo.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
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
stringEmpty []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{'[', ']'},
stringEmpty: []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
}

@ -1,41 +0,0 @@
// ------------------------------------------------------------------------
// 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
}

@ -1,53 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name new_builder.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
func (p *Builder) addSep () {
if p.state.Node.Count > 0 {
p.state.WriteByte(',')
}
}
func (p *Builder) addKey (key any) bool {
p.addSep()
return true
}
func (p *Builder) addName(name string) bool {
p.addSep()
p.state.WriteByte('"')
p.state.WriteString(name)
p.state.WriteByte('"')
p.state.WriteByte(':')
return true
}
func (p *Builder) stringifyKey(key any) string {
return ""
}

@ -1,59 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name options.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 (
JSONOptionsQuote Options = 1 << iota
JSONOptionsEscapeHTML
JSONOptionsIgnoreKeys
JSONOptionsQuoteFloats
JSONOptionsIgnoreDefaults
)
type Options uint8
func (o Options) Quoted() bool {
return o&JSONOptionsQuote != 0
}
func (o Options) QuoteFloats() bool {
return o&JSONOptionsQuoteFloats != 0
}
func (o Options) EscapeHTML() bool {
return o&JSONOptionsEscapeHTML != 0
}
func (o Options) IgnoreKeys() bool {
return o&JSONOptionsIgnoreKeys != 0
}
func (o Options) IgnoreDefaults() bool {
return o&JSONOptionsIgnoreDefaults != 0
}

@ -1,70 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name pack_builder.go
// Created by DEV
// Modified 16/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 __packs
import "time"
type (
Builder interface {
Data () []byte
Error () error
SetError(err error)
Any (value any)
Binary (value []byte)
String (value string)
Bool (value bool)
Rune (value rune)
Int8 (value int8)
Int16 (value int16)
Int32 (value int32)
Int64 (value int64)
UInt8 (value uint8)
UInt16 (value uint16)
UInt32 (value uint32)
UInt64 (value uint64)
Float32 (value float32)
Float64 (value float64)
Complex64 (value complex64)
Complex128(value complex128)
Date(value time.Time)
BuildList (builder func(packer BuilderList))
BuildMap (builder func(packer BuilderMap))
BuildObject(builder func(packer BuilderObject))
}
)

@ -1,63 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name pack_builder_list.go
// Created by DEV
// Modified 16/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 __packs
import "time"
type (
BuilderList interface {
ItemAny (value any)
ItemBinary (value []byte)
ItemString (value string)
ItemBool (value bool)
ItemRune (value rune)
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)
ItemComplex64 (value complex64)
ItemComplex128(value complex128)
ItemDate (value time.Time)
ItemList (builder func(packer BuilderList))
ItemMap (builder func(packer BuilderMap))
ItemObject(builder func(packer BuilderObject))
}
)

@ -1,64 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name pack_builder_map.go
// Created by DEV
// Modified 16/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 __packs
import "time"
type (
BuilderMap interface {
ElemAny (key any, value any)
ElemBinary (key any, value []byte)
ElemString (key any, value string)
ElemBool (key any, value bool)
ElemRune (key any, value rune)
ElemInt8 (key any, value int8)
ElemInt16 (key any, value int16)
ElemInt32 (key any, value int32)
ElemInt64 (key any, value int64)
ElemUInt8 (key any, value uint8)
ElemUInt16 (key any, value uint16)
ElemUInt32 (key any, value uint32)
ElemUInt64 (key any, value uint64)
ElemFloat32(key any, value float32)
ElemFloat64(key any, value float64)
ElemComplex64 (key any, value complex64)
ElemComplex128(key any, value complex128)
ElemDate(key any, value time.Time)
ElemList (key any, builder func(packer BuilderList))
ElemMap (key any, builder func(packer BuilderMap))
ElemObject(key any, builder func(packer BuilderObject))
}
)

@ -1,61 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name pack_builder_object.go
// Created by DEV
// Modified 16/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 __packs
import "time"
type (
BuilderObject interface {
PropAny (name string, value any)
PropBinary (name string, value []byte)
PropString (name string, value string)
PropBool (name string, value bool)
PropRune (name string, value rune)
PropInt8 (name string, value int8)
PropInt16 (name string, value int16)
PropInt32 (name string, value int32)
PropInt64 (name string, value int64)
PropUInt8 (name string, value uint8)
PropUInt16 (name string, value uint16)
PropUInt32 (name string, value uint32)
PropUInt64 (name string, value uint64)
PropFloat32(name string, value float32)
PropFloat64(name string, value float64)
PropComplex64 (name string, value complex64)
PropComplex128(name string, value complex128)
PropDate(name string, value time.Time)
PropList (name string, builder func(packer BuilderList))
PropMap (name string, builder func(packer BuilderMap))
PropObject(name string, builder func(packer BuilderObject))
}
)

@ -1,152 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name builder_state.go
// Created by DEV
// Modified 16/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 __packs
import (
"activething.com/go/gogo/core/bins"
"activething.com/go/gogo/core/slices"
"activething.com/go/gogo/core/syncs"
"sync/atomic"
)
const maxCyclesCheckIdle = 100
type (
State struct {
*bins.Buffer/*Embedded*/
Node *StateNode
Temp [64]byte
Seen map[any]struct{}
Error error
}
)
func NewState() *State {
if atomic.CompareAndSwapUint32(&G.poolsSem,0,1) {
G.nodePool = syncs.NewPool[StateNode](
syncs.PoolWithNew[StateNode](func()*StateNode{
return &StateNode{
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
}

@ -1,60 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name builder_node.go
// Created by DEV
// Modified 16/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 __packs
import (
"activething.com/go/gogo/core/slices"
)
type (
StateNode struct {
Parent *StateNode
Start int
Count int
Level int
Kind NodeKind
keys slices.String
}
)
func (n *StateNode) Init(parent *StateNode, kind NodeKind, start int) *StateNode {
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 *StateNode) Reset() *StateNode {
n.Parent = nil
n.keys = n.keys[:0]
return n
}

@ -1,35 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name node_kind.go
// Created by DEV
// Modified 16/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 __packs
const (
NodeKindValue NodeKind = iota
NodeKindList
NodeKindMap
NodeKindObject
)
type NodeKind uint8

@ -1,215 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name m.go
// Created by DEV
// Modified 16/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 __packs
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/core/syncs"
"reflect"
"time"
)
var (
G = struct {
poolsSem uint32
statePool *syncs.Pool[State]
nodePool *syncs.Pool[StateNode]
ErrInvalidNode errs.ErrCode
ErrInvalidElement errs.ErrCode
ErrInvalidKey errs.ErrCode
ErrDuplicatedKey errs.ErrCode
ErrKeyRequired errs.ErrCode
ErrValueRequired errs.ErrCode
ErrInvalidList errs.ErrCode
ErrRedundantPack 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"),
}
)
func BuildAny(builder Builder, value any, def func(value any) error) {
switch tp := value.(type) {
case Packabler: builder.SetError(tp.BuildPack(builder))
case error : builder.String(tp.Error())
case string : builder.String(tp)
case bool : builder.Bool (tp)
case int : builder.Int64(int64(tp))
case int8 : builder.Int8 (tp)
case int16 : builder.Int16(tp)
case int32 : builder.Int32(tp)
case int64 : builder.Int64(tp)
case uint : builder.UInt64(uint64(tp))
case uint8 : builder.UInt8 (tp)
case uint16 : builder.UInt16(tp)
case uint32 : builder.UInt32(tp)
case uint64 : builder.UInt64(tp)
case float32: builder.Float32(tp)
case float64: builder.Float64(tp)
case complex64 : builder.Complex64 (tp)
case complex128: builder.Complex128(tp)
case time.Time : builder.Date(tp)
case time.Duration: builder.Int64(int64(tp))
case reflect.Value:
switch tp.Kind() {
case reflect.Slice,
reflect.Array : packList (builder,value)
case reflect.Map : packMapReflected (builder,tp)
case reflect.Struct: packObjectReflected(builder,tp)
default:
builder.SetError(def(value))
}
default:
rf := reflect.ValueOf(value)
switch rf.Kind() {
case reflect.Slice,
reflect.Array : packList (builder,value)
case reflect.Map : packMapReflected (builder,rf)
case reflect.Struct: packObjectReflected(builder,rf)
}
BuildAny(builder,reflect.ValueOf(value),def)
}
}
func packListReflected(builder Builder, value reflect.Value) {
builder.List(func (p BuilderList) {
r := value
for i:=0; i<r.Len(); i++ {
p.ItemAny(r.Index(i).Interface())
if builder.Error() != nil {
return
}
}
})
}
func packMapReflected(builder Builder, value reflect.Value) {
value.Type().Elem().Key().Kind()
builder.Map(func (p BuilderMap) {
r := value
for _,k := range r.MapKeys() {
p.ElemAny(k.Interface(),r.MapIndex(k).Interface())
if builder.Error() != nil {
return
}
}
})
}
func packObjectReflected(builder Builder, value reflect.Value) {
builder.Object(func (p BuilderObject) {
r := value
t := r.Type()
for i:=0; i < r.NumField(); i++ {
if t.Field(i).IsExported() {
p.PropAny(t.Field(i).Name,r.Field(i).Interface())
if builder.Error() != nil {
return
}
}
}
})
}
func _packList[T any ] (builder Builder, values []T, call func(BuilderList,T)) {
builder.List(func (p BuilderList) {
for _,v := range values {
call(p,v)
if builder.Error() != nil {
return
}
}
})
}
func packList(builder Builder, value any) {
switch tp := value.(type) {
case []string : _packList[string](builder,tp, func (b BuilderList, v string) { b.ItemString(v) })
case []bool : _packList[bool ](builder,tp, func (b BuilderList, v bool ) { b.ItemBool (v) })
case []int8 : _packList[int8 ](builder,tp, func (b BuilderList, v int8 ) { b.ItemInt8 (v) })
case []int16 : _packList[int16 ](builder,tp, func (b BuilderList, v int16 ) { b.ItemInt16 (v) })
case []int32 : _packList[int32 ](builder,tp, func (b BuilderList, v int32 ) { b.ItemInt32 (v) })
case []int64 : _packList[int64 ](builder,tp, func (b BuilderList, v int64 ) { b.ItemInt64 (v) })
case []uint8 : _packList[uint8 ](builder,tp, func (b BuilderList, v uint8 ) { b.ItemUInt8 (v) })
case []uint16 : _packList[uint16](builder,tp, func (b BuilderList, v uint16) { b.ItemUInt16(v) })
case []uint32 : _packList[uint32](builder,tp, func (b BuilderList, v uint32) { b.ItemUInt32(v) })
case []uint64 : _packList[uint64](builder,tp, func (b BuilderList, v uint64) { b.ItemUInt64(v) })
case []float32 : _packList[float32](builder,tp, func (b BuilderList, v float32) { b.ItemFloat32(v) })
case []float64 : _packList[float64](builder,tp, func (b BuilderList, v float64) { b.ItemFloat64(v) })
case []complex64 : _packList[complex64] (builder,tp, func (b BuilderList, v complex64 ) { b.ItemComplex64 (v) })
case []complex128: _packList[complex128](builder,tp, func (b BuilderList, v complex128) { b.ItemComplex128(v) })
case []time.Time : _packList[time.Time] (builder,tp, func (b BuilderList, v time.Time) { b.ItemDate(v) })
case []time.Duration: _packList[time.Duration](builder,tp, func (b BuilderList, v time.Duration ) { b.ItemInt64 (int64(v)) })
case []any: _packList[any](builder,tp,func (b BuilderList, v any ) { b.ItemAny (v) })
case reflect.Value:
if tp.Type().Kind() != reflect.Slice && tp.Type().Kind() != reflect.Array {
builder.SetError(G.ErrInvalidList)
return
}
packListReflected(builder,tp)
default:
packListReflected(builder,reflect.ValueOf(value))
}
}

@ -1,124 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name builder.go
// Created by DEV
// Modified 21/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 jjson
import (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/core/syncs"
"activething.com/go/gogo/packs"
"encoding/json"
"reflect"
"sync/atomic"
"time"
)
const(
maxDeepUncheck = 100
)
type (
Builder struct {
options Options
encoder *json.Encoder
dateLayout string
scratch [64]byte
state *__packs.State
}
)
func NewBuilder(options ...opts.OptionFnc[Builder]) *Builder {
if atomic.CompareAndSwapUint32(&G.sentinel,0,1) {
G.builderPool = syncs.NewPool[Builder](
syncs.PoolWithNew[Builder](func() *Builder {
return &Builder{
options : jsonOptionsDefaults,
state : __packs.NewState(),
dateLayout: time.RFC822Z,
}
}),
)
}
return opts.Apply(G.builderPool.Get(),options...)
}
func releaseBuilder(builder *Builder) {
if builder != nil {
builder.reset()
if atomic.LoadUint32(&G.sentinel) == 1 {
G.builderPool.Put(builder)
}
}
}
func (b *Builder) Any (value any) {
switch value.(type) {
default:
rv := reflect.ValueOf(value)
switch rv.Kind() {
case reflect.Struct : b.objPacker(rv)
case reflect.Map : b.mapPacker(rv)
case reflect.Slice : b.listPacker(rv)
}
}
}
func (b *Builder) BuildMap (builder func(packer __packs.BuilderMap)) {}
func (b *Builder) BuildList(builder func(packer __packs.BuilderList)) {}
func (b *Builder) BuildObject(builder func(packer __packs.BuilderList)) {}
func (b *Builder) reset () *Builder {
//todo
b.options = jsonOptionsDefaults
b.encoder = nil
b.dateLayout = time.RFC822Z
b.state.Reset()
return b
}
func stringifyKey(key reflect.Value, ops Options) (string,bool) {
return "ss",true
}

@ -1,88 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name gogo.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 jjson
import (
"activething.com/go/gogo/core/syncs"
"sync"
"unicode/utf8"
)
var (
G = struct {
objectCache sync.Map
sentinel uint32
builderPool *syncs.Pool[Builder]
hex string
jsonChars [utf8.RuneSelf]jsonCharAtt
sep byte
nullValue []byte
zeroValue []byte
trueValue []byte
falseValue []byte
mapEmpty []byte
listEmpty []byte
objectEmpty []byte
stringEmpty []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{'[', ']'},
stringEmpty: []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
}

@ -1,42 +0,0 @@
// ------------------------------------------------------------------------
// 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 jjson
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
}

@ -1,29 +0,0 @@
// ------------------------------------------------------------------------
// 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 jjson

@ -1,66 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name options.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 jjson
const (
JSONOptionsQuote Options = 1 << iota
JSONOptionsEscapeHTML
JSONOptionsIgnoreKeys
JSONOptionsQuoteFloats
JSONOptionsIgnoreDefaults
JSONOptionsSortMapKeys
jsonOptionsDefaults = JSONOptionsQuote | JSONOptionsEscapeHTML
)
type Options uint8
func (o Options) Quoted() bool {
return o&JSONOptionsQuote != 0
}
func (o Options) QuoteFloats() bool {
return o&JSONOptionsQuoteFloats != 0
}
func (o Options) EscapeHTML() bool {
return o&JSONOptionsEscapeHTML != 0
}
func (o Options) IgnoreKeys() bool {
return o&JSONOptionsIgnoreKeys != 0
}
func (o Options) IgnoreDefaults() bool {
return o&JSONOptionsIgnoreDefaults != 0
}
func (o Options) SortMapKeys() bool {
return o&JSONOptionsSortMapKeys != 0
}

@ -1,58 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer.go
// Created by DEV
// Modified 22/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 jjson
import "activething.com/go/gogo/core/errs"
type (
JSONPacker struct {}
)
func (p JSONPacker) Pack (value any) (dt []byte, er error) {
dn := false
bl := NewBuilder()
defer func (b *Builder, v *bool, e *error) {
releaseBuilder(b)
if !(*v) {
*e = errs.ToError(recover())
}
}(bl,&dn,&er)
bl.Any(value)
if bl.state.Error != nil {
er = bl.state.Error
} else {
dt = append([]byte(nil),bl.state.Bytes() ...)
}
dn = true
return
}

@ -1,110 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name list_builder.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 jjson
import (
"activething.com/go/gogo/packs"
"reflect"
"time"
)
func (b *Builder) listPacker(rv reflect.Value) {
if rv.IsNil() {
b.state.Write(G.nullValue)
return
}
if rv.Len() == 0 {
b.state.Write2Byte('[',']')
return
}
if b.state.Node.Level > maxDeepUncheck {
p := struct {
ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
len int
}{
ptr: rv.UnsafePointer(),
len: rv.Len(),
}
if _,ok := b.state.Seen[p]; ok {
b.state.SetError(__packs.G.ErrRedundantPack)
return
}
b.state.Seen[p] = struct{}{}
defer delete(b.state.Seen,p)
}
switch rv.Type().Elem().Kind() {
case reflect.String: b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemString(ev.String()) })
case reflect.Bool : b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemBool(ev.Bool()) })
case reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Int : b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemInt64(ev.Int()) })
case reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uint : b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemUInt64(ev.Uint()) })
case reflect.Float32,
reflect.Float64: b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemFloat64(ev.Float()) })
case reflect.Complex64,
reflect.Complex128: b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemComplex128(ev.Complex()) })
case reflect.Map:
b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemAny(rv.Interface()) })
case reflect.Struct:
if rv.Type() == reflect.TypeOf(time.Time{}) {
b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemDate(rv.Interface().(time.Time)) })
return
}
b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemAny(rv.Interface()) })
case reflect.Array,
reflect.Slice :
b._listPacker (rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemAny(rv.Interface()) })
default:
b._listPacker(rv, func(lb __packs.BuilderList, ev reflect.Value) { lb.ItemAny(rv.Interface()) })
}
}
func (b *Builder) _listPacker (list reflect.Value, pack func(lb __packs.BuilderList, ev reflect.Value)) {
b.BuildList(func(l __packs.BuilderList) {
for i := 0; i < list.Len(); i++ {
pack(l, list.Index(i))
if b.state.Error != nil {
return
}
}
})
}

@ -1,87 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_map.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 jjson
import (
"activething.com/go/gogo/packs"
"reflect"
"sort"
)
func (b *Builder) mapPacker (rv reflect.Value) {
if rv.IsNil() {
b.state.Write(G.nullValue)
return
}
if rv.Len() == 0 {
b.state.Write2Byte('{','}')
return
}
if b.state.Node.Level > maxDeepUncheck {
p := rv.UnsafePointer()
if _,ok := b.state.Seen[p]; ok {
b.state.SetError(__packs.G.ErrRedundantPack)
return
}
b.state.Seen[p] = struct{}{}
defer delete(b.state.Seen,p)
}
mi := rv.MapRange()
if b.options.SortMapKeys() {
ls := make([]reflectMapElem, rv.Len())
for i := 0; mi.Next(); i++ {
ls[i].k = mi.Key()
ls[i].v = mi.Value()
if !ls[i].stringifyKey(b.options) {
b.state.SetError(__packs.G.ErrInvalidKey)
return
}
}
if b.options.SortMapKeys() {
sort.Slice(ls, func(i, j int) bool { return ls[i].s < ls[j].s })
}
b.Map(func(bm __packs.BuilderMap) {
for _, e := range ls {
bm.ElemAny(e.s, e.v)
if b.state.Error != nil {
return
}
}
})
return
}
b.Map(func(bm __packs.BuilderMap) {
for i:=0; mi.Next(); i++ {
bm.ElemAny(mi.Key(),mi.Value())
if b.state.Error != nil {
return
}
}
})
}

@ -1,46 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_object.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 jjson
import "reflect"
func (b *Builder) objPacker (rv reflect.Value) {
if rv.IsNil() {
b.state.Write(G.nullValue)
return
}
if rv.Len() == 0 {
b.state.Write2Byte('{','}')
return
}
}

@ -1,43 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name reflect_map_elem.go
// Created by DEV
// Modified 22/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 jjson
import "reflect"
type (
reflectMapElem struct {
k reflect.Value
v reflect.Value
s string
}
)
func (b *reflectMapElem) stringifyKey(ops Options) (is bool) {
b.s,is = stringifyKey(b.k,ops)
return
}

@ -1,31 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packabler.go
// Created by DEV
// Modified 16/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 __packs
type (
Packabler interface {
BuildPack(builder Builder) error
}
)

@ -1,35 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer.go
// Created by DEV
// Modified 16/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 __packs
type (
Packer interface {
Pack(value any) ([]byte, error)
}
)

@ -25,8 +25,8 @@ package main
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packets"
"activething.com/go/gogo/packets/pjson"
"activething.com/go/gogo/packs"
"activething.com/go/gogo/packs/pjson"
"fmt"
"time"
)
@ -37,13 +37,13 @@ func main() {
pk := pjson.NewPacker()
pk.PackMap(func(mp packets.MapPacker) {
pk.PackMap(func(mp packs.MapPacker) {
mp.KeyValueBool("boolean",true)
mp.KeyValueBinary("binary",[]byte{22,121,21,23,23,54,67})
mp.KeyValueDate("date",time.Now())
mp.KeyValueInt16("<unakey>",34)
mp.KeyValueObject("MiObjeto",func(op packets.ObjectPacker){
mp.KeyValueObject("MiObjeto",func(op packs.ObjectPacker){
op.FieldFloat64("23",43433.3)
op.FieldString("3","dfsdfsd<fdf}{43433.3")
})

@ -9,6 +9,6 @@ use (
./core/errs
./core/opts
./core/syncs
./packets
./packs
)

@ -1,7 +0,0 @@
module activething.com/go/gogo/packets
go 1.20

@ -1,3 +1,7 @@
module activething.com/go/gogo/packs
go 1.20

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import (
"activething.com/go/gogo/core/errs"
@ -32,29 +32,31 @@ var (
G = struct {
poolsSem uint32
statePool *syncs.Pool[State]
nodePool *syncs.Pool[Node]
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
ErrInvalidElement errs.ErrCode
ErrInvalidKey errs.ErrCode
ErrDuplicatedKey errs.ErrCode
ErrKeyRequired errs.ErrCode
ErrValueRequired errs.ErrCode
ErrInvalidList errs.ErrCode
ErrRedundantPack errs.ErrCode
ErrInvalidValue errs.ErrCode
ErrUnsupportedType errs.ErrCode
}{
ErrInvalidNode : errs.ErrCode("packs.invalid-node"),
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"),
ErrInvalidNode : errs.ErrCode("packs.invalid-node"),
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"),
ErrUnsupportedType: errs.ErrCode("packs:unsupported-type"),
}
)

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import "time"

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import "time"

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import "activething.com/go/gogo/core/slices"

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import "time"

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_cache.go
// File name packabler.go
// Created by DEV
// Modified 23/01/2024
// Modified 24/01/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -21,11 +21,16 @@
// limitations under the License.
// ------------------------------------------------------------------------
package jjson
package packs
type (
Packabler interface {
Build (packer Packer) ([]byte,error)
}
)

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import "time"
@ -53,7 +53,7 @@ type (
PackDate (value time.Time)
PackList (builder func(packer Packer))
PackList (builder func(packer ListPacker))
PackMap (builder func(packer MapPacker ))
PackObject(builder func(packer ObjectPacker))

@ -21,7 +21,7 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packets
package packs
import (
"activething.com/go/gogo/core/bins"

@ -43,9 +43,11 @@ var (
mapEmpty []byte
listEmpty []byte
objectEmpty []byte
/*
floatNaN []byte
floatInfPos []byte
floatInfNeg []byte
*/
}{
hex: "0123456789abcdef",
@ -59,9 +61,12 @@ var (
mapEmpty: []byte{'{', '}'},
objectEmpty: []byte{'{', '}'},
listEmpty: []byte{'[', ']'},
/*
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
*/
}
)

@ -52,8 +52,8 @@ 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) }
func (p *Packer) ItemList (builder func(packer packs.ListPacker)) { p.addSep().ItemList (builder) }
func (p *Packer) ItemMap (builder func(packer packs.MapPacker )) { p.addSep().ItemMap (builder) }
func (p *Packer) ItemObject(builder func(packer packs.ObjectPacker)) { p.addSep().ItemObject(builder) }

@ -54,9 +54,9 @@ func (p *Packer) KeyValueFloat64 ( key any, value float64) { p.addKey(key,func (
func (p *Packer) KeyValueDate ( key any, value time.Time) { p.addKey(key,func (pk *Packer) { pk.PackDate(value) }) }
func (p *Packer) KeyValueList (key any, builder func(packer packets.ListPacker)) { p.addKey(key,func (pk *Packer) { pk.PackList(builder) }) }
func (p *Packer) KeyValueMap (key any, builder func(packer packets.MapPacker )) { p.addKey(key,func (pk *Packer) { pk.PackMap (builder) }) }
func (p *Packer) KeyValueObject(key any, builder func(packer packets.ObjectPacker)) { p.addKey(key,func (pk *Packer){ pk.PackObject (builder) }) }
func (p *Packer) KeyValueList (key any, builder func(packer packs.ListPacker)) { p.addKey(key,func (pk *Packer) { pk.PackList(builder) }) }
func (p *Packer) KeyValueMap (key any, builder func(packer packs.MapPacker )) { p.addKey(key,func (pk *Packer) { pk.PackMap (builder) }) }
func (p *Packer) KeyValueObject(key any, builder func(packer packs.ObjectPacker)) { p.addKey(key,func (pk *Packer){ pk.PackObject (builder) }) }

@ -54,7 +54,7 @@ func (p *Packer) FieldFloat64( name string, value float64) { p.addField(name,fun
func (p *Packer) FieldDate ( name string, value time.Time) { p.addField(name,func(pk *Packer) { pk.PackDate(value) }) }
func (p *Packer) FieldList (name string, builder func(packer packets.ListPacker)) { p.addField(name,func(pk *Packer) { pk.PackList(builder) }) }
func (p *Packer) FieldMap (name string, builder func(packer packets.MapPacker )) { p.addField(name,func(pk *Packer) { pk.PackMap(builder) }) }
func (p *Packer) FieldObject(name string, builder func(packer packets.ObjectPacker)) { p.addField(name,func(pk *Packer) { pk.PackObject(builder) }) }
func (p *Packer) FieldList (name string, builder func(packer packs.ListPacker)) { p.addField(name,func(pk *Packer) { pk.PackList(builder) }) }
func (p *Packer) FieldMap (name string, builder func(packer packs.MapPacker )) { p.addField(name,func(pk *Packer) { pk.PackMap(builder) }) }
func (p *Packer) FieldObject(name string, builder func(packer packs.ObjectPacker)) { p.addField(name,func(pk *Packer) { pk.PackObject(builder) }) }

@ -27,9 +27,11 @@ import (
"activething.com/go/gogo/core/bins"
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/packets"
"activething.com/go/gogo/packs"
"encoding/base64"
"encoding/json"
"fmt"
"reflect"
"time"
"unicode/utf8"
)
@ -38,8 +40,7 @@ type (
Packer struct {
options Options
state *packets.State
state *packs.State
}
@ -51,14 +52,14 @@ func NewPacker (options ...opts.OptionFnc[Packer]) *Packer {
Flags: JSONFlagQuote | JSONFlagEscapeHTML,
dateLayout: time.RFC822Z,
},
state : packets.NewState(),
state : packs.NewState(),
})
}
func (p *Packer) Bytes () []byte {
defer p.reset()
defer p.Reset()
return append([]byte(nil),p.state.Bytes()...)
}
@ -68,13 +69,88 @@ func (p *Packer) Error () error {
}
func (p *Packer) Reset () {
p.state.Reset()
p.options.reset()
}
func (p *Packer) Pack (value any) {
if p.state.Error != nil {
panic(p.state.Error)
}
p.state.Node.Count++
if value == nil {
if p.options.Quote() {
p.state.WriteByte('"')
}
p.state.Write(G.nullValue)
if p.options.Quote() {
p.state.WriteByte('"')
}
p.state.Node.Count++
return
}
switch v := value.(type) {
case bool : p.PackBool(v)
case string : p.PackString(v)
case uint : p.PackUInt64(uint64(v))
case uint8 : p.PackUInt64(uint64(v))
case uint16 : p.PackUInt64(uint64(v))
case uint32 : p.PackUInt64(uint64(v))
case uint64 : p.PackUInt64(v)
case int : p.PackInt64(int64(v))
case int8 : p.PackInt64(int64(v))
case int16 : p.PackInt64(int64(v))
case int32 : p.PackInt64(int64(v))
case int64 : p.PackInt64(v)
case float32: p.packFloat(float64(v),32)
case float64: p.packFloat(v,64)
case reflect.Value : p.Pack(v.Elem())
default:
if pb,is := value.(packs.Packabler); is {
d,e := pb.Build(p)
if p.state.SetError(e) {
return
}
_,_ = p.state.Write(d)
p.state.Node.Count++
return
}
if ms,is := value.(json.Marshaler); is {
d,e := ms.MarshalJSON()
if p.state.SetError(e) {
return
}
_,_ = p.state.Write(d)
p.state.Node.Count++
return
}
rv := reflect.ValueOf(value)
switch rv.Kind() {
case reflect.Slice,reflect.Array :
p.packListReflected(rv)
return
case reflect.Map :
p.packMapReflected(rv)
return
case reflect.Struct:
p.packObjectReflected(rv)
return
}
p.state.SetError(packs.G.ErrUnsupportedType)
}
}
@ -165,10 +241,10 @@ func (p *Packer) packString(s string, scapeHTML bool) {
}
_ = 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')
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])
@ -289,7 +365,7 @@ func (p *Packer) packFloat (value float64, bits int) {
}
b := stringifyFloat(p.state.Temp[:0], value,bits)
if b == nil {
p.state.SetError(packets.G.ErrInvalidValue)
p.state.SetError(packs.G.ErrInvalidValue)
return
}
if p.options.QuoteNumbers() {
@ -315,22 +391,22 @@ func (p *Packer) PackDate (value time.Time) {
}
func (p *Packer) PackList (builder func(packer packets.ListPacker)) {
p.packCompound(packets.NodeKindList,'[',']',func(pk *Packer) { builder (pk) })
func (p *Packer) PackList (builder func(packer packs.ListPacker)) {
p.packCompound(packs.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) PackMap (builder func(packer packs.MapPacker )) {
p.packCompound(packs.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) PackObject(builder func(packer packs.ObjectPacker)) {
p.packCompound(packs.NodeKindObject,'{','}',func(pk *Packer) { builder (pk) })
}
func (p *Packer) packCompound(kind packets.NodeKind, opening, closing byte, buildFnc func(*Packer)) {
func (p *Packer) packCompound(kind packs.NodeKind, opening, closing byte, buildFnc func(*Packer)) {
dn := false
defer func(d *bool) {
if !(*d) {
@ -385,7 +461,7 @@ func (p *Packer) addKey (key any, call func(*Packer)) {
p.addSep()
k := stringifyKey(p.state.Temp[0:],key)
if k == nil {
p.state.SetError(packets.G.ErrInvalidKey)
p.state.SetError(packs.G.ErrInvalidKey)
return
}
@ -407,12 +483,10 @@ func (p *Packer) addField (name string, call func(*Packer)) {
}
p.addSep()
ks := string(name)
if !p.options.IgnoreKeys() && !p.state.SetKey(ks) {
if !p.options.IgnoreKeys() && !p.state.SetKey(name) {
return
}
p.packString(name,p.options.EscapeHTML())
_ = p.state.WriteByte(':')
call(p)
@ -420,7 +494,15 @@ func (p *Packer) addField (name string, call func(*Packer)) {
}
func (p *Packer) reset () {
p.state.Reset()
p.options.reset()
func (p *Packer) packListReflected (value reflect.Value) {
//todo
}
func (p *Packer) packMapReflected (value reflect.Value) {
//todo
}
func (p *Packer) packObjectReflected (value reflect.Value) {
//todo
}
Loading…
Cancel
Save

Powered by TurnKey Linux.