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

202 lines
4.8 KiB
Go

package jsonvalue
import (
"fmt"
"reflect"
"github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
)
func formatBool(b bool) string {
if b {
return "true"
}
return "false"
}
// reference:
// - [UTF-16](https://zh.wikipedia.org/zh-cn/UTF-16)
// - [JavaScript has a Unicode problem](https://mathiasbynens.be/notes/javascript-unicode)
// - [Meaning of escaped unicode characters in JSON](https://stackoverflow.com/questions/21995410/meaning-of-escaped-unicode-characters-in-json)
func escapeGreaterUnicodeToBuffByUTF16(r rune, buf buffer.Buffer) {
if r <= '\uffff' {
_, _ = buf.WriteString(fmt.Sprintf("\\u%04X", r))
return
}
// if r > 0x10FFFF {
// // invalid unicode
// buf.WriteRune(r)
// return
// }
r = r - 0x10000
lo := r & 0x003FF
hi := (r & 0xFFC00) >> 10
_, _ = buf.WriteString(fmt.Sprintf("\\u%04X", hi+0xD800))
_, _ = buf.WriteString(fmt.Sprintf("\\u%04X", lo+0xDC00))
}
func escapeGreaterUnicodeToBuffByUTF8(r rune, buf buffer.Buffer) {
// Comments below are copied from encoding/json:
//
// U+2028 is LINE SEPARATOR.
// U+2029 is PARAGRAPH SEPARATOR.
// They are both technically valid characters in JSON strings,
// but don't work in JSONP, which has to be evaluated as JavaScript,
// and can lead to security holes there. It is valid JSON to
// escape them, so we do so unconditionally.
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
if r == '\u2028' || r == '\u2029' {
escapeGreaterUnicodeToBuffByUTF16(r, buf)
} else {
_, _ = buf.WriteRune(r)
}
}
func escapeNothing(b byte, buf buffer.Buffer) {
_ = buf.WriteByte(b)
}
func escAsciiControlChar(b byte, buf buffer.Buffer) {
upper := b >> 4
lower := b & 0x0F
writeChar := func(c byte) {
if c < 0xA {
_ = buf.WriteByte('0' + c)
} else {
_ = buf.WriteByte('A' + (c - 0xA))
}
}
_, _ = buf.Write([]byte{'\\', 'u', '0', '0'})
writeChar(upper)
writeChar(lower)
}
func escDoubleQuote(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', '"'})
}
func escSlash(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', '/'})
}
func escBackslash(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', '\\'})
}
func escBackspace(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'b'})
}
func escVertTab(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'f'})
}
func escTab(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 't'})
}
func escNewLine(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'n'})
}
func escReturn(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'r'})
}
func escLeftAngle(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'u', '0', '0', '3', 'C'})
}
func escRightAngle(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'u', '0', '0', '3', 'E'})
}
func escAnd(_ byte, buf buffer.Buffer) {
_, _ = buf.Write([]byte{'\\', 'u', '0', '0', '2', '6'})
}
// func escPercent(_ byte, buf buffer.Buffer) {
// buf.Write([]byte{'\\', 'u', '0', '0', '2', '5'})
// }
func escapeStringToBuff(s string, buf buffer.Buffer, opt *Opt) {
for _, r := range s {
if r <= 0x7F {
b := byte(r)
opt.asciiCharEscapingFunc[b](b, buf)
} else {
opt.unicodeEscapingFunc(r, buf)
}
}
}
func anyToInt(v any) (u int, err error) {
if v == nil {
return 0, fmt.Errorf("%w: parameter is nil", ErrParameterError)
}
value := reflect.ValueOf(v)
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return int(value.Int()), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return int(value.Uint()), nil
default:
return 0, fmt.Errorf("%v is not a number", reflect.TypeOf(v))
}
}
func anyToString(v any) (s string, err error) {
if v == nil {
return "", fmt.Errorf("%w: parameter is nil", ErrParameterError)
}
rv := reflect.ValueOf(v)
if rv.Type().Kind() == reflect.String {
return rv.String(), nil
}
return "", fmt.Errorf("%w: %s is not a string", ErrParameterError, reflect.TypeOf(v).String())
}
func isSliceAndExtractDividedParams(p any) (ok bool, firstParam any, otherParams []any) {
v := reflect.ValueOf(p)
switch v.Kind() {
default:
return false, nil, nil
case reflect.Slice, reflect.Array:
// yes, go on
}
paramCount := v.Len()
if paramCount == 0 {
return true, nil, nil
}
firstParam = v.Index(0).Interface()
for i := 1; i < v.Len(); i++ {
element := v.Index(i)
otherParams = append(otherParams, element.Interface())
}
return true, firstParam, otherParams
}
func isSliceAndExtractJointParams(p any) (bool, []any) {
v := reflect.ValueOf(p)
switch v.Kind() {
default:
return false, nil
case reflect.Slice, reflect.Array:
// yes, go on
}
res := make([]any, 0, v.Len())
for i := 0; i < v.Len(); i++ {
element := v.Index(i)
res = append(res, element.Interface())
}
return true, res
}