redefiniendo el builder

packs2
DEV 3 years ago
parent 1df755eba9
commit 858f700161

@ -23,74 +23,8 @@
package main
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packs/pjson"
"fmt"
)
func main() {
pk := pjson.NewPacker()
/*
slc2 := [][]int16 {{1,2,3,4},{16,26,36,46}}
//slc2:= [][]int16 {{}}
slc2 = append(slc2,slc2 ...)
pk.PackMap(func(mp packs.MapPacker) {
mp.KeyValue("fb0",slc2)
mp.KeyValueList("l01",func(l packs.ListPacker){
l.ItemList(func(l1 packs.ListPacker){
l1.ItemUInt64(11)
l1.ItemUInt64(22)
})
l.ItemList(func(l1 packs.ListPacker){
l1.ItemUInt64(33)
l1.ItemUInt64(44)
})
})
mp.KeyValueBool("boolean",true)
mp.KeyValueFloat32("bf",12223234.34234)
mp.KeyValueBinary("binary",[]byte{22,121,21,23,23,54,67})
mp.KeyValueDate("date",time.Now())
mp.KeyValueInt16("una",34)
mp.KeyValueObject("MiObjeto",func(op packs.ObjectPacker){
op.FieldInt32("fb1",43433)
op.FieldString ("fb2","aaaaa")
op.Field("fb3",slc)
})
})
*/
var s = struct {
F1Int int
F2Uint uint
F3String string
F4Binary []byte
}{
F1Int :-111,
F2Uint: 333,
F3String: "Esto es un string <quoted & scaped >",
F4Binary: []byte("dklsdjflsdjflsdkfjlsdkfjlsdkfjlsdfjdlsfjsdlf"),
}
pk.Pack(s)
errs.Test(pk.Error(),true)
fmt.Printf("JSON \n%s",pk.Bytes())
reflects_main()
}

