// ------------------------------------------------------------------------ // 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 }