From 9dfaa3659d33c608f2a021333ceaf601a2d8309c Mon Sep 17 00:00:00 2001 From: DEV Date: Thu, 25 Jan 2024 18:49:45 +0100 Subject: [PATCH] redefiniendo el builder --- app/main.go | 19 ++-- core/errs/gogo.go | 4 +- core/errs/stack_trace_frame.go | 3 + packs/packer_state.go | 7 +- packs/pjson/list_packer.go | 49 +++++---- packs/pjson/map_packer.go | 2 +- packs/pjson/object_packer.go | 2 +- packs/pjson/options.go | 2 +- packs/pjson/options_flags.go | 13 ++- packs/pjson/packer.go | 179 ++++++++++++++++++++++----------- 10 files changed, 187 insertions(+), 93 deletions(-) diff --git a/app/main.go b/app/main.go index b32e416..8f3a018 100644 --- a/app/main.go +++ b/app/main.go @@ -28,7 +28,6 @@ import ( "activething.com/go/gogo/packs" "activething.com/go/gogo/packs/pjson" "fmt" - "time" ) func main() { @@ -36,17 +35,23 @@ func main() { pk := pjson.NewPacker() + slc := [][]int16 {[]int16{1,2,3,4},[]int16{16,26,36,46}} + pk.PackMap(func(mp packs.MapPacker) { - mp.KeyValueBool("boolean",true) - mp.KeyValueBinary("binary",[]byte{22,121,21,23,23,54,67}) + //mp.KeyValueBool("boolean",true) + //mp.KeyValueBinary("binary",[]byte{22,121,21,23,23,54,67}) + + //mp.KeyValueDate("date",time.Now()) + //mp.KeyValueInt16("",34) - mp.KeyValueDate("date",time.Now()) - mp.KeyValueInt16("",34) mp.KeyValueObject("MiObjeto",func(op packs.ObjectPacker){ - op.FieldFloat64("23",43433.3) - op.FieldString("3","dfsdfsd 0 { + if s.Node.Start > s.Len() { return !s.SetError(G.ErrInvalidNode) } s.Node.Init(s.Node.Parent, kind, s.Len()) @@ -141,6 +140,8 @@ func (s *State) Close() bool { G.nodePool.Put(p.Reset()) } s.Node.Count++ + + fmt.Printf("Level %d Count %d\n",s.Node.Level,s.Node.Count) return true } diff --git a/packs/pjson/list_packer.go b/packs/pjson/list_packer.go index ee71b40..572d8ba 100644 --- a/packs/pjson/list_packer.go +++ b/packs/pjson/list_packer.go @@ -24,36 +24,45 @@ package pjson import ( - "activething.com/go/gogo/packets" + "activething.com/go/gogo/packs" + "fmt" "time" ) -func (p *Packer) Item (value any) { p.addSep().Pack(value) } +func (p *Packer) Item (value any) { p.addItem().Pack(value) } -func (p *Packer) ItemRaw (value []byte) { p.addSep().PackRaw(value) } +func (p *Packer) ItemRaw (value []byte) { p.addItem().PackRaw(value) } -func (p *Packer) ItemBinary (value []byte) { p.addSep().PackBinary(value) } -func (p *Packer) ItemString (value string) { p.addSep().PackString(value) } +func (p *Packer) ItemBinary (value []byte) { p.addItem().PackBinary(value) } +func (p *Packer) ItemString (value string) { p.addItem().PackString(value) } -func (p *Packer) ItemBool (value bool) { p.addSep().PackBool(value) } +func (p *Packer) ItemBool (value bool) { p.addItem().PackBool(value) } -func (p *Packer) ItemInt8 (value int8) { p.addSep().PackInt64(int64(value)) } -func (p *Packer) ItemInt16 (value int16) { p.addSep().PackInt64(int64(value)) } -func (p *Packer) ItemInt32 (value int32) { p.addSep().PackInt64(int64(value)) } -func (p *Packer) ItemInt64 (value int64) { p.addSep().PackInt64(value) } +func (p *Packer) ItemInt8 (value int8) { p.addItem().PackInt64(int64(value)) } +func (p *Packer) ItemInt16 (value int16) { p.addItem().PackInt64(int64(value)) } +func (p *Packer) ItemInt32 (value int32) { p.addItem().PackInt64(int64(value)) } +func (p *Packer) ItemInt64 (value int64) { p.addItem().PackInt64(value) } -func (p *Packer) ItemUInt8 (value uint8) { p.addSep().PackUInt64(uint64(value)) } -func (p *Packer) ItemUInt16 (value uint16) { p.addSep().PackUInt64(uint64(value)) } -func (p *Packer) ItemUInt32 (value uint32) { p.addSep().PackUInt64(uint64(value)) } -func (p *Packer) ItemUInt64 (value uint64) { p.addSep().PackUInt64(value) } +func (p *Packer) ItemUInt8 (value uint8) { p.addItem().PackUInt64(uint64(value)) } +func (p *Packer) ItemUInt16 (value uint16) { p.addItem().PackUInt64(uint64(value)) } +func (p *Packer) ItemUInt32 (value uint32) { p.addItem().PackUInt64(uint64(value)) } +func (p *Packer) ItemUInt64 (value uint64) { p.addItem().PackUInt64(value) } -func (p *Packer) ItemFloat32 (value float32) { p.addSep().PackFloat64(float64(value))} -func (p *Packer) ItemFloat64 (value float64) { p.addSep().PackFloat64(value) } +func (p *Packer) ItemFloat32 (value float32) { p.addItem().PackFloat64(float64(value))} +func (p *Packer) ItemFloat64 (value float64) { p.addItem().PackFloat64(value) } -func (p *Packer) ItemDate (value time.Time) { p.addSep().PackDate(value) } +func (p *Packer) ItemDate (value time.Time) { p.addItem().PackDate(value) } -func (p *Packer) ItemList (builder func(packer packs.ListPacker)) { p.addSep().ItemList (builder) } -func (p *Packer) ItemMap (builder func(packer packs.MapPacker )) { p.addSep().ItemMap (builder) } -func (p *Packer) ItemObject(builder func(packer packs.ObjectPacker)) { p.addSep().ItemObject(builder) } +func (p *Packer) ItemList (builder func(packer packs.ListPacker)) { p.addItem().ItemList (builder) } +func (p *Packer) ItemMap (builder func(packer packs.MapPacker )) { p.addItem().ItemMap (builder) } +func (p *Packer) ItemObject(builder func(packer packs.ObjectPacker)) { p.addItem().ItemObject(builder) } +func (p *Packer) addItem () *Packer { + if p.state.Node.Count > 0 { + _ = p.state.WriteByte(',') + } + p.state.Node.Count++ + fmt.Printf("Set %d.%d\n",p.state.Node.Level,p.state.Node.Count) + return p +} \ No newline at end of file diff --git a/packs/pjson/map_packer.go b/packs/pjson/map_packer.go index 1ffa8fc..991ea9c 100644 --- a/packs/pjson/map_packer.go +++ b/packs/pjson/map_packer.go @@ -24,7 +24,7 @@ package pjson import ( - "activething.com/go/gogo/packets" + "activething.com/go/gogo/packs" "time" ) diff --git a/packs/pjson/object_packer.go b/packs/pjson/object_packer.go index aa0c403..848f97d 100644 --- a/packs/pjson/object_packer.go +++ b/packs/pjson/object_packer.go @@ -24,7 +24,7 @@ package pjson import ( - "activething.com/go/gogo/packets" + "activething.com/go/gogo/packs" "time" ) diff --git a/packs/pjson/options.go b/packs/pjson/options.go index e1bda5e..ba4dcd0 100644 --- a/packs/pjson/options.go +++ b/packs/pjson/options.go @@ -36,7 +36,7 @@ type ( func (o *Options) reset () { - o.Flags = JSONFlagEscapeHTML | JSONFlagQuote + o.Flags = JSONFlagEscapeHTML | JSONFlagQuote | JSONFlagResetOnRead | JSONByteSliceAsBinary o.dateLayout = time.RFC822Z } diff --git a/packs/pjson/options_flags.go b/packs/pjson/options_flags.go index bd263bc..4545ed4 100644 --- a/packs/pjson/options_flags.go +++ b/packs/pjson/options_flags.go @@ -31,10 +31,13 @@ const ( JSONFlagIgnoreKeys JSONFlagQuoteNumbers JSONFlagIgnoreDefaults + JSONByteSliceAsBinary + + JSONFlagResetOnRead ) -type Flags uint8 +type Flags uint16 @@ -59,3 +62,11 @@ func (o Flags) IgnoreDefaults() bool { return o&JSONFlagIgnoreDefaults != 0 } +func (o Flags) ByteSliceAsBinary() bool { + return o&JSONByteSliceAsBinary != 0 +} + + +func (o Flags) ResetOnRead() bool { + return o&JSONFlagResetOnRead != 0 +} \ No newline at end of file diff --git a/packs/pjson/packer.go b/packs/pjson/packer.go index 957acf4..1f5868e 100644 --- a/packs/pjson/packer.go +++ b/packs/pjson/packer.go @@ -30,17 +30,21 @@ import ( "activething.com/go/gogo/packs" "encoding/base64" "encoding/json" - "fmt" "reflect" "time" "unicode/utf8" ) + +const notDetectingCycles = 100 + + type ( Packer struct { options Options state *packs.State + checks map[any]struct{} } @@ -49,7 +53,7 @@ type ( func NewPacker (options ...opts.OptionFnc[Packer]) *Packer { return opts.Apply(&Packer{ options: Options{ - Flags: JSONFlagQuote | JSONFlagEscapeHTML, + Flags: JSONFlagQuote | JSONFlagEscapeHTML | JSONByteSliceAsBinary, dateLayout: time.RFC822Z, }, state : packs.NewState(), @@ -59,7 +63,9 @@ func NewPacker (options ...opts.OptionFnc[Packer]) *Packer { func (p *Packer) Bytes () []byte { - defer p.Reset() + if p.options.ResetOnRead() { + defer p.Reset() + } return append([]byte(nil),p.state.Bytes()...) } @@ -83,13 +89,12 @@ func (p *Packer) Pack (value any) { if value == nil { if p.options.Quote() { - p.state.WriteByte('"') + _ = p.state.WriteByte('"') } - p.state.Write(G.nullValue) + _,_ = p.state.Write(G.nullValue) if p.options.Quote() { - p.state.WriteByte('"') + _ = p.state.WriteByte('"') } - p.state.Node.Count++ return } @@ -113,16 +118,17 @@ func (p *Packer) Pack (value any) { case float32: p.packFloat(float64(v),32) case float64: p.packFloat(v,64) + case time.Time : p.PackDate(v) + case reflect.Value : p.Pack(v.Elem()) default: if pb,is := value.(packs.Packabler); is { - d,e := pb.Build(p) + d, e := pb.Build(p) if p.state.SetError(e) { return } - _,_ = p.state.Write(d) - p.state.Node.Count++ + _, _ = p.state.Write(d) return } if ms,is := value.(json.Marshaler); is { @@ -131,26 +137,21 @@ func (p *Packer) Pack (value any) { return } _,_ = p.state.Write(d) - p.state.Node.Count++ return } rv := reflect.ValueOf(value) switch rv.Kind() { - case reflect.Slice,reflect.Array : + case reflect.Slice, reflect.Array: p.packListReflected(rv) - return - case reflect.Map : + case reflect.Map: p.packMapReflected(rv) - return case reflect.Struct: p.packObjectReflected(rv) - return + default: + p.state.SetError(packs.G.ErrUnsupportedType) } - - p.state.SetError(packs.G.ErrUnsupportedType) } - } @@ -173,7 +174,7 @@ func (p *Packer) PackRaw (value []byte) { _ = p.state.WriteByte('"') } - p.state.Node.Count++ + //p.state.Node.Count++ } @@ -208,36 +209,34 @@ func (p *Packer) PackBinary (value []byte) { } _ = p.state.WriteByte('"') - p.state.Node.Count++ + //p.state.Node.Count++ } -func (p *Packer) PackString (value string) { + + +func (p *Packer) PackString(value string) { + if p.state.Error != nil { panic(p.state.Error) } if len(value) == 0 { p.state.Write2Byte('"','"') - } else { - p.packString(value,p.options.EscapeHTML()) + //p.state.Node.Count++ + return } - p.state.Node.Count++ -} - -func (p *Packer) packString(s string, scapeHTML bool) { - _ = p.state.WriteByte('"') start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if !G.jsonChars[b].isHtmlUnsafe() || (!scapeHTML && !G.jsonChars[b].isUnsafe()) { + for i := 0; i < len(value); { + if b := value[i]; b < utf8.RuneSelf { + if !G.jsonChars[b].isHtmlUnsafe() || (!p.options.EscapeHTML() && !G.jsonChars[b].isUnsafe()) { i++ continue } if start < i { - _,_ = p.state.WriteString(s[start:i]) + _,_ = p.state.WriteString(value[start:i]) } _ = p.state.WriteByte('\\') switch b { @@ -253,10 +252,10 @@ func (p *Packer) packString(s string, scapeHTML bool) { start = i continue } - c, size := utf8.DecodeRuneInString(s[i:]) + c, size := utf8.DecodeRuneInString(value[i:]) if c == utf8.RuneError && size == 1 { if start < i { - _,_ = p.state.WriteString(s[start:i]) + _,_ = p.state.WriteString(value[start:i]) } _,_ = p.state.WriteString(`\ufffd`) i += size @@ -266,7 +265,7 @@ func (p *Packer) packString(s string, scapeHTML bool) { if c == '\u2028' || c == '\u2029' { if start < i { - _,_ = p.state.WriteString(s[start:i]) + _,_ = p.state.WriteString(value[start:i]) } _,_ = p.state.WriteString(`\u202`) _ = p.state.WriteByte(G.hex[c&0xF]) @@ -276,10 +275,13 @@ func (p *Packer) packString(s string, scapeHTML bool) { } i += size } - if start < len(s) { - _,_ = p.state.WriteString(s[start:]) + if start < len(value) { + _,_ = p.state.WriteString(value[start:]) } _ = p.state.WriteByte('"') + + //p.state.Node.Count++ + } @@ -303,7 +305,7 @@ func (p *Packer) PackBool (value bool) { _ = p.state.WriteByte('"') } - p.state.Node.Count++ + //p.state.Node.Count++ } func (p *Packer) PackInt8 (value int8) { p.PackInt64(int64(value)) } @@ -326,7 +328,7 @@ func (p *Packer) PackInt64 (value int64) { _ = p.state.WriteByte('"') } - p.state.Node.Count++ + //p.state.Node.Count++ } func (p *Packer) PackUInt8 (value uint8 ) { p.PackUInt64(uint64(value)) } @@ -349,7 +351,7 @@ func (p *Packer) PackUInt64 (value uint64) { _ = p.state.WriteByte('"') } - p.state.Node.Count++ + //p.state.Node.Count++ } func (p *Packer) PackFloat32 (value float32) { p.packFloat(float64(value),32) } @@ -372,7 +374,7 @@ func (p *Packer) packFloat (value float64, bits int) { _ = p.state.WriteByte('"') } - p.state.Node.Count++ + //p.state.Node.Count++ } @@ -387,7 +389,7 @@ func (p *Packer) PackDate (value time.Time) { })) _ = p.state.WriteByte('"') - p.state.Node.Count++ + //p.state.Node.Count++ } @@ -414,19 +416,12 @@ func (p *Packer) packCompound(kind packs.NodeKind, opening, closing byte, buildF } }(&dn) + //p.addSep() + if p.state.Open(kind) { - fmt.Printf("Node Count %d\n",p.state.Node.Count) _ = p.state.WriteByte(opening) - - /* - if !p.state.SetValue() { - panic(p.state.Error) - } - - */ buildFnc(p) - if p.state.Error == nil { if p.state.Close() { _ = p.state.WriteByte(closing) @@ -470,10 +465,10 @@ func (p *Packer) addKey (key any, call func(*Packer)) { return } - p.packString(ks,p.options.EscapeHTML()) + p.PackString(ks) _ = p.state.WriteByte(':') call(p) - p.state.Node.Count++ + } @@ -487,17 +482,87 @@ func (p *Packer) addField (name string, call func(*Packer)) { return } - p.packString(name,p.options.EscapeHTML()) + p.PackString(name) _ = p.state.WriteByte(':') call(p) - p.state.Node.Count++ + } func (p *Packer) packListReflected (value reflect.Value) { - //todo + if value.IsNil() { + _,_ = p.state.Write(G.nullValue) + return + } + if value.Len() == 0 { + p.state.Write2Byte('[',']') + return + } + + tp := value.Type() + if tp.Elem().Kind() == reflect.Uint8 && p.options.ByteSliceAsBinary() { + p.PackBinary(value.Bytes()) + return + } + + // Comprobamos las llamadas recursivas + /* + if p.state.Node.Level > notDetectingCycles { + rf := value.Interface() + if _,is := p.checks[rf]; is { + p.state.SetError(packs.G.ErrRedundantPack) + return + } + p.checks[rf]=struct{}{} + defer delete(p.checks,rf) + } + */ + + switch tp.Elem().Kind() { + case reflect.String : + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ bl.ItemString(rv.String()) }) + case reflect.Bool : + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ bl.ItemBool (rv.Bool()) }) + case reflect.Uint8 , + reflect.Uint16 , + reflect.Uint32 , + reflect.Uint64 : + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ bl.ItemUInt64(rv.Uint()) }) + case reflect.Int8 , + reflect.Int16 , + reflect.Int32 , + reflect.Int64 : + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ bl.ItemInt64(rv.Int()) }) + case reflect.Float32, + reflect.Float64: + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ bl.ItemFloat64(rv.Float()) }) + case reflect.Slice : + p.buildList(value, func(bl packs.ListPacker, rv reflect.Value){ + p.packListReflected(rv) // Llamamos recursivamente a packListReflected para cada elemento del slice + if p.state.Error != nil { + return + } + }) + case reflect.Map : + case reflect.Struct : + + } + } +func (p *Packer) buildList (value reflect.Value, call func(lp packs.ListPacker, rv reflect.Value)) { + p.PackList(func (lp packs.ListPacker){ + for i:=0; i