Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(4102)

Delta Between Two Patch Sets: src/pkg/encoding/json/encode.go

Issue 9129044: code review 9129044: encoding/json: faster encoding (Closed)
Left Patch Set: diff -r 740d244b2047 https://go.googlecode.com/hg/ Created 10 years, 11 months ago
Right Patch Set: diff -r 07295f40fe71 https://go.googlecode.com/hg/ Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/encoding/json/decode_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2010 The Go Authors. All rights reserved. 1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package json implements encoding and decoding of JSON objects as defined in 5 // Package json implements encoding and decoding of JSON objects as defined in
6 // RFC 4627. The mapping between JSON objects and Go values is described 6 // RFC 4627. The mapping between JSON objects and Go values is described
7 // in the documentation for the Marshal and Unmarshal functions. 7 // in the documentation for the Marshal and Unmarshal functions.
8 // 8 //
9 // See "JSON and Go" for an introduction to this package: 9 // See "JSON and Go" for an introduction to this package:
10 // http://golang.org/doc/articles/json_and_go.html 10 // http://golang.org/doc/articles/json_and_go.html
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return nil, err 142 return nil, err
143 } 143 }
144 var buf bytes.Buffer 144 var buf bytes.Buffer
145 err = Indent(&buf, b, prefix, indent) 145 err = Indent(&buf, b, prefix, indent)
146 if err != nil { 146 if err != nil {
147 return nil, err 147 return nil, err
148 } 148 }
149 return buf.Bytes(), nil 149 return buf.Bytes(), nil
150 } 150 }
151 151
152 // HTMLEscape appends to dst the JSON-encoded src with <, >, and & 152 // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+202 9
153 // characters inside string literals changed to \u003c, \u003e, \u0026 153 // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
154 // so that the JSON will be safe to embed inside HTML <script> tags. 154 // so that the JSON will be safe to embed inside HTML <script> tags.
155 // For historical reasons, web browsers don't honor standard HTML 155 // For historical reasons, web browsers don't honor standard HTML
156 // escaping within <script> tags, so an alternative JSON encoding must 156 // escaping within <script> tags, so an alternative JSON encoding must
157 // be used. 157 // be used.
158 func HTMLEscape(dst *bytes.Buffer, src []byte) { 158 func HTMLEscape(dst *bytes.Buffer, src []byte) {
159 » // < > & can only appear in string literals, 159 » // The characters can only appear in string literals,
160 // so just scan the string one byte at a time. 160 // so just scan the string one byte at a time.
161 start := 0 161 start := 0
162 for i, c := range src { 162 for i, c := range src {
163 if c == '<' || c == '>' || c == '&' { 163 if c == '<' || c == '>' || c == '&' {
164 if start < i { 164 if start < i {
165 dst.Write(src[start:i]) 165 dst.Write(src[start:i])
166 } 166 }
167 dst.WriteString(`\u00`) 167 dst.WriteString(`\u00`)
168 dst.WriteByte(hex[c>>4]) 168 dst.WriteByte(hex[c>>4])
169 dst.WriteByte(hex[c&0xF]) 169 dst.WriteByte(hex[c&0xF])
170 start = i + 1 170 start = i + 1
171 } 171 }
172 // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
173 if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^ 1 == 0xA8 {
174 if start < i {
175 dst.Write(src[start:i])
176 }
177 dst.WriteString(`\u202`)
178 dst.WriteByte(hex[src[i+2]&0xF])
179 start = i + 3
180 }
172 } 181 }
173 if start < len(src) { 182 if start < len(src) {
174 dst.Write(src[start:]) 183 dst.Write(src[start:])
175 } 184 }
176 } 185 }
177 186
178 // Marshaler is the interface implemented by objects that 187 // Marshaler is the interface implemented by objects that
179 // can marshal themselves into valid JSON. 188 // can marshal themselves into valid JSON.
180 type Marshaler interface { 189 type Marshaler interface {
181 MarshalJSON() ([]byte, error) 190 MarshalJSON() ([]byte, error)
(...skipping 11 matching lines...) Expand all
193 202
194 type UnsupportedValueError struct { 203 type UnsupportedValueError struct {
195 Value reflect.Value 204 Value reflect.Value
196 Str string 205 Str string
197 } 206 }
198 207
199 func (e *UnsupportedValueError) Error() string { 208 func (e *UnsupportedValueError) Error() string {
200 return "json: unsupported value: " + e.Str 209 return "json: unsupported value: " + e.Str
201 } 210 }
202 211
203 // An InvalidUTF8Error is returned by Marshal when attempting 212 // Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
204 // to encode a string value with invalid UTF-8 sequences. 213 // attempting to encode a string value with invalid UTF-8 sequences.
214 // As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
215 // replacing invalid bytes with the Unicode replacement rune U+FFFD.
216 // This error is no longer generated but is kept for backwards compatibility
217 // with programs that might mention it.
205 type InvalidUTF8Error struct { 218 type InvalidUTF8Error struct {
206 S string // the whole string value that caused the error 219 S string // the whole string value that caused the error
207 } 220 }
208 221
209 func (e *InvalidUTF8Error) Error() string { 222 func (e *InvalidUTF8Error) Error() string {
210 return "json: invalid UTF-8 in string: " + strconv.Quote(e.S) 223 return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
211 } 224 }
212 225
213 type MarshalerError struct { 226 type MarshalerError struct {
214 Type reflect.Type 227 Type reflect.Type
215 Err error 228 Err error
216 } 229 }
217 230
218 func (e *MarshalerError) Error() string { 231 func (e *MarshalerError) Error() string {
219 return "json: error calling MarshalJSON for type " + e.Type.String() + " : " + e.Err.Error() 232 return "json: error calling MarshalJSON for type " + e.Type.String() + " : " + e.Err.Error()
220 } 233 }
221 234
222 var hex = "0123456789abcdef" 235 var hex = "0123456789abcdef"
223 236
224 // An encodeState encodes JSON into a bytes.Buffer. 237 // An encodeState encodes JSON into a bytes.Buffer.
225 type encodeState struct { 238 type encodeState struct {
226 bytes.Buffer // accumulated output 239 bytes.Buffer // accumulated output
227 scratch [64]byte 240 scratch [64]byte
228 } 241 }
229 242
230 // TODO: use a sync.Cache 243 // TODO(bradfitz): use a sync.Cache here
231 var encodeStateCache = make(chan *encodeState, 4) 244 var encodeStatePool = make(chan *encodeState, 8)
232 245
233 func newEncodeState() *encodeState { 246 func newEncodeState() *encodeState {
234 select { 247 select {
235 » case e := <-encodeStateCache: 248 » case e := <-encodeStatePool:
249 » » e.Reset()
236 return e 250 return e
237 default: 251 default:
238 return new(encodeState) 252 return new(encodeState)
239 } 253 }
240 } 254 }
241 255
242 func putEncodeState(e *encodeState) { 256 func putEncodeState(e *encodeState) {
243 select { 257 select {
244 » case encodeStateCache <- e: 258 » case encodeStatePool <- e:
245 default: 259 default:
246 } 260 }
247 } 261 }
248 262
249 func (e *encodeState) marshal(v interface{}) (err error) { 263 func (e *encodeState) marshal(v interface{}) (err error) {
250 defer func() { 264 defer func() {
251 if r := recover(); r != nil { 265 if r := recover(); r != nil {
252 if _, ok := r.(runtime.Error); ok { 266 if _, ok := r.(runtime.Error); ok {
253 panic(r) 267 panic(r)
254 } 268 }
(...skipping 26 matching lines...) Expand all
281 case reflect.Float32, reflect.Float64: 295 case reflect.Float32, reflect.Float64:
282 return v.Float() == 0 296 return v.Float() == 0
283 case reflect.Interface, reflect.Ptr: 297 case reflect.Interface, reflect.Ptr:
284 return v.IsNil() 298 return v.IsNil()
285 } 299 }
286 return false 300 return false
287 } 301 }
288 302
289 func (e *encodeState) reflectValue(v reflect.Value) { 303 func (e *encodeState) reflectValue(v reflect.Value) {
290 valueEncoder(v)(e, v, false) 304 valueEncoder(v)(e, v, false)
305 }
306
307 type encoderFunc func(e *encodeState, v reflect.Value, _ bool)
308
309 var encoderCache struct {
310 sync.RWMutex
311 m map[reflect.Type]encoderFunc
312 }
313
314 func valueEncoder(v reflect.Value) encoderFunc {
315 if !v.IsValid() {
316 return invalidValueEncoder
317 }
318 t := v.Type()
319 return typeEncoder(t, v)
320 }
321
322 func typeEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
323 encoderCache.RLock()
324 f := encoderCache.m[t]
325 encoderCache.RUnlock()
326 if f != nil {
327 return f
328 }
329
330 // To deal with recursive types, populate the map with an
331 // indirect func before we build it. This type waits on the
332 // real func (f) to be ready and then calls it. This indirect
333 // func is only used for recursive types.
334 encoderCache.Lock()
335 if encoderCache.m == nil {
336 encoderCache.m = make(map[reflect.Type]encoderFunc)
337 }
338 var wg sync.WaitGroup
339 wg.Add(1)
340 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
341 wg.Wait()
342 f(e, v, quoted)
343 }
344 encoderCache.Unlock()
345
346 // Compute fields without lock.
347 // Might duplicate effort but won't hold other computations back.
348 f = newTypeEncoder(t, vx)
349 wg.Done()
350 encoderCache.Lock()
351 encoderCache.m[t] = f
352 encoderCache.Unlock()
353 return f
354 }
355
356 // newTypeEncoder constructs an encoderFunc for a type.
357 // The provided vx is an example value of type t. It's the first seen
358 // value of that type and should not be used to encode. It may be
359 // zero.
360 func newTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
361 if !vx.IsValid() {
362 vx = reflect.New(t).Elem()
363 }
364 _, ok := vx.Interface().(Marshaler)
365 if ok {
366 return valueIsMarshallerEncoder
367 }
368 // T doesn't match the interface. Check against *T too.
369 if vx.Kind() != reflect.Ptr && vx.CanAddr() {
370 _, ok = vx.Addr().Interface().(Marshaler)
371 if ok {
372 return valueAddrIsMarshallerEncoder
373 }
374 }
375 switch vx.Kind() {
376 case reflect.Bool:
377 return boolEncoder
378 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64:
379 return intEncoder
380 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflec t.Uint64, reflect.Uintptr:
381 return uintEncoder
382 case reflect.Float32:
383 return float32Encoder
384 case reflect.Float64:
385 return float64Encoder
386 case reflect.String:
387 return stringEncoder
388 case reflect.Interface:
389 return interfaceEncoder
390 case reflect.Struct:
391 return newStructEncoder(t, vx)
392 case reflect.Map:
393 return newMapEncoder(t, vx)
394 case reflect.Slice:
395 return newSliceEncoder(t, vx)
396 case reflect.Array:
397 return newArrayEncoder(t, vx)
398 case reflect.Ptr:
399 return newPtrEncoder(t, vx)
400 default:
401 return unsupportedTypeEncoder
402 }
403 }
404
405 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
406 e.WriteString("null")
407 }
408
409 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) {
410 if v.Kind() == reflect.Ptr && v.IsNil() {
411 e.WriteString("null")
412 return
413 }
414 m := v.Interface().(Marshaler)
415 b, err := m.MarshalJSON()
416 if err == nil {
417 // copy JSON into buffer, checking validity.
418 err = compact(&e.Buffer, b, true)
419 }
420 if err != nil {
421 e.error(&MarshalerError{v.Type(), err})
422 }
423 }
424
425 func valueAddrIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) {
426 va := v.Addr()
427 if va.Kind() == reflect.Ptr && va.IsNil() {
428 e.WriteString("null")
429 return
430 }
431 m := va.Interface().(Marshaler)
432 b, err := m.MarshalJSON()
433 if err == nil {
434 // copy JSON into buffer, checking validity.
435 err = compact(&e.Buffer, b, true)
436 }
437 if err != nil {
438 e.error(&MarshalerError{v.Type(), err})
439 }
440 }
441
442 func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
443 if quoted {
444 e.WriteByte('"')
445 }
446 if v.Bool() {
447 e.WriteString("true")
448 } else {
449 e.WriteString("false")
450 }
451 if quoted {
452 e.WriteByte('"')
453 }
454 }
455
456 func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
457 b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
458 if quoted {
459 e.WriteByte('"')
460 }
461 e.Write(b)
462 if quoted {
463 e.WriteByte('"')
464 }
465 }
466
467 func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
468 b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
469 if quoted {
470 e.WriteByte('"')
471 }
472 e.Write(b)
473 if quoted {
474 e.WriteByte('"')
475 }
476 }
477
478 type floatEncoder int // number of bits
479
480 func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
481 f := v.Float()
482 if math.IsInf(f, 0) || math.IsNaN(f) {
483 e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1 , int(bits))})
484 }
485 b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
486 if quoted {
487 e.WriteByte('"')
488 }
489 e.Write(b)
490 if quoted {
491 e.WriteByte('"')
492 }
493 }
494
495 var (
496 float32Encoder = (floatEncoder(32)).encode
497 float64Encoder = (floatEncoder(64)).encode
498 )
499
500 func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
501 if v.Type() == numberType {
502 numStr := v.String()
503 if numStr == "" {
504 numStr = "0" // Number's zero-val
505 }
506 e.WriteString(numStr)
507 return
508 }
509 if quoted {
510 sb, err := Marshal(v.String())
511 if err != nil {
512 e.error(err)
513 }
514 e.string(string(sb))
515 } else {
516 e.string(v.String())
517 }
518 }
519
520 func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
521 if v.IsNil() {
522 e.WriteString("null")
523 return
524 }
525 e.reflectValue(v.Elem())
526 }
527
528 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
529 e.error(&UnsupportedTypeError{v.Type()})
530 }
531
532 type structEncoder struct {
533 fields []field
534 fieldEncs []encoderFunc
535 }
536
537 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
538 e.WriteByte('{')
539 first := true
540 for i, f := range se.fields {
541 fv := fieldByIndex(v, f.index)
542 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
543 continue
544 }
545 if first {
546 first = false
547 } else {
548 e.WriteByte(',')
549 }
550 e.string(f.name)
551 e.WriteByte(':')
552 if tenc := se.fieldEncs[i]; tenc != nil {
553 tenc(e, fv, f.quoted)
554 } else {
555 // Slower path.
556 e.reflectValue(fv)
557 }
558 }
559 e.WriteByte('}')
560 }
561
562 func newStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
563 fields := cachedTypeFields(t)
564 se := &structEncoder{
565 fields: fields,
566 fieldEncs: make([]encoderFunc, len(fields)),
567 }
568 for i, f := range fields {
569 vxf := fieldByIndex(vx, f.index)
570 if vxf.IsValid() {
571 se.fieldEncs[i] = typeEncoder(vxf.Type(), vxf)
572 }
573 }
574 return se.encode
575 }
576
577 type mapEncoder struct {
578 elemEnc encoderFunc
579 }
580
581 func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
582 if v.IsNil() {
583 e.WriteString("null")
584 return
585 }
586 e.WriteByte('{')
587 var sv stringValues = v.MapKeys()
588 sort.Sort(sv)
589 for i, k := range sv {
590 if i > 0 {
591 e.WriteByte(',')
592 }
593 e.string(k.String())
594 e.WriteByte(':')
595 me.elemEnc(e, v.MapIndex(k), false)
596 }
597 e.WriteByte('}')
598 }
599
600 func newMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
601 if t.Key().Kind() != reflect.String {
602 return unsupportedTypeEncoder
603 }
604 me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})}
605 return me.encode
606 }
607
608 func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
609 if v.IsNil() {
610 e.WriteString("null")
611 return
612 }
613 s := v.Bytes()
614 e.WriteByte('"')
615 if len(s) < 1024 {
616 // for small buffers, using Encode directly is much faster.
617 dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
618 base64.StdEncoding.Encode(dst, s)
619 e.Write(dst)
620 } else {
621 // for large buffers, avoid unnecessary extra temporary
622 // buffer space.
623 enc := base64.NewEncoder(base64.StdEncoding, e)
624 enc.Write(s)
625 enc.Close()
626 }
627 e.WriteByte('"')
628 }
629
630 // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn' t nil.
631 type sliceEncoder struct {
632 arrayEnc encoderFunc
633 }
634
635 func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
636 if v.IsNil() {
637 e.WriteString("null")
638 return
639 }
640 se.arrayEnc(e, v, false)
641 }
642
643 func newSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
644 // Byte slices get special treatment; arrays don't.
645 if vx.Type().Elem().Kind() == reflect.Uint8 {
646 return encodeByteSlice
647 }
648 enc := &sliceEncoder{newArrayEncoder(t, vx)}
649 return enc.encode
650 }
651
652 type arrayEncoder struct {
653 elemEnc encoderFunc
654 }
655
656 func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
657 e.WriteByte('[')
658 n := v.Len()
659 for i := 0; i < n; i++ {
660 if i > 0 {
661 e.WriteByte(',')
662 }
663 ae.elemEnc(e, v.Index(i), false)
664 }
665 e.WriteByte(']')
666 }
667
668 func newArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
669 enc := &arrayEncoder{typeEncoder(t.Elem(), reflect.Value{})}
670 return enc.encode
671 }
672
673 type ptrEncoder struct {
674 elemEnc encoderFunc
675 }
676
677 func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
678 if v.IsNil() {
679 e.WriteString("null")
680 return
681 }
682 pe.elemEnc(e, v.Elem(), false)
683 }
684
685 func newPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
686 enc := &ptrEncoder{typeEncoder(t.Elem(), reflect.Value{})}
687 return enc.encode
291 } 688 }
292 689
293 func isValidTag(s string) bool { 690 func isValidTag(s string) bool {
294 if s == "" { 691 if s == "" {
295 return false 692 return false
296 } 693 }
297 for _, c := range s { 694 for _, c := range s {
298 switch { 695 switch {
299 case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): 696 case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
300 // Backslash and quote chars are reserved, but 697 // Backslash and quote chars are reserved, but
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 e.WriteString(`\u00`) 759 e.WriteString(`\u00`)
363 e.WriteByte(hex[b>>4]) 760 e.WriteByte(hex[b>>4])
364 e.WriteByte(hex[b&0xF]) 761 e.WriteByte(hex[b&0xF])
365 } 762 }
366 i++ 763 i++
367 start = i 764 start = i
368 continue 765 continue
369 } 766 }
370 c, size := utf8.DecodeRuneInString(s[i:]) 767 c, size := utf8.DecodeRuneInString(s[i:])
371 if c == utf8.RuneError && size == 1 { 768 if c == utf8.RuneError && size == 1 {
372 » » » e.error(&InvalidUTF8Error{s}) 769 » » » if start < i {
770 » » » » e.WriteString(s[start:i])
771 » » » }
772 » » » e.WriteString(`\ufffd`)
773 » » » i += size
774 » » » start = i
775 » » » continue
776 » » }
777 » » // U+2028 is LINE SEPARATOR.
778 » » // U+2029 is PARAGRAPH SEPARATOR.
779 » » // They are both technically valid characters in JSON strings,
780 » » // but don't work in JSONP, which has to be evaluated as JavaScr ipt,
781 » » // and can lead to security holes there. It is valid JSON to
782 » » // escape them, so we do so unconditionally.
783 » » // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
784 » » if c == '\u2028' || c == '\u2029' {
785 » » » if start < i {
786 » » » » e.WriteString(s[start:i])
787 » » » }
788 » » » e.WriteString(`\u202`)
789 » » » e.WriteByte(hex[c&0xF])
790 » » » i += size
791 » » » start = i
792 » » » continue
373 } 793 }
374 i += size 794 i += size
375 } 795 }
376 if start < len(s) { 796 if start < len(s) {
377 e.WriteString(s[start:]) 797 e.WriteString(s[start:])
378 } 798 }
379 e.WriteByte('"') 799 e.WriteByte('"')
380 return e.Len() - len0, nil 800 return e.Len() - len0, nil
381 } 801 }
382 802
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 } 997 }
578 // All remaining fields have the same length. If there's more than one, 998 // All remaining fields have the same length. If there's more than one,
579 // we have a conflict (two fields named "X" at the same level) and we 999 // we have a conflict (two fields named "X" at the same level) and we
580 // return no field. 1000 // return no field.
581 if len(fields) > 1 { 1001 if len(fields) > 1 {
582 return field{}, false 1002 return field{}, false
583 } 1003 }
584 return fields[0], true 1004 return fields[0], true
585 } 1005 }
586 1006
587 type encoderFunc func(e *encodeState, v reflect.Value, quoted bool)
588
589 var encoderCache struct {
590 sync.RWMutex
591 m map[reflect.Type]encoderFunc
592 }
593
594 func valueEncoder(v reflect.Value) encoderFunc {
595 if !v.IsValid() {
596 return invalidValueEncoder
597 }
598 t := v.Type()
599 return typeEncoder(t, v)
600 }
601
602 func typeEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
603 encoderCache.RLock()
604 f := encoderCache.m[t]
605 encoderCache.RUnlock()
606 if f != nil {
607 return f
608 }
609
610 // To deal with recursive types, populate the map with an
611 // indirect func before we build it. This type waits on the
612 // real func (f) to be ready and then calls it. This indirect
613 // func is only used for recursive types.
614 encoderCache.Lock()
615 if encoderCache.m == nil {
616 encoderCache.m = make(map[reflect.Type]encoderFunc)
617 }
618 var wg sync.WaitGroup
619 wg.Add(1)
620 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
621 wg.Wait()
622 f(e, v, quoted)
623 }
624 encoderCache.Unlock()
625
626 // Compute fields without lock.
627 // Might duplicate effort but won't hold other computations back.
628 f = buildTypeEncoder(t, vx)
629 wg.Done()
630 encoderCache.Lock()
631 encoderCache.m[t] = f
632 encoderCache.Unlock()
633 return f
634 }
635
636 // buildTypeEncoder constructs an encoderFunc for a type.
637 // The provided vx is an example value of type t. It's the first seen
638 // value of that type and should not be used to encode. It may be
639 // zero.
640 func buildTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
641 if !vx.IsValid() {
642 vx = reflect.New(t).Elem()
643 }
644 _, ok := vx.Interface().(Marshaler)
645 if ok {
646 return valueIsMarshallerEncoder
647 }
648 // T doesn't match the interface. Check against *T too.
649 if vx.Kind() != reflect.Ptr && vx.CanAddr() {
650 _, ok = vx.Addr().Interface().(Marshaler)
651 if ok {
652 return valueAddrIsMarshallerEncoder
653 }
654 }
655 switch vx.Kind() {
656 case reflect.Bool:
657 return boolEncoder
658 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64:
659 return intEncoder
660 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflec t.Uint64, reflect.Uintptr:
661 return uintEncoder
662 case reflect.Float32:
663 return float32Encoder
664 case reflect.Float64:
665 return float64Encoder
666 case reflect.String:
667 return stringEncoder
668 case reflect.Interface:
669 return interfaceEncoder
670 case reflect.Struct:
671 return buildStructEncoder(t, vx)
672 case reflect.Map:
673 return buildMapEncoder(t, vx)
674 case reflect.Slice:
675 return buildSliceEncoder(t, vx)
676 case reflect.Array:
677 return buildArrayEncoder(t, vx)
678 case reflect.Ptr:
679 return buildPtrEncoder(t, vx)
680 default:
681 return unsupportedTypeEncoder
682 }
683 }
684
685 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
686 e.WriteString("null")
687 }
688
689 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) {
690 if v.Kind() == reflect.Ptr && v.IsNil() {
691 e.WriteString("null")
692 return
693 }
694 m := v.Interface().(Marshaler)
695 b, err := m.MarshalJSON()
696 if err == nil {
697 // copy JSON into buffer, checking validity.
698 err = compact(&e.Buffer, b, true)
699 }
700 if err != nil {
701 e.error(&MarshalerError{v.Type(), err})
702 }
703 }
704
705 func valueAddrIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) {
706 va := v.Addr()
707 if va.Kind() == reflect.Ptr && va.IsNil() {
708 e.WriteString("null")
709 return
710 }
711 m := va.Interface().(Marshaler)
712 b, err := m.MarshalJSON()
713 if err == nil {
714 // copy JSON into buffer, checking validity.
715 err = compact(&e.Buffer, b, true)
716 }
717 if err != nil {
718 e.error(&MarshalerError{v.Type(), err})
719 }
720 }
721
722 func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
723 if quoted {
724 e.WriteByte('"')
725 }
726 if v.Bool() {
727 e.WriteString("true")
728 } else {
729 e.WriteString("false")
730 }
731 if quoted {
732 e.WriteByte('"')
733 }
734 }
735
736 func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
737 b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
738 if quoted {
739 e.WriteByte('"')
740 }
741 e.Write(b)
742 if quoted {
743 e.WriteByte('"')
744 }
745 }
746
747 func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
748 b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
749 if quoted {
750 e.WriteByte('"')
751 }
752 e.Write(b)
753 if quoted {
754 e.WriteByte('"')
755 }
756 }
757
758 type floatEncoder int // number of bits
759
760 func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
761 f := v.Float()
762 if math.IsInf(f, 0) || math.IsNaN(f) {
763 e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1 , int(bits))})
764 }
765 b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
766 if quoted {
767 e.WriteByte('"')
768 }
769 e.Write(b)
770 if quoted {
771 e.WriteByte('"')
772 }
773 }
774
775 var (
776 float32Encoder = (floatEncoder(32)).encode
777 float64Encoder = (floatEncoder(64)).encode
778 )
779
780 func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
781 if v.Type() == numberType {
782 numStr := v.String()
783 if numStr == "" {
784 numStr = "0" // Number's zero-val
785 }
786 e.WriteString(numStr)
787 return
788 }
789 if quoted {
790 sb, err := Marshal(v.String())
791 if err != nil {
792 e.error(err)
793 }
794 e.string(string(sb))
795 } else {
796 e.string(v.String())
797 }
798 }
799
800 func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
801 if v.IsNil() {
802 e.WriteString("null")
803 return
804 }
805 e.reflectValue(v.Elem())
806 }
807
808 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
809 e.error(&UnsupportedTypeError{v.Type()})
810 }
811
812 type structEncoder struct {
813 fields []field
814 fieldFuncs []encoderFunc
815 }
816
817 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
818 e.WriteByte('{')
819 first := true
820 for i, f := range se.fields {
821 fv := fieldByIndex(v, f.index)
822 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
823 continue
824 }
825 if first {
826 first = false
827 } else {
828 e.WriteByte(',')
829 }
830 e.string(f.name)
831 e.WriteByte(':')
832 if tenc := se.fieldFuncs[i]; tenc != nil {
833 tenc(e, fv, f.quoted)
834 } else {
835 // Slower path.
836 e.reflectValue(fv)
837 }
838 }
839 e.WriteByte('}')
840 }
841
842 func buildStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
843 fields := cachedTypeFields(t)
844 se := &structEncoder{
845 fields: fields,
846 fieldFuncs: make([]encoderFunc, len(fields)),
847 }
848 for i, f := range fields {
849 vxf := fieldByIndex(vx, f.index)
850 if vxf.IsValid() {
851 se.fieldFuncs[i] = typeEncoder(vxf.Type(), vxf)
852 }
853 }
854 return se.encode
855 }
856
857 func buildMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
858 if t.Key().Kind() != reflect.String {
859 return func(e *encodeState, v reflect.Value, quoted bool) {
860 e.error(&UnsupportedTypeError{v.Type()})
861 }
862 }
863 elemEnc := typeEncoder(vx.Type().Elem(), reflect.Value{})
864 return func(e *encodeState, v reflect.Value, _ bool) {
865 if v.IsNil() {
866 e.WriteString("null")
867 return
868 }
869 e.WriteByte('{')
870 var sv stringValues = v.MapKeys()
871 sort.Sort(sv)
872 for i, k := range sv {
873 if i > 0 {
874 e.WriteByte(',')
875 }
876 e.string(k.String())
877 e.WriteByte(':')
878 elemEnc(e, v.MapIndex(k), false)
879 }
880 e.WriteByte('}')
881 }
882 }
883
884 func buildSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
885 // Byte slices get special treatment; arrays don't.
886 if vx.Type().Elem().Kind() == reflect.Uint8 {
887 return func(e *encodeState, v reflect.Value, _ bool) {
888 if v.IsNil() {
889 e.WriteString("null")
890 return
891 }
892 s := v.Bytes()
893 e.WriteByte('"')
894 if len(s) < 1024 {
895 // for small buffers, using Encode directly is m uch faster.
896 dst := make([]byte, base64.StdEncoding.EncodedLe n(len(s)))
897 base64.StdEncoding.Encode(dst, s)
898 e.Write(dst)
899 } else {
900 // for large buffers, avoid unnecessary extra te mporary
901 // buffer space.
902 enc := base64.NewEncoder(base64.StdEncoding, e)
903 enc.Write(s)
904 enc.Close()
905 }
906 e.WriteByte('"')
907 }
908 }
909 arrayEnc := buildArrayEncoder(t, vx)
910 return func(e *encodeState, v reflect.Value, _ bool) {
911 if v.IsNil() {
912 e.WriteString("null")
913 return
914 }
915 arrayEnc(e, v, false)
916 }
917 }
918
919 func buildArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
920 elemEnc := typeEncoder(t.Elem(), reflect.Value{})
921 return func(e *encodeState, v reflect.Value, _ bool) {
922 e.WriteByte('[')
923 n := v.Len()
924 for i := 0; i < n; i++ {
925 if i > 0 {
926 e.WriteByte(',')
927 }
928 elemEnc(e, v.Index(i), false)
929 }
930 e.WriteByte(']')
931 }
932 }
933
934 func buildPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
935 elemEnc := typeEncoder(t.Elem(), reflect.Value{})
936 return func(e *encodeState, v reflect.Value, quoted bool) {
937 if v.IsNil() {
938 e.WriteString("null")
939 return
940 }
941 elemEnc(e, v.Elem(), false)
942 }
943 }
944
945 var fieldCache struct { 1007 var fieldCache struct {
946 sync.RWMutex 1008 sync.RWMutex
947 m map[reflect.Type][]field 1009 m map[reflect.Type][]field
948 } 1010 }
949 1011
950 // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. 1012 // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
951 func cachedTypeFields(t reflect.Type) []field { 1013 func cachedTypeFields(t reflect.Type) []field {
952 fieldCache.RLock() 1014 fieldCache.RLock()
953 f := fieldCache.m[t] 1015 f := fieldCache.m[t]
954 fieldCache.RUnlock() 1016 fieldCache.RUnlock()
955 if f != nil { 1017 if f != nil {
956 return f 1018 return f
957 } 1019 }
958 1020
959 // Compute fields without lock. 1021 // Compute fields without lock.
960 // Might duplicate effort but won't hold other computations back. 1022 // Might duplicate effort but won't hold other computations back.
961 f = typeFields(t) 1023 f = typeFields(t)
962 if f == nil { 1024 if f == nil {
963 f = []field{} 1025 f = []field{}
964 } 1026 }
965 1027
966 fieldCache.Lock() 1028 fieldCache.Lock()
967 if fieldCache.m == nil { 1029 if fieldCache.m == nil {
968 fieldCache.m = map[reflect.Type][]field{} 1030 fieldCache.m = map[reflect.Type][]field{}
969 } 1031 }
970 fieldCache.m[t] = f 1032 fieldCache.m[t] = f
971 fieldCache.Unlock() 1033 fieldCache.Unlock()
972 return f 1034 return f
973 } 1035 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b