redefiniendo el builder

packs2
DEV 3 years ago
parent 3d0c541f69
commit d0529f9c2a

@ -26,55 +26,24 @@ package main
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packs"
"activething.com/go/gogo/packs/js"
"encoding/json"
"activething.com/go/gogo/packs/pjson"
"fmt"
)
func createDefer () func() {
return func() {
fmt.Printf("Saliend\n")
}
}
func execute () {
defer createDefer()()
fmt.Printf("Execute\n")
}
type miTextor struct{}
func (_ miTextor) MarshalText ()([]byte,error) {
return []byte("ClaveDeTexto"),nil
}
func main() {
execute()
st := packs.NewState()
cas := []string {"a1111","b2222","c3333"}
js.RPacker(st,cas,0)
fmt.Printf("JSON \n%s\n",st.Bytes())
st.Reset()
//a := map[int]string {1:"344343",3:"4343434",5:"frtrtrtr"}
a := map[string]int {"{basd1/>":344343,"{casd2/>":4343434,"{asd41/>":67}
js.RPacker(st,a,0)
errs.Test(st.Error,true)
fmt.Printf("Pack \n%s\n",st.Bytes())
st.Reset()
pk := pjson.NewPacker()
d,e:=json.Marshal(a)
errs.Test(e,true)
fmt.Printf("JSON \n%s\n",d)
pk.PackList(func(p packs.ListPacker, flags packs.Flags){
p.ItemUInt64(0,flags)
p.ItemFloat64(7.8,flags)
p.ItemList(func (p1 packs.ListPacker, f packs.Flags){
p1.ItemString("MICasa",flags)
p1.ItemString("Coche",flags)
},flags)
},0)
errs.Test(pk.Error(),true)
fmt.Printf("Paquete %s\n",pk.Packet())
}

