redefiniendo el builder

packs2
DEV 3 years ago
parent bc0d45885a
commit 3752aca0d8

@ -24,29 +24,18 @@
package main
import (
"actiovething.com/go/gogo/packs/_pjson"
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packs"
"activething.com/go/gogo/packs/jjson"
"fmt"
)
func main() {
p := _pjson.NewBuilder(func (pk *_pjson.Builder) {
})
p := jjson.JSONPacker{}
d,e := p.Pack(22)
errs.Test(e,false)
fmt.Printf("Data = %s\n",d)
p.Object(func(b packs.BuilderObject) {
b.FieldBinary("0", []byte{43,53,32,34,53,35})
})
errs.Test(p.Error())
fmt.Printf("Data \n%s",p.Data())
/*
d,_ := json.Marshal("<html>asdadasd<html>")
fmt.Printf("Data \n%s",d)
*/
}

@ -116,9 +116,11 @@ func getStackTrace(err error) StackTrace {
return nil
}
func Test(err error) {
func Test(err error, halt bool) {
if err != nil {
fmt.Printf("err %v\n", err.Error())
panic(err)
if halt {
panic(err)
}
}
}

@ -25,7 +25,13 @@ package packs
import "time"
type (
Builder interface {
Data () []byte
Error () error

@ -30,7 +30,7 @@ type (
BuilderMap interface {
ElemAny (key any, value any)
ElemAny (key any, value any)
ElemBinary (key any, value []byte)
ElemString (key any, value string)

@ -25,29 +25,44 @@ 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
Error error
State struct {
*bins.Buffer/*Embedded*/
Node *StateNode
Temp [64]byte
Seen map[any]struct{}
Error error
}
)
func AcquireState () *State {
if atomic.CompareAndSwapUint32(&G.stateSem,0,1) {
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 : AcquireNode(nil, NodeKindValue, 0),
Node : G.nodePool.Get().Init(nil, NodeKindValue, 0),
Buffer: bins.NewBuffer(),
Seen: make(map[any]struct{}),
}
}),
)
@ -57,7 +72,7 @@ func AcquireState () *State {
func ReleaseState (state *State) {
if state == nil {
if state == nil && atomic.LoadUint32(&G.poolsSem) == 1 {
return
}
state.Buffer.Reset()
@ -112,7 +127,7 @@ func (s *State) Open(kind NodeKind) bool {
}
s.Node.Init(s.Node.Parent, kind, s.Len())
} else {
s.Node = AcquireNode(s.Node, kind, s.Len())
s.Node = G.nodePool.Get().Init(s.Node, kind, s.Len())
}
return true
}
@ -124,10 +139,11 @@ func (s *State) Close() bool {
if s.Node.Kind == NodeKindValue {
return !s.SetError(G.ErrInvalidNode)
}
if s.Node.Parent != nil {
p := s.Node
s.Node = s.Node.Parent
ReleaseNode(p.Reset())
G.nodePool.Put(p.Reset())
}
s.Node.Count++
return true

@ -25,8 +25,6 @@ package packs
import (
"activething.com/go/gogo/core/slices"
"activething.com/go/gogo/core/syncs"
"sync/atomic"
)
type (
@ -41,27 +39,6 @@ type (
}
)
func AcquireNode(parent *StateNode, kind NodeKind, start int) *StateNode {
if atomic.CompareAndSwapUint32(&G.nodeSem, 0, 1) {
G.nodePool = syncs.NewPool[StateNode](
syncs.PoolWithNew[StateNode](func()*StateNode{
return &StateNode{
Kind: NodeKindValue,
keys: make(slices.String, 0, 10),
}
}),
)
}
return G.nodePool.Get().Init(parent, kind, start)
}
func ReleaseNode(node *StateNode) {
if node != nil {
G.nodePool.Put(node.Reset())
}
}
func (n *StateNode) Init(parent *StateNode, kind NodeKind, start int) *StateNode {
n.Parent = parent
if parent != nil {

@ -24,6 +24,7 @@
package packs
const (
NodeKindValue NodeKind = iota
NodeKindList
NodeKindMap

@ -33,11 +33,10 @@ import (
var (
G = struct {
nodeSem uint32
nodePool *syncs.Pool[StateNode]
stateSem uint32
poolsSem uint32
statePool *syncs.Pool[State]
nodePool *syncs.Pool[StateNode]
ErrInvalidNode errs.ErrCode
ErrInvalidElement errs.ErrCode
@ -46,6 +45,7 @@ var (
ErrKeyRequired errs.ErrCode
ErrValueRequired errs.ErrCode
ErrInvalidList errs.ErrCode
ErrRedundantPack errs.ErrCode
}{
ErrInvalidNode : errs.ErrCode("packs.invalid-StateNode"),
ErrInvalidElement: errs.ErrCode("packs.invalid-element"),
@ -54,6 +54,7 @@ var (
ErrKeyRequired : errs.ErrCode("packs:key-required"),
ErrValueRequired : errs.ErrCode("packs:value-required"),
ErrInvalidList : errs.ErrCode("packs:invalid-list"),
ErrRedundantPack : errs.ErrCode("packs:redundant-pack"),
}
)

@ -28,10 +28,16 @@ import (
"activething.com/go/gogo/core/syncs"
"activething.com/go/gogo/packs"
"encoding/json"
"reflect"
"sort"
"sync/atomic"
"time"
)
const(
maxDeepUncheck = 100
)
type (
@ -46,6 +52,7 @@ type (
)
func AcquireBuilder (options ...opts.OptionFnc[Builder]) *Builder {
if atomic.CompareAndSwapUint32(&G.sentinel,0,1) {
G.builderPool = syncs.NewPool[Builder](
@ -70,7 +77,22 @@ func ReleaseBuilder (builder *Builder) {
func (b *Builder) Any (value any) {}
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) Map (builder func(packer packs.BuilderMap)) {}
@ -82,4 +104,126 @@ func (b *Builder) reset () *Builder {
b.dateLayout = time.RFC822Z
b.state.Reset()
return b
}
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
}
}
})
}
func (b *Builder) objPacker (rv reflect.Value) {
if rv.IsNil() {
b.state.Write(G.nullValue)
return
}
if rv.Len() == 0 {
b.state.Write2Byte('{','}')
return
}
}
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.Int : b._listPacker (rv, func(lb packs.BuilderList, ev reflect.Value) { lb.ItemInt64(int64(ev.Int())) })
}
}
func (b *Builder) _listPacker (rlist reflect.Value, add func(lb packs.BuilderList, ev reflect.Value)) {
for i:=0; i< rlist.Len(); i++ {
add(b,rlist.Index(i))
if b.state.Error != nil {
return
}
}
}
func stringifyKey(key reflect.Value, ops Options) (string,bool) {
return "ss",true
}

@ -25,12 +25,16 @@ package jjson
import (
"activething.com/go/gogo/core/syncs"
"sync"
"unicode/utf8"
)
var (
G = struct {
objectCache sync.Map
sentinel uint32
builderPool *syncs.Pool[Builder]

@ -30,6 +30,7 @@ const (
JSONOptionsIgnoreKeys
JSONOptionsQuoteFloats
JSONOptionsIgnoreDefaults
JSONOptionsSortMapKeys
jsonOptionsDefaults = JSONOptionsQuote | JSONOptionsEscapeHTML
@ -59,3 +60,7 @@ func (o Options) IgnoreKeys() bool {
func (o Options) IgnoreDefaults() bool {
return o&JSONOptionsIgnoreDefaults != 0
}
func (o Options) SortMapKeys() bool {
return o&JSONOptionsSortMapKeys != 0
}

@ -37,16 +37,17 @@ type (
func (p JSONPacker) Pack (value any) (d []byte, e error) {
dn := false
defer func (v *bool, er *error) {
bl := AcquireBuilder()
defer func (b *Builder, v *bool, er *error) {
if !(*v) {
*er = errs.ToError(recover())
}
}(&dn,&e)
ReleaseBuilder(b)
}(bl,&dn,&e)
bd := AcquireBuilder()
bd.Any(value)
bl.Any(value)
dn = true
return bd.state.Bytes(),bd.state.Error
return bl.state.Bytes(),bl.state.Error
}

@ -0,0 +1,31 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packer_cache.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

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

@ -27,7 +27,9 @@ type (
Packer interface {
Pack(value any) ([]byte, error)
}
)

Loading…
Cancel
Save

Powered by TurnKey Linux.