dt_automate/vendor/github.com/Andrew-M-C/go.jsonvalue/new.go
2025-02-27 10:48:32 +08:00

274 lines
8.5 KiB
Go

package jsonvalue
import (
"encoding/base64"
"fmt"
"math"
"reflect"
"strconv"
)
// New generate a new jsonvalue type via given type. If given type is not supported,
// the returned type would equal to NotExist. If you are not sure whether given value
// type is OK in runtime, use Import() instead.
//
// New 函数按照给定参数类型创建一个 jsonvalue 类型。如果给定参数不是 JSON 支持的类型, 那么返回的
// *V 对象的类型为 NotExist。如果在代码中无法确定入参是否是 JSON 支持的类型, 请改用函数
// Import()。
func New(value any) *V {
v, _ := Import(value)
return v
}
// NewString returns an initialized string jsonvalue object
//
// NewString 用给定的 string 返回一个初始化好的字符串类型的 jsonvalue 值
func NewString(s string) *V {
v := new(globalPool{}, String)
v.valueStr = s
return v
}
// NewBytes returns an initialized string with Base64 string by given bytes
//
// NewBytes 用给定的字节串,返回一个初始化好的字符串类型的 jsonvalue 值,内容是字节串 Base64 之后的字符串。
func NewBytes(b []byte) *V {
s := base64.StdEncoding.EncodeToString(b)
return NewString(s)
}
// NewInt64 returns an initialized num jsonvalue object by int64 type
//
// NewInt64 用给定的 int64 返回一个初始化好的数字类型的 jsonvalue 值
func NewInt64(i int64) *V {
v := new(globalPool{}, Number)
// v.num = &num{}
v.num.floated = false
v.num.negative = i < 0
v.num.f64 = float64(i)
v.num.i64 = i
v.num.u64 = uint64(i)
s := strconv.FormatInt(v.num.i64, 10)
v.srcByte = []byte(s)
return v
}
// NewUint64 returns an initialized num jsonvalue object by uint64 type
//
// NewUint64 用给定的 uint64 返回一个初始化好的数字类型的 jsonvalue 值
func NewUint64(u uint64) *V {
v := new(globalPool{}, Number)
// v.num = &num{}
v.num.floated = false
v.num.negative = false
v.num.f64 = float64(u)
v.num.i64 = int64(u)
v.num.u64 = u
s := strconv.FormatUint(v.num.u64, 10)
v.srcByte = []byte(s)
return v
}
// NewInt returns an initialized num jsonvalue object by int type
//
// NewInt 用给定的 int 返回一个初始化好的数字类型的 jsonvalue 值
func NewInt(i int) *V {
return NewInt64(int64(i))
}
// NewUint returns an initialized num jsonvalue object by uint type
//
// NewUint 用给定的 uint 返回一个初始化好的数字类型的 jsonvalue 值
func NewUint(u uint) *V {
return NewUint64(uint64(u))
}
// NewInt32 returns an initialized num jsonvalue object by int32 type
//
// NewInt32 用给定的 int32 返回一个初始化好的数字类型的 jsonvalue 值
func NewInt32(i int32) *V {
return NewInt64(int64(i))
}
// NewUint32 returns an initialized num jsonvalue object by uint32 type
//
// NewUint32 用给定的 uint32 返回一个初始化好的数字类型的 jsonvalue 值
func NewUint32(u uint32) *V {
return NewUint64(uint64(u))
}
// NewBool returns an initialized boolean jsonvalue object
//
// NewBool 用给定的 bool 返回一个初始化好的布尔类型的 jsonvalue 值
func NewBool(b bool) *V {
v := new(globalPool{}, Boolean)
v.valueBool = b
return v
}
// NewNull returns an initialized null jsonvalue object
//
// NewNull 返回一个初始化好的 null 类型的 jsonvalue 值
func NewNull() *V {
v := new(globalPool{}, Null)
return v
}
// NewObject returns an object-typed jsonvalue object. If keyValues is specified, it will also create some key-values in
// the object. Now we supports basic types only. Such as int/uint, int/int8/int16/int32/int64,
// uint/uint8/uint16/uint32/uint64 series, string, bool, nil.
//
// NewObject 返回一个初始化好的 object 类型的 jsonvalue 值。可以使用可选的 map[string]any 类型参数初始化该 object 的下一级键值对,
// 不过目前只支持基础类型,也就是: int/uint, int/int8/int16/int32/int64, uint/uint8/uint16/uint32/uint64, string, bool, nil。
func NewObject(keyValues ...M) *V {
v := newObject(globalPool{})
if len(keyValues) > 0 {
kv := keyValues[0]
if kv != nil {
parseNewObjectKV(v, kv)
}
}
return v
}
// M is the alias of map[string]any
type M map[string]any
func parseNewObjectKV(v *V, kv M) {
for k, val := range kv {
rv := reflect.ValueOf(val)
switch rv.Kind() {
case reflect.Invalid:
v.MustSetNull().At(k)
case reflect.Bool:
v.MustSetBool(rv.Bool()).At(k)
case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
v.MustSetInt64(rv.Int()).At(k)
case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
v.MustSetUint64(rv.Uint()).At(k)
case reflect.Float32, reflect.Float64:
v.MustSetFloat64(rv.Float()).At(k)
case reflect.String:
v.MustSetString(rv.String()).At(k)
// case reflect.Map:
// if rv.Type().Key().Kind() == reflect.String && rv.Type().Elem().Kind() == reflect.Interface {
// if m, ok := rv.Interface().(M); ok {
// sub := NewObject(m)
// if sub != nil {
// v.Set(sub).At(k)
// }
// }
// }
default:
// continue
}
}
}
// NewArray returns an empty array-typed jsonvalue object
//
// NewArray 返回一个初始化好的 array 类型的 jsonvalue 值。
func NewArray() *V {
return newArray(globalPool{})
}
// NewFloat64 returns an initialized num jsonvalue value by float64 type. The format and precision control is the same
// with encoding/json: https://github.com/golang/go/blob/master/src/encoding/json/encode.go#L575
//
// NewFloat64 根据指定的 flout64 类型返回一个初始化好的数字类型的 jsonvalue 值。数字转出来的字符串格式参照 encoding/json 中的逻辑。
func NewFloat64(f float64) *V {
abs := math.Abs(f)
format := byte('f')
if abs < 1e-6 || abs >= 1e21 {
format = byte('e')
}
return newFloat64f(globalPool{}, f, format, -1, 64)
}
// NewFloat64f returns an initialized num jsonvalue value by float64 type. The format and prec parameter are used in
// strconv.FormatFloat(). Only 'f', 'E', 'e', 'G', 'g' formats are supported, other formats will be mapped to 'g'.
//
// NewFloat64f 根据指定的 float64 类型返回一个初始化好的数字类型的 jsonvalue 值。其中参数 format 和 prec 分别用于
// strconv.FormatFloat() 函数. 只有 'f'、'E'、'e'、'G'、'g' 格式是支持的,其他配置均统一映射为 'g'。
func NewFloat64f(f float64, format byte, prec int) *V {
if err := validateFloat64Format(format); err != nil {
format = 'g'
}
return newFloat64f(globalPool{}, f, format, prec, 64)
}
// NewFloat32 returns an initialized num jsonvalue value by float32 type. The format and precision control is the same
// with encoding/json: https://github.com/golang/go/blob/master/src/encoding/json/encode.go#L575
//
// NewFloat32 根据指定的 float32 类型返回一个初始化好的数字类型的 jsonvalue 值。数字转出来的字符串格式参照 encoding/json 中的逻辑。
func NewFloat32(f float32) *V {
f64 := float64(f)
abs := math.Abs(f64)
format := byte('f')
if abs < 1e-6 || abs >= 1e21 {
format = byte('e')
}
return newFloat64f(globalPool{}, f64, format, -1, 32)
}
// NewFloat32f returns an initialized num jsonvalue value by float64 type. The format and prec parameter are used in
// strconv.FormatFloat(). Only 'f', 'E', 'e', 'G', 'g' formats are supported, other formats will be mapped to 'g'.
//
// NewFloat32f 根据指定的 float64 类型返回一个初始化好的数字类型的 jsonvalue 值。其中参数 format 和 prec 分别用于
// strconv.FormatFloat() 函数. 只有 'f'、'E'、'e'、'G'、'g' 格式是支持的,其他配置均统一映射为 'g'。
func NewFloat32f(f float32, format byte, prec int) *V {
if err := validateFloat64Format(format); err != nil {
format = 'g'
}
return newFloat64f(globalPool{}, float64(f), format, prec, 64)
}
// -------- internal functions --------
func new(p pool, t ValueType) *V {
v := pool.get(p)
v.valueType = t
return v
}
func newObject(p pool) *V {
v := new(p, Object)
v.children.object = make(map[string]childWithProperty)
v.children.lowerCaseKeys = nil
return v
}
func newArray(p pool) *V {
v := new(p, Array)
return v
}
func newFloat64f(p pool, f float64, format byte, prec, bitSize int) *V {
v := new(p, Number)
// v.num = &num{}
v.num.negative = f < 0
v.num.f64 = f
v.num.i64 = int64(f)
v.num.u64 = uint64(f)
if isValidFloat(f) {
s := strconv.FormatFloat(f, format, prec, bitSize)
v.srcByte = []byte(s)
}
return v
}
func validateFloat64Format(f byte) error {
switch f {
case 'f', 'E', 'e', 'G', 'g':
return nil
default:
return fmt.Errorf("unsupported float value in option: %c", f)
}
}