redefiniendo el builder

packs2
DEV 3 years ago
parent 9c824de31a
commit 63f83a353b

@ -1,49 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name cache.go
// Created by DEV
// Modified 30/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 js
import (
"reflect"
"sync"
)
type (
cachePackers struct {
sync.RWMutex
packers map[reflect.Type]packerFn
keyers map[reflect.Type]StringerFn
}
)
func NewCachePackers () *cachePackers {
return &cachePackers{
keyers : make(map[reflect.Type]StringerFn),
packers: make(map[reflect.Type]packerFn),
}
}

@ -2,7 +2,7 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name flags.go
// File name f.go
// Created by DEV
// Modified 29/01/2024
//

@ -25,8 +25,11 @@ package js
import (
"encoding"
"encoding/json"
"math"
"reflect"
"strconv"
"sync"
"unicode/utf8"
)
@ -46,14 +49,17 @@ var (
mapEmpty []byte
listEmpty []byte
objectEmpty []byte
/*
floatNaN []byte
floatInfPos []byte
floatInfNeg []byte
*/
packers *cachePackers
packers sync.Map
keyers sync.Map
jsonMarshalerType reflect.Type
textMarshalerType reflect.Type
}{
@ -68,14 +74,14 @@ var (
mapEmpty: []byte{'{', '}'},
objectEmpty: []byte{'{', '}'},
listEmpty: []byte{'[', ']'},
/*
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
*/
packers: NewCachePackers(),
jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(),
textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(),
}

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name key_val_packer.go
// File name rkey.go
// Created by DEV
// Modified 03/02/2024
// Modified 04/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -27,110 +27,41 @@ import (
"activething.com/go/gogo/packs"
"encoding"
"reflect"
"sort"
"strconv"
)
type (
kvPacker struct {
keyFn keyStringerFnc
valFn packerFn
}
keyStringerFnc func(entry *kvEntry, rkey reflect.Value) error
)
func newKVPacker (rtype reflect.Type) *kvPacker {
return &kvPacker{
valFn : typePacker(rtype.Elem()),
keyFn : _keyStringer(rtype.Key()),
func stringifyRKey(rt reflect.Type) rMapEntryFnc {
fn,ok := G.keyers.Load(rt)
if !ok {
fn, _ = G.keyers.LoadOrStore(rt, _stringifyRKey(rt))
}
return fn.(rMapEntryFnc)
}
func (p *kvPacker) pack (s *packs.State, v reflect.Value, f 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(kvEntryList,v.Len())
for i:=0; mi.Next(); i++ {
ls[i] = kvEntry {
rval: 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].key,ls[i].flags)
if s.Error != nil {
return
}
s.WriteByte(':')
p.valFn(s,ls[i].rval,0)
if s.Error != nil {
return
}
}
s.Close('}')
}
func _stringifyRKey(rt reflect.Type) rMapEntryFnc {
func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
if rt.Kind() == reflect.String {
return func(e *kvEntry, k reflect.Value) error {
e.key = k.String()
e.flags = FlagScapeHTML
return func(e *rMapEntry, k reflect.Value) error {
e.k = k.String()
e.f = FlagScapeHTML
return nil
}
}
if rt.Implements(reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()) {
return func(e *kvEntry, k reflect.Value) error {
if rt.Implements(G.textMarshalerType) {
return func(e *rMapEntry, k reflect.Value) error {
if k.Kind() == reflect.Pointer && k.IsNil() {
return nil
}
bf, er := (k.Interface().(encoding.TextMarshaler)).MarshalText()
if er == nil {
e.key = string(bf)
e.flags = FlagScapeHTML
e.k = string(bf)
e.f = FlagScapeHTML
}
return er
}
@ -143,8 +74,8 @@ func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
reflect.Int16,
reflect.Int32,
reflect.Int64:
return func(e *kvEntry, k reflect.Value) error {
e.key = strconv.FormatInt(k.Int(), 10)
return func(e *rMapEntry, k reflect.Value) error {
e.k = strconv.FormatInt(k.Int(), 10)
return nil
}
case reflect.Uint,
@ -153,18 +84,18 @@ func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
return func(e *kvEntry, k reflect.Value) error {
e.key = strconv.FormatUint(k.Uint(), 10)
return func(e *rMapEntry, k reflect.Value) error {
e.k = strconv.FormatUint(k.Uint(), 10)
return nil
}
case reflect.Interface:
return func(e *kvEntry, k reflect.Value) error {
return func(e *rMapEntry, k reflect.Value) error {
k = k.Elem()
if k.Type().Kind() == reflect.String {
e.key = k.String()
e.flags = FlagScapeHTML
e.k = k.String()
e.f = FlagScapeHTML
return nil
}
@ -174,8 +105,8 @@ func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
}
bf, er := t.MarshalText()
if er == nil {
e.key = string(bf)
e.flags = FlagScapeHTML
e.k = string(bf)
e.f = FlagScapeHTML
}
return er
}
@ -187,7 +118,7 @@ func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
reflect.Int16,
reflect.Int32,
reflect.Int64:
e.key = strconv.FormatInt(k.Int(), 10)
e.k = strconv.FormatInt(k.Int(), 10)
return nil
case reflect.Uint,
@ -196,7 +127,7 @@ func _keyStringer(rt reflect.Type) func(me *kvEntry, key reflect.Value) error {
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
e.key = strconv.FormatUint(k.Uint(), 10)
e.k = strconv.FormatUint(k.Uint(), 10)
return nil
default:

@ -30,13 +30,13 @@ import (
type (
typeSlicePacker struct {
packer packerFn
rList struct {
valFn packerFn
}
)
func (p typeSlicePacker) pack (s *packs.State, v reflect.Value, f Flags) {
func (p rList) pack (s *packs.State, v reflect.Value, f Flags) {
if v.IsNil() {
_,_ = s.Write(G.nullValue)
return
@ -50,7 +50,7 @@ func (p typeSlicePacker) pack (s *packs.State, v reflect.Value, f Flags) {
if i > 0 {
s.WriteByte(',')
}
p.packer(s,v.Index(i),f)
p.valFn(s,v.Index(i),f)
if s.Error != nil {
return
}

@ -0,0 +1,110 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name key_val_packer.go
// Created by DEV
// Modified 03/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 js
import (
"activething.com/go/gogo/packs"
"reflect"
"sort"
)
type (
rMap struct {
keyFn rMapEntryFnc
valFn packerFn
}
)
func newRMap (rtype reflect.Type) *rMap {
return &rMap{
valFn : typePacker(rtype.Elem()),
keyFn : stringifyRKey(rtype.Key()),
}
}
func (p *rMap) pack (s *packs.State, v reflect.Value, f 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(rMapEntryList,v.Len())
for i:=0; mi.Next(); i++ {
ls[i] = rMapEntry{
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.valFn(s,ls[i].v,0)
if s.Error != nil {
return
}
}
s.Close('}')
}

@ -28,13 +28,15 @@ import "reflect"
type (
kvEntry struct {
flags Flags
rval reflect.Value
key string
rMapEntry struct {
f Flags // flags
v reflect.Value // value
k string // Key
}
kvEntryList []kvEntry
rMapEntryFnc func(entry *rMapEntry, rkey reflect.Value) error
rMapEntryList []rMapEntry
)
@ -42,15 +44,15 @@ type (
func (e kvEntryList) Len() int {
func (e rMapEntryList) Len() int {
return len(e)
}
func (e kvEntryList) Less(i, j int) bool {
return e[i].key < e[j].key
func (e rMapEntryList) Less(i, j int) bool {
return e[i].k < e[j].k
}
func (e kvEntryList) Swap(i, j int) {
func (e rMapEntryList) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}

@ -50,24 +50,15 @@ func RPacker(state *packs.State, value any, flags Flags ) {
func typePacker (rtype reflect.Type) packerFn {
G.packers.RLock()
if f,h := G.packers.packers[rtype]; h {
G.packers.RUnlock()
return f
fn,ok := G.packers.Load(rtype)
if !ok {
fn,_ = G.packers.LoadOrStore(rtype, _rTypePacker(rtype))
}
G.packers.RUnlock()
f := buildTypePacker(rtype)
G.packers.Lock()
G.packers.packers[rtype]=f
G.packers.Unlock()
return f
return fn.(packerFn)
}
func buildTypePacker(t reflect.Type) packerFn {
func _rTypePacker(t reflect.Type) packerFn {
switch t.Kind() {
case reflect.Bool : return func(s *packs.State, v reflect.Value, f Flags) { packBool (s,v.Bool (),f )}
@ -87,11 +78,10 @@ func buildTypePacker(t reflect.Type) packerFn {
case reflect.Slice,
reflect.Array :
return (typeSlicePacker{ packer: typePacker(t.Elem()) }).pack
return (rList{ valFn: typePacker(t.Elem()) }).pack
case reflect.Map :
return newKVPacker(t).pack
// return newTypeMapPacker(t).pack
return newRMap(t).pack
}

@ -1,289 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name type_map_packer.go
// Created by DEV
// Modified 30/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 js
import (
"activething.com/go/gogo/packs"
"encoding"
"reflect"
"sort"
"strconv"
)
type (
typeMapPacker struct {
keyStringer StringerFn
valPacker packerFn
}
StringerFn func(me *TypeMapEntry, key reflect.Value) error
TypeMapEntry struct {
Val reflect.Value
Key string
flags Flags
}
Entries []TypeMapEntry
)
func (e Entries) Len() int {
return len(e)
}
// Less compares two entries based on their keys
func (e Entries) Less(i, j int) bool {
return e[i].Key < e[j].Key
}
// Swap swaps two entries in the slice
func (e Entries) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}
func newTypeMapPacker (rtype reflect.Type) *typeMapPacker {
return &typeMapPacker{
valPacker : typePacker (rtype.Elem()),
keyStringer: keyStringer(rtype.Key ()),
}
}
func (m typeMapPacker) pack (s *packs.State, v reflect.Value, _ Flags) {
if v.IsNil() {
_,_ = s.Write(G.nullValue)
return
}
mi := v.MapRange()
ls := make(Entries,v.Len())
if s.Level > startDetectingCyclesAfter {
if fn,ok := s.CheckCycle(v.UnsafePointer()); ok {
defer fn()
} else {
s.SetError(packs.G.ErrRedundantPack)
return
}
}
for i:=0; mi.Next(); i++ {
ls[i] = TypeMapEntry{
Val: mi.Value(),
}
if er := m.keyStringer(&ls[i], mi.Key()); er != nil {
s.SetError(er)
return
}
}
sort.Sort(ls)
//sort.Slice(ls, func(i, j int) bool { return ls[i].Key < ls[j].Key })
s.Open ('{')
for i:=0; i<len(ls); i++ {
if i>0 {
s.WriteByte(',')
}
packString(s,ls[i].Key,ls[i].flags)
if s.Error != nil {
return
}
s.WriteByte(':')
m.valPacker(s,ls[i].Val,0)
if s.Error != nil {
return
}
}
s.Close('}')
}
/*
func (m typeMapPacker) pack (s *packs.State, v reflect.Value, _ Flags) {
if v.IsNil() {
_,_ = s.Write(G.nullValue)
return
}
mi := v.MapRange()
ls := make(Entries,v.Len())
if s.Level > startDetectingCyclesAfter {
if fn,ok := s.CheckCycle(v.UnsafePointer()); ok {
defer fn()
} else {
s.SetError(packs.G.ErrRedundantPack)
return
}
}
for i:=0; mi.Next(); i++ {
ls[i] = TypeMapEntry{
Val: mi.Value(),
}
if er := m.keyStringer(&ls[i], mi.Key()); er != nil {
s.SetError(er)
return
}
}
sort.Sort(ls)
//sort.Slice(ls, func(i, j int) bool { return ls[i].Key < ls[j].Key })
s.Open ('{')
for i:=0; i<len(ls); i++ {
if i>0 {
s.WriteByte(',')
}
packString(s,ls[i].Key,ls[i].flags)
if s.Error != nil {
return
}
s.WriteByte(':')
m.valPacker(s,ls[i].Val,0)
if s.Error != nil {
return
}
}
s.Close('}')
}
*/
func keyStringer(rt reflect.Type) func(me *TypeMapEntry, key reflect.Value) error {
if rt.Kind() == reflect.String {
return func(e *TypeMapEntry, k reflect.Value) error {
e.Key = k.String()
e.flags = FlagScapeHTML
return nil
}
}
if rt.Implements(reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()) {
return func(e *TypeMapEntry, k reflect.Value) error {
if k.Kind() == reflect.Pointer && k.IsNil() {
return nil
}
bf, er := (k.Interface().(encoding.TextMarshaler)).MarshalText()
if er == nil {
e.Key = string(bf)
e.flags = FlagScapeHTML
}
return er
}
}
switch rt.Kind() {
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
return func(e *TypeMapEntry, k reflect.Value) error {
e.Key = strconv.FormatInt(k.Int(), 10)
return nil
}
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
return func(e *TypeMapEntry, k reflect.Value) error {
e.Key = strconv.FormatUint(k.Uint(), 10)
return nil
}
case reflect.Interface:
return func(e *TypeMapEntry, k reflect.Value) error {
k = k.Elem()
if k.Type().Kind() == reflect.String {
e.Key = k.String()
e.flags = 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.Key = string(bf)
e.flags = FlagScapeHTML
}
return er
}
switch rt.Kind() {
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
e.Key = strconv.FormatInt(k.Int(), 10)
return nil
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Uintptr:
e.Key = strconv.FormatUint(k.Uint(), 10)
return nil
default:
return packs.G.ErrInvalidKey
}
}
default:
return func(e *TypeMapEntry, k reflect.Value) error {
return packs.G.ErrInvalidKey
}
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.