@ -0,0 +1,96 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name packs.go
// Created by DEV
// Modified 27/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 main
import (
"activething.com/go/gogo/core/errs"
"activething.com/go/gogo/packs/pjson"
"fmt"
)
func packs_main () {
pk := pjson.NewPacker()
/*
slc2 := [][]int16 {{1,2,3,4},{16,26,36,46}}
//slc2:= [][]int16 {{}}
slc2 = append(slc2,slc2 ...)
pk.PackMap(func(mp packs.MapPacker) {
mp.KeyValue("fb0",slc2)
mp.KeyValueList("l01",func(l packs.ListPacker){
l.ItemList(func(l1 packs.ListPacker){
l1.ItemUInt64(11)
l1.ItemUInt64(22)
})
l.ItemList(func(l1 packs.ListPacker){
l1.ItemUInt64(33)
l1.ItemUInt64(44)
})
})
mp.KeyValueBool("boolean",true)
mp.KeyValueFloat32("bf",12223234.34234)
mp.KeyValueBinary("binary",[]byte{22,121,21,23,23,54,67})
mp.KeyValueDate("date",time.Now())
mp.KeyValueInt16("una",34)
mp.KeyValueObject("MiObjeto",func(op packs.ObjectPacker){
op.FieldInt32("fb1",43433)
op.FieldString ("fb2","aaaaa")
op.Field("fb3",slc)
})
})
*/
var s = struct {
F1Int int
F2Uint uint
F3String string
F4Binary []byte
}{
F1Int :-111,
F2Uint: 333,
F3String: "Esto es un string <quoted & scaped >",
F4Binary: []byte("dklsdjflsdjflsdkfjlsdkfjlsdkfjlsdfjdlsfjsdlf"),
}
pk.Pack(s)
errs.Test(pk.Error(),true)
fmt.Printf("JSON \n%s",pk.Bytes())
}

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name RStructFieldFlags.go
// File name reflects.go
// Created by DEV
// Modified 26/01/2024
// Modified 27/01/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -21,32 +21,52 @@
// limitations under the License.
// ------------------------------------------------------------------------
package reflects
package main
import (
"activething.com/go/gogo/core/reflects"
"fmt"
"reflect"
)
type (
const(
MiTipo struct {
FS1 string `json:"nombre,omitempty,binary"`
FU2 uint
FB3 bool
}
RFieldFlagTagged RFieldFlags = 1 >> iota
RFieldOmitEmpty
RFieldQuoted
)
type (
RFieldFlags uint8
)
func reflects_main () {
func (f RFieldFlags) Tagged () bool {
return RFieldFlagTagged&f != 0
}
t := MiTipo {
FS1 : "dfdfdf",
FU2 : 233,
FB3 : true,
}
rf := reflect.TypeOf(t)
for i:=0; i<rf.NumField(); i++ {
f := rf.Field(i)
fmt.Printf("Campo %s %s\n",f.Name,f.Tag.Get("json"))
reflects.NewRFieldTag(f,"json",func(rf reflect.Type,pos int, name string) uint8 {
fmt.Printf("Opcion %s\n",name)
return 1
})
}
func (f RFieldFlags) OmitEmpty () bool {
return RFieldOmitEmpty&f != 0
}
func (f RFieldFlags) Quote () bool {
return RFieldQuoted&f != 0
}

@ -23,13 +23,16 @@
package reflects
import "reflect"
import (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/core/slices"
"reflect"
)
type (
RField struct {
RFieldFlags
RType reflect.Type
RField reflect.StructField
Name string
SName string // scaped name
@ -40,24 +43,28 @@ type (
BName []byte // name bytes
Index []int
Options map[string]RFieldTag
Tags map[string]slices.String
}
RFields []RField
)
func (f RFields) Dominant() (RField, bool) {
// The Fields are sorted in increasing index-length order, then by presence of tag.
// That means that the first RField is the dominant one. We need only check
// for error cases: two Fields at top level, either both tagged or neither tagged.
if len(f) > 1 && len(f[0].Index) == len(f[1].Index) && f[0].Tagged() == f[1].Tagged() {
return RField{}, false
func NewRField (rfield reflect.StructField, options ...opts.OptionFnc[RField]) *RField {
rf := &RField {
RField: rfield,
}
return f[0], true
return opts.Apply(rf,options...)
}
func (f *RField) parseTag (tag string) slices.String {
var l slices.String
s,h := f.Tags[tag]
if !h {
}
return l
}

@ -21,29 +21,43 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packs
package reflects
import "strings"
import (
"reflect"
"strings"
)
type (
RFieldTag struct {
Tag string
Options map[string]struct{}
parsed bool
Name string
Flags uint8
}
)
func NewRFieldTag (tag string, onOption func(o string)) *RFieldTag {
m := make(map[string]struct{})
for _,v := range strings.Split(tag,",") {
m[v]=struct{}{}
func NewRFieldTag (rfield reflect.StructField, tag string, onOption func(rf reflect.Type, position int, option string) uint8) *RFieldTag {
f := &RFieldTag {
Tag : rfield.Tag.Get(tag),
}
var ops string
f.Name,ops,_ = strings.Cut(f.Tag,",")
if len(ops) == 0 {
f.parsed = true
} else if onOption != nil {
f.parsed = true
for pos:=0; ops != ""; pos++ {
var name string
name, ops, _ = strings.Cut(ops, ",")
f.Flags = onOption(rfield.Type, pos,name)
}
return &RFieldTag{
Tag : tag,
Options : m,
}
return f
}

@ -2,9 +2,9 @@
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name reflect_struct_field.go
// File name rfields.go
// Created by DEV
// Modified 26/01/2024
// Modified 27/01/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -21,35 +21,17 @@
// limitations under the License.
// ------------------------------------------------------------------------
package packs
package reflects
import "reflect"
type (
RField struct {
RFieldFlags
RType reflect.Type
Name string
SName string // scaped name
HName string // html name
EqualFoldFn func(s, t []byte) bool
BName []byte // name bytes
Index []int
Options map[string]RFieldTag
}
type (
RFields []RField
)
/*
func (f RFields) Dominant() (RField, bool) {
// The Fields are sorted in increasing index-length order, then by presence of tag.
// That means that the first RField is the dominant one. We need only check
@ -59,5 +41,24 @@ func (f RFields) Dominant() (RField, bool) {
}
return f[0], true
}
*/
func (f RFields) Len() int { return len(f) }
func (f RFields) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f RFields) Less(i, j int) bool {
for k, xik := range f[i].Index {
if k >= len(f[j].Index) {
return false
}
if xik != f[j].Index[k] {
return xik < f[j].Index[k]
}
}
return len(f[i].Index) < len(f[j].Index)
}

@ -1,47 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rfields_by_index.go
// Created by DEV
// Modified 26/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 reflects
// byIndex sorts field by index sequence.
type RFieldsByIndex []RField
func (x RFieldsByIndex) Len() int { return len(x) }
func (x RFieldsByIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RFieldsByIndex) Less(i, j int) bool {
for k, xik := range x[i].Index {
if k >= len(x[j].Index) {
return false
}
if xik != x[j].Index[k] {
return xik < x[j].Index[k]
}
}
return len(x[i].Index) < len(x[j].Index)
}

@ -23,24 +23,22 @@
package reflects
import (
"bytes"
"reflect"
"sort"
"strings"
"unicode"
)
type (
RTypeFields struct {
RStruct struct {
Fields RFields
Index map[string]int
NameIndex map[string]int
}
)
func NewRTypeFields (t reflect.Type) *RTypeFields {
/*
func NewRStruct (t reflect.Type) *RStruct {
// Anonymous Fields to explore at the current level and the next.
current := RFields{}
next := []RField{{RType: t}}
@ -129,12 +127,12 @@ func NewRTypeFields (t reflect.Type) *RTypeFields {
Index: index,
RType: ft,
}
/*
if opts.Contains("omitempty") {
rf.Flags|=RFieldOmitEmpty
}
*/
rf.BName = []byte(rf.Name)
//rf.EqualFold = foldFunc(rf.BName)
@ -224,9 +222,9 @@ func NewRTypeFields (t reflect.Type) *RTypeFields {
nameIndex[f.Name] = i
}
return &RTypeFields{
return &RStruct{
Fields: fs,
Index : nameIndex,
FieldsIndex: nameIndex,
}
}
@ -256,3 +254,5 @@ func isValidTag(s string) bool {
}
return true
}
*/

@ -9,6 +9,7 @@ use (
./core/errs
./core/opts
./core/syncs
./core/reflects
./packs
)

@ -1,52 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name RStructFieldFlags.go
// Created by DEV
// Modified 26/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 packs
const(
RFieldFlagTagged RFieldFlags = 1 >> iota
RFieldOmitEmpty
RFieldQuoted
)
type (
RFieldFlags uint8
)
func (f RFieldFlags) Tagged () bool {
return RFieldFlagTagged&f != 0
}
func (f RFieldFlags) OmitEmpty () bool {
return RFieldOmitEmpty&f != 0
}
func (f RFieldFlags) Quote () bool {
return RFieldQuoted&f != 0
}

@ -1,47 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rfields_by_index.go
// Created by DEV
// Modified 26/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 packs
// byIndex sorts field by index sequence.
type RFieldsByIndex []RField
func (x RFieldsByIndex) Len() int { return len(x) }
func (x RFieldsByIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RFieldsByIndex) Less(i, j int) bool {
for k, xik := range x[i].Index {
if k >= len(x[j].Index) {
return false
}
if xik != x[j].Index[k] {
return xik < x[j].Index[k]
}
}
return len(x[i].Index) < len(x[j].Index)
}

@ -1,258 +0,0 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rRFields_type.go
// Created by DEV
// Modified 26/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 packs
import (
"bytes"
"reflect"
"sort"
"strings"
"unicode"
)
type (
RTypeFields struct {
Fields RFields
Index map[string]int
}
)
func NewRTypeFields (t reflect.Type) *RTypeFields {
// Anonymous Fields to explore at the current level and the next.
current := RFields{}
next := []RField{{RType: t}}
// Count of queued names for current level and the next.
var count, nextCount map[reflect.Type]int
// Types already visited at an earlier level.
visited := map[reflect.Type]bool{}
// Fields found.
var fs []RField
// Buffer to run HTMLEscape on RField names.
var nameEscBuf bytes.Buffer
for len(next) > 0 {
current, next = next, current[:0]
count, nextCount = nextCount, map[reflect.Type]int{}
for _, f := range current {
if visited[f.RType] {
continue
}
visited[f.RType] = true
// Scan f.RType for Fields to include.
for i := 0; i < f.RType.NumField(); i++ {
var flags RFieldFlags
sf := f.RType.Field(i)
if sf.Anonymous {
t := sf.Type
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
if !sf.IsExported() && t.Kind() != reflect.Struct {
// Ignore embedded Fields of unexported non-struct types.
continue
}
// Do not ignore embedded Fields of unexported struct types
// since they may have exported Fields.
} else if !sf.IsExported() {
// Ignore unexported non-embedded Fields.
continue
}
tag := sf.Tag.Get("json")
if tag == "-" {
continue
}
name, opts := parseTag(tag)
if !isValidTag(name) {
name = ""
}
index := make([]int, len(f.Index)+1)
copy(index, f.Index)
index[len(f.Index)] = i
ft := sf.Type
if ft.Name() == "" && ft.Kind() == reflect.Pointer {
// Follow pointer.
ft = ft.Elem()
}
// Only strings, floats, integers, and booleans can be quoted.
if opts.Contains("string") {
switch ft.Kind() {
case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
reflect.Float32, reflect.Float64,
reflect.String:
flags|=RFieldQuoted
}
}
// Record found RField and index sequence.
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
if name != "" {
flags |= RFieldFlagTagged
}
if name == "" {
name = sf.Name
}
rf := RField{
Name : name,
Index: index,
RType: ft,
}
/*
if opts.Contains("omitempty") {
rf.Flags|=RFieldOmitEmpty
}
*/
rf.BName = []byte(rf.Name)
//rf.EqualFold = foldFunc(rf.BName)
// Build nameEscHTML and nameNonEsc ahead of time.
nameEscBuf.Reset()
nameEscBuf.WriteString(`"`)
//HTMLEscape(&nameEscBuf, rf.BName)
nameEscBuf.WriteString(`":`)
rf.HName = nameEscBuf.String()
//rf. = `"` + rf.Name + `":`
fs = append(fs, rf)
if count[f.RType] > 1 {
// If there were multiple instances, add a second,
// so that the annihilation code will see a duplicate.
// It only cares about the distinction between 1 or 2,
// so don't bother generating any more copies.
fs = append(fs, fs[len(fs)-1])
}
continue
}
// Record new anonymous struct to explore in next round.
nextCount[ft]++
if nextCount[ft] == 1 {
next = append(next, RField{Name: ft.Name(), Index: index, RType: ft})
}
}
}
}
sort.Slice(fs, func(i, j int) bool {
x := fs
// sort RField by name, breaking ties with depth, then
// breaking ties with "name came from json tag", then
// breaking ties with index sequence.
if x[i].Name != x[j].Name {
return x[i].Name < x[j].Name
}
if len(x[i].Index) != len(x[j].Index) {
return len(x[i].Index) < len(x[j].Index)
}
if x[i].Tagged() != x[j].Tagged() {
return x[i].Tagged()
}
return RFieldsByIndex(x).Less(i, j)
})
// Delete all Fields that are hidden by the Go rules for embedded Fields,
// except that Fields with JSON tags are promoted.
// The Fields are sorted in primary order of name, secondary order
// of RField index length. Loop over names; for each name, delete
// hidden Fields by choosing the one dominant RField that survives.
out := fs[:0]
for advance, i := 0, 0; i < len(fs); i += advance {
// One iteration per name.
// Find the sequence of Fields with the name of this first RField.
fi := fs[i]
name := fi.Name
for advance = 1; i+advance < len(fs); advance++ {
fj := fs[i+advance]
if fj.Name != name {
break
}
}
if advance == 1 { // Only one RField with this name
out = append(out, fi)
continue
}
dominant, ok := RFields(fs[i : i+advance]).Dominant()
if ok {
out = append(out, dominant)
}
}
fs = out
sort.Sort(RFieldsByIndex(fs))
for i := range fs {
//f := &fs[i]
//f.encoder = typeEncoder(typeByIndex(t, f.index))
}
nameIndex := make(map[string]int, len(fs))
for i, f := range fs {
nameIndex[f.Name] = i
}
return &RTypeFields{
Fields: fs,
Index : nameIndex,
}
}
func parseTag(tag string) (string, tagOptions) {
tag, opt, _ := strings.Cut(tag, ",")
return tag, tagOptions(opt)
}
func isValidTag(s string) bool {
if s == "" {
return false
}
for _, c := range s {
switch {
case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
// Backslash and quote chars are reserved, but
// otherwise any punctuation chars are allowed
// in a tag name.
case !unicode.IsLetter(c) && !unicode.IsDigit(c):
return false
}
}
return true
}
Loading…
Cancel
Save

Powered by TurnKey Linux.