1
16
17 package value
18
19 import (
20 "bytes"
21 "fmt"
22 "io"
23 "strings"
24
25 jsoniter "github.com/json-iterator/go"
26 "gopkg.in/yaml.v2"
27 )
28
29 var (
30 readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()
31 writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool()
32 )
33
34
35
36
37 type Value interface {
38
39 IsMap() bool
40
41 IsList() bool
42
43 IsBool() bool
44
45 IsInt() bool
46
47
48 IsFloat() bool
49
50
51 IsString() bool
52
53 IsNull() bool
54
55
56
57 AsMap() Map
58
59
60 AsMapUsing(Allocator) Map
61
62
63 AsList() List
64
65
66 AsListUsing(Allocator) List
67
68
69 AsBool() bool
70
71
72 AsInt() int64
73
74
75 AsFloat() float64
76
77
78 AsString() string
79
80
81 Unstructured() interface{}
82 }
83
84
85 func FromJSON(input []byte) (Value, error) {
86 return FromJSONFast(input)
87 }
88
89
90 func FromJSONFast(input []byte) (Value, error) {
91 iter := readPool.BorrowIterator(input)
92 defer readPool.ReturnIterator(iter)
93 return ReadJSONIter(iter)
94 }
95
96
97 func ToJSON(v Value) ([]byte, error) {
98 buf := bytes.Buffer{}
99 stream := writePool.BorrowStream(&buf)
100 defer writePool.ReturnStream(stream)
101 WriteJSONStream(v, stream)
102 b := stream.Buffer()
103 err := stream.Flush()
104
105
106
107
108 stream.SetBuffer(b[:0])
109 return buf.Bytes(), err
110 }
111
112
113 func ReadJSONIter(iter *jsoniter.Iterator) (Value, error) {
114 v := iter.Read()
115 if iter.Error != nil && iter.Error != io.EOF {
116 return nil, iter.Error
117 }
118 return NewValueInterface(v), nil
119 }
120
121
122 func WriteJSONStream(v Value, stream *jsoniter.Stream) {
123 stream.WriteVal(v.Unstructured())
124 }
125
126
127 func ToYAML(v Value) ([]byte, error) {
128 return yaml.Marshal(v.Unstructured())
129 }
130
131
132 func Equals(lhs, rhs Value) bool {
133 return EqualsUsing(HeapAllocator, lhs, rhs)
134 }
135
136
137 func EqualsUsing(a Allocator, lhs, rhs Value) bool {
138 if lhs.IsFloat() || rhs.IsFloat() {
139 var lf float64
140 if lhs.IsFloat() {
141 lf = lhs.AsFloat()
142 } else if lhs.IsInt() {
143 lf = float64(lhs.AsInt())
144 } else {
145 return false
146 }
147 var rf float64
148 if rhs.IsFloat() {
149 rf = rhs.AsFloat()
150 } else if rhs.IsInt() {
151 rf = float64(rhs.AsInt())
152 } else {
153 return false
154 }
155 return lf == rf
156 }
157 if lhs.IsInt() {
158 if rhs.IsInt() {
159 return lhs.AsInt() == rhs.AsInt()
160 }
161 return false
162 } else if rhs.IsInt() {
163 return false
164 }
165 if lhs.IsString() {
166 if rhs.IsString() {
167 return lhs.AsString() == rhs.AsString()
168 }
169 return false
170 } else if rhs.IsString() {
171 return false
172 }
173 if lhs.IsBool() {
174 if rhs.IsBool() {
175 return lhs.AsBool() == rhs.AsBool()
176 }
177 return false
178 } else if rhs.IsBool() {
179 return false
180 }
181 if lhs.IsList() {
182 if rhs.IsList() {
183 lhsList := lhs.AsListUsing(a)
184 defer a.Free(lhsList)
185 rhsList := rhs.AsListUsing(a)
186 defer a.Free(rhsList)
187 return lhsList.EqualsUsing(a, rhsList)
188 }
189 return false
190 } else if rhs.IsList() {
191 return false
192 }
193 if lhs.IsMap() {
194 if rhs.IsMap() {
195 lhsList := lhs.AsMapUsing(a)
196 defer a.Free(lhsList)
197 rhsList := rhs.AsMapUsing(a)
198 defer a.Free(rhsList)
199 return lhsList.EqualsUsing(a, rhsList)
200 }
201 return false
202 } else if rhs.IsMap() {
203 return false
204 }
205 if lhs.IsNull() {
206 if rhs.IsNull() {
207 return true
208 }
209 return false
210 } else if rhs.IsNull() {
211 return false
212 }
213
214 return true
215 }
216
217
218 func ToString(v Value) string {
219 if v.IsNull() {
220 return "null"
221 }
222 switch {
223 case v.IsFloat():
224 return fmt.Sprintf("%v", v.AsFloat())
225 case v.IsInt():
226 return fmt.Sprintf("%v", v.AsInt())
227 case v.IsString():
228 return fmt.Sprintf("%q", v.AsString())
229 case v.IsBool():
230 return fmt.Sprintf("%v", v.AsBool())
231 case v.IsList():
232 strs := []string{}
233 list := v.AsList()
234 for i := 0; i < list.Length(); i++ {
235 strs = append(strs, ToString(list.At(i)))
236 }
237 return "[" + strings.Join(strs, ",") + "]"
238 case v.IsMap():
239 strs := []string{}
240 v.AsMap().Iterate(func(k string, v Value) bool {
241 strs = append(strs, fmt.Sprintf("%v=%v", k, ToString(v)))
242 return true
243 })
244 return strings.Join(strs, "")
245 }
246
247 return "{{undefined}}"
248 }
249
250
251
252 func Less(lhs, rhs Value) bool {
253 return Compare(lhs, rhs) == -1
254 }
255
256
257
258
259 func Compare(lhs, rhs Value) int {
260 return CompareUsing(HeapAllocator, lhs, rhs)
261 }
262
263
264
265
266
267 func CompareUsing(a Allocator, lhs, rhs Value) int {
268 if lhs.IsFloat() {
269 if !rhs.IsFloat() {
270
271 if rhs.IsInt() {
272 return FloatCompare(lhs.AsFloat(), float64(rhs.AsInt()))
273 }
274 return -1
275 }
276 return FloatCompare(lhs.AsFloat(), rhs.AsFloat())
277 } else if rhs.IsFloat() {
278
279 if lhs.IsInt() {
280 return FloatCompare(float64(lhs.AsInt()), rhs.AsFloat())
281 }
282 return 1
283 }
284
285 if lhs.IsInt() {
286 if !rhs.IsInt() {
287 return -1
288 }
289 return IntCompare(lhs.AsInt(), rhs.AsInt())
290 } else if rhs.IsInt() {
291 return 1
292 }
293
294 if lhs.IsString() {
295 if !rhs.IsString() {
296 return -1
297 }
298 return strings.Compare(lhs.AsString(), rhs.AsString())
299 } else if rhs.IsString() {
300 return 1
301 }
302
303 if lhs.IsBool() {
304 if !rhs.IsBool() {
305 return -1
306 }
307 return BoolCompare(lhs.AsBool(), rhs.AsBool())
308 } else if rhs.IsBool() {
309 return 1
310 }
311
312 if lhs.IsList() {
313 if !rhs.IsList() {
314 return -1
315 }
316 lhsList := lhs.AsListUsing(a)
317 defer a.Free(lhsList)
318 rhsList := rhs.AsListUsing(a)
319 defer a.Free(rhsList)
320 return ListCompareUsing(a, lhsList, rhsList)
321 } else if rhs.IsList() {
322 return 1
323 }
324 if lhs.IsMap() {
325 if !rhs.IsMap() {
326 return -1
327 }
328 lhsMap := lhs.AsMapUsing(a)
329 defer a.Free(lhsMap)
330 rhsMap := rhs.AsMapUsing(a)
331 defer a.Free(rhsMap)
332 return MapCompareUsing(a, lhsMap, rhsMap)
333 } else if rhs.IsMap() {
334 return 1
335 }
336 if lhs.IsNull() {
337 if !rhs.IsNull() {
338 return -1
339 }
340 return 0
341 } else if rhs.IsNull() {
342 return 1
343 }
344
345
346 return 0
347 }
348
View as plain text