corregido el formateador de error para que no escriba la seccion Causes en caso de que no tenga ninguna
parent
f340c61f2b
commit
acb1ffc10b
@ -0,0 +1,58 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name string.go
|
||||
// Created by DEV
|
||||
// Modified 16/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 slices
|
||||
|
||||
|
||||
|
||||
type Strings []string
|
||||
|
||||
|
||||
|
||||
|
||||
func MakeStrings(size, capacity int) Strings {
|
||||
return make(Strings, size, capacity)
|
||||
}
|
||||
|
||||
func (s Strings) Reset() Strings {
|
||||
if s != nil {
|
||||
return s[:0]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s Strings) Has(value string) bool {
|
||||
if len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, k := range s {
|
||||
if k == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s Strings) Append(value string) Strings {
|
||||
return append(s, value)
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
*
|
||||
* ---------------------------------------------------------
|
||||
* Project $PROJECT_NAME
|
||||
* Active Thing (activething.com) git.activething.com/go
|
||||
*
|
||||
* File name $FILE_NAME
|
||||
* Created by ${USER}
|
||||
* Modified ${DAY}/${MONTH}/${YEAR}
|
||||
*
|
||||
* Copyright ${YEAR} 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 bits
|
||||
|
||||
import "errs"
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
|
||||
ErrUnsupportedFlagType Err
|
||||
}{
|
||||
|
||||
ErrUnsupportedFlagType : Err{errs.ErrCode ("unsupported-bit-flag-type") },
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bflag_16.go
|
||||
// Created by DEV
|
||||
// Modified 15/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 bits
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
|
||||
type BFlags16 uint16
|
||||
|
||||
|
||||
|
||||
func (f BFlags16) Has ( flag BFlags16) bool {
|
||||
return f&flag != 0 }
|
||||
|
||||
|
||||
func (f BFlags16) Add ( flag BFlags16) BFlags16 {
|
||||
return f|flag }
|
||||
|
||||
|
||||
func (f BFlags16) AddWithMask ( flag BFlags16, mask BFlags16) BFlags16 {
|
||||
return (f&mask) | flag }
|
||||
|
||||
|
||||
func (f BFlags16) Del ( flag BFlags16) BFlags16 {
|
||||
return f&^flag }
|
||||
|
||||
|
||||
func (f BFlags16) Invert () BFlags16 {
|
||||
return ^f }
|
||||
|
||||
|
||||
func (f BFlags16) Count() int {
|
||||
return bits.OnesCount16(uint16(f)) }
|
||||
|
||||
|
||||
|
||||
func (f BFlags16) Extract() []BFlags16 {
|
||||
if f == 0 {
|
||||
return []BFlags16{}
|
||||
}
|
||||
l := make([]BFlags16,0,16)
|
||||
c := BFlags16(1)
|
||||
for i:=1; i<= 7; i++ {
|
||||
if c&f == c {
|
||||
l = append(l,c)
|
||||
}
|
||||
c <<= 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
|
||||
func (f BFlags16) FlagsToNames (namer func(flags BFlags16) string) []string {
|
||||
if f == 0 {
|
||||
return []string{}
|
||||
}
|
||||
l := make([]string,0,16)
|
||||
c := BFlags16(1)
|
||||
for i:=1; i<= 7; i++ {
|
||||
if c&f == c {
|
||||
l = append(l,namer(c))
|
||||
}
|
||||
c <<= 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
|
||||
func (f BFlags16) NamesToFlags (names []string, flagger func(name string) BFlags16) BFlags16 {
|
||||
for _,s := range names {
|
||||
f|=flagger(s)
|
||||
}
|
||||
return f
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err_bits.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 bits
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bflag.go
|
||||
// Created by DEV
|
||||
// Modified 15/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 bits
|
||||
|
||||
import (
|
||||
"atypes"
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
func Has [T atypes.UnsignedAll](source T, flag T) bool {
|
||||
return source&flag != 0 }
|
||||
|
||||
|
||||
func Add [T atypes.UnsignedAll](source T, flag T) T {
|
||||
return source|flag }
|
||||
|
||||
|
||||
func AddWithMask [T atypes.UnsignedAll](source T, flag T, mask T) T {
|
||||
return (source&mask) | flag }
|
||||
|
||||
|
||||
func Del [T atypes.UnsignedAll](source T, flag T) T {
|
||||
return source&^flag }
|
||||
|
||||
|
||||
func Invert [T atypes.UnsignedAll](source T) T {
|
||||
return ^source }
|
||||
|
||||
|
||||
func Count[T atypes.UnsignedAll](source T) int {
|
||||
switch binary.Size(source) {
|
||||
case 1 : return bits.OnesCount8 (uint8(source))
|
||||
case 2 : return bits.OnesCount16(uint16(source))
|
||||
case 4 : return bits.OnesCount32(uint32(source))
|
||||
case 8 : return bits.OnesCount64(uint64(source))
|
||||
default:
|
||||
panic(G.ErrUnsupportedFlagType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func Extract[T atypes.UnsignedAll](source T) []T {
|
||||
if source == 0 {
|
||||
return []T{}
|
||||
}
|
||||
l := make([]T,0,16)
|
||||
c := T(1)
|
||||
for i:=1; i<= 7; i++ {
|
||||
if c&source == c {
|
||||
l = append(l,c)
|
||||
}
|
||||
c <<= 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
|
||||
func FlagsToNames [T atypes.UnsignedAll](source T, namer func(flags T) string) []string {
|
||||
if source == 0 {
|
||||
return []string{}
|
||||
}
|
||||
l := make([]string,0,16)
|
||||
c := T(1)
|
||||
for i:=1; i<= 7; i++ {
|
||||
if c&source == c {
|
||||
l = append(l,namer(c))
|
||||
}
|
||||
c <<= 1
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
|
||||
func NamesToFlags [T atypes.UnsignedAll](names []string, flagger func(name string) T) T {
|
||||
var f T
|
||||
for _,s := range names {
|
||||
f|=flagger(s)
|
||||
}
|
||||
return f
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
module bits
|
||||
|
||||
go 1.22
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err_btes.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 bfers
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 19/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 bfields
|
||||
|
||||
import "errs"
|
||||
|
||||
const(
|
||||
|
||||
notFound = -1
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
ErrInvalidName Err
|
||||
ErrDuplicated Err
|
||||
ErrFixed Err
|
||||
ErrReadOnly Err
|
||||
|
||||
}{
|
||||
ErrInvalidName: Err{ errs.ErrCode("invalid-name")},
|
||||
ErrDuplicated : Err{ errs.ErrCode("duplicated-field")},
|
||||
ErrFixed : Err{ errs.ErrCode("bfields-fixed")},
|
||||
ErrReadOnly : Err{ errs.ErrCode("bfields-read-only")},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bfields_att.go
|
||||
// Created by DEV
|
||||
// Modified 19/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 bfields
|
||||
|
||||
|
||||
const(
|
||||
|
||||
AttReadOnly Att = 1 << iota
|
||||
AttFixed
|
||||
AttMultiple
|
||||
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
Att uint8
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func (a Att) IsReadOnly() bool {
|
||||
return a&AttReadOnly != 0 }
|
||||
|
||||
|
||||
func (a Att) IsFixed() bool {
|
||||
return a&AttFixed != 0 }
|
||||
|
||||
|
||||
func (a Att) IsMultiple() bool {
|
||||
return a&AttMultiple != 0 }
|
||||
@ -0,0 +1,109 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bfield.go
|
||||
// Created by DEV
|
||||
// Modified 19/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 bfields
|
||||
|
||||
import "strconv"
|
||||
|
||||
type (
|
||||
|
||||
BField struct {
|
||||
name []byte
|
||||
value []byte
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
func NewBField (name, value []byte) (*BField,error) {
|
||||
if len(name) == 0 {
|
||||
return nil,G.ErrInvalidName
|
||||
}
|
||||
return &BField {
|
||||
name: append(make([]byte,0,len(name)),name...),
|
||||
value: append(make([]byte,0,len(value)),value...),
|
||||
},nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (f BField) Name () []byte {
|
||||
return f.name }
|
||||
|
||||
|
||||
func (f BField) Value() []byte {
|
||||
return f.value }
|
||||
|
||||
|
||||
func (f BField) String () string {
|
||||
r := make([]byte,len(f.name)+len(f.value)+1)
|
||||
copy(r,f.name)
|
||||
r[len(f.name)]=':'
|
||||
copy(r[len(f.name)+1:],f.value)
|
||||
return string(r)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (f *BField) SetValue(val []byte) {
|
||||
ln := len(val)
|
||||
cp := cap(f.value)
|
||||
if ln <= cp {
|
||||
copy(f.value, val)
|
||||
f.value = f.value[:ln]
|
||||
return
|
||||
}
|
||||
nv := make([]byte, ln)
|
||||
copy(f.value, nv)
|
||||
}
|
||||
|
||||
|
||||
func (f *BField) SetByte(val byte) {
|
||||
f.value = append(f.value[:0], val) }
|
||||
|
||||
|
||||
func (f *BField) SetBool(val bool) {
|
||||
f.value = strconv.AppendBool(f.value[:0], val) }
|
||||
|
||||
|
||||
func (f *BField) SetRune(val rune) {
|
||||
f.value = strconv.AppendQuoteRune(f.value[:0], val) }
|
||||
|
||||
|
||||
func (f *BField) SetString(val string) {
|
||||
f.SetValue([]byte(val)) }
|
||||
|
||||
|
||||
|
||||
func (f *BField) SetInt(val int64, bse int) {
|
||||
f.value = strconv.AppendInt(f.value[:0], val, bse) }
|
||||
|
||||
|
||||
func (f *BField) SetUInt(val uint64, bse int) {
|
||||
f.value = strconv.AppendUint(f.value[:0], val, bse) }
|
||||
|
||||
|
||||
func (f *BField) SetFloat(val float64, fmt byte, prc, sze int) {
|
||||
f.value = strconv.AppendFloat(f.value[:0], val, fmt, prc, sze) }
|
||||
|
||||
|
||||
@ -0,0 +1,197 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bfield_list.go
|
||||
// Created by DEV
|
||||
// Modified 19/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 bfields
|
||||
|
||||
import (
|
||||
|
||||
"bytes"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
BFields struct {
|
||||
Att
|
||||
fields []BField
|
||||
}
|
||||
|
||||
BFieldsFnc func (bfls *BFields) error
|
||||
|
||||
BFieldsWalkFnc func(index int, field *BField) bool
|
||||
)
|
||||
|
||||
|
||||
|
||||
func NewBFields (options ...BFieldsFnc) (*BFields,error) {
|
||||
fs := &BFields{}
|
||||
for _,o := range options {
|
||||
if er := o(fs); er != nil {
|
||||
return nil,er
|
||||
}
|
||||
}
|
||||
if fs.IsReadOnly() {
|
||||
//todo
|
||||
}
|
||||
return fs,nil
|
||||
}
|
||||
|
||||
|
||||
func (f BFields) Get(nme []byte) *BField {
|
||||
if ix := findField(f.fields, 0, nme); ix != notFound {
|
||||
f.get(ix)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (f BFields) get(index int) *BField {
|
||||
if f.IsReadOnly() {
|
||||
vl := f.fields[index]
|
||||
return &vl
|
||||
}
|
||||
return &f.fields[index]
|
||||
}
|
||||
|
||||
|
||||
func (f *BFields) Add(nme, val []byte) error {
|
||||
if f.IsFixed() {
|
||||
return G.ErrFixed
|
||||
}
|
||||
if ix := findField(f.fields, 0, nme); ix != notFound {
|
||||
if !f.IsMultiple() {
|
||||
return G.ErrDuplicated
|
||||
}
|
||||
}
|
||||
fl, er := NewBField(nme, val)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
f.fields = append(f.fields, *fl)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *BFields) Del(nme []byte) error {
|
||||
if f.IsFixed() {
|
||||
return G.ErrFixed
|
||||
}
|
||||
if f.IsReadOnly() {
|
||||
return G.ErrReadOnly
|
||||
}
|
||||
fm := 0
|
||||
ix := -1
|
||||
ln := len(f.fields)
|
||||
for {
|
||||
if ix = findField(f.fields, fm, nme); ix == notFound {
|
||||
break
|
||||
}
|
||||
f.fields[ix] = f.fields[ln-1]
|
||||
f.fields = f.fields[:ln-1]
|
||||
ln -= 1
|
||||
if !f.IsMultiple() || ix == ln-1 {
|
||||
break
|
||||
}
|
||||
fm = ix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *BFields) Upsert(nme, val []byte) error {
|
||||
if len(nme) == 0 {
|
||||
return nil
|
||||
}
|
||||
if f.IsReadOnly() {
|
||||
return G.ErrReadOnly
|
||||
}
|
||||
if ix := findField(f.fields, 0, nme); ix != -1 {
|
||||
f.fields[ix].SetValue(val)
|
||||
return nil
|
||||
}
|
||||
if f.IsFixed() {
|
||||
return G.ErrFixed
|
||||
}
|
||||
fl, er := NewBField(nme, val)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
f.fields = append(f.fields, *fl)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (f BFields) Len() int {
|
||||
return len(f.fields) }
|
||||
|
||||
|
||||
func (f BFields) Has(nme []byte) bool {
|
||||
return findField(f.fields, 0, nme) != notFound }
|
||||
|
||||
|
||||
func (f BFields) Count(nme []byte) int {
|
||||
rs := 0
|
||||
for _, fl := range f.fields {
|
||||
if bytes.Equal(fl.name, nme) {
|
||||
rs++
|
||||
}
|
||||
}
|
||||
return rs
|
||||
}
|
||||
|
||||
|
||||
func (f BFields) Walk(walker BFieldsWalkFnc) {
|
||||
for ln, ix := len(f.fields), 0; ix < ln; ix++ {
|
||||
if !walker(ix, f.get(ix)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func findField(list []BField, from int, name []byte) int {
|
||||
for ln, ix := len(list), from; ix < ln; ix++ {
|
||||
if bytes.Equal(list[ix].name, name) {
|
||||
return ix
|
||||
}
|
||||
}
|
||||
return notFound
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func WithField(nme, val []byte) BFieldsFnc {
|
||||
return func(f *BFields) error { return f.Add(nme, val) }}
|
||||
|
||||
|
||||
func WithAtts(atts Att) BFieldsFnc {
|
||||
return func(f *BFields) error {
|
||||
f.Att = atts
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 bfields
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
|
||||
)
|
||||
@ -0,0 +1,35 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 16/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 crypts
|
||||
|
||||
import "errs"
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
ErrNotImplemented Err
|
||||
}{
|
||||
ErrNotImplemented: Err { errs.ErrCode("crypter-not-implemented")} ,
|
||||
}
|
||||
)
|
||||
@ -0,0 +1,35 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name crypter.go
|
||||
// Created by DEV
|
||||
// Modified 16/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 crypts
|
||||
|
||||
|
||||
type (
|
||||
|
||||
Crypter interface {
|
||||
Encrypter
|
||||
Decrypter
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name decrypter.go
|
||||
// Created by DEV
|
||||
// Modified 16/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 crypts
|
||||
|
||||
import "rsts"
|
||||
|
||||
type (
|
||||
|
||||
Decrypter interface {
|
||||
Decrypt (data []byte) rsts.Bytes
|
||||
}
|
||||
|
||||
|
||||
DecrypterNop struct {}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func (_ DecrypterNop) Decrypt (_ []byte) rsts.Bytes {
|
||||
return rsts.MakeBytesError(G.ErrNotImplemented) }
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name encrypter.go
|
||||
// Created by DEV
|
||||
// Modified 16/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 crypts
|
||||
|
||||
import (
|
||||
|
||||
"rsts"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
Encrypter interface {
|
||||
Encrypt (data []byte) rsts.Bytes
|
||||
}
|
||||
|
||||
|
||||
|
||||
EncrypterNop struct {}
|
||||
)
|
||||
|
||||
|
||||
func (_ EncrypterNop) Encrypt (_ []byte) rsts.Bytes {
|
||||
return rsts.MakeBytesError(G.ErrNotImplemented) }
|
||||
@ -0,0 +1,30 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 crypts
|
||||
|
||||
import "errs"
|
||||
|
||||
type Err struct { errs.ErrCode }
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
module crypts
|
||||
|
||||
|
||||
go 1.20
|
||||
@ -0,0 +1,80 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.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 packs
|
||||
|
||||
import (
|
||||
"errs"
|
||||
"syncs"
|
||||
)
|
||||
|
||||
const(
|
||||
|
||||
TagKey = "pack"
|
||||
)
|
||||
|
||||
const (
|
||||
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
|
||||
kelvin = '\u212a'
|
||||
smallLongEss = '\u017f'
|
||||
)
|
||||
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
|
||||
ErrInvalidState Err
|
||||
ErrInvalidNode Err
|
||||
ErrInvalidKey Err
|
||||
ErrDuplicatedKey Err
|
||||
ErrKeyRequired Err
|
||||
ErrValueRequired Err
|
||||
ErrInvalidList Err
|
||||
ErrRedundantPack Err
|
||||
ErrInvalidValue Err
|
||||
ErrUnsupportedType Err
|
||||
}{
|
||||
ErrInvalidState : Err{errs.ErrCode("invalid-state")},
|
||||
ErrInvalidNode : Err{errs.ErrCode("invalid-node")},
|
||||
ErrInvalidKey : Err{errs.ErrCode("invalid-key")},
|
||||
ErrDuplicatedKey : Err{errs.ErrCode("duplicated-key")},
|
||||
ErrKeyRequired : Err{errs.ErrCode("key-required")},
|
||||
ErrValueRequired : Err{errs.ErrCode("value-required")},
|
||||
ErrInvalidList : Err{errs.ErrCode("invalid-list")},
|
||||
ErrRedundantPack : Err{errs.ErrCode("redundant-pack")},
|
||||
ErrInvalidValue : Err{errs.ErrCode("invalid-value")},
|
||||
ErrUnsupportedType: Err{errs.ErrCode("unsupported-type")},
|
||||
}
|
||||
|
||||
g = struct {
|
||||
poolsSem uint32
|
||||
statePool *syncs.Pool[State]
|
||||
} {}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packabler.go
|
||||
// Created by DEV
|
||||
// Modified 24/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
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
Builder interface {
|
||||
|
||||
Build (packer Packer) error
|
||||
}
|
||||
|
||||
|
||||
BuildFnc func (packer Packer) error
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func (f BuildFnc) Build (packer Packer) error {
|
||||
return f(packer) }
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,241 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name f.go
|
||||
// Created by DEV
|
||||
// Modified 29/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 (
|
||||
"bits"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
FlagOmit Flags = 1 << iota
|
||||
FlagOmitEmpty
|
||||
FlagQuote
|
||||
FlagScapeHTML
|
||||
FlagString
|
||||
FlagEncrypted
|
||||
|
||||
FlagBinary64 Flags = 0b0000100000000000
|
||||
FlagBinary32 Flags = 0b0000010000000000
|
||||
flagMaskBin Flags = 0b0000110000000000
|
||||
|
||||
FlagDateRFC822 Flags = 0b0001000000000000
|
||||
FlagDateUnix Flags = 0b0010000000000000
|
||||
FlagDateANSIC Flags = 0b0100000000000000
|
||||
FlagDateRFC850 Flags = 0b1000000000000000
|
||||
flagMaskDate Flags = 0b1111000000000000
|
||||
|
||||
)
|
||||
|
||||
|
||||
type Flags bits.BFlags16
|
||||
|
||||
|
||||
func (f Flags) Omit () bool {
|
||||
return f&FlagOmit != 0 }
|
||||
|
||||
|
||||
func (f Flags) OmitEmpty () bool {
|
||||
return f&FlagOmitEmpty != 0 }
|
||||
|
||||
|
||||
func (f Flags) Quote () bool {
|
||||
return f&FlagQuote != 0 }
|
||||
|
||||
|
||||
func (f Flags) EscapeHTML () bool {
|
||||
return f&FlagScapeHTML != 0 }
|
||||
|
||||
|
||||
func (f Flags) String () bool {
|
||||
return f&FlagString != 0 }
|
||||
|
||||
|
||||
func (f Flags) Encrypted() bool {
|
||||
return f&FlagEncrypted != 0 }
|
||||
|
||||
|
||||
func (f Flags) Binary () bool {
|
||||
return f&(FlagBinary64|FlagBinary32) != 0 }
|
||||
|
||||
|
||||
func (f Flags) Bin64 () bool {
|
||||
return f&FlagBinary64 != 0 }
|
||||
|
||||
|
||||
func (f Flags) Bin32 () bool {
|
||||
return f&FlagBinary32 != 0 }
|
||||
|
||||
|
||||
|
||||
|
||||
func (f Flags) SetDate (flagDate Flags) Flags {
|
||||
return (f&flagMaskDate) | flagDate }
|
||||
|
||||
|
||||
func (f Flags) SetBinary (flagBinary Flags) Flags {
|
||||
return (f&flagMaskBin) | flagBinary }
|
||||
|
||||
|
||||
|
||||
|
||||
func (f Flags) Names () string {
|
||||
var ls []string
|
||||
if f&FlagOmit != 0 { ls = append(ls,"omit")}
|
||||
if f&FlagOmitEmpty != 0 { ls = append(ls,"omitempty")}
|
||||
if f&FlagQuote != 0 { ls = append(ls,"quote")}
|
||||
if f&FlagScapeHTML != 0 { ls = append(ls,"html")}
|
||||
if f&FlagString != 0 { ls = append(ls,"string")}
|
||||
|
||||
if f&flagMaskBin != 0 {
|
||||
ls = append(ls,f.binName())
|
||||
}
|
||||
if f&flagMaskDate != 0 {
|
||||
ls = append(ls,f.dateName())
|
||||
}
|
||||
|
||||
if len(ls) > 0 {
|
||||
return strings.Join(ls,",")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
func (f Flags) binName () string {
|
||||
switch f & flagMaskBin {
|
||||
case FlagBinary64 : return "b64"
|
||||
case FlagBinary32 : return "b32"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
func (f Flags) dateName() string {
|
||||
switch f & flagMaskDate {
|
||||
case FlagDateUnix : return "unix"
|
||||
case FlagDateRFC822: return "rfc822"
|
||||
case FlagDateANSIC : return "ansic"
|
||||
case FlagDateRFC850: return "rfc8550"
|
||||
default: return "rfc822z"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (f Flags) DateFormat () string {
|
||||
switch f & flagMaskDate {
|
||||
case FlagDateUnix : return time.UnixDate
|
||||
case FlagDateRFC822: return time.RFC822
|
||||
case FlagDateANSIC : return time.ANSIC
|
||||
case FlagDateRFC850: return time.RFC850
|
||||
default: return time.RFC822Z
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func FlagByName (flag string) (f Flags) {
|
||||
switch strings.ToLower(flag) {
|
||||
|
||||
case "-","omit" : return FlagOmit
|
||||
case "o","omitempty": return FlagOmitEmpty
|
||||
case "q","quote" : return FlagQuote
|
||||
case "h","html" : return FlagScapeHTML
|
||||
case "s","string" : return FlagString
|
||||
case "e","encrypted": return FlagEncrypted
|
||||
|
||||
// formato binario
|
||||
case "b64","bin64" : return FlagBinary64
|
||||
case "b32","bin32" : return FlagBinary32
|
||||
|
||||
// formatos de fechas
|
||||
case "unix" : return FlagDateUnix
|
||||
case "rfc822" : return FlagDateRFC822
|
||||
case "ansic" : return FlagDateANSIC
|
||||
case "rfc850" : return FlagDateRFC850
|
||||
case "rfc822z": return 0
|
||||
|
||||
default: return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func FlagsWithNames(flags ... string) Flags {
|
||||
var f Flags
|
||||
for _,n := range flags {
|
||||
f |= FlagByName(n)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
||||
|
||||
func FlagsWithString(flags string, onOption func(string) Flags) Flags {
|
||||
|
||||
var f Flags
|
||||
if len(flags) == 0 {
|
||||
return f
|
||||
}
|
||||
nf := f
|
||||
for flags != "" {
|
||||
var op string
|
||||
op,flags,_ = strings.Cut(flags,",")
|
||||
nf |= onOption(op)
|
||||
}
|
||||
return nf
|
||||
}
|
||||
|
||||
func FlagsFromPackTag (raw reflect.StructTag) (string,Flags,bool) {
|
||||
return FlagsFromTag(raw,TagKey,FlagByName) }
|
||||
|
||||
|
||||
|
||||
func FlagsFromTag(raw reflect.StructTag, tag string, onOption func(string) Flags) (string,Flags,bool) {
|
||||
st,ok := raw.Lookup(tag)
|
||||
if !ok {
|
||||
return "",0,false
|
||||
}
|
||||
nm,op,_ := strings.Cut(st,",")
|
||||
return nm,FlagsWithString(op,onOption),true
|
||||
}
|
||||
|
||||
|
||||
func CheckTag(tag string) bool {
|
||||
if tag == "" {
|
||||
return false
|
||||
}
|
||||
for _, c := range tag {
|
||||
switch {
|
||||
case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
|
||||
case !unicode.IsLetter(c) && !unicode.IsDigit(c):
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
module packs
|
||||
|
||||
|
||||
go 1.22
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com, flags Flags) git.activething.com/go
|
||||
//
|
||||
// File name list_Itemer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License", flags Flags);
|
||||
// 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 "time"
|
||||
|
||||
type (
|
||||
|
||||
ListPackBuilder interface {
|
||||
|
||||
Error () error
|
||||
|
||||
ItemAny (value any, flags Flags)
|
||||
|
||||
ItemRaw (value []byte, flags Flags)
|
||||
|
||||
ItemBinary (value []byte, flags Flags)
|
||||
ItemString (value string, flags Flags)
|
||||
|
||||
ItemBool (value bool, flags Flags)
|
||||
|
||||
ItemInt8 (value int8, flags Flags)
|
||||
ItemInt16 (value int16, flags Flags)
|
||||
ItemInt32 (value int32, flags Flags)
|
||||
ItemInt64 (value int64, flags Flags)
|
||||
|
||||
ItemUInt8 (value uint8, flags Flags)
|
||||
ItemUInt16 (value uint16, flags Flags)
|
||||
ItemUInt32 (value uint32, flags Flags)
|
||||
ItemUInt64 (value uint64, flags Flags)
|
||||
|
||||
ItemFloat32 (value float32, flags Flags)
|
||||
ItemFloat64 (value float64, flags Flags)
|
||||
|
||||
ItemDate (value time.Time, flags Flags)
|
||||
|
||||
ItemList (builder func(ListPackBuilder, Flags), flags Flags)
|
||||
ItemMap (builder func(MapPackBuilder, Flags), flags Flags)
|
||||
ItemObject(builder func(ObjectPackBuilder,Flags), flags Flags)
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com, flags Flags) git.activething.com/go
|
||||
//
|
||||
// File name map_packer.go
|
||||
// Created by DEV
|
||||
// Modified 23/01/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License", flags Flags);
|
||||
// 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 "time"
|
||||
|
||||
type (
|
||||
|
||||
MapPackBuilder interface {
|
||||
|
||||
KeyValueAny (key any, value any, flags Flags)
|
||||
|
||||
KeyValueRaw (key any,value []byte, flags Flags)
|
||||
|
||||
KeyValueBinary(key any, value []byte, flags Flags)
|
||||
KeyValueString(key any, value string, flags Flags)
|
||||
|
||||
KeyValueBool (key any, value bool, flags Flags)
|
||||
|
||||
KeyValueInt8 (key any, value int8 , flags Flags)
|
||||
KeyValueInt16 (key any, value int16, flags Flags)
|
||||
KeyValueInt32 (key any, value int32, flags Flags)
|
||||
KeyValueInt64 (key any, value int64, flags Flags)
|
||||
|
||||
KeyValueUInt8 (key any, value uint8 , flags Flags)
|
||||
KeyValueUInt16 (key any, value uint16, flags Flags)
|
||||
KeyValueUInt32 (key any, value uint32, flags Flags)
|
||||
KeyValueUInt64 (key any, value uint64, flags Flags)
|
||||
|
||||
KeyValueFloat32(key any, value float32, flags Flags)
|
||||
KeyValueFloat64(key any, value float64, flags Flags)
|
||||
|
||||
KeyValueDate (key any, value time.Time, flags Flags)
|
||||
|
||||
KeyValueList (key any, builder func(ListPackBuilder, Flags), flags Flags)
|
||||
KeyValueMap (key any, builder func(MapPackBuilder, Flags), flags Flags)
|
||||
KeyValueObject(key any, builder func(ObjectPackBuilder,Flags), flags Flags)
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name object_packer.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 packs
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
ObjectPackBuilder interface {
|
||||
|
||||
Error () error
|
||||
|
||||
FieldAny (name string, value any, flags Flags)
|
||||
|
||||
FieldRaw (name string, value []byte, flags Flags)
|
||||
|
||||
FieldBinary (name string, value []byte, flags Flags)
|
||||
FieldString (name string, value string, flags Flags)
|
||||
|
||||
FieldBool (name string, value bool, flags Flags)
|
||||
|
||||
FieldInt8 (name string, value int8 , flags Flags)
|
||||
FieldInt16 (name string, value int16, flags Flags)
|
||||
FieldInt32 (name string, value int32, flags Flags)
|
||||
FieldInt64 (name string, value int64, flags Flags)
|
||||
|
||||
FieldUInt8 (name string, value uint8, flags Flags)
|
||||
FieldUInt16 (name string, value uint16, flags Flags)
|
||||
FieldUInt32 (name string, value uint32, flags Flags)
|
||||
FieldUInt64 (name string, value uint64, flags Flags)
|
||||
|
||||
FieldFloat32 (name string, value float32, flags Flags)
|
||||
FieldFloat64 (name string, value float64, flags Flags)
|
||||
|
||||
FieldDate (name string, value time.Time, flags Flags)
|
||||
|
||||
FieldList (name string, builder func(ListPackBuilder, Flags), flags Flags)
|
||||
FieldMap (name string, builder func(MapPackBuilder, Flags), flags Flags)
|
||||
FieldObject(name string, builder func(ObjectPackBuilder,Flags), flags Flags)
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer.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 packs
|
||||
|
||||
type (
|
||||
|
||||
Packer interface {
|
||||
|
||||
Pack (value any, flags Flags)
|
||||
|
||||
Packet () []byte
|
||||
Error () error
|
||||
|
||||
Reset ()
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,153 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer_state.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 packs
|
||||
|
||||
import (
|
||||
|
||||
"bins/bfers"
|
||||
"crypts"
|
||||
"sync/atomic"
|
||||
"syncs"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
|
||||
State struct {
|
||||
/*Embedded*/*bfers.Buffer
|
||||
Temp [64]byte
|
||||
Level int
|
||||
Error error
|
||||
checks map[any]struct{}
|
||||
counts []int
|
||||
Encrypter crypts.Encrypter
|
||||
}
|
||||
|
||||
StateFnc func (st *State)
|
||||
|
||||
)
|
||||
|
||||
|
||||
func NewState(options ...StateFnc) *State {
|
||||
if atomic.CompareAndSwapUint32(&g.poolsSem,0,1) {
|
||||
g.statePool = syncs.NewPool[State](
|
||||
syncs.PoolWithNew[State](func() *State {
|
||||
return &State{
|
||||
Buffer : bfers.NewBuffer(),
|
||||
checks : make(map[any]struct{}),
|
||||
counts : []int{0},
|
||||
Encrypter: crypts.EncrypterNop{},
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
if len(options) == 0 {
|
||||
return g.statePool.Get()
|
||||
}
|
||||
st := g.statePool.Get()
|
||||
for _,o := range options {
|
||||
o(st)
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
|
||||
func ReleaseState (state *State) {
|
||||
if state == nil {
|
||||
state.Encrypter = crypts.EncrypterNop{}
|
||||
state.Buffer.Reset()
|
||||
state.Error = nil
|
||||
state.counts= append(state.counts[:0],0)
|
||||
if len(state.checks) > 0 {
|
||||
for k,_ := range state.checks {
|
||||
delete(state.checks,k)
|
||||
}
|
||||
}
|
||||
if atomic.LoadUint32(&g.poolsSem) == 1 {
|
||||
g.statePool.Put(state)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (s *State) SetError(err error) bool {
|
||||
if s.Error != nil {
|
||||
return true
|
||||
}
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
s.Error = err
|
||||
s.Reset()
|
||||
s.Level = 0
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (s *State) CheckCycle (ptr any) (func(),bool) {
|
||||
if _,hs := s.checks[ptr]; hs {
|
||||
s.SetError(G.ErrRedundantPack)
|
||||
return nil,false
|
||||
}
|
||||
s.checks[ptr]=struct{}{}
|
||||
return func(){ delete(s.checks,ptr) },true
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (s *State) Open(opener byte) {
|
||||
s.WriteByte(opener)
|
||||
s.Level++
|
||||
s.counts = append(s.counts,0)
|
||||
}
|
||||
|
||||
|
||||
func (s *State) Close(closer byte) {
|
||||
s.WriteByte(closer)
|
||||
s.Level--
|
||||
if s.Level < 0 {
|
||||
s.SetError(G.ErrInvalidNode)
|
||||
}
|
||||
s.counts = s.counts[:len(s.counts)-1]
|
||||
}
|
||||
|
||||
|
||||
func (s *State) Count() int {
|
||||
if s.Error != nil {
|
||||
return 0
|
||||
}
|
||||
return s.counts[s.Level]
|
||||
}
|
||||
|
||||
|
||||
func (s *State) Inc () {
|
||||
if s.Error == nil {
|
||||
s.counts[s.Level] += 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.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 pjson
|
||||
|
||||
import (
|
||||
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"packs"
|
||||
"reflect"
|
||||
"rsts"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
|
||||
const (
|
||||
|
||||
jsonTag = "json"
|
||||
|
||||
maxCyclesAfter = 100
|
||||
|
||||
defaultFlags = packs.Flags(0)
|
||||
)
|
||||
|
||||
|
||||
|
||||
var (
|
||||
g = struct {
|
||||
hex string
|
||||
jsonChars [utf8.RuneSelf]jsonCharAtt
|
||||
|
||||
nullValue []byte
|
||||
zeroValue []byte
|
||||
trueValue []byte
|
||||
falseValue []byte
|
||||
|
||||
floatNaN []byte
|
||||
floatInfPos []byte
|
||||
floatInfNeg []byte
|
||||
|
||||
|
||||
packersCache sync.Map
|
||||
keyersCache sync.Map
|
||||
fieldsCache sync.Map
|
||||
|
||||
jsonMarshalerType reflect.Type
|
||||
textMarshalerType reflect.Type
|
||||
packMarshalerType reflect.Type
|
||||
|
||||
}{
|
||||
|
||||
hex: "0123456789abcdef",
|
||||
jsonChars: initJSONChars(),
|
||||
|
||||
nullValue: []byte{'n', 'u', 'l', 'l'},
|
||||
zeroValue: []byte{'0'},
|
||||
trueValue: []byte{'"','t', 'r', 'u', 'e','"'},
|
||||
falseValue: []byte{'"','f', 'a', 'l', 's', 'e','"'},
|
||||
|
||||
floatNaN: []byte{'"', 'N', 'a', 'N', '"'},
|
||||
floatInfPos: []byte{'"', 'I', 'n', 'f', '"'},
|
||||
floatInfNeg: []byte{'"', '-', 'I', 'n', 'f', '"'},
|
||||
|
||||
|
||||
jsonMarshalerType: reflect.TypeOf((*json.Marshaler)(nil)).Elem(),
|
||||
textMarshalerType: reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(),
|
||||
packMarshalerType: reflect.TypeOf((*packs.Packer)(nil)).Elem(),
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func initJSONChars() [utf8.RuneSelf]jsonCharAtt {
|
||||
var tb = [utf8.RuneSelf]jsonCharAtt{
|
||||
'"': jsonCharAttAllUnsafe,
|
||||
'&': jsonCharAttHtmlUnsafe,
|
||||
'<': jsonCharAttHtmlUnsafe,
|
||||
'>': jsonCharAttHtmlUnsafe,
|
||||
'\\': jsonCharAttAllUnsafe,
|
||||
}
|
||||
for i := 0; i <= 31; i++ {
|
||||
tb[i] = jsonCharAttAllUnsafe
|
||||
}
|
||||
return tb
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func Pack (value any, options ... PackerFnc) (res rsts.Bytes) {
|
||||
p := NewPacker(options ...)
|
||||
p.Pack(value,defaultFlags)
|
||||
if p.Error() != nil {
|
||||
res = rsts.MakeBytesError(p.Error())
|
||||
} else {
|
||||
res = rsts.MakeBytesSuccess(p.Packet())
|
||||
}
|
||||
p.Release()
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name json_char_atts.go
|
||||
// Created by DEV
|
||||
// Modified 18/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 pjson
|
||||
|
||||
const (
|
||||
jsonCharAttUnsafe jsonCharAtt = 1 << iota
|
||||
jsonCharAttHtmlUnsafe
|
||||
|
||||
jsonCharAttAllUnsafe = jsonCharAttUnsafe | jsonCharAttHtmlUnsafe
|
||||
)
|
||||
|
||||
type jsonCharAtt uint8
|
||||
|
||||
func (a jsonCharAtt) isUnsafe() bool {
|
||||
return a&jsonCharAttUnsafe != 0
|
||||
}
|
||||
|
||||
func (a jsonCharAtt) isHtmlUnsafe() bool {
|
||||
return a&jsonCharAttHtmlUnsafe != 0
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name builder_list.go
|
||||
// Created by DEV
|
||||
// Modified 06/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) ItemAny (value any, flags packs.Flags) { p.addItem(func(){ p.PackAny(value,flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) ItemRaw (value []byte, flags packs.Flags) { p.addItem(func() { p.PackRaw(value,flags) }) }
|
||||
|
||||
func (p *Packer) ItemBinary (value []byte, flags packs.Flags) { p.addItem(func (){ p.PackBinary(value,flags) }) }
|
||||
|
||||
func (p *Packer) ItemString (value string, flags packs.Flags) { p.addItem(func (){ p.PackString(value,flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) ItemBool (value bool, flags packs.Flags) { p.addItem(func (){ p.PackBool(value,flags) }) }
|
||||
|
||||
func (p *Packer) ItemInt8 (value int8 , flags packs.Flags) { p.addItem(func (){ packInt(p.state,int64(value),flags) }) }
|
||||
func (p *Packer) ItemInt16 (value int16, flags packs.Flags) { p.addItem(func (){ packInt(p.state,int64(value),flags) }) }
|
||||
func (p *Packer) ItemInt32 (value int32, flags packs.Flags) { p.addItem(func (){ packInt(p.state,int64(value),flags) }) }
|
||||
func (p *Packer) ItemInt64 (value int64, flags packs.Flags) { p.addItem(func (){ packInt(p.state,value,flags) }) }
|
||||
|
||||
func (p *Packer) ItemUInt8 (value uint8 , flags packs.Flags){ p.addItem(func (){ packUInt(p.state,uint64(value),flags) }) }
|
||||
func (p *Packer) ItemUInt16 (value uint16, flags packs.Flags){ p.addItem(func (){ packUInt(p.state,uint64(value),flags) }) }
|
||||
func (p *Packer) ItemUInt32 (value uint32, flags packs.Flags){ p.addItem(func (){ packUInt(p.state,uint64(value),flags) }) }
|
||||
func (p *Packer) ItemUInt64 (value uint64, flags packs.Flags){ p.addItem(func (){ packUInt(p.state,uint64(value),flags) }) }
|
||||
|
||||
func (p *Packer) ItemFloat32 (value float32, flags packs.Flags){ p.addItem(func (){ packFloatString(p.state,float64(value),flags,32)})}
|
||||
func (p *Packer) ItemFloat64 (value float64, flags packs.Flags){ p.addItem(func (){ packFloatString(p.state,value,flags,64) })}
|
||||
|
||||
func (p *Packer) ItemDate (value time.Time, flags packs.Flags) { p.addItem(func(){ packDate(p.state,value,flags); p.state.Inc() })}
|
||||
|
||||
|
||||
func (p *Packer) ItemList (builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addItem(func(){ p.PackList(builder,flags) }) }
|
||||
|
||||
func (p *Packer) ItemMap (builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addItem(func(){ p.PackMap(builder,flags) }) }
|
||||
|
||||
func (p *Packer) ItemObject(builder func(packs.ObjectPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addItem(func(){ p.PackObject(builder,flags) }) }
|
||||
|
||||
|
||||
|
||||
func (p *Packer) addItem (caller func()) {
|
||||
if p.state.Count() > 0 {
|
||||
p.state.WriteByte(',')
|
||||
}
|
||||
caller()
|
||||
if p.state != nil {
|
||||
p.state.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,115 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name builderMap.go
|
||||
// Created by DEV
|
||||
// Modified 06/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) KeyValueAny (key any, value any, flags packs.Flags) {
|
||||
p.addKeyValue(key, func(){ p.PackAny(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueRaw (key any,value []byte, flags packs.Flags) {
|
||||
p.addKeyValue(key, func(){ p.PackRaw(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueBinary (key any, value []byte, flags packs.Flags) {
|
||||
p.addKeyValue(key, func(){ p.PackBinary(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueString (key any, value string, flags packs.Flags) {
|
||||
p.addKeyValue(key, func(){ p.PackString(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueBool (key any, value bool, flags packs.Flags) {
|
||||
p.addKeyValue(key, func(){ p.PackBool(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueInt8 (key any, value int8 , flags packs.Flags) { p.addKeyValue(key, func(){ p.PackInt64(int64(value),flags)}) }
|
||||
func (p *Packer) KeyValueInt16 (key any, value int16, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackInt64(int64(value),flags)}) }
|
||||
func (p *Packer) KeyValueInt32 (key any, value int32, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackInt64(int64(value),flags)}) }
|
||||
func (p *Packer) KeyValueInt64 (key any, value int64, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackInt64(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueUInt8 (key any, value uint8 , flags packs.Flags) { p.addKeyValue(key, func(){ p.PackUInt64(uint64(value),flags)}) }
|
||||
func (p *Packer) KeyValueUInt16 (key any, value uint16, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackUInt64(uint64(value),flags)}) }
|
||||
func (p *Packer) KeyValueUInt32 (key any, value uint32, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackUInt64(uint64(value),flags)}) }
|
||||
func (p *Packer) KeyValueUInt64 (key any, value uint64, flags packs.Flags) { p.addKeyValue(key, func(){ p.PackUInt64(value,flags)}) }
|
||||
|
||||
func (p *Packer) KeyValueFloat32(key any, value float32, flags packs.Flags){
|
||||
p.addKeyValue(key,func(){ p.PackFloat32(value, flags) }) }
|
||||
|
||||
func (p *Packer) KeyValueFloat64(key any, value float64, flags packs.Flags){
|
||||
p.addKeyValue(key,func(){ p.PackFloat64(value, flags) }) }
|
||||
|
||||
func (p *Packer) KeyValueDate (key any, value time.Time, flags packs.Flags){
|
||||
p.addKeyValue(key,func(){ p.PackDate(value, flags) }) }
|
||||
|
||||
|
||||
|
||||
func (p *Packer) KeyValueList (key any, builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addKeyValue(key,func(){ p.PackList(builder, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) KeyValueMap (key any, builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addKeyValue(key,func(){ p.PackMap(builder, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) KeyValueObject (key any, builder func(packs.ObjectPackBuilder,packs.Flags), flags packs.Flags) {
|
||||
p.addKeyValue(key,func(){ p.PackObject(builder, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) addKeyValue(key any, caller func()) {
|
||||
if p.state.Count() > 0 {
|
||||
p.state.WriteByte(',')
|
||||
}
|
||||
p.packStringifyKey(key)
|
||||
if p.state.Error != nil {
|
||||
return
|
||||
}
|
||||
p.state.WriteByte(':')
|
||||
caller()
|
||||
p.state.Inc()
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) packStringifyKey(key any) {
|
||||
switch v := key.(type) {
|
||||
case string : p.PackString(v,packs.FlagScapeHTML)
|
||||
case float32: p.PackFloat32(v,packs.FlagScapeHTML|packs.FlagQuote)
|
||||
case float64: p.PackFloat64(v,packs.FlagScapeHTML|packs.FlagQuote)
|
||||
default:
|
||||
me := &rMapEntry{
|
||||
v : reflect.ValueOf(key),
|
||||
}
|
||||
fn := stringifyRKey(me.v.Type())
|
||||
if fn == nil {
|
||||
p.state.SetError(packs.G.ErrInvalidKey)
|
||||
return
|
||||
}
|
||||
if er := fn(me,me.v); er != nil {
|
||||
p.state.SetError(er)
|
||||
return
|
||||
}
|
||||
p.PackString(me.k,me.f)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name builder_object.go
|
||||
// Created by DEV
|
||||
// Modified 06/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Packer) FieldAny (name string, value any, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackAny(value, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) FieldRaw (name string, value []byte, flags packs.Flags){
|
||||
p.addField(name, func() { p.PackRaw(value, flags) }) }
|
||||
|
||||
func (p *Packer) FieldBinary (name string, value []byte, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackBinary(value, flags) }) }
|
||||
|
||||
func (p *Packer) FieldString (name string, value string, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackString(value, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldBool (name string, value bool, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackBool(value, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldInt8 (name string, value int8 , flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackInt64(int64(value), flags) })}
|
||||
|
||||
func (p *Packer) FieldInt16 (name string, value int16, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackInt64(int64(value), flags) })}
|
||||
|
||||
func (p *Packer) FieldInt32 (name string, value int32, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackInt64(int64(value), flags) }) }
|
||||
|
||||
func (p *Packer) FieldInt64 (name string, value int64, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackInt64(value, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) FieldUInt8 (name string, value uint8, flags packs.Flags) {
|
||||
p.addField(name, func() { p.PackUInt64(uint64(value), flags) }) }
|
||||
|
||||
func (p *Packer) FieldUInt16 (name string, value uint16, flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackUInt64(uint64(value), flags) }) }
|
||||
|
||||
func (p *Packer) FieldUInt32 (name string, value uint32, flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackUInt64(uint64(value), flags) }) }
|
||||
|
||||
func (p *Packer) FieldUInt64 (name string, value uint64, flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackUInt64(value, flags) }) }
|
||||
|
||||
|
||||
func (p *Packer) FieldFloat32(name string, value float32,flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackFloat32(value, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldFloat64(name string, value float64,flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackFloat64(value, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldDate (name string, value time.Time,flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackDate(value, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldList (name string, builder func(packs.ListPackBuilder,packs.Flags), flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackList(builder, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldMap (name string, builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackMap(builder, flags) })
|
||||
}
|
||||
|
||||
func (p *Packer) FieldObject (name string, builder func(packs.ObjectPackBuilder,packs.Flags), flags packs.Flags) {
|
||||
p.addField(name,func(){ p.PackObject(builder, flags) })
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (p *Packer) addField(name string, caller func()) {
|
||||
if p.state.Count() > 0 {
|
||||
p.state.WriteByte(',')
|
||||
}
|
||||
packString(p.state,name,packs.FlagScapeHTML)
|
||||
if p.state.Error != nil {
|
||||
return
|
||||
}
|
||||
p.state.WriteByte(':')
|
||||
caller()
|
||||
if p.state != nil {
|
||||
p.state.Inc()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,649 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name value_packer.go
|
||||
// Created by DEV
|
||||
// Modified 06/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 pjson
|
||||
|
||||
import (
|
||||
"crypts"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errs"
|
||||
"math"
|
||||
"packs"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
|
||||
type (
|
||||
|
||||
|
||||
Packer struct {
|
||||
state *packs.State
|
||||
dirty bool
|
||||
}
|
||||
|
||||
|
||||
PackerFnc func (packer *Packer)
|
||||
)
|
||||
|
||||
|
||||
func NewPacker (options ... PackerFnc) *Packer {
|
||||
pk := &Packer {
|
||||
state : packs.NewState(),
|
||||
}
|
||||
for _,o := range options {
|
||||
o(pk)
|
||||
}
|
||||
return pk
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (p *Packer) Pack (value any, flags packs.Flags) {
|
||||
if p.state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(p.state.Error))
|
||||
}
|
||||
if p.dirty {
|
||||
panic(packs.G.ErrInvalidState)
|
||||
}
|
||||
p.dirty = true
|
||||
p.PackAny(value,flags)
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) Packet () []byte {
|
||||
|
||||
|
||||
|
||||
return p.state.Bytes() }
|
||||
|
||||
|
||||
func (p *Packer) Error () error {
|
||||
return p.state.Error }
|
||||
|
||||
|
||||
func (p *Packer) Reset () {
|
||||
p.state.Reset()
|
||||
p.dirty = false
|
||||
}
|
||||
|
||||
func (p *Packer) Release () {
|
||||
p.dirty = false
|
||||
packs.ReleaseState(p.state)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (p *Packer) PackAny (value any, flags packs.Flags) {
|
||||
if p.state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(p.state.Error))
|
||||
}
|
||||
if value == nil {
|
||||
p.state.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case packs.Builder:
|
||||
p.state.SetError(v.Build(p))
|
||||
|
||||
case json.Marshaler:
|
||||
d,e := v.MarshalJSON()
|
||||
if e != nil {
|
||||
p.state.SetError(e)
|
||||
} else {
|
||||
p.state.W(d)
|
||||
}
|
||||
|
||||
case bool : packBool (p.state,v,flags )
|
||||
|
||||
case string : packString(p.state,v,flags )
|
||||
|
||||
case int : packInt(p.state,int64(v),flags)
|
||||
case int8 : packInt(p.state,int64(v),flags)
|
||||
case int16 : packInt(p.state,int64(v),flags)
|
||||
case int32 : packInt(p.state,int64(v),flags)
|
||||
case int64 : packInt(p.state,v,flags )
|
||||
|
||||
case uint : packUInt(p.state,uint64(v),flags)
|
||||
case uint8 : packUInt(p.state,uint64(v),flags)
|
||||
case uint16 : packUInt(p.state,uint64(v),flags)
|
||||
case uint32 : packUInt(p.state,uint64(v),flags)
|
||||
case uint64 : packUInt(p.state,v,flags )
|
||||
|
||||
case float32: packFloatString(p.state,float64(v),flags,32)
|
||||
case float64: packFloatString(p.state,v,flags,64)
|
||||
|
||||
case time.Time: packDate (p.state,v,flags)
|
||||
|
||||
case reflect.Value: rTypePacker(v.Type())(p.state,v,flags)
|
||||
|
||||
case []uint8 :
|
||||
if flags.Binary() {
|
||||
packBinary(p.state,v,flags)
|
||||
return
|
||||
}
|
||||
packListUInt[uint8 ](p.state,v,flags)
|
||||
case []uint : packListUInt [uint ] (p.state,v,flags)
|
||||
case []uint16 : packListUInt [uint16] (p.state,v,flags)
|
||||
case []uint32 : packListUInt [uint32] (p.state,v,flags)
|
||||
case []uint64 : packListUInt [uint64] (p.state,v,flags)
|
||||
case []int : packListInt [int ] (p.state,v,flags)
|
||||
case []int8 : packListInt [int8 ] (p.state,v,flags)
|
||||
case []int16 : packListInt [int16] (p.state,v,flags)
|
||||
case []int32 : packListInt [int32] (p.state,v,flags)
|
||||
case []int64 : packListInt [int64] (p.state,v,flags)
|
||||
case []float32: packListFloat[float32](p.state,v,flags,32)
|
||||
case []float64: packListFloat[float64](p.state,v,flags,64)
|
||||
|
||||
case []bool : packListBool (p.state,v,flags)
|
||||
case []string : packListString(p.state,v,flags)
|
||||
case []time.Time: packListDate(p.state,v,flags)
|
||||
|
||||
default:
|
||||
rv := reflect.ValueOf(value)
|
||||
rTypePacker(rv.Type())(p.state,rv,flags)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (p *Packer) PackRaw (value []byte, flags packs.Flags) { packRaw(p.state,value,flags) }
|
||||
|
||||
func (p *Packer) PackBinary (value []byte, flags packs.Flags) { packBinary(p.state,value,flags) }
|
||||
func (p *Packer) PackString (value string, flags packs.Flags) { packString (p.state,value,flags) }
|
||||
|
||||
func (p *Packer) PackBool (value bool, flags packs.Flags) { packBool(p.state,value,flags) }
|
||||
|
||||
func (p *Packer) PackInt8 (value int8 , flags packs.Flags) { packInt(p.state,int64(value),flags) }
|
||||
func (p *Packer) PackInt16 (value int16, flags packs.Flags) { packInt(p.state,int64(value),flags) }
|
||||
func (p *Packer) PackInt32 (value int32, flags packs.Flags) { packInt(p.state,int64(value),flags) }
|
||||
func (p *Packer) PackInt64 (value int64, flags packs.Flags) { packInt(p.state,value,flags)}
|
||||
|
||||
func (p *Packer) PackUInt8 (value uint8 , flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
|
||||
func (p *Packer) PackUInt16 (value uint16, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
|
||||
func (p *Packer) PackUInt32 (value uint32, flags packs.Flags) { packUInt(p.state,uint64(value),flags) }
|
||||
func (p *Packer) PackUInt64 (value uint64, flags packs.Flags) { packUInt(p.state, value,flags) }
|
||||
|
||||
func (p *Packer) PackFloat32 (value float32, flags packs.Flags) { packFloatString(p.state, float64(value), flags, 32) }
|
||||
func (p *Packer) PackFloat64 (value float64, flags packs.Flags) { packFloatString(p.state, value, flags, 64) }
|
||||
|
||||
func (p *Packer) PackDate (value time.Time, flags packs.Flags) { packDate(p.state,value,flags) }
|
||||
|
||||
|
||||
func (p *Packer) PackList (builder func(packs.ListPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.packCompound('[',']',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
|
||||
}
|
||||
|
||||
func (p *Packer) PackMap (builder func(packs.MapPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
|
||||
}
|
||||
|
||||
func (p *Packer) PackObject(builder func(packs.ObjectPackBuilder, packs.Flags), flags packs.Flags) {
|
||||
p.packCompound('{','}',builder==nil,func(pk *Packer, fl packs.Flags){ builder(pk,fl) },flags)
|
||||
}
|
||||
|
||||
|
||||
func (p *Packer) packCompound (opener, closer byte, isnil bool, buildFn func(*Packer,packs.Flags), flags packs.Flags) {
|
||||
if p.state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(p.state.Error))
|
||||
}
|
||||
if isnil {
|
||||
p.state.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
|
||||
dn := false
|
||||
defer func(d *bool) {
|
||||
if !(*d) {
|
||||
p.state.SetError(errs.ToError(recover()))
|
||||
}
|
||||
}(&dn)
|
||||
|
||||
p.state.Open(opener)
|
||||
buildFn(p,flags)
|
||||
if p.state.Error != nil {
|
||||
return
|
||||
}
|
||||
p.state.Close(closer)
|
||||
dn = true
|
||||
}
|
||||
|
||||
|
||||
|
||||
func packRaw (state *packs.State, value []byte, flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
if value == nil {
|
||||
state.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
if len(value) == 0 {
|
||||
state.Write2Byte('"','"')
|
||||
return
|
||||
}
|
||||
state.WOQ(flags.Quote(),'"',value)
|
||||
}
|
||||
|
||||
func packString (state *packs.State, value string , flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
|
||||
if len(value) == 0 {
|
||||
state.Write2Byte('"','"')
|
||||
return
|
||||
}
|
||||
|
||||
if flags.Encrypted() {
|
||||
packEncrypted(state, []byte(value), flags|packs.FlagBinary64)
|
||||
return
|
||||
}
|
||||
|
||||
if flags.Binary() {
|
||||
packBinary(state,[]byte(value),flags)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
state.WriteByte('"')
|
||||
start := 0
|
||||
for i := 0; i < len(value); {
|
||||
if b := value[i]; b < utf8.RuneSelf {
|
||||
if !g.jsonChars[b].isHtmlUnsafe() || (!flags.EscapeHTML() && !g.jsonChars[b].isUnsafe()) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if start < i {
|
||||
state.WriteString(value[start:i])
|
||||
}
|
||||
state.WriteByte('\\')
|
||||
switch b {
|
||||
case '\\', '"': state.WriteByte(b)
|
||||
case '\n': state.WriteByte('n')
|
||||
case '\r': state.WriteByte('r')
|
||||
case '\t': state.WriteByte('t')
|
||||
default:
|
||||
state.WriteString(`u00`)
|
||||
state.Write2Byte(g.hex[b>>4], g.hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
c, size := utf8.DecodeRuneInString(value[i:])
|
||||
if c == utf8.RuneError && size == 1 {
|
||||
if start < i {
|
||||
state.WriteString(value[start:i])
|
||||
}
|
||||
state.WriteString(`\ufffd`)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
|
||||
if c == '\u2028' || c == '\u2029' {
|
||||
if start < i {
|
||||
state.WriteString(value[start:i])
|
||||
}
|
||||
state.WriteString(`\u202`)
|
||||
state.WriteByte(g.hex[c&0xF])
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
}
|
||||
if start < len(value) {
|
||||
state.WriteString(value[start:])
|
||||
}
|
||||
state.WriteByte('"')
|
||||
}
|
||||
|
||||
|
||||
func packEncrypted (state *packs.State, value []byte, flags packs.Flags) {
|
||||
r := state.Encrypter.Encrypt(value)
|
||||
if !r.Ok() {
|
||||
state.SetError(r.Fail())
|
||||
return
|
||||
}
|
||||
|
||||
state.WriteByte('"')
|
||||
if flags.Bin64() || !flags.Binary() {
|
||||
packBinary64(state, r.Value(), flags)
|
||||
} else {
|
||||
packBinary32(state, r.Value(), flags)
|
||||
}
|
||||
if state.Error == nil {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func packBinary (state *packs.State, value []byte , flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
|
||||
if value == nil {
|
||||
_,_ = state.Write(g.nullValue)
|
||||
return
|
||||
}
|
||||
if len(value) == 0 {
|
||||
state.Write2Byte('"','"')
|
||||
return
|
||||
}
|
||||
|
||||
if flags.Encrypted() {
|
||||
packEncrypted(state,value,flags)
|
||||
return
|
||||
}
|
||||
|
||||
state.WriteByte('"')
|
||||
if flags.Bin64() {
|
||||
packBinary64(state, value, 0)
|
||||
} else if flags.Bin32() {
|
||||
packBinary32(state, value, 0)
|
||||
} else {
|
||||
state.SetError(packs.G.ErrUnsupportedType)
|
||||
return
|
||||
}
|
||||
if state.Error == nil {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func packBinary64 (state *packs.State, value []byte , _ packs.Flags) {
|
||||
ln := base64.StdEncoding.EncodedLen(len(value))
|
||||
if ln <= len(state.Temp) {
|
||||
dst := state.Temp[:ln]
|
||||
base64.StdEncoding.Encode(dst, value)
|
||||
_,_= state.Write(dst)
|
||||
} else if ln <= 1024 {
|
||||
dst := make([]byte, ln)
|
||||
base64.StdEncoding.Encode(dst, value)
|
||||
_,_ = state.Write(dst)
|
||||
} else {
|
||||
ec := base64.NewEncoder(base64.StdEncoding, state)
|
||||
_,_ = ec.Write(value)
|
||||
state.SetError(ec.Close())
|
||||
}
|
||||
}
|
||||
|
||||
func packBinary32 (state *packs.State, value []byte , _ packs.Flags) {
|
||||
ln := base32.StdEncoding.EncodedLen(len(value))
|
||||
if ln <= len(state.Temp) {
|
||||
dst := state.Temp[:ln]
|
||||
base32.StdEncoding.Encode(dst, value)
|
||||
_,_= state.Write(dst)
|
||||
} else if ln <= 1024 {
|
||||
dst := make([]byte, ln)
|
||||
base32.StdEncoding.Encode(dst, value)
|
||||
_,_ = state.Write(dst)
|
||||
} else {
|
||||
ec := base32.NewEncoder(base32.StdEncoding, state)
|
||||
_,_ = ec.Write(value)
|
||||
state.SetError(ec.Close())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func packBool (state *packs.State, value bool , flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
if value {
|
||||
state.WOQ(flags.Quote(),'"', g.trueValue)
|
||||
} else {
|
||||
state.WOQ(flags.Quote(),'"', g.falseValue)
|
||||
}
|
||||
}
|
||||
|
||||
func packInt (state *packs.State, value int64 , flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
|
||||
q :=flags.Quote()
|
||||
if q {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
if value == 0 {
|
||||
state.WriteByte('0')
|
||||
} else {
|
||||
state.WriteIntStr(value, 10)
|
||||
}
|
||||
if q {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func packUInt (state *packs.State, value uint64 , flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
q :=flags.Quote()
|
||||
if q {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
if value == 0 {
|
||||
state.WriteByte('0')
|
||||
} else {
|
||||
state.WriteUIntStr(value, 10)
|
||||
}
|
||||
if q {
|
||||
state.WriteByte('"')
|
||||
}
|
||||
}
|
||||
|
||||
func packFloat (state *packs.State, value float64, flags packs.Flags) {
|
||||
packFloatString(state, value, flags, 64)
|
||||
}
|
||||
|
||||
func packFloatString (state *packs.State, f float64, flags packs.Flags, bits int) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
|
||||
if math.IsInf(f, 0) || math.IsNaN(f) {
|
||||
state.SetError(packs.G.ErrInvalidValue)
|
||||
return
|
||||
}
|
||||
|
||||
abs := math.Abs(f)
|
||||
fm := byte('f')
|
||||
|
||||
if abs != 0 {
|
||||
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
||||
fm = 'e'
|
||||
}
|
||||
}
|
||||
bf := state.Temp[:0]
|
||||
bf = strconv.AppendFloat(bf, f, fm, -1, int(bits))
|
||||
if fm == 'e' {
|
||||
// clean up e-09 to e-9
|
||||
n := len(bf)
|
||||
if n >= 4 && bf[n-4] == 'e' && bf[n-3] == '-' && bf[n-2] == '0' {
|
||||
bf[n-2] = bf[n-1]
|
||||
bf = bf[:n-1]
|
||||
}
|
||||
}
|
||||
|
||||
state.WOQ(flags.Quote(),'"',bf)
|
||||
}
|
||||
|
||||
|
||||
func packDate(state *packs.State, value time.Time, flags packs.Flags) {
|
||||
if state.Error != nil {
|
||||
panic(packs.G.ErrInvalidState.WrapWithCause(state.Error))
|
||||
}
|
||||
state.WOQ(true,'"',value.AppendFormat(state.Temp[:0],flags.DateFormat()))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func packListString (state *packs.State, list []string, flags packs.Flags) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packString(state,v,flags)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
|
||||
func packListBool (state *packs.State, list []bool, flags packs.Flags) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packBool(state,v,flags)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
|
||||
func packListInt [T int | int8 | int16 | int32 | int64](state *packs.State, list []T, flags packs.Flags) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packInt(state,int64(v),flags)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
|
||||
func packListUInt [T uint | uint8 | uint16 | uint32 | uint64](state *packs.State, list []T, flags packs.Flags) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packUInt(state,uint64(v),flags)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
|
||||
func packListFloat[T float32 | float64](state *packs.State, list []T, flags packs.Flags, bits int) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packFloatString(state,float64(v),flags,bits)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
func packListDate (state *packs.State, list []time.Time, flags packs.Flags) {
|
||||
if !checkList(state,list == nil, len(list) ==0) {
|
||||
return
|
||||
}
|
||||
state.WriteByte('[')
|
||||
for i,v := range list {
|
||||
if i > 0 {
|
||||
state.WriteByte(',')
|
||||
}
|
||||
packDate(state,v,flags)
|
||||
if state.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
state.WriteByte(']')
|
||||
}
|
||||
|
||||
|
||||
func checkList (state *packs.State, isNull, isEmpty bool) bool {
|
||||
if isNull {
|
||||
state.Write2Byte('"','"')
|
||||
return false
|
||||
}
|
||||
if isEmpty {
|
||||
state.Write2Byte('[',']')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
func WithEncrypter(encrypter crypts.Encrypter) PackerFnc {
|
||||
return func(p *Packer) {
|
||||
if encrypter == nil {
|
||||
encrypter = crypts.EncrypterNop{}
|
||||
}
|
||||
p.state.Encrypter = encrypter
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
|
||||
rPackerFnc func (state *packs.State, rvalue reflect.Value, flags packs.Flags)
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func rTypePacker (rtype reflect.Type) rPackerFnc {
|
||||
if fn,ok := g.packersCache.Load(rtype); ok {
|
||||
return fn.(rPackerFnc)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var fn rPackerFnc
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
fi,ld := g.packersCache.LoadOrStore(rtype, rPackerFnc(func (e *packs.State, v reflect.Value, f packs.Flags) {
|
||||
wg.Wait()
|
||||
fn(e,v,f)
|
||||
}))
|
||||
if ld {
|
||||
return fi.(rPackerFnc)
|
||||
}
|
||||
|
||||
fn = _rTypePacker(rtype)
|
||||
wg.Done()
|
||||
|
||||
g.packersCache.Store(rtype,fn)
|
||||
return fn
|
||||
}
|
||||
|
||||
|
||||
func _rTypePacker(rtype reflect.Type) rPackerFnc {
|
||||
|
||||
switch rtype.Kind() {
|
||||
case reflect.Bool : return func(s *packs.State, v reflect.Value, f packs.Flags) { packBool (s,v.Bool (),f )}
|
||||
case reflect.String : return func(s *packs.State, v reflect.Value, f packs.Flags) { packString(s,v.String(),f )}
|
||||
case reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64 : return func(s *packs.State, v reflect.Value, f packs.Flags) { packInt (s,v.Int (),f )}
|
||||
case reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64 : return func(s *packs.State, v reflect.Value, f packs.Flags) { packUInt (s,v.Uint (),f )}
|
||||
case reflect.Float32: return func(s *packs.State, v reflect.Value, f packs.Flags) { packFloatString(s,v.Float(),f,32) }
|
||||
case reflect.Float64: return func(s *packs.State, v reflect.Value, f packs.Flags) { packFloatString(s,v.Float(),f,64) }
|
||||
|
||||
case reflect.Pointer:
|
||||
return rPointerPacker(rtype)
|
||||
|
||||
case reflect.Interface:
|
||||
return rInterfacePacker
|
||||
|
||||
case reflect.Slice,
|
||||
reflect.Array :
|
||||
return rListPacker(rtype)
|
||||
|
||||
case reflect.Map :
|
||||
return rMapPacker(rtype)
|
||||
|
||||
case reflect.Struct:
|
||||
return rObjectPacker(rtype)
|
||||
|
||||
default:
|
||||
return unsupportedTypePacker
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func unsupportedTypePacker(state *packs.State, _ reflect.Value, _ packs.Flags) {
|
||||
state.SetError(packs.G.ErrUnsupportedType)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_interface.go
|
||||
// Created by DEV
|
||||
// Modified 13/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func rInterfacePacker (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if v.IsNil() {
|
||||
s.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
rValuePacker(v.Elem())(s,v,f)
|
||||
}
|
||||
@ -0,0 +1,166 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rkey.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 pjson
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"math"
|
||||
"packs"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func stringifyRKey(rt reflect.Type) rMapEntryFnc {
|
||||
fn,ok := g.keyersCache.Load(rt)
|
||||
if !ok {
|
||||
fn, _ = g.keyersCache.LoadOrStore(rt, _stringifyRKey(rt))
|
||||
}
|
||||
return fn.(rMapEntryFnc)
|
||||
}
|
||||
|
||||
|
||||
func _stringifyRKey(rt reflect.Type) rMapEntryFnc {
|
||||
|
||||
if rt.Kind() == reflect.String {
|
||||
return func(e *rMapEntry, k reflect.Value) error {
|
||||
e.k = k.String()
|
||||
e.f = packs.FlagScapeHTML
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
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.k = string(bf)
|
||||
e.f = packs.FlagScapeHTML
|
||||
}
|
||||
return er
|
||||
}
|
||||
}
|
||||
|
||||
switch rt.Kind() {
|
||||
|
||||
case reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64:
|
||||
return func(e *rMapEntry, k reflect.Value) error {
|
||||
e.k = strconv.FormatInt(k.Int(), 10)
|
||||
return nil
|
||||
}
|
||||
case reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Uintptr:
|
||||
return func(e *rMapEntry, k reflect.Value) error {
|
||||
e.k = strconv.FormatUint(k.Uint(), 10)
|
||||
return nil
|
||||
}
|
||||
|
||||
case reflect.Interface:
|
||||
return func(e *rMapEntry, k reflect.Value) error {
|
||||
k = k.Elem()
|
||||
|
||||
if k.Type().Kind() == reflect.String {
|
||||
e.k = k.String()
|
||||
e.f = packs.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.k = string(bf)
|
||||
e.f = packs.FlagScapeHTML
|
||||
}
|
||||
return er
|
||||
}
|
||||
|
||||
switch rt.Kind() {
|
||||
|
||||
case reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64:
|
||||
e.k = strconv.FormatInt(k.Int(), 10)
|
||||
return nil
|
||||
|
||||
case reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Uintptr:
|
||||
e.k = strconv.FormatUint(k.Uint(), 10)
|
||||
return nil
|
||||
|
||||
default:
|
||||
return packs.G.ErrInvalidKey
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func stringifyFloat (buffer []byte, f float64, bits int) []byte {
|
||||
if math.IsInf(f, 0) || math.IsNaN(f) {
|
||||
return nil
|
||||
}
|
||||
|
||||
abs := math.Abs(f)
|
||||
fmt := byte('f')
|
||||
|
||||
if abs != 0 {
|
||||
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
||||
fmt = 'e'
|
||||
}
|
||||
}
|
||||
buffer = strconv.AppendFloat(buffer[:0], f, fmt, -1, int(bits))
|
||||
if fmt == 'e' {
|
||||
// clean up e-09 to e-9
|
||||
n := len(buffer)
|
||||
if n >= 4 && buffer[n-4] == 'e' && buffer[n-3] == '-' && buffer[n-2] == '0' {
|
||||
buffer[n-2] = buffer[n-1]
|
||||
buffer = buffer[:n-1]
|
||||
}
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
||||
@ -0,0 +1,132 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name packer_list.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
rList struct {
|
||||
packFn rPackerFnc
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func rListPacker (rtype reflect.Type) rPackerFnc {
|
||||
lp := *newRList(rtype)
|
||||
if rtype.Elem().Kind() != reflect.Uint8 {
|
||||
return lp.pack
|
||||
}
|
||||
if rtype.Kind() == reflect.Slice {
|
||||
return lp.packBinarySlice
|
||||
}
|
||||
return lp.packBinary
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func newRList(rtype reflect.Type) *rList {
|
||||
return &rList{ packFn: rTypePacker(rtype.Elem()) }}
|
||||
|
||||
|
||||
|
||||
func (p rList) packBinary (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if f.Binary() {
|
||||
packBinary(s, v.Interface().([]byte), f)
|
||||
return
|
||||
}
|
||||
p.pack(s,v,f)
|
||||
}
|
||||
|
||||
|
||||
func (p rList) packBinarySlice (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if f.Binary() {
|
||||
packBinary(s, v.Interface().([]byte), f)
|
||||
return
|
||||
}
|
||||
p.packSlice(s,v,f)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (p rList) packSlice(s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if v.IsNil() {
|
||||
s.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
|
||||
if s.Level > maxCyclesAfter {
|
||||
cp := struct {
|
||||
p interface{}
|
||||
l int
|
||||
}{
|
||||
p: v.UnsafePointer(),
|
||||
l: v.Len(),
|
||||
}
|
||||
if fn,ok := s.CheckCycle(cp); ok {
|
||||
defer fn()
|
||||
} else {
|
||||
s.SetError(packs.G.ErrRedundantPack)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
p.pack(s,v,f)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (p rList) pack (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if v.IsNil() {
|
||||
s.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
|
||||
if v.Len() == 0 {
|
||||
s.Write2Byte('[',']')
|
||||
return
|
||||
}
|
||||
|
||||
s.Open('[')
|
||||
for i:=0; i<v.Len(); i++ {
|
||||
if i > 0 {
|
||||
s.WriteByte(',')
|
||||
}
|
||||
p.packFn(s,v.Index(i),f)
|
||||
if s.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
s.Close(']')
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_map.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
rMap struct {
|
||||
keyFn rMapEntryFnc
|
||||
packFn rPackerFnc
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
func rMapPacker (rtype reflect.Type) rPackerFnc {
|
||||
return (*newRMap(rtype)).pack
|
||||
}
|
||||
|
||||
|
||||
func newRMap(rtype reflect.Type) *rMap {
|
||||
return &rMap{
|
||||
packFn: rTypePacker (rtype.Elem()),
|
||||
keyFn : stringifyRKey(rtype.Key()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (p *rMap) pack (s *packs.State, v reflect.Value, f packs.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 > maxCyclesAfter {
|
||||
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.packFn(s,ls[i].v,0)
|
||||
if s.Error != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
s.Close('}')
|
||||
}
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_map_entry.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
rMapEntry struct {
|
||||
f packs.Flags // flags
|
||||
v reflect.Value // value
|
||||
k string // Key
|
||||
}
|
||||
|
||||
rMapEntryFnc func(entry *rMapEntry, rkey reflect.Value) error
|
||||
|
||||
rMapEntryList []rMapEntry
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (e rMapEntryList) Len() int {
|
||||
return len(e)
|
||||
}
|
||||
|
||||
func (e rMapEntryList) Less(i, j int) bool {
|
||||
return e[i].k < e[j].k
|
||||
}
|
||||
|
||||
func (e rMapEntryList) Swap(i, j int) {
|
||||
e[i], e[j] = e[j], e[i]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,280 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_object.go
|
||||
// Created by DEV
|
||||
// Modified 07/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 pjson
|
||||
|
||||
import (
|
||||
"bins/bfers"
|
||||
"packs"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
rObject struct {
|
||||
fields rFieldList
|
||||
nameIndex map[string]int
|
||||
}
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
func rObjectPacker (rtype reflect.Type) rPackerFnc {
|
||||
op,ok := g.fieldsCache.Load(rtype)
|
||||
if !ok {
|
||||
op,_ = g.fieldsCache.LoadOrStore(rtype,*newRObject(rtype))
|
||||
}
|
||||
return func(s *packs.State, value reflect.Value, flags packs.Flags) {
|
||||
op.(rObject).pack(s,value,flags)
|
||||
}
|
||||
//return (op.(rObject)).pack
|
||||
}
|
||||
|
||||
|
||||
func newRObject(rtype reflect.Type) *rObject {
|
||||
cur := rFieldList{}
|
||||
nxt := rFieldList{{ rtype: rtype}}
|
||||
|
||||
var fls rFieldList
|
||||
var cnt, nxCnt map[reflect.Type]int
|
||||
vis := map[reflect.Type]bool{}
|
||||
nms := bfers.NewBuffer()
|
||||
|
||||
for len(nxt) > 0 {
|
||||
cur,nxt = nxt,cur[:0]
|
||||
|
||||
for _,f := range cur {
|
||||
if vis[f.rtype] {
|
||||
continue
|
||||
}
|
||||
vis[f.rtype]=true
|
||||
|
||||
for i:=0; i<f.rtype.NumField(); i++ {
|
||||
sf := f.rtype.Field(i)
|
||||
if sf.Anonymous {
|
||||
tp := sf.Type
|
||||
if tp.Kind() == reflect.Pointer {
|
||||
tp = tp.Elem()
|
||||
}
|
||||
if !sf.IsExported() && tp.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
} else if !sf.IsExported() {
|
||||
continue
|
||||
}
|
||||
|
||||
nm, fg, has := packs.FlagsFromPackTag(sf.Tag)
|
||||
if !has {
|
||||
nm, fg, has = jsonTags(sf.Tag)
|
||||
}
|
||||
if has {
|
||||
if nm == "-" || fg.Omit() {
|
||||
continue
|
||||
}
|
||||
if !packs.CheckTag(nm) {
|
||||
nm = ""
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
if fg.String() && !fg.Quote() {
|
||||
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:
|
||||
fg = fg|packs.FlagQuote
|
||||
}
|
||||
}
|
||||
|
||||
if nm != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tged := nm != ""
|
||||
if nm == "" {
|
||||
nm = sf.Name
|
||||
}
|
||||
of := rObjectField {
|
||||
name : nm,
|
||||
isTagged: tged,
|
||||
index : index,
|
||||
rtype : ft,
|
||||
flags : fg,
|
||||
}
|
||||
of.nameB = []byte(of.name)
|
||||
of.foldFn= packs.GetFoldFunc(of.nameB)
|
||||
|
||||
// Build nameEscHTML and nameNonEsc ahead of time.
|
||||
nms.Reset()
|
||||
nms.WriteByte('"')
|
||||
nms.WriteHTML(of.nameB)
|
||||
nms.Write2Byte('"',':')
|
||||
of.nameS = nms.String()
|
||||
of.nameU = `"` + of.name + `":`
|
||||
|
||||
fls = append(fls,of)
|
||||
if cnt[f.rtype] > 1 {
|
||||
fls = append(fls,fls[len(fls)-1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
nxCnt[ft]++
|
||||
if nxCnt[ft] == 1 {
|
||||
nxt = append(nxt,rObjectField{ name: ft.Name(), index: index, rtype: ft})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sort.Slice(fls,func(i,j int) bool {
|
||||
ls := fls
|
||||
if ls[i].name != ls[j].name {
|
||||
return ls[i].name < ls[j].name
|
||||
}
|
||||
if len(ls[i].index) != len(ls[j].index) {
|
||||
return len(ls[i].index) < len(ls[j].index)
|
||||
}
|
||||
if ls[i].isTagged != ls[j].isTagged {
|
||||
return ls[i].isTagged
|
||||
}
|
||||
return rFieldIndexList(ls).Less(i, j)
|
||||
})
|
||||
|
||||
out := fls[:0]
|
||||
for ad,i :=0,0; i< len(fls); i += ad {
|
||||
fi := fls[i]
|
||||
nm := fi.name
|
||||
for ad=1; i+ad <len(fls); ad++ {
|
||||
fj := fls[i+ad]
|
||||
if fj.name != nm {
|
||||
break
|
||||
}
|
||||
}
|
||||
if ad == 1 {
|
||||
out = append(out,fi)
|
||||
continue
|
||||
}
|
||||
do,ok := fls[i:i+ad].dominant()
|
||||
if ok {
|
||||
out = append(out,do)
|
||||
}
|
||||
}
|
||||
|
||||
fls = out
|
||||
sort.Sort(rFieldIndexList(fls))
|
||||
|
||||
for i:= range fls {
|
||||
f := &fls[i]
|
||||
f.packerFn = rTypePacker(f.typeByIndex(rtype))
|
||||
}
|
||||
nmIdx := make(map[string]int,len(fls))
|
||||
for i,fd := range fls {
|
||||
nmIdx[fd.name]=i
|
||||
}
|
||||
return &rObject{
|
||||
fields: fls,
|
||||
nameIndex: nmIdx,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (o rObject) pack (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
nx := byte('{')
|
||||
FieldLoop:
|
||||
for i:= range o.fields {
|
||||
fd := &o.fields[i]
|
||||
|
||||
fv := v
|
||||
for _,i := range fd.index {
|
||||
if fv.Kind() == reflect.Pointer {
|
||||
if fv.IsNil() {
|
||||
continue FieldLoop
|
||||
}
|
||||
fv = fv.Elem()
|
||||
}
|
||||
fv = fv.Field(i)
|
||||
}
|
||||
if fd.flags.OmitEmpty() && isEmptyValue(v) {
|
||||
continue
|
||||
}
|
||||
s.WriteByte(nx)
|
||||
nx = ','
|
||||
if fd.flags.EscapeHTML() {
|
||||
s.WriteString(fd.nameS)
|
||||
} else {
|
||||
s.WriteString(fd.nameU)
|
||||
}
|
||||
fd.packerFn(s,fv, fd.flags|f)
|
||||
}
|
||||
if nx == '{' {
|
||||
s.Write2Byte('{','}')
|
||||
} else {
|
||||
s.WriteByte('}')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func jsonTags (tag reflect.StructTag) (string,packs.Flags,bool) {
|
||||
return packs.FlagsFromTag(tag,jsonTag,func(n string) packs.Flags {
|
||||
switch n {
|
||||
case "omitempty" : return packs.FlagOmitEmpty
|
||||
case "quote" : return packs.FlagQuote
|
||||
default : return 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Pointer:
|
||||
return v.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_field.go
|
||||
// Created by DEV
|
||||
// Modified 07/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
rObjectField struct {
|
||||
name string
|
||||
nameB []byte
|
||||
nameU string // Unscaped name
|
||||
nameS string // Escaped HTML name
|
||||
|
||||
isTagged bool
|
||||
index []int
|
||||
rtype reflect.Type
|
||||
flags packs.Flags
|
||||
|
||||
foldFn packs.FoldFnc
|
||||
packerFn rPackerFnc
|
||||
}
|
||||
|
||||
rFieldList []rObjectField
|
||||
|
||||
rFieldIndexList []rObjectField
|
||||
)
|
||||
|
||||
|
||||
func (f rObjectField) typeByIndex(rtype reflect.Type) reflect.Type {
|
||||
for _,i := range f.index {
|
||||
if rtype.Kind() == reflect.Pointer {
|
||||
rtype = rtype.Elem()
|
||||
}
|
||||
rtype = rtype.Field(i).Type
|
||||
}
|
||||
return rtype
|
||||
}
|
||||
|
||||
|
||||
func (l rFieldList) dominant () (rObjectField,bool) {
|
||||
if len(l) > 1 && len(l[0].index) == len(l[1].index) && l[0].isTagged == l[1].isTagged {
|
||||
return rObjectField{},false
|
||||
}
|
||||
return l[0],true
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (x rFieldIndexList) Len() int { return len(x) }
|
||||
|
||||
func (x rFieldIndexList) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x rFieldIndexList) 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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_pointer.go
|
||||
// Created by DEV
|
||||
// Modified 09/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
rPointer struct {
|
||||
elemPackFn rPackerFnc
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
func rPointerPacker (rtype reflect.Type) rPackerFnc {
|
||||
return (*newRPointer(rtype)).pack
|
||||
}
|
||||
|
||||
|
||||
func newRPointer (rtype reflect.Type) *rPointer {
|
||||
return &rPointer { elemPackFn: rTypePacker(rtype.Elem()) }
|
||||
}
|
||||
|
||||
|
||||
func (p rPointer) pack (s *packs.State, v reflect.Value, f packs.Flags) {
|
||||
if v.IsNil() {
|
||||
s.W(g.nullValue)
|
||||
return
|
||||
}
|
||||
s.Level++
|
||||
if s.Level > maxCyclesAfter {
|
||||
if fn,ok := s.CheckCycle(v.Interface()); ok {
|
||||
defer fn()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
p.elemPackFn(s,v.Elem(),f)
|
||||
s.Level--
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rpacker_value.go
|
||||
// Created by DEV
|
||||
// Modified 13/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 pjson
|
||||
|
||||
import (
|
||||
"packs"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func rValuePacker (rvalue reflect.Value) rPackerFnc {
|
||||
if !rvalue.IsValid() {
|
||||
return invalidValuePacker
|
||||
}
|
||||
return rTypePacker(rvalue.Type())
|
||||
}
|
||||
|
||||
|
||||
func invalidValuePacker(state *packs.State, _ reflect.Value, _ packs.Flags) {
|
||||
state.SetError(packs.G.ErrInvalidValue)
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name value_packer.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 packs
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
ValuePacker interface {
|
||||
|
||||
PackAny (value any, flags Flags)
|
||||
|
||||
PackRaw (value []byte, flags Flags)
|
||||
PackBinary (value []byte, flags Flags)
|
||||
PackString (value string, flags Flags)
|
||||
|
||||
PackBool (value bool, flags Flags)
|
||||
|
||||
PackInt8 (value int8, flags Flags)
|
||||
PackInt16 (value int16, flags Flags)
|
||||
PackInt32 (value int32, flags Flags)
|
||||
PackInt64 (value int64, flags Flags)
|
||||
|
||||
PackUInt8 (value uint8 , flags Flags)
|
||||
PackUInt16 (value uint16, flags Flags)
|
||||
PackUInt32 (value uint32, flags Flags)
|
||||
PackUInt64 (value uint64, flags Flags)
|
||||
|
||||
PackFloat32 (value float32, flags Flags)
|
||||
PackFloat64 (value float64, flags Flags)
|
||||
|
||||
PackDate (value time.Time, flags Flags)
|
||||
|
||||
PackList (flags Flags, builder func(ListPackBuilder, Flags))
|
||||
PackMap (flags Flags, builder func(MapPackBuilder, Flags))
|
||||
PackObject(flags Flags, builder func(ObjectPackBuilder,Flags))
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
module rets
|
||||
|
||||
go 1.22
|
||||
@ -0,0 +1,3 @@
|
||||
module rsts
|
||||
|
||||
go 1.22
|
||||
@ -0,0 +1,32 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err_timer.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 timers
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
|
||||
)
|
||||
@ -0,0 +1,83 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 times
|
||||
|
||||
import "errs"
|
||||
|
||||
const(
|
||||
|
||||
secondsDay = 24 * 60 * 60
|
||||
|
||||
)
|
||||
|
||||
|
||||
var (
|
||||
|
||||
G = struct {
|
||||
|
||||
ErrInvalidDateRange Err
|
||||
}{
|
||||
|
||||
ErrInvalidDateRange : Err{ errs.ErrCode ("invalid-date-range")},
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
func IsYearLeap (year int) bool {
|
||||
return year%4 == 0 && (year%100 != 0 || year%400 == 0) }
|
||||
|
||||
|
||||
func DaysInYear (year int) int {
|
||||
if IsYearLeap(year) {
|
||||
return 366 }
|
||||
return 365
|
||||
}
|
||||
|
||||
|
||||
func DaysIn (year, month int) int {
|
||||
if month <= 0 || month > 12 {
|
||||
return 0 }
|
||||
d := [12]int{ 31,28,31,30,31,30,31,30,31,30,31 }
|
||||
if month == 2 && IsYearLeap(year) {
|
||||
return 29 }
|
||||
return d[month]
|
||||
}
|
||||
|
||||
|
||||
func DayOfWeek (year, month, day int) int {
|
||||
if month < 3 {
|
||||
month += 12
|
||||
year--
|
||||
}
|
||||
J := year / 100
|
||||
K := year % 100
|
||||
h := (day + (13*(month+1))/5 + K + K/4 + J/4 + 5*J) % 7
|
||||
if h <= 1 {
|
||||
return h+6
|
||||
}
|
||||
return h-1
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name gogo.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 bdates
|
||||
|
||||
import "errs"
|
||||
|
||||
const(
|
||||
|
||||
minBYear int = 1900
|
||||
maxBYear int = 2155
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
|
||||
G = struct {
|
||||
ErrInvalidDay Err
|
||||
ErrInvalidMonth Err
|
||||
ErrInvalidYear Err
|
||||
}{
|
||||
ErrInvalidDay : Err{errs.ErrCode("invalid-day")},
|
||||
ErrInvalidMonth : Err{errs.ErrCode("invalid-month")},
|
||||
ErrInvalidYear : Err{errs.ErrCode("invalid-year")},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func checkDayNumber (day int) bool {
|
||||
return day >=1 && day <=7 }
|
||||
|
||||
|
||||
func checkMonthNumber(month int) bool {
|
||||
return month >=1 && month <=12 }
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bmonth.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 bdates
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
BMonth uint32
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,125 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name bweek.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 bdates
|
||||
|
||||
import "math/bits"
|
||||
|
||||
const(
|
||||
|
||||
BWeekDaysMon BWeekDays = 1 << iota
|
||||
BWeekDaysTue
|
||||
BWeekDaysWed
|
||||
BWeekDaysThu
|
||||
BWeekDaysFri
|
||||
BWeekDaysSat
|
||||
BWeekDaysSun
|
||||
|
||||
_BWeekFlag
|
||||
|
||||
BWeekDaysAll = 0x1111111
|
||||
|
||||
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
// BWeekDays
|
||||
// Type: uint8
|
||||
// Desc: Representa una lista de los dias de la semana
|
||||
// a través de un byte
|
||||
BWeekDays uint8
|
||||
|
||||
)
|
||||
|
||||
|
||||
func (w BWeekDays) GetFlag() bool {
|
||||
return w&_BWeekFlag==_BWeekFlag }
|
||||
|
||||
|
||||
func (w BWeekDays) SetFlag(val bool) BWeekDays {
|
||||
if val {
|
||||
return w|_BWeekFlag
|
||||
}
|
||||
return w&^_BWeekFlag
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (w BWeekDays) SetDay (num int, val bool) BWeekDays {
|
||||
if num < 0 || num > 7 {
|
||||
return w
|
||||
}
|
||||
if val {
|
||||
w |= 1 << num-1
|
||||
} else {
|
||||
w &^= 1 << num-1
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
|
||||
func (w BWeekDays) GetDay (num int) bool {
|
||||
if num < 0 || num > 7 {
|
||||
return false
|
||||
}
|
||||
c := BWeekDays(1 << num-1)
|
||||
return (w&c)==c
|
||||
}
|
||||
|
||||
|
||||
func (w BWeekDays) Invert () BWeekDays {
|
||||
return ^w }
|
||||
|
||||
|
||||
func (w BWeekDays) Count () int {
|
||||
return bits.OnesCount8(uint8(w)) }
|
||||
|
||||
|
||||
func (w BWeekDays) List () []int {
|
||||
c := BWeekDays(1)
|
||||
r := make([]int,0,7)
|
||||
for i:=1; i<=7; i++ {
|
||||
if c&w == c {
|
||||
r = append(r,i)
|
||||
}
|
||||
c <<=1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
func (w BWeekDays) ToSlice () []bool {
|
||||
c := BWeekDays(1)
|
||||
r := make([]bool,7)
|
||||
for i:=0; i<7; i++ {
|
||||
r[i]=c&w == c
|
||||
c <<=1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (w BWeekDays) Common (dst BWeekDays) BWeekDays { return w & dst }
|
||||
@ -0,0 +1,128 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name byear.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 bdates
|
||||
|
||||
import "times"
|
||||
|
||||
type (
|
||||
|
||||
BYear struct {
|
||||
atts BYearAtt
|
||||
first byte
|
||||
year byte
|
||||
months [12]BMonth
|
||||
}
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
func NewBYear (year int) *BYear {
|
||||
if year < minBYear || year > maxBYear {
|
||||
panic(G.ErrInvalidYear)
|
||||
}
|
||||
at := BYearAtt(BYearAttSet)
|
||||
if times.IsYearLeap(year) {
|
||||
at|=BYearAttLeap
|
||||
}
|
||||
return &BYear {
|
||||
atts : at,
|
||||
first: byte(times.DayOfWeek(year,1,1)),
|
||||
year : byte(year-1900),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (y *BYear) Atts () BYearAtt {
|
||||
return y.atts }
|
||||
|
||||
func (y *BYear) First () int {
|
||||
return int(y.first) }
|
||||
|
||||
func (y *BYear) Year () int {
|
||||
return minBYear + int(y.year) }
|
||||
|
||||
|
||||
func (y *BYear) Clear (month ...int) {
|
||||
if len(month) == 0 {
|
||||
for i := 0; i < 12; i++ {
|
||||
y.months[i] = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
for _,i := range month {
|
||||
if !checkMonthNumber(i){
|
||||
panic(G.ErrInvalidMonth)
|
||||
}
|
||||
y.months[i]=0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (y *BYear) GetDay (month, day int) bool {
|
||||
if !checkMonthNumber(month) {
|
||||
panic(G.ErrInvalidMonth )
|
||||
}
|
||||
if day < 1 || day > y.daysInMonth(month) {
|
||||
panic(G.ErrInvalidDay)
|
||||
}
|
||||
return (uint32(1 << day) & uint32(y.months[month])) != 0
|
||||
}
|
||||
|
||||
func (y *BYear) SetDay (month, day int, active bool) {
|
||||
if !checkMonthNumber(month) {
|
||||
panic(G.ErrInvalidMonth )
|
||||
}
|
||||
if day < 1 || day > y.daysInMonth(month) {
|
||||
panic(G.ErrInvalidDay)
|
||||
}
|
||||
month-=1
|
||||
if active {
|
||||
y.months[month] = y.months[month] | BMonth(1 << day)
|
||||
return
|
||||
}
|
||||
y.months[month] = y.months[month] &^ BMonth(1 << day)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (y *BYear) GetMonth (month int) BMonth {
|
||||
if !checkMonthNumber(month) {
|
||||
panic(G.ErrInvalidMonth)
|
||||
}
|
||||
return y.months[month-1]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (y BYear) daysInMonth (month int) int {
|
||||
d := [12]int{ 31,28,31,30,31,30,31,30,31,30,31 }
|
||||
if month == 2 && y.Atts().IsLeap() {
|
||||
return 29
|
||||
}
|
||||
return d[month-1]
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name byear_att.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 bdates
|
||||
|
||||
|
||||
const(
|
||||
|
||||
BYearAttSet BYearAtt = iota << 1
|
||||
BYearAttLeap
|
||||
|
||||
)
|
||||
|
||||
|
||||
type BYearAtt byte
|
||||
|
||||
|
||||
func (a BYearAtt) IsSet () bool {
|
||||
return a&BYearAttSet != 0 }
|
||||
|
||||
|
||||
func (a BYearAtt) IsLeap () bool {
|
||||
return a&BYearAttLeap != 0 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err_bdates.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 bdates
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name days.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 times
|
||||
|
||||
import "time"
|
||||
|
||||
|
||||
type (
|
||||
|
||||
DateDays int32
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
func (d DateDays) AddDate(years, months, days int) DateDays {
|
||||
return TimeToDays(d.ToTime().AddDate(years,months,days)) }
|
||||
|
||||
|
||||
func (d DateDays) ToTime() time.Time {
|
||||
return DaysToTime(d) }
|
||||
|
||||
func (d DateDays) Before (days DateDays) bool {
|
||||
return d < days }
|
||||
|
||||
func (d DateDays) After (days DateDays) bool {
|
||||
return d > days }
|
||||
|
||||
func (d DateDays) Compare(days DateDays) int {
|
||||
if d < days {
|
||||
return -1 }
|
||||
if d == days {
|
||||
return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
func (d DateDays) Min (days DateDays) DateDays {
|
||||
if d > days {
|
||||
return days
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d DateDays) Max (days DateDays) DateDays {
|
||||
if d < days {
|
||||
return days
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func TimeToDays (time time.Time) DateDays {
|
||||
_,x := time.Zone()
|
||||
s := time.Unix() + int64(x)
|
||||
if s >= 0 {
|
||||
return DateDays(s/ secondsDay) }
|
||||
return -DateDays((secondsDay -1 -s)/ secondsDay)
|
||||
}
|
||||
|
||||
|
||||
func DaysToTime(days DateDays) time.Time {
|
||||
return time.Unix(int64(days) *secondsDay,0).UTC() }
|
||||
|
||||
|
||||
/*
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
|
||||
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
|
||||
|
||||
SIDDHARTA
|
||||
- HERMANN HESSE -
|
||||
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
*/
|
||||
@ -0,0 +1,94 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name date_days_range.go
|
||||
// Created by DEV
|
||||
// Modified 21/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 times
|
||||
|
||||
type (
|
||||
|
||||
DateDaysRange struct {
|
||||
Start DateDays
|
||||
End DateDays
|
||||
}
|
||||
|
||||
|
||||
DateDaysRangeFnc func(daysRange *DateDaysRange)
|
||||
)
|
||||
|
||||
func NewDateRange (options ...DateDaysRangeFnc) *DateDaysRange {
|
||||
dr := &DateDaysRange{}
|
||||
for _,o := range options {
|
||||
o(dr)
|
||||
}
|
||||
return dr
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (r DateDaysRange) IsZero () bool {
|
||||
return r.End-r.Start <= 0 }
|
||||
|
||||
|
||||
func (r DateDaysRange) Size () DateDays {
|
||||
return DateDays(r.End -r.Start) }
|
||||
|
||||
|
||||
func (r DateDaysRange) Contains (days DateDays) bool {
|
||||
if r.IsZero() {
|
||||
return false }
|
||||
return r.Start < days && r.End > days
|
||||
}
|
||||
|
||||
|
||||
func (r DateDaysRange) ContainsRange (drange DateDaysRange) bool {
|
||||
if r.IsZero() {
|
||||
return false }
|
||||
return r.Start > drange.Start && r.End < drange.End
|
||||
}
|
||||
|
||||
|
||||
func (r DateDaysRange) IsRangeOverlap (drange DateDaysRange) bool {
|
||||
if r.IsZero() {
|
||||
return false }
|
||||
if r.Start == drange.Start || r.Start == drange.End || r.End == drange.End {
|
||||
return true }
|
||||
if r.Start > drange.Start {
|
||||
return drange.End < r.End
|
||||
}
|
||||
return r.End > drange.Start
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
|
||||
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
|
||||
|
||||
SIDDHARTA
|
||||
- HERMANN HESSE -
|
||||
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
*/
|
||||
@ -0,0 +1,83 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rkey.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 times
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
DurationFormatter interface {
|
||||
|
||||
FormatDuration (dur time.Duration, dst []byte) []byte
|
||||
}
|
||||
|
||||
|
||||
FormatDurationFnc func (dur time.Duration, dst []byte) []byte
|
||||
|
||||
)
|
||||
|
||||
|
||||
func (f FormatDurationFnc) FormatDuration (dur time.Duration, dst []byte) []byte {
|
||||
return f(dur,dst) }
|
||||
|
||||
|
||||
func WrapDurationFormatterQuoted (dfm DurationFormatter, qte byte) DurationFormatter {
|
||||
return FormatDurationFnc(func(tme time.Duration, dst []byte) []byte {
|
||||
dst = append(dst, qte)
|
||||
dst = dfm.FormatDuration(tme, dst)
|
||||
return append(dst, qte)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func DurationMillis (dur time.Duration, dst []byte) []byte {
|
||||
return strconv.AppendFloat(dst, float64(dur)/float64(time.Millisecond), 'f', -1, 64) }
|
||||
|
||||
|
||||
|
||||
func DurationNanos(dur time.Duration, dst []byte) []byte {
|
||||
return strconv.AppendInt(dst, int64(dur), 10) }
|
||||
|
||||
|
||||
|
||||
func DurationSecs(dur time.Duration, dst []byte) []byte {
|
||||
return strconv.AppendFloat(dst, float64(dur)/float64(time.Second), 'f', -1, 64) }
|
||||
|
||||
/*
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
|
||||
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
|
||||
|
||||
SIDDHARTA
|
||||
- HERMANN HESSE -
|
||||
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
*/
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 times
|
||||
|
||||
import "errs"
|
||||
|
||||
type (
|
||||
|
||||
Err struct { errs.ErrCode }
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
module times
|
||||
|
||||
|
||||
|
||||
go 1.20
|
||||
@ -0,0 +1,145 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project atila
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name rkey.go
|
||||
// Created by DEV
|
||||
// Modified 05/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 times
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
|
||||
TimeFormatter interface {
|
||||
|
||||
FormatTime (tme time.Time, dst []byte) []byte
|
||||
}
|
||||
|
||||
|
||||
FormatTimeFnc func (tme time.Time, dst []byte) []byte
|
||||
|
||||
)
|
||||
|
||||
|
||||
func (f FormatTimeFnc) FormatTime (tme time.Time, dst []byte) []byte {
|
||||
return f(tme,dst) }
|
||||
|
||||
|
||||
|
||||
|
||||
func WrapTimeFormatterQuoted (tmf TimeFormatter, qte byte) TimeFormatter {
|
||||
return FormatTimeFnc(func(tme time.Time, dst []byte) []byte {
|
||||
dst = append(dst, qte)
|
||||
dst = tmf.FormatTime(tme, dst)
|
||||
return append(dst, qte)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func TimeRFC3339Nano(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC3339Nano) }
|
||||
|
||||
|
||||
func TimeANSIC(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.ANSIC) }
|
||||
|
||||
|
||||
func TimeUnixDate(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.UnixDate) }
|
||||
|
||||
|
||||
func TimeRubyDate(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RubyDate) }
|
||||
|
||||
|
||||
func TimeRFC822(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC822) }
|
||||
|
||||
|
||||
func TimeRFC822Z(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC822Z) }
|
||||
|
||||
|
||||
func TimeRFC850(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC850) }
|
||||
|
||||
|
||||
func TimeRFC1123(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC1123) }
|
||||
|
||||
|
||||
func TimeRFC1123Z(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC1123Z) }
|
||||
|
||||
|
||||
func TimeRFC3339(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.RFC3339) }
|
||||
|
||||
|
||||
func TimeKitchen(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.Kitchen) }
|
||||
|
||||
|
||||
func TimeISO8601(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, "2006-01-02T15:04:05.000Z0700") }
|
||||
|
||||
|
||||
|
||||
func TimeEpoch(tme time.Time, dst []byte) []byte {
|
||||
return strconv.AppendFloat(dst, float64(tme.UnixNano())/float64(time.Second), 'f', -1, 64) }
|
||||
|
||||
|
||||
func TimeEpochMillis(tme time.Time, dst []byte) []byte {
|
||||
return strconv.AppendFloat(dst, float64(tme.UnixNano())/float64(time.Millisecond), 'f', -1, 64) }
|
||||
|
||||
|
||||
func TimeStamp(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.Stamp) }
|
||||
|
||||
|
||||
func TimeStampMilli(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.StampMilli) }
|
||||
|
||||
|
||||
func TimeStampMicro(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.StampMicro) }
|
||||
|
||||
|
||||
func TimeStampNano(tme time.Time, dst []byte) []byte {
|
||||
return tme.AppendFormat(dst, time.StampNano) }
|
||||
|
||||
|
||||
/*
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
|
||||
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
|
||||
|
||||
SIDDHARTA
|
||||
- HERMANN HESSE -
|
||||
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
*/
|
||||
@ -0,0 +1,33 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err.go
|
||||
// Created by DEV
|
||||
// Modified 20/04/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 vals
|
||||
|
||||
import "errs"
|
||||
|
||||
|
||||
|
||||
|
||||
type Err struct { errs.ErrCode }
|
||||
|
||||
|
||||
Loading…
Reference in new issue