@ -26,6 +26,7 @@ package main
import (
"activething.com/go/gogo/packs"
"activething.com/go/gogo/packs/js"
"activething.com/go/gogo/packs/pjson"
j "encoding/json"
"testing"
)
@ -154,10 +155,20 @@ func BenchmarkListJSON (b *testing.B) {
//var ma = map[string]string {"{asd1/>":"344343","{asd2/>":"4343434","{asd41/>":"frtrtrtr"}
var mas = map[string]int {"{basd1/>":344343,"{casd2/>":4343434,"{asd41/>":67,"{ba2sd1/>":344343,"{11casd2/>":4343434,"{33asd41/>":67}
var mas = map[string]any {"{basd1/>":344343,"{casd2/>":4343434,"{asd41/>":67,"{ba2sd1/>":344343,"{11casd2/>":4343434,"{33asd41/>":67,"slice":[]int{34,34,234,4}}
func BenchmarkMapPack (b *testing.B) {
s := pjson.NewPacker()
for i:=0; i< b.N; i++ {
s.Pack(ma,0)
s.Reset()
}
}
func BenchmarkPacker (b *testing.B) {
s := packs.NewState()
for i:=0; i< b.N; i++ {
js.RPacker(s,ma,0)
@ -177,7 +188,6 @@ func BenchmarkMapJSON (b *testing.B) {
var ma = map[string]string {
"clave0": "valor123",
"clave1": "rojo",

@ -218,6 +218,18 @@ func (b *Buffer) W (value []byte) {
copy(b.data[b.tryGrow(len(value)):], value)
}
// WOQ With Optional Quoted
func (b *Buffer) WOQ (add bool, quote byte, value []byte) {
b.lastOp = opInvalid
if !add {
copy(b.data[b.tryGrow(len(value)):], value)
return
}
sz := b.tryGrow(len(value)+2)
copy(b.data[sz:],value)
}
func (b *Buffer) WriteByte(value byte) {
b.lastOp = opInvalid
b.data[b.tryGrow(1)] = value

@ -43,6 +43,7 @@ const (
)
type (
BufferPool struct {
syncs.PoolStats
@ -57,6 +58,7 @@ type (
threshold uint64
percentile float32
}
)
func NewBufferPool(options ...opts.OptionFnc[BufferPool]) *BufferPool {

@ -33,6 +33,8 @@ var (
ErrTooLarge errs.ErrCode
ErrNegativeRead errs.ErrCode
ErrUnreadInvalid errs.ErrCode
}{
ErrOutOfRange: errs.ErrCode("core:bins.out-of-range"),
ErrWriteCount: errs.ErrCode("core:bins.write-count"),

@ -36,6 +36,7 @@ var (
statePool *syncs.Pool[State]
ErrInvalidState errs.ErrCode
ErrInvalidNode errs.ErrCode
ErrInvalidKey errs.ErrCode
ErrDuplicatedKey errs.ErrCode
ErrKeyRequired errs.ErrCode
@ -45,7 +46,8 @@ var (
ErrInvalidValue errs.ErrCode
ErrUnsupportedType errs.ErrCode
}{
ErrInvalidState : errs.ErrCode("packs.invalid-stae"),
ErrInvalidState : errs.ErrCode("packs.invalid-state"),
ErrInvalidNode : errs.ErrCode("packs.invalid-node"),
ErrInvalidKey : errs.ErrCode("packs.invalid-key"),
ErrDuplicatedKey : errs.ErrCode("packs:duplicated-key"),
ErrKeyRequired : errs.ErrCode("packs:key-required"),

@ -27,7 +27,6 @@ import (
"activething.com/go/gogo/packs"
"encoding/base32"
"encoding/base64"
"encoding/json"
"io"
"math"
"reflect"
@ -74,11 +73,13 @@ func pack (state *packs.State, value any , flags Flags) {
case float32: packFloat(state,float64(v),flags)
case float64: packFloat(state,v,flags)
case time.Time : PackDate(v)
case time.Time : PackDate(state,v,flags)
case reflect.Value : Pack(v.Elem())
case reflect.Value : RPacker(state,v.Elem(),0)
default:
/*
if pb,is := value.(packs.Builder); is {
e := pb.Build(pb)
if e != nil {
@ -113,6 +114,8 @@ func pack (state *packs.State, value any , flags Flags) {
}
state.Write(d)
}
*/
}
}

@ -42,7 +42,6 @@ func stringifyRKey(rt reflect.Type) rMapEntryFnc {
func _stringifyRKey(rt reflect.Type) rMapEntryFnc {
if rt.Kind() == reflect.String {

@ -23,42 +23,16 @@
package packs
import "time"
type (
Packer interface {
Pack (value any, flags Flags) ([]byte,error)
PackAny (value any, flags Flags)
PackRaw (value []byte, flags Flags)
PackBinary (value []byte, flags Flags)
PackString (value string, flags Flags)
PackBool (value bool, flags Flags)
PackInt8 (value int8, flags Flags)
PackInt16 (value int16, flags Flags)
PackInt32 (value int32, flags Flags)
PackInt64 (value int64, flags Flags)
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)
PackDate (value time.Time, flags Flags)
Pack (value any, flags Flags)
PackList (builder func(packer ListPacker , flags Flags))
PackMap (builder func(packer MapPacker , flags Flags))
PackObject(builder func(packer ObjectPacker, flags Flags))
Packet () []byte
Error () error
Reset ()
}
)

@ -0,0 +1,62 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com, flags Flags) git.activething.com/go
//
// File name list_Itemer.go
// Created by DEV
// Modified 23/01/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License", flags Flags);
// 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 (
ListPacker interface {
ItemAny (value any, flags Flags)
ItemRaw (value []byte, flags Flags)
ItemBinary (value []byte, flags Flags)
ItemString (value string, flags Flags)
ItemBool (value bool, flags Flags)
ItemInt8 (value int8, flags Flags)
ItemInt16 (value int16, flags Flags)
ItemInt32 (value int32, flags Flags)
ItemInt64 (value int64, flags Flags)
ItemUInt8 (value uint8, flags Flags)
ItemUInt16 (value uint16, flags Flags)
ItemUInt32 (value uint32, flags Flags)
ItemUInt64 (value uint64, flags Flags)
ItemFloat32 (value float32, flags Flags)
ItemFloat64 (value float64, flags Flags)
ItemDate (value time.Time, flags Flags)
ItemList (builder func(packer ListPacker, flags Flags), flags Flags)
ItemMap (builder func(packer MapPacker , flags Flags), flags Flags)
ItemObject(builder func(packer ObjectPacker, flags Flags), flags Flags)
}
)

@ -29,9 +29,9 @@ type (
MapPacker interface {
KeyValue (key any, value any)
KeyValueAny (key any, value any)
KeyValueRaw (key any,value []byte)
KeyValueRaw (key any,value []byte)
KeyValueBinary(key any, value []byte)
KeyValueString(key any, value string)

@ -41,6 +41,7 @@ type (
Level int
Error error
checks map[any]struct{}
counts []int
}
)
@ -53,6 +54,7 @@ func NewState() *State {
return &State{
Buffer: bins.NewBuffer(),
checks: make(map[any]struct{}),
counts: []int{0},
}
}),
)
@ -65,6 +67,7 @@ func ReleaseState (state *State) {
if state == nil {
state.Buffer.Reset()
state.Error = nil
state.counts= append(state.counts[:0],0)
if len(state.checks) > 0 {
for k,_ := range state.checks {
delete(state.checks,k)
@ -107,6 +110,7 @@ func (s *State) CheckCycle (ptr any) (func(),bool) {
func (s *State) Open(opener byte) {
s.WriteByte(opener)
s.Level++
s.counts = append(s.counts,0)
}
@ -116,6 +120,18 @@ func (s *State) Close(closer byte) {
if s.Level < 0 {
s.SetError(G.ErrInvalidNode)
}
s.counts = s.counts[:len(s.counts)-1]
}
func (s *State) Count() int {
if s.Error != nil {
return 0
}
return s.counts[s.Level]
}
func (s *State) Inc () {
if s.Error == nil {
s.counts[s.Level] += 1
}
}

@ -0,0 +1,65 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name value_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 packs
import "time"
type (
ValuePacker interface {
PackAny (value any, flags Flags)
PackRaw (value []byte, flags Flags)
PackBinary (value []byte, flags Flags)
PackString (value string, flags Flags)
PackBool (value bool, flags Flags)
PackInt8 (value int8, flags Flags)
PackInt16 (value int16, flags Flags)
PackInt32 (value int32, flags Flags)
PackInt64 (value int64, flags Flags)
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)
PackDate (value time.Time, flags Flags)
PackList (builder func(packer ListPacker , flags Flags), flags Flags)
PackMap (builder func(packer MapPacker , flags Flags), flags Flags)
PackObject(builder func(packer ObjectPacker, flags Flags), flags Flags)
}
)

@ -27,9 +27,7 @@ import (
"activething.com/go/gogo/packs"
"encoding"
"encoding/json"
"math"
"reflect"
"strconv"
"sync"
"unicode/utf8"
)
@ -79,10 +77,10 @@ var (
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,
@ -99,70 +97,7 @@ func initJSONChars() [utf8.RuneSelf]jsonCharAtt {
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
}

@ -31,3 +31,4 @@ type (
)
func (o *Options) reset () {}

@ -26,14 +26,6 @@ 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 (
@ -41,6 +33,7 @@ type (
Packer struct {
state *packs.State
dirty bool
Options
}
@ -49,353 +42,39 @@ type (
)
func NewPacker (options opts.OptionFnc[Packer]) *Packer {
func NewPacker (options ... opts.OptionFnc[Packer]) *Packer {
return opts.Apply[Packer](&Packer {
state : packs.NewState(),
}, options)
}, 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) {
func (p *Packer) Pack (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
}
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('"')
if p.dirty {
panic(packs.G.ErrInvalidState)
}
p.dirty = true
p.PackAny(value,flags)
}
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 (p *Packer) Packet () []byte {
return p.state.Bytes()
}
func packFloat (state *packs.State, value float64, flags packs.Flags) {
packFloatString(state, value, flags, 64)
func (p *Packer) Error () error {
return p.state.Error
}
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 (p *Packer) Reset () {
p.state.Reset()
p.Options.reset()
}
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,187 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_list.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"
"time"
)
func (p *Packer) ItemAny (value any, flags packs.Flags) { p.addSep(); p.PackAny(value,flags) }
func (p *Packer) ItemRaw (value []byte, flags packs.Flags) { p.addSep(); packRaw(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemBinary (value []byte, flags packs.Flags) { p.addSep(); packBinary(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemString (value string, flags packs.Flags) { p.addSep(); packString(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemBool (value bool, flags packs.Flags) { p.addSep(); packBool(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemInt8 (value int8 , flags packs.Flags) { p.addSep(); packInt(p.state,int64(value),flags); p.state.Inc() }
func (p *Packer) ItemInt16 (value int16, flags packs.Flags) { p.addSep(); packInt(p.state,int64(value),flags); p.state.Inc() }
func (p *Packer) ItemInt32 (value int32, flags packs.Flags) { p.addSep(); packInt(p.state,int64(value),flags); p.state.Inc() }
func (p *Packer) ItemInt64 (value int64, flags packs.Flags) { p.addSep(); packInt(p.state, value,flags); p.state.Inc() }
func (p *Packer) ItemUInt8 (value uint8 , flags packs.Flags){ p.addSep(); packUInt(p.state,uint64(value),flags); p.state.Inc() }
func (p *Packer) ItemUInt16 (value uint16, flags packs.Flags){ p.addSep(); packUInt(p.state,uint64(value),flags); p.state.Inc() }
func (p *Packer) ItemUInt32 (value uint32, flags packs.Flags){ p.addSep(); packUInt(p.state,uint64(value),flags); p.state.Inc() }
func (p *Packer) ItemUInt64 (value uint64, flags packs.Flags){ p.addSep(); packUInt(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemFloat32 (value float32, flags packs.Flags) { p.addSep(); packFloatString(p.state,float64(value),flags,32); p.state.Inc() }
func (p *Packer) ItemFloat64 (value float64, flags packs.Flags) { p.addSep(); packFloatString(p.state,value,flags,64); p.state.Inc() }
func (p *Packer) ItemDate (value time.Time, flags packs.Flags) { p.addSep(); packDate(p.state,value,flags); p.state.Inc() }
func (p *Packer) ItemList (builder func(packer packs.ListPacker, flags packs.Flags), flags packs.Flags) {
p.addSep()
p.PackList(builder,flags)
p.state.Inc()
}
func (p *Packer) ItemMap (builder func(packer packs.MapPacker , flags packs.Flags), flags packs.Flags) {}
func (p *Packer) ItemObject(builder func(packer packs.ObjectPacker, flags packs.Flags), flags packs.Flags) {}
func (p *Packer) addSep () {
if p.state.Count() > 0 {
p.state.WriteByte(',')
}
}
func packListString (state *packs.State, list []string, flags packs.Flags) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packString(state,v,flags)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func packListBool (state *packs.State, list []bool, flags packs.Flags) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packBool(state,v,flags)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func packListInt [T int | int8 | int16 | int32 | int64](state *packs.State, list []T, flags packs.Flags) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packInt(state,int64(v),flags)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func packListUInt [T uint | uint8 | uint16 | uint32 | uint64](state *packs.State, list []T, flags packs.Flags) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packUInt(state,uint64(v),flags)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func packListFloat[T float32 | float64](state *packs.State, list []T, flags packs.Flags, bits int) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packFloatString(state,float64(v),flags,bits)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func packListDate (state *packs.State, list []time.Time, flags packs.Flags) {
if !checkList(state,list == nil, len(list) ==0) {
return
}
state.WriteByte('[')
for i,v := range list {
if i > 0 {
state.WriteByte(',')
}
packDate(state,v,flags)
if state.Error != nil {
return
}
}
state.WriteByte(']')
}
func checkList (state *packs.State, isNull, isEmpty bool) bool {
if isNull {
state.Write2Byte('"','"')
return false
}
if isEmpty {
state.Write2Byte('[',']')
return false
}
return true
}

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_value.go
// File name value_packer.go
// Created by DEV
// Modified 05/02/2024
// Modified 06/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -24,6 +24,7 @@
package pjson
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packs"
"encoding/base32"
"encoding/base64"
@ -56,42 +57,67 @@ func (p *Packer) PackAny (value any, flags packs.Flags) {
p.state.W(d)
}
case reflect.Value:
rPackAny(p.state,v,flags)
case bool : packBool (p.state,v,flags )
default:
rPackAny(p.state,reflect.ValueOf(value), flags)
}
}
case string : packString(p.state,v,flags )
case int : packInt(p.state,int64(v),flags)
case int8 : packInt(p.state,int64(v),flags)
case int16 : packInt(p.state,int64(v),flags)
case int32 : packInt(p.state,int64(v),flags)
case int64 : packInt(p.state,v,flags )
case uint : packUInt(p.state,uint64(v),flags)
case uint8 : packUInt(p.state,uint64(v),flags)
case uint16 : packUInt(p.state,uint64(v),flags)
case uint32 : packUInt(p.state,uint64(v),flags)
case uint64 : packUInt(p.state,v,flags )
case float32: packFloatString(p.state,float64(v),flags,32)
case float64: packFloatString(p.state,v,flags,64)
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
case time.Time: packDate (p.state,v,flags)
case reflect.Value: rTypePacker(v.Type())(p.state,v,flags)
case []uint8 :
if flags.Binary() {
packBinary(p.state,v,flags)
return
}
packListUInt[uint8 ](p.state,v,flags)
case []uint : packListUInt [uint ] (p.state,v,flags)
case []uint16 : packListUInt [uint16] (p.state,v,flags)
case []uint32 : packListUInt [uint32] (p.state,v,flags)
case []uint64 : packListUInt [uint64] (p.state,v,flags)
case []int : packListInt [int ] (p.state,v,flags)
case []int8 : packListInt [int8 ] (p.state,v,flags)
case []int16 : packListInt [int16] (p.state,v,flags)
case []int32 : packListInt [int32] (p.state,v,flags)
case []int64 : packListInt [int64] (p.state,v,flags)
case []float32: packListFloat[float32](p.state,v,flags,32)
case []float64: packListFloat[float64](p.state,v,flags,64)
case []bool : packListBool (p.state,v,flags)
case []string : packListString(p.state,v,flags)
case []time.Time: packListDate(p.state,v,flags)
default:
rv := reflect.ValueOf(value)
rTypePacker(rv.Type())(p.state,rv,flags)
}
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) PackRaw (value []byte, flags packs.Flags) { packRaw(p.state,value,flags) }
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) }
@ -105,17 +131,67 @@ func (p *Packer) PackUInt64 (value uint64, flags packs.Flags) { packUInt(p.stat
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) PackDate (value time.Time, flags packs.Flags) { packDate(p.state,value,flags) }
func (p *Packer) PackList (builder func(packs.ListPacker, packs.Flags), flags packs.Flags) {
p.packCompound('[',']',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}
func (p *Packer) PackMap (builder func(packs.MapPacker, packs.Flags), flags packs.Flags) {
//p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}
func (p *Packer) PackObject(builder func(packs.ObjectPacker, packs.Flags), flags packs.Flags) {
//p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
}
func (p *Packer) packCompound (opener, closer byte, isnil bool, buildFn func(*Packer,packs.Flags), flags packs.Flags) {
if p.state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(p.state.Error))
}
if isnil {
p.state.W(G.nullValue)
return
}
dn := false
defer func(d *bool) {
if !(*d) {
p.state.SetError(errs.ToError(recover()))
}
}(&dn)
p.state.Open(opener)
buildFn(p,flags)
if p.state.Error != nil {
return
}
p.state.Close(closer)
dn = true
}
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 packRaw (state *packs.State, value []byte, flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if value == nil {
state.W(G.nullValue)
return
}
if len(value) == 0 {
state.Write2Byte('"','"')
return
}
state.WOQ(flags.Quote(),'"',value)
}
func packString (state *packs.State, value string , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
@ -198,7 +274,7 @@ func packBinary (state *packs.State, value []byte , flags packs.Flags) {
return
}
state.WriteByte('"')
if flags.Bin64() {
packBinary64(state, value, 0)
} else if flags.Bin32() {
@ -255,16 +331,10 @@ 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('"')
state.WOQ(flags.Quote(),'"',G.trueValue)
} else {
state.WOQ(flags.Quote(),'"',G.falseValue)
}
}
@ -273,7 +343,8 @@ func packInt (state *packs.State, value int64 , flags packs.Flags) {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
}
if flags.Quote() {
q :=flags.Quote()
if q {
state.WriteByte('"')
}
if value == 0 {
@ -281,11 +352,12 @@ func packInt (state *packs.State, value int64 , flags packs.Flags) {
} else {
state.WriteIntStr(value, 10)
}
if flags.Quote() {
if q {
state.WriteByte('"')
}
}
func packUInt (state *packs.State, value uint64 , flags packs.Flags) {
if state.Error != nil {
panic(packs.G.ErrInvalidState.WithCause(state.Error))
@ -337,26 +409,16 @@ func packFloatString (state *packs.State, f float64, flags packs.Flags, bits int
}
}
if flags.Quote() {
state.WriteByte('"')
state.W(bf)
state.WriteByte('"')
return
}
state.W(bf)
state.WOQ(flags.Quote(),'"',bf)
}
func PackDate (state *packs.State, value time.Time, flags packs.Flags) {
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('"')
state.WOQ(true,'"',bf)
}

@ -26,6 +26,7 @@ package pjson
import (
"activething.com/go/gogo/packs"
"reflect"
"sync"
)
type (
@ -38,5 +39,64 @@ type (
func rTypePacker (rtype reflect.Type) rPackerFnc {
if fn,ok := G.packersCache.Load(rtype); ok {
return fn.(rPackerFnc)
}
var wg sync.WaitGroup
var fn rPackerFnc
wg.Add(1)
fi,ld := G.packersCache.LoadOrStore(rtype, rPackerFnc(func (e *packs.State, v reflect.Value, f packs.Flags) {
wg.Wait()
fn(e,v,f)
}))
if ld {
return fi.(rPackerFnc)
}
fn = _rTypePacker(rtype)
wg.Done()
G.packersCache.Store(rtype,fn)
return fn
}
func _rTypePacker(t reflect.Type) rPackerFnc {
switch t.Kind() {
case reflect.Bool : return func(s *packs.State, v reflect.Value, f packs.Flags) { packBool (s,v.Bool (),f )}
case reflect.String : return func(s *packs.State, v reflect.Value, f packs.Flags) { packString(s,v.String(),f )}
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64 : return func(s *packs.State, v reflect.Value, f packs.Flags) { packInt (s,v.Int (),f )}
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64 : return func(s *packs.State, v reflect.Value, f packs.Flags) { packUInt (s,v.Uint (),f )}
case reflect.Float32: return func(s *packs.State, v reflect.Value, f packs.Flags) { packFloatString(s,v.Float(),f,32) }
case reflect.Float64: return func(s *packs.State, v reflect.Value, f packs.Flags) { packFloatString(s,v.Float(),f,64) }
case reflect.Slice,
reflect.Array :
return (*newRPackerList(t.Elem())).pack
case reflect.Map :
return (*newRPackerMap(t)).pack
}
return unsupportedTypePacker
}
func unsupportedTypePacker(state *packs.State, _ reflect.Value, _ packs.Flags) {
state.SetError(packs.G.ErrUnsupportedType)
}
func rPackAny (state *packs.State, rvalue reflect.Value, flags packs.Flags) {}

@ -0,0 +1,166 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.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"
"math"
"reflect"
"strconv"
)
func stringifyRKey(rt reflect.Type) rPackerMapEntryFnc {
fn,ok := G.keyersCache.Load(rt)
if !ok {
fn, _ = G.keyersCache.LoadOrStore(rt, _stringifyRKey(rt))
}
return fn.(rPackerMapEntryFnc)
}
func _stringifyRKey(rt reflect.Type) rPackerMapEntryFnc {
if rt.Kind() == reflect.String {
return func(e *rPackerMapEntry, k reflect.Value) error {
e.k = k.String()
e.f = packs.FlagScapeHTML
return nil
}
}
if rt.Implements(G.textMarshalerType) {
return func(e *rPackerMapEntry, k reflect.Value) error {
if k.Kind() == reflect.Pointer && k.IsNil() {
return nil
}
bf, er := (k.Interface().(encoding.TextMarshaler)).MarshalText()
if er == nil {
e.k = string(bf)
e.f = packs.FlagScapeHTML
}
return er
}
}
switch rt.Kind() {
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
return func(e *rPackerMapEntry, k reflect.Value) error {
e.k = strconv.FormatInt(k.Int(), 10)
return nil
}
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
return func(e *rPackerMapEntry, k reflect.Value) error {
e.k = strconv.FormatUint(k.Uint(), 10)
return nil
}
case reflect.Interface:
return func(e *rPackerMapEntry, k reflect.Value) error {
k = k.Elem()
if k.Type().Kind() == reflect.String {
e.k = k.String()
e.f = packs.FlagScapeHTML
return nil
}
if t,h := k.Interface().(encoding.TextMarshaler); h {
if k.Type().Kind() == reflect.Pointer && k.IsNil() {
return nil
}
bf, er := t.MarshalText()
if er == nil {
e.k = string(bf)
e.f = packs.FlagScapeHTML
}
return er
}
switch rt.Kind() {
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
e.k = strconv.FormatInt(k.Int(), 10)
return nil
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
e.k = strconv.FormatUint(k.Uint(), 10)
return nil
default:
return packs.G.ErrInvalidKey
}
}
default:
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
}

@ -0,0 +1,69 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_list.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"
"reflect"
)
type (
rPackerList struct {
packFn rPackerFnc
}
)
func newRPackerList (rtype reflect.Type) *rPackerList {
return &rPackerList{
packFn: rTypePacker(rtype),
}
}
func (p rPackerList) pack (s *packs.State, v reflect.Value, f packs.Flags) {
if v.IsNil() {
_,_ = s.Write(G.nullValue)
return
}
if v.Len() == 0 {
s.Write2Byte('[',']')
return
}
s.Open('[')
for i:=0; i<v.Len(); i++ {
if i > 0 {
s.WriteByte(',')
}
p.packFn(s,v.Index(i),f)
if s.Error != nil {
return
}
}
s.Close(']')
}

@ -0,0 +1,107 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rpacker_map.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"
"reflect"
"sort"
)
type (
rPackerMap struct {
keyFn rPackerMapEntryFnc
packFn rPackerFnc
}
)
func newRPackerMap (rtype reflect.Type) *rPackerMap {
return &rPackerMap{
packFn: rTypePacker (rtype.Elem()),
keyFn : stringifyRKey(rtype.Key()),
}
}
func (p *rPackerMap) pack (s *packs.State, v reflect.Value, f packs.Flags) {
if p.keyFn == nil {
s.SetError(packs.G.ErrInvalidKey)
return
}
if v.IsNil() {
s.W(G.nullValue)
return
}
if v.Len() == 0 {
s.Write2Byte('{','}')
return
}
if s.Level > startDetectingCyclesAfter {
if fn,ok := s.CheckCycle(v.UnsafePointer()); ok {
defer fn()
} else {
s.SetError(packs.G.ErrRedundantPack)
return
}
}
mi := v.MapRange()
ls := make(rPackerMapEntryList,v.Len())
for i:=0; mi.Next(); i++ {
ls[i] = rPackerMapEntry{
v: mi.Value(),
}
if er := p.keyFn(&ls[i], mi.Key()); er != nil {
s.SetError(er)
return
}
}
sort.Sort(ls)
s.Open ('{')
for i:=0; i<len(ls); i++ {
if i>0 {
s.WriteByte(',')
}
packString(s,ls[i].k,ls[i].f)
if s.Error != nil {
return
}
s.WriteByte(':')
p.packFn(s,ls[i].v,0)
if s.Error != nil {
return
}
}
s.Close('}')
}

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name list_Itemer.go
// File name rpacker_map_entry.go
// Created by DEV
// Modified 23/01/2024
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -21,44 +21,45 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packs
package pjson
import "time"
import (
"activething.com/go/gogo/packs"
"reflect"
)
type (
ListPacker interface {
Item (value any)
ItemRaw (value []byte)
ItemBinary (value []byte)
ItemString (value string)
rPackerMapEntry struct {
f packs.Flags // flags
v reflect.Value // value
k string // Key
}
rPackerMapEntryFnc func(entry *rPackerMapEntry, rkey reflect.Value) error
ItemBool (value bool)
rPackerMapEntryList []rPackerMapEntry
ItemInt8 (value int8)
ItemInt16 (value int16)
ItemInt32 (value int32)
ItemInt64 (value int64)
)
ItemUInt8 (value uint8)
ItemUInt16 (value uint16)
ItemUInt32 (value uint32)
ItemUInt64 (value uint64)
ItemFloat32 (value float32)
ItemFloat64 (value float64)
ItemDate (value time.Time)
ItemList (builder func(packer ListPacker))
ItemMap (builder func(packer MapPacker ))
ItemObject(builder func(packer ObjectPacker))
}
)
func (e rPackerMapEntryList) Len() int {
return len(e)
}
func (e rPackerMapEntryList) Less(i, j int) bool {
return e[i].k < e[j].k
}
func (e rPackerMapEntryList) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}
Loading…
Cancel
Save

Powered by TurnKey Linux.