redefiniendo el builder

packs2
DEV 3 years ago
parent 0d97e820e4
commit 3d0c541f69

@ -27,19 +27,19 @@ package packs
type ( type (
Packabler interface { Builder interface {
Build (packer Packer) ([]byte,error) Build (packer Packer) error
} }
PackableFnc func (packer Packer)([]byte,error) BuildFnc func (packer Packer) error
) )
func (f PackableFnc) Build (packer Packer)([]byte,error) { func (f BuildFnc) Build (packer Packer) error {
return f(packer) return f(packer)
} }

@ -0,0 +1,192 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name f.go
// Created by DEV
// Modified 29/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 (
"strings"
"time"
)
const (
FlagOmitEmpty Flags = 1 << iota
FlagQuote
FlagScapeHTML
FlagBinary64 Flags = 0b0000100000000000
FlagBinary32 Flags = 0b0000010000000000
FlagDateRFC822 Flags = 0b0001000000000000
FlagDateUnix Flags = 0b0010000000000000
FlagDateANSIC Flags = 0b0100000000000000
FlagDateRFC850 Flags = 0b1000000000000000
binMask = 0b0000110000000000
dateMask = 0b1111000000000000
flagMaskBin Flags = 0b1111001111111111
flagMaskDate Flags = 0b0000111111111111
)
type Flags uint16
func (f Flags) OmitEmpty () bool {
return f&FlagOmitEmpty != 0
}
func (f Flags) Quote () bool {
return f&FlagQuote != 0
}
func (f Flags) EscapeHTML () bool {
return f&FlagScapeHTML != 0
}
func (f Flags) Binary () bool {
return f&(FlagBinary64|FlagBinary32) != 0
}
func (f Flags) Bin64 () bool {
return f&FlagBinary64 != 0
}
func (f Flags) Bin32 () bool {
return f&FlagBinary32 != 0
}
func (f Flags) SetWithName(flag string) Flags {
switch strings.ToLower(flag) {
case "o","omitempty": return f | FlagOmitEmpty
case "q","quote" : return f | FlagQuote
case "h","html" : return f | FlagScapeHTML
// formato binario
case "b64","bin64" : return (f & flagMaskBin) | FlagBinary64
case "b32","bin32" : return (f & flagMaskBin) | FlagBinary32
// formatos de fechas
case "unix" : return (f & flagMaskDate) | FlagDateUnix
case "rfc822" : return (f & flagMaskDate) | FlagDateRFC822
case "ansic" : return (f & flagMaskDate) | FlagDateANSIC
case "rfc850" : return (f & flagMaskDate) | FlagDateRFC850
case "rfc822z": return f & flagMaskDate
default: return f
}
}
func (f Flags) SetWithNames(flags ... string) Flags {
nf := f
for _,n := range flags {
switch strings.ToLower(n) {
case "o","omitempty": nf |= FlagOmitEmpty
case "q","quote" : nf |= FlagQuote
case "h","html" : nf |= FlagScapeHTML
// formatos binarios
case "b32","bin32" : nf = (nf & flagMaskBin) | FlagBinary32
case "b64","bin64" : nf = (nf & flagMaskBin) | FlagBinary64
// formatos de fechas
case "unix" : nf = (nf & flagMaskDate) | FlagDateUnix
case "rfc822" : nf = (nf & flagMaskDate) | FlagDateRFC822
case "ansic" : nf = (nf & flagMaskDate) | FlagDateANSIC
case "rfc850" : nf = (nf & flagMaskDate) | FlagDateRFC850
case "rfc822z": nf &= flagMaskDate
}
}
return nf
}
func (f Flags) SetWithString (flags string) Flags {
if len(flags) == 0 {
return f
}
nf := f
for flags != "" {
var op string
op,flags,_ = strings.Cut(flags,",")
nf |= f.SetWithName(op)
}
return nf
}
func (f Flags) Names () string {
var ls []string
if f&FlagOmitEmpty != 0 { ls = append(ls,"omitempty")}
if f&FlagQuote != 0 { ls = append(ls,"quote")}
if f&FlagScapeHTML != 0 { ls = append(ls,"html")}
if f&flagMaskBin != 0 {
ls = append(ls,f.binName())
}
if f&dateMask != 0 {
ls = append(ls,f.dateName())
}
if len(ls) > 0 {
return strings.Join(ls,",")
}
return ""
}
func (f Flags) binName () string {
switch f & binMask {
case FlagBinary64 : return "b64"
case FlagBinary32 : return "b32"
}
return ""
}
func (f Flags) dateName() string {
switch f & dateMask {
case FlagDateUnix : return "unix"
case FlagDateRFC822: return "rfc822"
case FlagDateANSIC : return "ansic"
case FlagDateRFC850: return "rfc8550"
default: return time.RFC822Z
}
}
func (f Flags) DateFormat () string {
switch f & dateMask {
case FlagDateUnix : return time.UnixDate
case FlagDateRFC822: return time.RFC822
case FlagDateANSIC : return time.ANSIC
case FlagDateRFC850: return time.RFC850
default: return time.RFC822Z
}
}

