-
Notifications
You must be signed in to change notification settings - Fork 0
/
encoding.go
120 lines (118 loc) · 2.68 KB
/
encoding.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package comp
import "strconv"
// Return the JSON for (error if any, value if none)
func ValueJSON(v any, err error) string {
if err != nil {
return QuoteToJSON(err.Error())
}
switch w := v.(type) {
case nil:
return "null"
case bool:
return Cond(w, "true", "false").(string)
case int64:
return strconv.FormatInt(w, 10)
case int32:
return strconv.FormatInt(int64(w), 10)
case int16:
return strconv.FormatInt(int64(w), 10)
case int8:
return strconv.FormatInt(int64(w), 10)
case int:
return strconv.FormatInt(int64(w), 10)
case uint64:
return strconv.FormatUint(w, 10)
case uint32:
return strconv.FormatUint(uint64(w), 10)
case uint16:
return strconv.FormatUint(uint64(w), 10)
case uint8:
return strconv.FormatUint(uint64(w), 10)
case uint:
return strconv.FormatUint(uint64(w), 10)
case uintptr:
return strconv.FormatUint(uint64(w), 10)
case float32:
s := strconv.FormatFloat(float64(w), 'g', -1, 32)
switch s {
case "NaN", "-Inf", "+Inf":
return "\"" + s + "\""
default:
return s
}
case float64:
s := strconv.FormatFloat(w, 'g', -1, 64)
switch s {
case "NaN", "-Inf", "+Inf":
return "\"" + s + "\""
default:
return s
}
case complex64:
s := strconv.FormatComplex(complex128(w), 'g', -1, 32)
return "\"" + s[1:len(s)-1] + "\""
case complex128:
s := strconv.FormatComplex(w, 'g', -1, 32)
return "\"" + s[1:len(s)-1] + "\""
case string:
return QuoteToJSON(w)
case []rune:
return QuoteToJSON(string(w))
case []byte:
return QuoteToJSON(string(w))
}
return "{}" //Temporarily reserved empty object
}
// Last Hexadigit
func Hex(i byte, cap bool) byte {
if cap {
return "0123456789ABCDEF"[i&15]
} else {
return "0123456789abcdef"[i&15]
}
}
func Escape(r rune, cap bool) []byte {
s := [6]byte{'\\', 'u'}
for i := 3; i >= 0; i-- {
s[5-i] = Hex(byte(r>>i), cap)
}
return s[:]
}
// Quote friendly to JSON string
func QuoteToJSON(s string) string {
q := []byte{}
for i, v := range s {
switch v {
case '\b':
q = append(q, '\\', 'b')
case '\f':
q = append(q, '\\', 'f')
case '\n':
q = append(q, '\\', 'n')
case '\r':
q = append(q, '\\', 'r')
case '\t':
q = append(q, '\\', 't')
case '"':
q = append(q, '\\', '"')
case '\\':
q = append(q, '\\', '\\')
case '/':
q = append(q, '\\', '/')
case 0xFFFD:
q = append(append(q, "\\ufffd(0x"...),
Hex(s[i]>>4, false), Hex(s[i], false), ')')
default:
if v >= 0x20 && v <= 0x7E {
q = append(q, byte(v))
} else if v >= 0x10000 {
v -= 0x10000
h, l := 0xD800+(v>>10&0x03FF), 0xDC00+(v&0x03FF)
q = append(append(q, Escape(h, false)...), Escape(l, false)...)
} else {
q = append(q, Escape(v, false)...)
}
}
}
return string(q)
}