diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-kv/v2/format')
| -rw-r--r-- | vendor/codeberg.org/gruf/go-kv/v2/format/abi.go | 45 | ||||
| -rw-r--r-- | vendor/codeberg.org/gruf/go-kv/v2/format/format.go | 123 | ||||
| -rw-r--r-- | vendor/codeberg.org/gruf/go-kv/v2/format/methods.go | 8 |
3 files changed, 128 insertions, 48 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go b/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go index 815660a5e..b68d3cb73 100644 --- a/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go +++ b/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go @@ -1,4 +1,4 @@ -//go:build go1.24 && !go1.25 +//go:build go1.24 && !go1.26 package format @@ -39,26 +39,36 @@ type abi_EmptyInterface struct { Data unsafe.Pointer } +// abi_NonEmptyInterface is a copy of the memory layout of abi.NonEmptyInterface{}, +// which is to say also the memory layout of any interface containing method(s). +// +// see: go/src/internal/abi/iface.go on 1.25+ +// see: go/src/reflect/value.go on 1.24 +type abi_NonEmptyInterface struct { + ITab uintptr + Data unsafe.Pointer +} + // see: go/src/internal/abi/type.go Type.Kind() func abi_Type_Kind(t reflect.Type) uint8 { - iface := (*reflect_nonEmptyInterface)(unsafe.Pointer(&t)) - atype := (*abi_Type)(unsafe.Pointer(iface.word)) + iface := (*abi_NonEmptyInterface)(unsafe.Pointer(&t)) + atype := (*abi_Type)(unsafe.Pointer(iface.Data)) return atype.Kind_ & abi_KindMask } // see: go/src/internal/abi/type.go Type.IfaceIndir() func abi_Type_IfaceIndir(t reflect.Type) bool { - iface := (*reflect_nonEmptyInterface)(unsafe.Pointer(&t)) - atype := (*abi_Type)(unsafe.Pointer(iface.word)) + iface := (*abi_NonEmptyInterface)(unsafe.Pointer(&t)) + atype := (*abi_Type)(unsafe.Pointer(iface.Data)) return atype.Kind_&abi_KindDirectIface == 0 } -// pack_iface packs a new reflect.nonEmptyInterface{} using shielded itab -// pointer and data (word) pointer, returning a pointer for caller casting. +// pack_iface packs a new reflect.nonEmptyInterface{} using shielded +// itab and data pointer, returning a pointer for caller casting. func pack_iface(itab uintptr, word unsafe.Pointer) unsafe.Pointer { - return unsafe.Pointer(&reflect_nonEmptyInterface{ - itab: itab, - word: word, + return unsafe.Pointer(&abi_NonEmptyInterface{ + ITab: itab, + Data: word, }) } @@ -68,8 +78,8 @@ func pack_iface(itab uintptr, word unsafe.Pointer) unsafe.Pointer { // this is useful for later calls to pack_iface for known type. func get_iface_ITab[I any](t reflect.Type) uintptr { s := reflect.New(t).Elem().Interface().(I) - i := (*reflect_nonEmptyInterface)(unsafe.Pointer(&s)) - return i.itab + i := (*abi_NonEmptyInterface)(unsafe.Pointer(&s)) + return i.ITab } // unpack_eface returns the .Data portion of an abi.EmptyInterface{}. @@ -162,15 +172,6 @@ func reflect_map_elem_flags(elemType reflect.Type) reflect_flag { return reflect_flag(abi_Type_Kind(elemType)) } -// reflect_nonEmptyInterface is a copy of the memory layout of reflect.nonEmptyInterface, -// which is also to say the memory layout of any non-empty (i.e. w/ method) interface. -// -// see: go/src/reflect/value.go -type reflect_nonEmptyInterface struct { - itab uintptr - word unsafe.Pointer -} - // reflect_Value is a copy of the memory layout of reflect.Value{}. // // see: go/src/reflect/value.go @@ -190,7 +191,7 @@ func init() { // as the reflect.nonEmptyInterface{}, which itself will be a pointer // to the actual abi.Type{} that this reflect.Type{} is wrapping. func reflect_type_data(t reflect.Type) unsafe.Pointer { - return (*reflect_nonEmptyInterface)(unsafe.Pointer(&t)).word + return (*abi_NonEmptyInterface)(unsafe.Pointer(&t)).Data } // build_reflect_value manually builds a reflect.Value{} by setting the internal field members. diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/format.go b/vendor/codeberg.org/gruf/go-kv/v2/format/format.go index 2ab62eb06..69edcb597 100644 --- a/vendor/codeberg.org/gruf/go-kv/v2/format/format.go +++ b/vendor/codeberg.org/gruf/go-kv/v2/format/format.go @@ -8,6 +8,9 @@ import ( "unsafe" ) +// Global formatter instance. +var Global Formatter + // FormatFunc defines a function capable of formatting // the value contained in State{}.P, based on args in // State{}.A, storing the result in buffer State{}.B. @@ -48,7 +51,7 @@ const ringsz = 16 // ptr_ring is a ring buffer of pointers, // purposely stored as uintptrs as all we -// need them for is value comparisons and +// need them for is integer comparisons and // we don't want to hold-up the GC. type ptr_ring struct { p [ringsz]uintptr @@ -296,38 +299,60 @@ func (fmt *Formatter) get(t typenode) (fn FormatFunc) { func (fmt *Formatter) getInterfaceType(t typenode) FormatFunc { if t.rtype.NumMethod() == 0 { return func(s *State) { + // Unpack empty interface. eface := *(*any)(s.P) s.P = unpack_eface(eface) + + // Get reflected type information. rtype := reflect.TypeOf(eface) if rtype == nil { appendNil(s) return } + + // Check for ptr recursion. if s.ifaces.contains(s.P) { getPointerType(t)(s) return } + + // Store value ptr. s.ifaces.set(s.P) + + // Wrap in our typenode for before load. flags := reflect_iface_elem_flags(rtype) t := new_typenode(rtype, flags) + + // Load + pass to func. fmt.loadOrStore(t)(s) } } else { return func(s *State) { + // Unpack interface-with-method ptr. iface := *(*interface{ M() })(s.P) s.P = unpack_eface(iface) + + // Get reflected type information. rtype := reflect.TypeOf(iface) if rtype == nil { appendNil(s) return } + + // Check for ptr recursion. if s.ifaces.contains(s.P) { getPointerType(t)(s) return } + + // Store value ptr. s.ifaces.set(s.P) + + // Wrap in our typenode for before load. flags := reflect_iface_elem_flags(rtype) t := new_typenode(rtype, flags) + + // Load + pass to func. fmt.loadOrStore(t)(s) } } @@ -360,14 +385,11 @@ func getIntType(t typenode) FormatFunc { switch { case s.A.AsNumber(): // fallthrough - case s.A.AsQuotedText(): - s.B = strconv.AppendQuoteRune(s.B, *(*rune)(s.P)) - return case s.A.AsQuotedASCII(): s.B = strconv.AppendQuoteRuneToASCII(s.B, *(*rune)(s.P)) return - case s.A.AsText(): - s.B = AppendEscapeRune(s.B, *(*rune)(s.P)) + case s.A.AsText() || s.A.AsQuotedText(): + s.B = strconv.AppendQuoteRune(s.B, *(*rune)(s.P)) return } appendInt(s, int64(*(*int32)(s.P))) @@ -388,12 +410,9 @@ func getUintType(t typenode) FormatFunc { switch { case s.A.AsNumber(): // fallthrough - case s.A.AsQuotedText() || s.A.AsQuotedASCII(): + case s.A.AsText() || s.A.AsQuotedText() || s.A.AsQuotedASCII(): s.B = AppendQuoteByte(s.B, *(*byte)(s.P)) return - case s.A.AsText(): - s.B = AppendEscapeByte(s.B, *(*byte)(s.P)) - return } appendUint(s, uint64(*(*uint8)(s.P))) }) @@ -468,10 +487,17 @@ func with_typestr_ptrs(t typenode, fn FormatFunc) FormatFunc { if fn == nil { panic("nil func") } + + // Check for type wrapping. if !t.needs_typestr() { return fn } + + // Get type string with pointers. typestr := t.typestr_with_ptrs() + + // Wrap format func to include + // type information when needed. return func(s *State) { if s.A.WithType() { s.B = append(s.B, "("+typestr+")("...) @@ -485,7 +511,22 @@ func with_typestr_ptrs(t typenode, fn FormatFunc) FormatFunc { func appendString(s *State, v string) { switch { - case s.A.Logfmt() || s.A.WithType(): + case s.A.WithType(): + if len(v) > SingleTermLine || !IsSafeASCII(v) { + // Requires quoting AND escaping + s.B = strconv.AppendQuote(s.B, v) + } else if ContainsDoubleQuote(v) { + // Contains double quotes, needs escaping + s.B = append(s.B, '"') + s.B = AppendEscape(s.B, v) + s.B = append(s.B, '"') + } else { + // All else, needs quotes + s.B = append(s.B, '"') + s.B = append(s.B, v...) + s.B = append(s.B, '"') + } + case s.A.Logfmt(): if len(v) > SingleTermLine || !IsSafeASCII(v) { // Requires quoting AND escaping s.B = strconv.AppendQuote(s.B, v) @@ -494,8 +535,7 @@ func appendString(s *State, v string) { s.B = append(s.B, '"') s.B = AppendEscape(s.B, v) s.B = append(s.B, '"') - } else if s.A.WithType() || - len(v) == 0 || ContainsSpaceOrTab(v) { + } else if len(v) == 0 || ContainsSpaceOrTab(v) { // Contains space / empty, needs quotes s.B = append(s.B, '"') s.B = append(s.B, v...) @@ -515,75 +555,114 @@ func appendString(s *State, v string) { func appendInt(s *State, v int64) { args := s.A.Int + + // Set argument defaults. if args == zeroArgs.Int { args = defaultArgs.Int } + + // Add any padding. if args.Pad > 0 { const zeros = `00000000000000000000` if args.Pad > len(zeros) { panic("cannot pad > " + zeros) } + if v == 0 { s.B = append(s.B, zeros[:args.Pad]...) return } + + // Get absolute. abs := abs64(v) + + // Get number of required chars. chars := int(v / int64(args.Base)) if v%int64(args.Base) != 0 { chars++ } + if abs != v { + // If this is a negative value, + // prepend minus ourselves and + // set value as the absolute. s.B = append(s.B, '-') v = abs } - if n := args.Pad - chars; n > 0 { - s.B = append(s.B, zeros[:n]...) - } + + // Prepend required zeros. + n := args.Pad - chars + s.B = append(s.B, zeros[:n]...) } + + // Append value as signed integer w/ args. s.B = strconv.AppendInt(s.B, v, args.Base) } func appendUint(s *State, v uint64) { args := s.A.Int + + // Set argument defaults. if args == zeroArgs.Int { args = defaultArgs.Int } + + // Add any padding. if args.Pad > 0 { const zeros = `00000000000000000000` if args.Pad > len(zeros) { panic("cannot pad > " + zeros) } + if v == 0 { s.B = append(s.B, zeros[:args.Pad]...) return } + + // Get number of required chars. chars := int(v / uint64(args.Base)) if v%uint64(args.Base) != 0 { chars++ } - if n := args.Pad - chars; n > 0 { - s.B = append(s.B, zeros[:n]...) - } + + // Prepend required zeros. + n := args.Pad - chars + s.B = append(s.B, zeros[:n]...) } + + // Append value as unsigned integer w/ args. s.B = strconv.AppendUint(s.B, v, args.Base) } func appendFloat(s *State, v float64, bits int) { args := s.A.Float + + // Set argument defaults. if args == zeroArgs.Float { args = defaultArgs.Float } - s.B = strconv.AppendFloat(s.B, float64(v), args.Fmt, args.Prec, bits) + + // Append value as float${bit} w/ args. + s.B = strconv.AppendFloat(s.B, float64(v), + args.Fmt, args.Prec, bits) } func appendComplex(s *State, r, i float64, bits int) { args := s.A.Complex + + // Set argument defaults. if args == zeroArgs.Complex { args = defaultArgs.Complex } - s.B = strconv.AppendFloat(s.B, float64(r), args.Real.Fmt, args.Real.Prec, bits) + + // Append real value as float${bit} w/ args. + s.B = strconv.AppendFloat(s.B, float64(r), + args.Real.Fmt, args.Real.Prec, bits) s.B = append(s.B, '+') - s.B = strconv.AppendFloat(s.B, float64(i), args.Imag.Fmt, args.Imag.Prec, bits) + + // Append imag value as float${bit} w/ args. + s.B = strconv.AppendFloat(s.B, float64(i), + args.Imag.Fmt, args.Imag.Prec, bits) s.B = append(s.B, 'i') } diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go b/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go index 7c1795771..fcbffd3a4 100644 --- a/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go +++ b/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go @@ -45,7 +45,7 @@ func getInterfaceStringerType(t typenode) FormatFunc { case true: return with_typestr_ptrs(t, func(s *State) { s.P = *(*unsafe.Pointer)(s.P) - if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil { + if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil { appendNil(s) return } @@ -54,7 +54,7 @@ func getInterfaceStringerType(t typenode) FormatFunc { }) case false: return with_typestr_ptrs(t, func(s *State) { - if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil { + if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil { appendNil(s) return } @@ -102,7 +102,7 @@ func getInterfaceErrorType(t typenode) FormatFunc { case true: return with_typestr_ptrs(t, func(s *State) { s.P = *(*unsafe.Pointer)(s.P) - if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil { + if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil { appendNil(s) return } @@ -111,7 +111,7 @@ func getInterfaceErrorType(t typenode) FormatFunc { }) case false: return with_typestr_ptrs(t, func(s *State) { - if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil { + if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil { appendNil(s) return } |
