diff --git a/app/main.go b/app/main.go index 1fa4232..74bd560 100644 --- a/app/main.go +++ b/app/main.go @@ -24,7 +24,10 @@ package main import ( + "activething.com/go/gogo/core/errs" + "activething.com/go/gogo/packs" "activething.com/go/gogo/packs/js" + "encoding/json" "fmt" ) @@ -50,9 +53,9 @@ func main() { execute() - //st := packs.NewState() + st := packs.NewState() + -/* cas := []string {"a1111","b2222","c3333"} js.RPacker(st,cas,0) @@ -74,12 +77,4 @@ func main() { fmt.Printf("JSON \n%s\n",d) - */ - keys := []string {"B","G","K","9","Z","L"} - - kc := js.NewKeyCollection(10) - for _,v := range keys { - kc.AddKey(v) - } - kc.Iterate() } diff --git a/app/tests/benchmarks_test.go b/app/tests/benchmarks_test.go index 100db2c..3927165 100644 --- a/app/tests/benchmarks_test.go +++ b/app/tests/benchmarks_test.go @@ -175,58 +175,7 @@ func BenchmarkMapJSON (b *testing.B) { -type s struct { - start int - end int -} - -func BenchmarkAppend (b *testing.B) { - - for i:=0; i< b.N; i++ { - data := make([]byte,0,3200) - list := make([]s,0,100) - for k,_ := range ma { - list = append(list,s{ - start: len(data), - end : len(data)+len(k), - }) - data = append(data,[]byte(k)...) - } - for _,v := range list { - if len(string(data[v.start:v.end])) > 100 { - panic("Errror") - } - } - data=data[:0] - } -} - - -type s1 struct { - cadena string - -} - -func BenchmarkCrate (b *testing.B) { - - for i:=0; i< b.N; i++ { - data := make([]byte,0,3200) - list := make([]s1,0,100) - for k,_ := range ma { - list = append(list,s1{ - cadena: k, - }) - data = append(data,[]byte(k)...) - } - for _,v := range list { - if len(v.cadena) > 100 { - panic("Errror") - } - } - data=data[:0] - } -} var ma = map[string]string { diff --git a/packs/js/key_val_entry.go b/packs/js/kv_entry.go similarity index 82% rename from packs/js/key_val_entry.go rename to packs/js/kv_entry.go index f0824a2..7caf11f 100644 --- a/packs/js/key_val_entry.go +++ b/packs/js/kv_entry.go @@ -28,26 +28,30 @@ import "reflect" type ( - keyValEntry struct { - flags Flags - value reflect.Value - key string + kvEntry struct { + flags Flags + rval reflect.Value + key string } - keyValEntries []keyValEntry + kvEntryList []kvEntry ) -func (e keyValEntries) Len() int { + + +func (e kvEntryList) Len() int { return len(e) } -func (e keyValEntries) Less(i, j int) bool { +func (e kvEntryList) Less(i, j int) bool { return e[i].key < e[j].key } -func (e keyValEntries) Swap(i, j int) { +func (e kvEntryList) Swap(i, j int) { e[i], e[j] = e[j], e[i] } + + diff --git a/packs/js/kv_packer.go b/packs/js/kv_packer.go new file mode 100644 index 0000000..e7d401c --- /dev/null +++ b/packs/js/kv_packer.go @@ -0,0 +1,212 @@ +// ------------------------------------------------------------------------ +// 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" + "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 (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; i0 { + 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 _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 nil + } + } + + if rt.Implements(reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()) { + return func(e *kvEntry, 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 *kvEntry, 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 *kvEntry, k reflect.Value) error { + e.key = strconv.FormatUint(k.Uint(), 10) + return nil + } + + case reflect.Interface: + return func(e *kvEntry, 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 nil + } + + +} diff --git a/packs/js/type_map_packer.go b/packs/js/type_map_packer.go index 311b79f..e1ee16c 100644 --- a/packs/js/type_map_packer.go +++ b/packs/js/type_map_packer.go @@ -39,7 +39,8 @@ type ( } - StringerFn func(entry *TypeMapEntry, value reflect.Value) error + StringerFn func(me *TypeMapEntry, key reflect.Value) error + TypeMapEntry struct { @@ -71,11 +72,13 @@ func (e Entries) Swap(i, j int) { func newTypeMapPacker (rtype reflect.Type) *typeMapPacker { return &typeMapPacker{ valPacker : typePacker (rtype.Elem()), - keyStringer: buildKeyStringer(rtype.Key ()), + keyStringer: keyStringer(rtype.Key ()), } } + + func (m typeMapPacker) pack (s *packs.State, v reflect.Value, _ Flags) { if v.IsNil() { _,_ = s.Write(G.nullValue) @@ -128,7 +131,64 @@ func (m typeMapPacker) pack (s *packs.State, v reflect.Value, _ Flags) { -func buildKeyStringer(rt reflect.Type) func(me *TypeMapEntry, key reflect.Value) error { +/* +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; i0 { + 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() @@ -225,53 +285,5 @@ func buildKeyStringer(rt reflect.Type) func(me *TypeMapEntry, key reflect.Value) } } - // caso de map[any]cualquiertypo - /* - return func(e *TypeMapEntry, k reflect.Value) error { - k = k.Elem() - - fmt.Printf("Ejecutando packer general\n %v\n",k) - 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 - } - } - */ } diff --git a/packs/js/type_packer.go b/packs/js/type_packer.go index d0e1412..3f1b57d 100644 --- a/packs/js/type_packer.go +++ b/packs/js/type_packer.go @@ -90,7 +90,8 @@ func buildTypePacker(t reflect.Type) packerFn { return (typeSlicePacker{ packer: typePacker(t.Elem()) }).pack case reflect.Map : - return newTypeMapPacker(t).pack + return newKVPacker(t).pack + // return newTypeMapPacker(t).pack }