1
2
3
4
5 package json
6
7 import (
8 "bytes"
9 "io"
10 "math"
11 "math/bits"
12 "strconv"
13 "unicode/utf16"
14 "unicode/utf8"
15 )
16
17
18
19
20 type EncodeOptions struct {
21 requireKeyedLiterals
22 nonComparable
23
24
25 multiline bool
26
27
28
29 omitTopLevelNewline bool
30
31
32
33
34
35
36 AllowDuplicateNames bool
37
38
39
40
41
42 AllowInvalidUTF8 bool
43
44
45
46 preserveRawStrings bool
47
48
49
50 canonicalizeNumbers bool
51
52
53
54
55
56 EscapeRune func(rune) bool
57
58
59
60
61
62
63 Indent string
64
65
66
67
68
69
70 IndentPrefix string
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 type Encoder struct {
103 state
104 encodeBuffer
105 options EncodeOptions
106
107 seenPointers seenPointers
108 }
109
110
111
112
113
114 type encodeBuffer struct {
115 buf []byte
116
117
118
119 baseOffset int64
120
121 wr io.Writer
122
123
124 maxValue int
125
126 unusedCache []byte
127
128
129 bufStats bufferStatistics
130 }
131
132
133 func NewEncoder(w io.Writer) *Encoder {
134 return EncodeOptions{}.NewEncoder(w)
135 }
136
137
138
139
140
141
142
143
144 func (o EncodeOptions) NewEncoder(w io.Writer) *Encoder {
145 e := new(Encoder)
146 o.ResetEncoder(e, w)
147 return e
148 }
149
150
151
152 func (o EncodeOptions) ResetEncoder(e *Encoder, w io.Writer) {
153 if e == nil {
154 panic("json: invalid nil Encoder")
155 }
156 if w == nil {
157 panic("json: invalid nil io.Writer")
158 }
159 e.reset(nil, w, o)
160 }
161
162 func (e *Encoder) reset(b []byte, w io.Writer, o EncodeOptions) {
163 if len(o.Indent) > 0 {
164 o.multiline = true
165 if s := trimLeftSpaceTab(o.IndentPrefix); len(s) > 0 {
166 panic("json: invalid character " + quoteRune([]byte(s)) + " in indent prefix")
167 }
168 if s := trimLeftSpaceTab(o.Indent); len(s) > 0 {
169 panic("json: invalid character " + quoteRune([]byte(s)) + " in indent")
170 }
171 }
172 e.state.reset()
173 e.encodeBuffer = encodeBuffer{buf: b, wr: w, bufStats: e.bufStats}
174 e.options = o
175 if bb, ok := w.(*bytes.Buffer); ok && bb != nil {
176 e.buf = bb.Bytes()[bb.Len():]
177 }
178 }
179
180
181
182 func (e *Encoder) Reset(w io.Writer) {
183 e.options.ResetEncoder(e, w)
184 }
185
186
187 func (e *Encoder) needFlush() bool {
188
189
190
191
192
193
194 return e.wr != nil && (e.tokens.depth() == 1 || len(e.buf) > 3*cap(e.buf)/4)
195 }
196
197
198
199 func (e *Encoder) flush() error {
200 if e.wr == nil || e.avoidFlush() {
201 return nil
202 }
203
204
205 if e.tokens.depth() == 1 && !e.options.omitTopLevelNewline {
206 e.buf = append(e.buf, '\n')
207 }
208
209
210 e.names.copyQuotedBuffer(e.buf)
211
212
213 if bb, ok := e.wr.(*bytes.Buffer); ok {
214
215
216
217
218 n, _ := bb.Write(e.buf)
219 e.baseOffset += int64(n)
220
221
222
223
224
225
226 if avail := bb.Cap() - bb.Len(); avail < bb.Len()/4 {
227 bb.Grow(avail + 1)
228 }
229
230 e.buf = bb.Bytes()[bb.Len():]
231 return nil
232 }
233
234
235 n, err := e.wr.Write(e.buf)
236 e.baseOffset += int64(n)
237 if err != nil {
238
239
240
241 if n > 0 {
242 e.buf = e.buf[:copy(e.buf, e.buf[n:])]
243 }
244 return &ioError{action: "write", err: err}
245 }
246 e.buf = e.buf[:0]
247
248
249
250
251 const maxBufferSize = 4 << 10
252 const growthSizeFactor = 2
253 const growthRateFactor = 2
254
255 grow := cap(e.buf) <= maxBufferSize/growthSizeFactor
256
257
258 grow = grow && int64(cap(e.buf)) < e.previousOffsetEnd()/growthRateFactor
259 if grow {
260 e.buf = make([]byte, 0, cap(e.buf)*growthSizeFactor)
261 }
262
263 return nil
264 }
265
266 func (e *encodeBuffer) previousOffsetEnd() int64 { return e.baseOffset + int64(len(e.buf)) }
267 func (e *encodeBuffer) unflushedBuffer() []byte { return e.buf }
268
269
270
271 func (e *Encoder) avoidFlush() bool {
272 switch {
273 case e.tokens.last.length() == 0:
274
275
276 return true
277 case e.tokens.last.needObjectValue():
278
279
280 return true
281 case e.tokens.last.needObjectName() && len(e.buf) >= 2:
282
283 switch string(e.buf[len(e.buf)-2:]) {
284 case `ll`, `""`, `{}`, `[]`:
285 return true
286 }
287 }
288 return false
289 }
290
291
292
293 func (e *Encoder) unwriteEmptyObjectMember(prevName *string) bool {
294 if last := e.tokens.last; !last.isObject() || !last.needObjectName() || last.length() == 0 {
295 panic("BUG: must be called on an object after writing a value")
296 }
297
298
299
300 b := e.unflushedBuffer()
301
302
303 var n int
304 if len(b) >= 3 {
305 switch string(b[len(b)-2:]) {
306 case "ll":
307 n = len(`null`)
308 case `""`:
309
310
311 if b[len(b)-3] == '\\' {
312 return false
313 }
314 n = len(`""`)
315 case `{}`:
316 n = len(`{}`)
317 case `[]`:
318 n = len(`[]`)
319 }
320 }
321 if n == 0 {
322 return false
323 }
324
325
326 b = b[:len(b)-n]
327 b = trimSuffixWhitespace(b)
328 b = trimSuffixByte(b, ':')
329 b = trimSuffixString(b)
330 b = trimSuffixWhitespace(b)
331 b = trimSuffixByte(b, ',')
332 e.buf = b
333
334
335 e.tokens.last.decrement()
336 e.tokens.last.decrement()
337 if !e.options.AllowDuplicateNames {
338 if e.tokens.last.isActiveNamespace() {
339 e.namespaces.last().removeLast()
340 }
341 e.names.clearLast()
342 if prevName != nil {
343 e.names.copyQuotedBuffer(e.buf)
344 e.names.replaceLastUnquotedName(*prevName)
345 }
346 }
347 return true
348 }
349
350
351
352 func (e *Encoder) unwriteOnlyObjectMemberName() string {
353 if last := e.tokens.last; !last.isObject() || last.length() != 1 {
354 panic("BUG: must be called on an object after writing first name")
355 }
356
357
358 b := trimSuffixString(e.buf)
359 isVerbatim := bytes.IndexByte(e.buf[len(b):], '\\') < 0
360 name := string(unescapeStringMayCopy(e.buf[len(b):], isVerbatim))
361 e.buf = trimSuffixWhitespace(b)
362
363
364 e.tokens.last.decrement()
365 if !e.options.AllowDuplicateNames {
366 if e.tokens.last.isActiveNamespace() {
367 e.namespaces.last().removeLast()
368 }
369 e.names.clearLast()
370 }
371 return name
372 }
373
374 func trimSuffixWhitespace(b []byte) []byte {
375
376 n := len(b) - 1
377 for n >= 0 && (b[n] == ' ' || b[n] == '\t' || b[n] == '\r' || b[n] == '\n') {
378 n--
379 }
380 return b[:n+1]
381 }
382
383 func trimSuffixString(b []byte) []byte {
384
385 if len(b) > 0 && b[len(b)-1] == '"' {
386 b = b[:len(b)-1]
387 }
388 for len(b) >= 2 && !(b[len(b)-1] == '"' && b[len(b)-2] != '\\') {
389 b = b[:len(b)-1]
390 }
391 if len(b) > 0 && b[len(b)-1] == '"' {
392 b = b[:len(b)-1]
393 }
394 return b
395 }
396
397 func hasSuffixByte(b []byte, c byte) bool {
398
399 return len(b) > 0 && b[len(b)-1] == c
400 }
401
402 func trimSuffixByte(b []byte, c byte) []byte {
403
404 if len(b) > 0 && b[len(b)-1] == c {
405 return b[:len(b)-1]
406 }
407 return b
408 }
409
410
411
412
413
414
415
416
417
418 func (e *Encoder) WriteToken(t Token) error {
419 k := t.Kind()
420 b := e.buf
421
422
423 b = e.tokens.mayAppendDelim(b, k)
424 if e.options.multiline {
425 b = e.appendWhitespace(b, k)
426 }
427
428
429 var err error
430 switch k {
431 case 'n':
432 b = append(b, "null"...)
433 err = e.tokens.appendLiteral()
434 case 'f':
435 b = append(b, "false"...)
436 err = e.tokens.appendLiteral()
437 case 't':
438 b = append(b, "true"...)
439 err = e.tokens.appendLiteral()
440 case '"':
441 n0 := len(b)
442 if b, err = t.appendString(b, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune); err != nil {
443 break
444 }
445 if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() {
446 if !e.tokens.last.isValidNamespace() {
447 err = errInvalidNamespace
448 break
449 }
450 if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) {
451 err = &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"}
452 break
453 }
454 e.names.replaceLastQuotedOffset(n0)
455 }
456 err = e.tokens.appendString()
457 case '0':
458 if b, err = t.appendNumber(b, e.options.canonicalizeNumbers); err != nil {
459 break
460 }
461 err = e.tokens.appendNumber()
462 case '{':
463 b = append(b, '{')
464 if err = e.tokens.pushObject(); err != nil {
465 break
466 }
467 if !e.options.AllowDuplicateNames {
468 e.names.push()
469 e.namespaces.push()
470 }
471 case '}':
472 b = append(b, '}')
473 if err = e.tokens.popObject(); err != nil {
474 break
475 }
476 if !e.options.AllowDuplicateNames {
477 e.names.pop()
478 e.namespaces.pop()
479 }
480 case '[':
481 b = append(b, '[')
482 err = e.tokens.pushArray()
483 case ']':
484 b = append(b, ']')
485 err = e.tokens.popArray()
486 default:
487 return &SyntacticError{str: "invalid json.Token"}
488 }
489 if err != nil {
490 return err
491 }
492
493
494 e.buf = b
495 if e.needFlush() {
496 return e.flush()
497 }
498 return nil
499 }
500
501 const (
502 rawIntNumber = -1
503 rawUintNumber = -2
504 )
505
506
507
508
509
510 func (e *Encoder) writeNumber(v float64, bits int, quote bool) error {
511 b := e.buf
512
513
514 b = e.tokens.mayAppendDelim(b, '0')
515 if e.options.multiline {
516 b = e.appendWhitespace(b, '0')
517 }
518
519 if quote {
520
521 n0 := len(b)
522 b = append(b, '"')
523 switch bits {
524 case rawIntNumber:
525 b = strconv.AppendInt(b, int64(math.Float64bits(v)), 10)
526 case rawUintNumber:
527 b = strconv.AppendUint(b, uint64(math.Float64bits(v)), 10)
528 default:
529 b = appendNumber(b, v, bits)
530 }
531 b = append(b, '"')
532
533
534 if e.options.EscapeRune != nil {
535 b2 := append(e.unusedCache, b[n0+len(`"`):len(b)-len(`"`)]...)
536 b, _ = appendString(b[:n0], string(b2), false, e.options.EscapeRune)
537 e.unusedCache = b2[:0]
538 }
539
540
541 if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() {
542 if !e.tokens.last.isValidNamespace() {
543 return errInvalidNamespace
544 }
545 if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) {
546 return &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"}
547 }
548 e.names.replaceLastQuotedOffset(n0)
549 }
550 if err := e.tokens.appendString(); err != nil {
551 return err
552 }
553 } else {
554 switch bits {
555 case rawIntNumber:
556 b = strconv.AppendInt(b, int64(math.Float64bits(v)), 10)
557 case rawUintNumber:
558 b = strconv.AppendUint(b, uint64(math.Float64bits(v)), 10)
559 default:
560 b = appendNumber(b, v, bits)
561 }
562 if err := e.tokens.appendNumber(); err != nil {
563 return err
564 }
565 }
566
567
568 e.buf = b
569 if e.needFlush() {
570 return e.flush()
571 }
572 return nil
573 }
574
575
576
577
578
579
580
581
582
583 func (e *Encoder) WriteValue(v RawValue) error {
584 e.maxValue |= len(v)
585
586 k := v.Kind()
587 b := e.buf
588
589
590 b = e.tokens.mayAppendDelim(b, k)
591 if e.options.multiline {
592 b = e.appendWhitespace(b, k)
593 }
594
595
596 var err error
597 v = v[consumeWhitespace(v):]
598 n0 := len(b)
599 b, v, err = e.reformatValue(b, v, e.tokens.depth())
600 if err != nil {
601 return err
602 }
603 v = v[consumeWhitespace(v):]
604 if len(v) > 0 {
605 return newInvalidCharacterError(v[0:], "after top-level value")
606 }
607
608
609 switch k {
610 case 'n', 'f', 't':
611 err = e.tokens.appendLiteral()
612 case '"':
613 if !e.options.AllowDuplicateNames && e.tokens.last.needObjectName() {
614 if !e.tokens.last.isValidNamespace() {
615 err = errInvalidNamespace
616 break
617 }
618 if e.tokens.last.isActiveNamespace() && !e.namespaces.last().insertQuoted(b[n0:], false) {
619 err = &SyntacticError{str: "duplicate name " + string(b[n0:]) + " in object"}
620 break
621 }
622 e.names.replaceLastQuotedOffset(n0)
623 }
624 err = e.tokens.appendString()
625 case '0':
626 err = e.tokens.appendNumber()
627 case '{':
628 if err = e.tokens.pushObject(); err != nil {
629 break
630 }
631 if err = e.tokens.popObject(); err != nil {
632 panic("BUG: popObject should never fail immediately after pushObject: " + err.Error())
633 }
634 case '[':
635 if err = e.tokens.pushArray(); err != nil {
636 break
637 }
638 if err = e.tokens.popArray(); err != nil {
639 panic("BUG: popArray should never fail immediately after pushArray: " + err.Error())
640 }
641 }
642 if err != nil {
643 return err
644 }
645
646
647 e.buf = b
648 if e.needFlush() {
649 return e.flush()
650 }
651 return nil
652 }
653
654
655 func (e *Encoder) appendWhitespace(b []byte, next Kind) []byte {
656 if e.tokens.needDelim(next) == ':' {
657 return append(b, ' ')
658 } else {
659 return e.appendIndent(b, e.tokens.needIndent(next))
660 }
661 }
662
663
664
665 func (e *Encoder) appendIndent(b []byte, n int) []byte {
666 if n == 0 {
667 return b
668 }
669 b = append(b, '\n')
670 b = append(b, e.options.IndentPrefix...)
671 for ; n > 1; n-- {
672 b = append(b, e.options.Indent...)
673 }
674 return b
675 }
676
677
678
679
680 func (e *Encoder) reformatValue(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) {
681
682 if len(src) == 0 {
683 return dst, src, io.ErrUnexpectedEOF
684 }
685 var n int
686 var err error
687 switch k := Kind(src[0]).normalize(); k {
688 case 'n':
689 if n = consumeNull(src); n == 0 {
690 n, err = consumeLiteral(src, "null")
691 }
692 case 'f':
693 if n = consumeFalse(src); n == 0 {
694 n, err = consumeLiteral(src, "false")
695 }
696 case 't':
697 if n = consumeTrue(src); n == 0 {
698 n, err = consumeLiteral(src, "true")
699 }
700 case '"':
701 if n := consumeSimpleString(src); n > 0 && e.options.EscapeRune == nil {
702 dst, src = append(dst, src[:n]...), src[n:]
703 return dst, src, nil
704 }
705 return reformatString(dst, src, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune)
706 case '0':
707 if n := consumeSimpleNumber(src); n > 0 && !e.options.canonicalizeNumbers {
708 dst, src = append(dst, src[:n]...), src[n:]
709 return dst, src, nil
710 }
711 return reformatNumber(dst, src, e.options.canonicalizeNumbers)
712 case '{':
713 return e.reformatObject(dst, src, depth)
714 case '[':
715 return e.reformatArray(dst, src, depth)
716 default:
717 return dst, src, newInvalidCharacterError(src, "at start of value")
718 }
719 if err != nil {
720 return dst, src, err
721 }
722 dst, src = append(dst, src[:n]...), src[n:]
723 return dst, src, nil
724 }
725
726
727
728
729 func (e *Encoder) reformatObject(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) {
730
731 if src[0] != '{' {
732 panic("BUG: reformatObject must be called with a buffer that starts with '{'")
733 }
734 dst, src = append(dst, '{'), src[1:]
735
736
737 src = src[consumeWhitespace(src):]
738 if len(src) == 0 {
739 return dst, src, io.ErrUnexpectedEOF
740 }
741 if src[0] == '}' {
742 dst, src = append(dst, '}'), src[1:]
743 return dst, src, nil
744 }
745
746 var err error
747 var names *objectNamespace
748 if !e.options.AllowDuplicateNames {
749 e.namespaces.push()
750 defer e.namespaces.pop()
751 names = e.namespaces.last()
752 }
753 depth++
754 for {
755
756 if e.options.multiline {
757 dst = e.appendIndent(dst, depth)
758 }
759
760
761 src = src[consumeWhitespace(src):]
762 if len(src) == 0 {
763 return dst, src, io.ErrUnexpectedEOF
764 }
765 n0 := len(dst)
766 n := consumeSimpleString(src)
767 if n > 0 && e.options.EscapeRune == nil {
768 dst, src = append(dst, src[:n]...), src[n:]
769 } else {
770 dst, src, err = reformatString(dst, src, !e.options.AllowInvalidUTF8, e.options.preserveRawStrings, e.options.EscapeRune)
771 }
772 if err != nil {
773 return dst, src, err
774 }
775 if !e.options.AllowDuplicateNames && !names.insertQuoted(dst[n0:], false) {
776 return dst, src, &SyntacticError{str: "duplicate name " + string(dst[n0:]) + " in object"}
777 }
778
779
780 src = src[consumeWhitespace(src):]
781 if len(src) == 0 {
782 return dst, src, io.ErrUnexpectedEOF
783 }
784 if src[0] != ':' {
785 return dst, src, newInvalidCharacterError(src, "after object name (expecting ':')")
786 }
787 dst, src = append(dst, ':'), src[1:]
788 if e.options.multiline {
789 dst = append(dst, ' ')
790 }
791
792
793 src = src[consumeWhitespace(src):]
794 if len(src) == 0 {
795 return dst, src, io.ErrUnexpectedEOF
796 }
797 dst, src, err = e.reformatValue(dst, src, depth)
798 if err != nil {
799 return dst, src, err
800 }
801
802
803 src = src[consumeWhitespace(src):]
804 if len(src) == 0 {
805 return dst, src, io.ErrUnexpectedEOF
806 }
807 switch src[0] {
808 case ',':
809 dst, src = append(dst, ','), src[1:]
810 continue
811 case '}':
812 if e.options.multiline {
813 dst = e.appendIndent(dst, depth-1)
814 }
815 dst, src = append(dst, '}'), src[1:]
816 return dst, src, nil
817 default:
818 return dst, src, newInvalidCharacterError(src, "after object value (expecting ',' or '}')")
819 }
820 }
821 }
822
823
824
825
826 func (e *Encoder) reformatArray(dst []byte, src RawValue, depth int) ([]byte, RawValue, error) {
827
828 if src[0] != '[' {
829 panic("BUG: reformatArray must be called with a buffer that starts with '['")
830 }
831 dst, src = append(dst, '['), src[1:]
832
833
834 src = src[consumeWhitespace(src):]
835 if len(src) == 0 {
836 return dst, src, io.ErrUnexpectedEOF
837 }
838 if src[0] == ']' {
839 dst, src = append(dst, ']'), src[1:]
840 return dst, src, nil
841 }
842
843 var err error
844 depth++
845 for {
846
847 if e.options.multiline {
848 dst = e.appendIndent(dst, depth)
849 }
850
851
852 src = src[consumeWhitespace(src):]
853 if len(src) == 0 {
854 return dst, src, io.ErrUnexpectedEOF
855 }
856 dst, src, err = e.reformatValue(dst, src, depth)
857 if err != nil {
858 return dst, src, err
859 }
860
861
862 src = src[consumeWhitespace(src):]
863 if len(src) == 0 {
864 return dst, src, io.ErrUnexpectedEOF
865 }
866 switch src[0] {
867 case ',':
868 dst, src = append(dst, ','), src[1:]
869 continue
870 case ']':
871 if e.options.multiline {
872 dst = e.appendIndent(dst, depth-1)
873 }
874 dst, src = append(dst, ']'), src[1:]
875 return dst, src, nil
876 default:
877 return dst, src, newInvalidCharacterError(src, "after array value (expecting ',' or ']')")
878 }
879 }
880 }
881
882
883
884
885
886 func (e *Encoder) OutputOffset() int64 {
887 return e.previousOffsetEnd()
888 }
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903 func (e *Encoder) UnusedBuffer() []byte {
904
905
906
907
908
909
910 n := 1 << bits.Len(uint(e.maxValue|63))
911 if cap(e.unusedCache) < n {
912 e.unusedCache = make([]byte, 0, n)
913 }
914 return e.unusedCache
915 }
916
917
918
919
920
921
922 func (e *Encoder) StackDepth() int {
923
924 return e.tokens.depth() - 1
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938
939 func (e *Encoder) StackIndex(i int) (Kind, int) {
940
941 switch s := e.tokens.index(i); {
942 case i > 0 && s.isObject():
943 return '{', s.length()
944 case i > 0 && s.isArray():
945 return '[', s.length()
946 default:
947 return 0, s.length()
948 }
949 }
950
951
952
953
954 func (e *Encoder) StackPointer() string {
955 e.names.copyQuotedBuffer(e.buf)
956 return string(e.appendStackPointer(nil))
957 }
958
959
960
961
962
963
964
965
966
967
968
969
970 func appendString(dst []byte, src string, validateUTF8 bool, escapeRune func(rune) bool) ([]byte, error) {
971 appendEscapedASCII := func(dst []byte, c byte) []byte {
972 switch c {
973 case '"', '\\':
974 dst = append(dst, '\\', c)
975 case '\b':
976 dst = append(dst, "\\b"...)
977 case '\f':
978 dst = append(dst, "\\f"...)
979 case '\n':
980 dst = append(dst, "\\n"...)
981 case '\r':
982 dst = append(dst, "\\r"...)
983 case '\t':
984 dst = append(dst, "\\t"...)
985 default:
986 dst = append(dst, "\\u"...)
987 dst = appendHexUint16(dst, uint16(c))
988 }
989 return dst
990 }
991 appendEscapedUnicode := func(dst []byte, r rune) []byte {
992 if r1, r2 := utf16.EncodeRune(r); r1 != '\ufffd' && r2 != '\ufffd' {
993 dst = append(dst, "\\u"...)
994 dst = appendHexUint16(dst, uint16(r1))
995 dst = append(dst, "\\u"...)
996 dst = appendHexUint16(dst, uint16(r2))
997 } else {
998 dst = append(dst, "\\u"...)
999 dst = appendHexUint16(dst, uint16(r))
1000 }
1001 return dst
1002 }
1003
1004
1005 if escapeRune == nil {
1006 var i, n int
1007 dst = append(dst, '"')
1008 for uint(len(src)) > uint(n) {
1009
1010 if c := src[n]; c < utf8.RuneSelf {
1011 n++
1012 if c < ' ' || c == '"' || c == '\\' {
1013 dst = append(dst, src[i:n-1]...)
1014 dst = appendEscapedASCII(dst, c)
1015 i = n
1016 }
1017 continue
1018 }
1019
1020
1021 _, rn := utf8.DecodeRuneInString(src[n:])
1022 n += rn
1023 if rn == 1 {
1024 dst = append(dst, src[i:n-rn]...)
1025 if validateUTF8 {
1026 return dst, &SyntacticError{str: "invalid UTF-8 within string"}
1027 }
1028 dst = append(dst, "\ufffd"...)
1029 i = n
1030 }
1031 }
1032 dst = append(dst, src[i:n]...)
1033 dst = append(dst, '"')
1034 return dst, nil
1035 }
1036
1037
1038 var i, n int
1039 dst = append(dst, '"')
1040 for uint(len(src)) > uint(n) {
1041 switch r, rn := utf8.DecodeRuneInString(src[n:]); {
1042 case r == utf8.RuneError && rn == 1:
1043 dst = append(dst, src[i:n]...)
1044 if validateUTF8 {
1045 return dst, &SyntacticError{str: "invalid UTF-8 within string"}
1046 }
1047 if escapeRune('\ufffd') {
1048 dst = append(dst, `\ufffd`...)
1049 } else {
1050 dst = append(dst, "\ufffd"...)
1051 }
1052 n += rn
1053 i = n
1054 case escapeRune(r):
1055 dst = append(dst, src[i:n]...)
1056 dst = appendEscapedUnicode(dst, r)
1057 n += rn
1058 i = n
1059 case r < ' ' || r == '"' || r == '\\':
1060 dst = append(dst, src[i:n]...)
1061 dst = appendEscapedASCII(dst, byte(r))
1062 n += rn
1063 i = n
1064 default:
1065 n += rn
1066 }
1067 }
1068 dst = append(dst, src[i:n]...)
1069 dst = append(dst, '"')
1070 return dst, nil
1071 }
1072
1073
1074
1075
1076 func reformatString(dst, src []byte, validateUTF8, preserveRaw bool, escapeRune func(rune) bool) ([]byte, []byte, error) {
1077
1078 var flags valueFlags
1079 n, err := consumeString(&flags, src, validateUTF8)
1080 if err != nil {
1081 return dst, src[n:], err
1082 }
1083 if preserveRaw || (escapeRune == nil && flags.isCanonical()) {
1084 dst = append(dst, src[:n]...)
1085 return dst, src[n:], nil
1086 }
1087
1088
1089
1090
1091
1092 b, _ := unescapeString(make([]byte, 0, n), src[:n])
1093 dst, _ = appendString(dst, string(b), validateUTF8, escapeRune)
1094 return dst, src[n:], nil
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108 func appendNumber(dst []byte, src float64, bits int) []byte {
1109 if bits == 32 {
1110 src = float64(float32(src))
1111 }
1112
1113 abs := math.Abs(src)
1114 fmt := byte('f')
1115 if abs != 0 {
1116 if bits == 64 && (float64(abs) < 1e-6 || float64(abs) >= 1e21) ||
1117 bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
1118 fmt = 'e'
1119 }
1120 }
1121 dst = strconv.AppendFloat(dst, src, fmt, -1, bits)
1122 if fmt == 'e' {
1123
1124 n := len(dst)
1125 if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' {
1126 dst[n-2] = dst[n-1]
1127 dst = dst[:n-1]
1128 }
1129 }
1130 return dst
1131 }
1132
1133
1134
1135
1136 func reformatNumber(dst, src []byte, canonicalize bool) ([]byte, []byte, error) {
1137 n, err := consumeNumber(src)
1138 if err != nil {
1139 return dst, src[n:], err
1140 }
1141 if !canonicalize {
1142 dst = append(dst, src[:n]...)
1143 return dst, src[n:], nil
1144 }
1145
1146
1147
1148 const maxExactIntegerDigits = 16
1149 if n < maxExactIntegerDigits && consumeSimpleNumber(src[:n]) == n {
1150 dst = append(dst, src[:n]...)
1151 return dst, src[n:], nil
1152 }
1153 fv, _ := strconv.ParseFloat(string(src[:n]), 64)
1154 switch {
1155 case fv == 0:
1156 fv = 0
1157 case math.IsInf(fv, +1):
1158 fv = +math.MaxFloat64
1159 case math.IsInf(fv, -1):
1160 fv = -math.MaxFloat64
1161 }
1162 return appendNumber(dst, fv, 64), src[n:], nil
1163 }
1164
1165
1166 func appendHexUint16(dst []byte, src uint16) []byte {
1167 dst = append(dst, "0000"[1+(bits.Len16(src)-1)/4:]...)
1168 dst = strconv.AppendUint(dst, uint64(src), 16)
1169 return dst
1170 }
1171
View as plain text