@ -34,10 +34,8 @@ var (
poolsSem uint32 poolsSem uint32
statePool *syncs.Pool[State] statePool *syncs.Pool[State]
nodePool *syncs.Pool[Node]
ErrInvalidNode errs.ErrCode ErrInvalidState errs.ErrCode
ErrInvalidElement errs.ErrCode
ErrInvalidKey errs.ErrCode ErrInvalidKey errs.ErrCode
ErrDuplicatedKey errs.ErrCode ErrDuplicatedKey errs.ErrCode
ErrKeyRequired errs.ErrCode ErrKeyRequired errs.ErrCode
@ -47,8 +45,7 @@ var (
ErrInvalidValue errs.ErrCode ErrInvalidValue errs.ErrCode
ErrUnsupportedType errs.ErrCode ErrUnsupportedType errs.ErrCode
}{ }{
ErrInvalidNode : errs.ErrCode("packs.invalid-node"), ErrInvalidState : errs.ErrCode("packs.invalid-stae"),
ErrInvalidElement : errs.ErrCode("packs.invalid-element"),
ErrInvalidKey : errs.ErrCode("packs.invalid-key"), ErrInvalidKey : errs.ErrCode("packs.invalid-key"),
ErrDuplicatedKey : errs.ErrCode("packs:duplicated-key"), ErrDuplicatedKey : errs.ErrCode("packs:duplicated-key"),
ErrKeyRequired : errs.ErrCode("packs:key-required"), ErrKeyRequired : errs.ErrCode("packs:key-required"),

@ -24,6 +24,7 @@
package js package js
import ( import (
"activething.com/go/gogo/packs"
"encoding" "encoding"
"encoding/json" "encoding/json"
"math" "math"
@ -41,39 +42,32 @@ var (
hex string hex string
jsonChars [utf8.RuneSelf]jsonCharAtt jsonChars [utf8.RuneSelf]jsonCharAtt
sep byte
nullValue []byte nullValue []byte
zeroValue []byte zeroValue []byte
trueValue []byte trueValue []byte
falseValue []byte falseValue []byte
mapEmpty []byte
listEmpty []byte
objectEmpty []byte
floatNaN []byte floatNaN []byte
floatInfPos []byte floatInfPos []byte
floatInfNeg []byte floatInfNeg []byte
packers sync.Map packersCache sync.Map
keyers sync.Map keyersCache sync.Map
jsonMarshalerType reflect.Type jsonMarshalerType reflect.Type
textMarshalerType reflect.Type textMarshalerType reflect.Type
packMarshalerType reflect.Type
}{ }{
hex: "0123456789abcdef", hex: "0123456789abcdef",
jsonChars: initJSONChars(), jsonChars: initJSONChars(),
sep: ',',
nullValue: []byte{'n', 'u', 'l', 'l'}, nullValue: []byte{'n', 'u', 'l', 'l'},
zeroValue: []byte{'0'}, zeroValue: []byte{'0'},
trueValue: []byte{'"','t', 'r', 'u', 'e','"'}, trueValue: []byte{'"','t', 'r', 'u', 'e','"'},
falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'}, falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'},
mapEmpty: []byte{'{', '}'},
objectEmpty: []byte{'{', '}'},
listEmpty: []byte{'[', ']'},
floatNaN: []byte{'"', 'N', 'a', 'N', '"'}, floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'}, floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
@ -82,6 +76,7 @@ var (
jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(), jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(),
textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(), textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(),
packMarshalerType: reflect.TypeOf((*packs.Packer)(nil)).Elem(),
} }

@ -79,9 +79,10 @@ func pack (state *packs.State, value any , flags Flags) {
case reflect.Value : Pack(v.Elem()) case reflect.Value : Pack(v.Elem())
default: default:
if pb,is := value.(packs.Packabler); is { if pb,is := value.(packs.Builder); is {
d, e := pb.Build(p) e := pb.Build(pb)
if state.SetError(e) { if e != nil {
state.SetError(e)
return return
} }
_, _ = state.Write(d) _, _ = state.Write(d)
@ -329,8 +330,6 @@ func packFloatString (state *packs.State, f float64, bits int, quote bool) {
} }
func PackDate (state *packs.State, value time.Time, flags Flags) { func PackDate (state *packs.State, value time.Time, flags Flags) {
if state.Error != nil { if state.Error != nil {
panic(state.Error) panic(state.Error)

@ -32,9 +32,9 @@ import (
func stringifyRKey(rt reflect.Type) rMapEntryFnc { func stringifyRKey(rt reflect.Type) rMapEntryFnc {
fn,ok := G.keyers.Load(rt) fn,ok := G.keyersCache.Load(rt)
if !ok { if !ok {
fn, _ = G.keyers.LoadOrStore(rt, _stringifyRKey(rt)) fn, _ = G.keyersCache.LoadOrStore(rt, _stringifyRKey(rt))
} }
return fn.(rMapEntryFnc) return fn.(rMapEntryFnc)
} }

@ -50,7 +50,7 @@ func RPacker(state *packs.State, value any, flags Flags ) {
func rTypePacker(rtype reflect.Type) packerFn { func rTypePacker(rtype reflect.Type) packerFn {
if fn,ok := G.packers.Load(rtype); ok { if fn,ok := G.packersCache.Load(rtype); ok {
return fn.(packerFn) return fn.(packerFn)
} }
@ -59,7 +59,7 @@ func rTypePacker(rtype reflect.Type) packerFn {
wg.Add(1) wg.Add(1)
fi,ld := G.packers.LoadOrStore(rtype, packerFn(func (e *packs.State, v reflect.Value, f Flags) { fi,ld := G.packersCache.LoadOrStore(rtype, packerFn(func (e *packs.State, v reflect.Value, f Flags) {
wg.Wait() wg.Wait()
fn(e,v,f) fn(e,v,f)
})) }))
@ -70,7 +70,7 @@ func rTypePacker(rtype reflect.Type) packerFn {
fn = _rTypePacker(rtype) fn = _rTypePacker(rtype)
wg.Done() wg.Done()
G.packers.Store(rtype,fn) G.packersCache.Store(rtype,fn)
return fn return fn
} }

@ -29,33 +29,35 @@ type (
Packer interface { Packer interface {
Pack (value any) Pack (value any, flags Flags) ([]byte,error)
PackRaw (value []byte)
PackBinary (value []byte)
PackString (value string)
PackBool (value bool) PackAny (value any, flags Flags)
PackInt8 (value int8) PackRaw (value []byte, flags Flags)
PackInt16 (value int16) PackBinary (value []byte, flags Flags)
PackInt32 (value int32) PackString (value string, flags Flags)
PackInt64 (value int64)
PackUInt8 (value uint8) PackBool (value bool, flags Flags)
PackUInt16 (value uint16)
PackUInt32 (value uint32)
PackUInt64 (value uint64)
PackFloat32 (value float32) PackInt8 (value int8, flags Flags)
PackFloat64 (value float64) PackInt16 (value int16, flags Flags)
PackInt32 (value int32, flags Flags)
PackInt64 (value int64, flags Flags)
PackDate (value time.Time) PackUInt8 (value uint8 , flags Flags)
PackUInt16 (value uint16, flags Flags)
PackUInt32 (value uint32, flags Flags)
PackUInt64 (value uint64, flags Flags)
PackFloat32 (value float32, flags Flags)
PackFloat64 (value float64, flags Flags)
PackList (builder func(packer ListPacker)) PackDate (value time.Time, flags Flags)
PackMap (builder func(packer MapPacker ))
PackObject(builder func(packer ObjectPacker)) PackList (builder func(packer ListPacker , flags Flags))
PackMap (builder func(packer MapPacker , flags Flags))
PackObject(builder func(packer ObjectPacker, flags Flags))
} }
) )

@ -39,8 +39,8 @@ type (
/*Embedded*/*bins.Buffer /*Embedded*/*bins.Buffer
Temp [64]byte Temp [64]byte
Level int Level int
checks map[any]struct{}
Error error Error error
checks map[any]struct{}
} }
) )

@ -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,168 @@
// ------------------------------------------------------------------------
// 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 (
"activething.com/go/gogo/packs"
"encoding"
"encoding/json"
"math"
"reflect"
"strconv"
"sync"
"unicode/utf8"
)
const startDetectingCyclesAfter = 100
var (
G = struct {
hex string
jsonChars [utf8.RuneSelf]jsonCharAtt
nullValue []byte
zeroValue []byte
trueValue []byte
falseValue []byte
floatNaN []byte
floatInfPos []byte
floatInfNeg []byte
packersCache sync.Map
keyersCache sync.Map
jsonMarshalerType reflect.Type
textMarshalerType reflect.Type
packMarshalerType reflect.Type
}{
hex: "0123456789abcdef",
jsonChars: initJSONChars(),
nullValue: []byte{'n', 'u', 'l', 'l'},
zeroValue: []byte{'0'},
trueValue: []byte{'"','t', 'r', 'u', 'e','"'},
falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'},
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(),
textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(),
packMarshalerType: reflect.TypeOf((*packs.Packer)(nil)).Elem(),
}
)
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
}
func stringifyKey(buffer []byte, value any) []byte {
if value == nil {
return G.nullValue
}
if st,is := value.(string); is {
return append(buffer[:0],st...)
}
if tm,is := value.(encoding.TextMarshaler); is {
if bf,er := tm.MarshalText(); er == nil {
return append(buffer[:0],bf...)
}
return nil
}
switch tp := value.(type) {
case bool:
if tp {
return G.trueValue
}
return G.falseValue
case int : return strconv.AppendInt (buffer[:0],int64(tp), 10)
case int8 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
case int16 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
case int32 : return strconv.AppendInt (buffer[:0],int64(tp), 10)
case int64 : return strconv.AppendInt (buffer[:0],tp, 10)
case uint : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
case uint8 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
case uint16 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
case uint32 : return strconv.AppendUint(buffer[:0],uint64(tp), 10)
case uint64 : return strconv.AppendUint(buffer[:0],tp, 10)
case float32: return stringifyFloat(buffer[:0],float64(tp),32)
case float64: return stringifyFloat(buffer[:0],tp,64)
}
return nil
}
func stringifyFloat (buffer []byte, f float64, bits int) []byte {
if math.IsInf(f, 0) || math.IsNaN(f) {
return nil
}
abs := math.Abs(f)
fmt := byte('f')
if abs != 0 {
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
fmt = 'e'
}
}
buffer = strconv.AppendFloat(buffer[:0], f, fmt, -1, int(bits))
if fmt == 'e' {
// clean up e-09 to e-9
n := len(buffer)
if n >= 4 && buffer[n-4] == 'e' && buffer[n-3] == '-' && buffer[n-2] == '0' {
buffer[n-2] = buffer[n-1]
buffer = buffer[:n-1]
}
}
return buffer
}

@ -2,9 +2,9 @@
// Project atila // Project atila
// Active Thing (activething.com) git.activething.com/go // Active Thing (activething.com) git.activething.com/go
// //
// File name node_kind.go // File name options.go
// Created by DEV // Created by DEV
// Modified 23/01/2024 // Modified 05/02/2024
// //
// Copyright 2024 activething.com // Copyright 2024 activething.com
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -21,20 +21,13 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package packs package pjson
const ( type (
NodeKindValue NodeKind = iota Options struct {}
NodeKindList
NodeKindMap
NodeKindObject
) )
type NodeKind uint8

@ -0,0 +1,401 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer.go
// Created by DEV
// Modified 05/02/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/opts"
"activething.com/go/gogo/packs"
"encoding/base32"
"encoding/base64"
"encoding/json"
"math"
"reflect"
"strconv"
"time"
"unicode/utf8"
)
type (
Packer struct {
state *packs.State
Options
}
)
func NewPacker (options opts.OptionFnc[Packer]) *Packer {
return opts.Apply[Packer](&Packer {
state : packs.NewState(),
}, options)
}
func (p *Packer) Pack (value any, flags packs.Flags) ([]byte,error) {
if p.state.Error != nil {
return nil,packs.G.ErrInvalidState.WithCause(p.state.Error)
}
p.PackAny(value,flags)
if p.state.Error != nil {
return nil,p.state.Error
}
return p.state.Bytes(),nil
}
func (p *Packer) PackAny (value any, flags packs.Flags) {
if p.state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(p.state.Error))
}
if value == nil {
p.state.W(G.nullValue)
return
}
switch v := value.(type) {
case packs.Builder:
p.state.SetError(v.Build(p))
case json.Marshaler:
d,e := v.MarshalJSON()
if e != nil {
p.state.SetError(e)
} else {
p.state.W(d)
}
case reflect.Value:
rPackAny(p.state,v,flags)
default:
rPackAny(p.state,reflect.ValueOf(value), flags)
}
}
func (p *Packer) PackRaw (value []byte, flags packs.Flags) {
if p.state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(p.state.Error))
}
if value == nil {
p.state.W(G.nullValue)
return
}
if len(value) == 0 {
p.state.Write2Byte('"','"')
return
}
p.state.W(value)
}
func (p *Packer) PackBinary (value []byte, flags packs.Flags) { packBinary(p.state,value,flags) }
func (p *Packer) PackString (value string, flags packs.Flags) { packString (p.state,value,flags) }
func (p *Packer) PackBool (value bool, flags packs.Flags) { packBool(p.state,value,flags) }
func (p *Packer) PackInt8 (value int8 , flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt16 (value int16, flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt32 (value int32, flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt64 (value int64, flags packs.Flags) { packInt(p.state,value,flags)}
func (p *Packer) PackUInt8 (value uint8 , flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt16 (value uint16, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt32 (value uint32, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt64 (value uint64, flags packs.Flags) { packUInt(p.state, value,flags) }
func (p *Packer) PackFloat32 (value float32, flags packs.Flags) { packFloatString(p.state, float64(value), flags, 32) }
func (p *Packer) PackFloat64 (value float64, flags packs.Flags) { packFloatString(p.state, value, flags, 64) }
func (p *Packer) PackDate (value time.Time, flags packs.Flags) { PackDate(p.state,value,flags) }
func (p *Packer) PackList (builder func(packs.ListPacker, packs.Flags)) {}
func (p *Packer) PackMap (builder func(packs.MapPacker, packs.Flags)) {}
func (p *Packer) PackObject(builder func(packs.ObjectPacker, packs.Flags)) {}
func packString (state *packs.State, value string , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if len(value) == 0 {
state.Write2Byte('"','"')
return
}
state.WriteByte('"')
start := 0
for i := 0; i < len(value); {
if b := value[i]; b < utf8.RuneSelf {
if !G.jsonChars[b].isHtmlUnsafe() || (!flags.EscapeHTML() && !G.jsonChars[b].isUnsafe()) {
i++
continue
}
if start < i {
state.WriteString(value[start:i])
}
state.WriteByte('\\')
switch b {
case '\\', '"': state.WriteByte(b)
case '\n': state.WriteByte('n')
case '\r': state.WriteByte('r')
case '\t': state.WriteByte('t')
default:
state.WriteString(`u00`)
state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
}
i++
start = i
continue
}
c, size := utf8.DecodeRuneInString(value[i:])
if c == utf8.RuneError && size == 1 {
if start < i {
state.WriteString(value[start:i])
}
state.WriteString(`\ufffd`)
i += size
start = i
continue
}
if c == '\u2028' || c == '\u2029' {
if start < i {
state.WriteString(value[start:i])
}
state.WriteString(`\u202`)
state.WriteByte(G.hex[c&0xF])
i += size
start = i
continue
}
i += size
}
if start < len(value) {
state.WriteString(value[start:])
}
state.WriteByte('"')
}
func packBinary (state *packs.State, value []byte , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if value == nil {
_,_ = state.Write(G.nullValue)
return
}
if len(value) == 0 {
state.Write2Byte('"','"')
return
}
state.WriteByte('"')
if flags.Bin64() {
packBinary64(state, value, 0)
} else if flags.Bin32() {
packBinary32(state, value, 0)
} else {
state.SetError(packs.G.ErrUnsupportedType)
return
}
if state.Error == nil {
state.WriteByte('"')
}
}
func packBinary64 (state *packs.State, value []byte , _ packs.Flags) {
ln := base64.StdEncoding.EncodedLen(len(value))
if ln <= len(state.Temp) {
dst := state.Temp[:ln]
base64.StdEncoding.Encode(dst, value)
_,_= state.Write(dst)
} else if ln <= 1024 {
dst := make([]byte, ln)
base64.StdEncoding.Encode(dst, value)
_,_ = state.Write(dst)
} else {
ec := base64.NewEncoder(base64.StdEncoding, state)
_,_ = ec.Write(value)
state.SetError(ec.Close())
}
}
func packBinary32 (state *packs.State, value []byte , _ packs.Flags) {
ln := base32.StdEncoding.EncodedLen(len(value))
if ln <= len(state.Temp) {
dst := state.Temp[:ln]
base32.StdEncoding.Encode(dst, value)
_,_= state.Write(dst)
} else if ln <= 1024 {
dst := make([]byte, ln)
base32.StdEncoding.Encode(dst, value)
_,_ = state.Write(dst)
} else {
ec := base32.NewEncoder(base32.StdEncoding, state)
_,_ = ec.Write(value)
state.SetError(ec.Close())
}
}
func packBool (state *packs.State, value bool , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if flags.Quote() {
state.WriteByte('"')
}
if value {
state.W(G.trueValue)
} else {
state.W(G.falseValue)
}
if flags.Quote() {
state.WriteByte('"')
}
}
func packInt (state *packs.State, value int64 , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if flags.Quote() {
state.WriteByte('"')
}
if value == 0 {
state.WriteByte('0')
} else {
state.WriteIntStr(value, 10)
}
if flags.Quote() {
state.WriteByte('"')
}
}
func packUInt (state *packs.State, value uint64 , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
q :=flags.Quote()
if q {
state.WriteByte('"')
}
if value == 0 {
state.WriteByte('0')
} else {
state.WriteUIntStr(value, 10)
}
if q {
state.WriteByte('"')
}
}
func packFloat (state *packs.State, value float64, flags packs.Flags) {
packFloatString(state, value, flags, 64)
}
func packFloatString (state *packs.State, f float64, flags packs.Flags, bits int) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if math.IsInf(f, 0) || math.IsNaN(f) {
state.SetError(packs.G.ErrInvalidValue)
return
}
abs := math.Abs(f)
fmt := byte('f')
if abs != 0 {
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
fmt = 'e'
}
}
bf := state.Temp[:0]
bf = strconv.AppendFloat(bf, f, fmt, -1, int(bits))
if fmt == 'e' {
// clean up e-09 to e-9
n := len(bf)
if n >= 4 && bf[n-4] == 'e' && bf[n-3] == '-' && bf[n-2] == '0' {
bf[n-2] = bf[n-1]
bf = bf[:n-1]
}
}
if flags.Quote() {
state.WriteByte('"')
state.W(bf)
state.WriteByte('"')
return
}
state.W(bf)
}
func PackDate (state *packs.State, value time.Time, flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
state.WriteByte('"')
bf := state.Temp[:0]
bf = value.AppendFormat(bf,flags.DateFormat())
state.W(bf)
state.WriteByte('"')
}

@ -0,0 +1,363 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_value.go
// Created by DEV
// Modified 05/02/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"
"encoding/base32"
"encoding/base64"
"encoding/json"
"math"
"reflect"
"strconv"
"time"
"unicode/utf8"
)
func (p *Packer) PackAny (value any, flags packs.Flags) {
if p.state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(p.state.Error))
}
if value == nil {
p.state.W(G.nullValue)
return
}
switch v := value.(type) {
case packs.Builder:
p.state.SetError(v.Build(p))
case json.Marshaler:
d,e := v.MarshalJSON()
if e != nil {
p.state.SetError(e)
} else {
p.state.W(d)
}
case reflect.Value:
rPackAny(p.state,v,flags)
default:
rPackAny(p.state,reflect.ValueOf(value), flags)
}
}
func (p *Packer) PackRaw (value []byte, flags packs.Flags) {
if p.state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(p.state.Error))
}
if value == nil {
p.state.W(G.nullValue)
return
}
if len(value) == 0 {
p.state.Write2Byte('"','"')
return
}
p.state.W(value)
}
func (p *Packer) PackBinary (value []byte, flags packs.Flags) { packBinary(p.state,value,flags) }
func (p *Packer) PackString (value string, flags packs.Flags) { packString (p.state,value,flags) }
func (p *Packer) PackBool (value bool, flags packs.Flags) { packBool(p.state,value,flags) }
func (p *Packer) PackInt8 (value int8 , flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt16 (value int16, flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt32 (value int32, flags packs.Flags) { packInt(p.state,int64(value),flags) }
func (p *Packer) PackInt64 (value int64, flags packs.Flags) { packInt(p.state,value,flags)}
func (p *Packer) PackUInt8 (value uint8 , flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt16 (value uint16, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt32 (value uint32, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
func (p *Packer) PackUInt64 (value uint64, flags packs.Flags) { packUInt(p.state, value,flags) }
func (p *Packer) PackFloat32 (value float32, flags packs.Flags) { packFloatString(p.state, float64(value), flags, 32) }
func (p *Packer) PackFloat64 (value float64, flags packs.Flags) { packFloatString(p.state, value, flags, 64) }
func (p *Packer) PackDate (value time.Time, flags packs.Flags) { PackDate(p.state,value,flags) }
func (p *Packer) PackList (builder func(packs.ListPacker, packs.Flags)) {}
func (p *Packer) PackMap (builder func(packs.MapPacker, packs.Flags)) {}
func (p *Packer) PackObject(builder func(packs.ObjectPacker, packs.Flags)) {}
func packString (state *packs.State, value string , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if len(value) == 0 {
state.Write2Byte('"','"')
return
}
state.WriteByte('"')
start := 0
for i := 0; i < len(value); {
if b := value[i]; b < utf8.RuneSelf {
if !G.jsonChars[b].isHtmlUnsafe() || (!flags.EscapeHTML() && !G.jsonChars[b].isUnsafe()) {
i++
continue
}
if start < i {
state.WriteString(value[start:i])
}
state.WriteByte('\\')
switch b {
case '\\', '"': state.WriteByte(b)
case '\n': state.WriteByte('n')
case '\r': state.WriteByte('r')
case '\t': state.WriteByte('t')
default:
state.WriteString(`u00`)
state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
}
i++
start = i
continue
}
c, size := utf8.DecodeRuneInString(value[i:])
if c == utf8.RuneError && size == 1 {
if start < i {
state.WriteString(value[start:i])
}
state.WriteString(`\ufffd`)
i += size
start = i
continue
}
if c == '\u2028' || c == '\u2029' {
if start < i {
state.WriteString(value[start:i])
}
state.WriteString(`\u202`)
state.WriteByte(G.hex[c&0xF])
i += size
start = i
continue
}
i += size
}
if start < len(value) {
state.WriteString(value[start:])
}
state.WriteByte('"')
}
func packBinary (state *packs.State, value []byte , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if value == nil {
_,_ = state.Write(G.nullValue)
return
}
if len(value) == 0 {
state.Write2Byte('"','"')
return
}
state.WriteByte('"')
if flags.Bin64() {
packBinary64(state, value, 0)
} else if flags.Bin32() {
packBinary32(state, value, 0)
} else {
state.SetError(packs.G.ErrUnsupportedType)
return
}
if state.Error == nil {
state.WriteByte('"')
}
}
func packBinary64 (state *packs.State, value []byte , _ packs.Flags) {
ln := base64.StdEncoding.EncodedLen(len(value))
if ln <= len(state.Temp) {
dst := state.Temp[:ln]
base64.StdEncoding.Encode(dst, value)
_,_= state.Write(dst)
} else if ln <= 1024 {
dst := make([]byte, ln)
base64.StdEncoding.Encode(dst, value)
_,_ = state.Write(dst)
} else {
ec := base64.NewEncoder(base64.StdEncoding, state)
_,_ = ec.Write(value)
state.SetError(ec.Close())
}
}
func packBinary32 (state *packs.State, value []byte , _ packs.Flags) {
ln := base32.StdEncoding.EncodedLen(len(value))
if ln <= len(state.Temp) {
dst := state.Temp[:ln]
base32.StdEncoding.Encode(dst, value)
_,_= state.Write(dst)
} else if ln <= 1024 {
dst := make([]byte, ln)
base32.StdEncoding.Encode(dst, value)
_,_ = state.Write(dst)
} else {
ec := base32.NewEncoder(base32.StdEncoding, state)
_,_ = ec.Write(value)
state.SetError(ec.Close())
}
}
func packBool (state *packs.State, value bool , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if flags.Quote() {
state.WriteByte('"')
}
if value {
state.W(G.trueValue)
} else {
state.W(G.falseValue)
}
if flags.Quote() {
state.WriteByte('"')
}
}
func packInt (state *packs.State, value int64 , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if flags.Quote() {
state.WriteByte('"')
}
if value == 0 {
state.WriteByte('0')
} else {
state.WriteIntStr(value, 10)
}
if flags.Quote() {
state.WriteByte('"')
}
}
func packUInt (state *packs.State, value uint64 , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
q :=flags.Quote()
if q {
state.WriteByte('"')
}
if value == 0 {
state.WriteByte('0')
} else {
state.WriteUIntStr(value, 10)
}
if q {
state.WriteByte('"')
}
}
func packFloat (state *packs.State, value float64, flags packs.Flags) {
packFloatString(state, value, flags, 64)
}
func packFloatString (state *packs.State, f float64, flags packs.Flags, bits int) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if math.IsInf(f, 0) || math.IsNaN(f) {
state.SetError(packs.G.ErrInvalidValue)
return
}
abs := math.Abs(f)
fmt := byte('f')
if abs != 0 {
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
fmt = 'e'
}
}
bf := state.Temp[:0]
bf = strconv.AppendFloat(bf, f, fmt, -1, int(bits))
if fmt == 'e' {
// clean up e-09 to e-9
n := len(bf)
if n >= 4 && bf[n-4] == 'e' && bf[n-3] == '-' && bf[n-2] == '0' {
bf[n-2] = bf[n-1]
bf = bf[:n-1]
}
}
if flags.Quote() {
state.WriteByte('"')
state.W(bf)
state.WriteByte('"')
return
}
state.W(bf)
}
func PackDate (state *packs.State, value time.Time, flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
state.WriteByte('"')
bf := state.Temp[:0]
bf = value.AppendFormat(bf,flags.DateFormat())
state.W(bf)
state.WriteByte('"')
}

@ -2,9 +2,9 @@
// Project atila // Project atila
// Active Thing (activething.com) git.activething.com/go // Active Thing (activething.com) git.activething.com/go
// //
// File name packer_node.go // File name rpacker.go
// Created by DEV // Created by DEV
// Modified 23/01/2024 // Modified 05/02/2024
// //
// Copyright 2024 activething.com // Copyright 2024 activething.com
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -21,34 +21,22 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package packs package pjson
import "activething.com/go/gogo/core/slices" import (
"activething.com/go/gogo/packs"
"reflect"
)
type ( type (
Node struct {
Parent *Node
Start int
Count int
Kind NodeKind
keys slices.String
}
)
func (n *Node) Init(parent *Node, kind NodeKind, start int) *Node {
n.Parent = parent
n.Count = 0
n.Start = start
n.Kind = kind
return n
}
func (n *Node) Reset() *Node { rPackerFnc func (state *packs.State, rvalue reflect.Value, flags packs.Flags)
n.Parent = nil
n.keys = n.keys[:0] )
return n
}
func rPackAny (state *packs.State, rvalue reflect.Value, flags packs.Flags) {}
Loading…
Cancel
Save

Powered by TurnKey Linux.