...
1
2
3
4
5 package json
6
7 import "bytes"
8
9
10
11 func Compact(dst *bytes.Buffer, src []byte) error {
12 return compact(dst, src, false)
13 }
14
15 func compact(dst *bytes.Buffer, src []byte, escape bool) error {
16 origLen := dst.Len()
17 var scan scanner
18 scan.reset()
19 start := 0
20 for i, c := range src {
21 if escape && (c == '<' || c == '>' || c == '&') {
22 if start < i {
23 dst.Write(src[start:i])
24 }
25 dst.WriteString(`\u00`)
26 dst.WriteByte(hex[c>>4])
27 dst.WriteByte(hex[c&0xF])
28 start = i + 1
29 }
30
31 if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
32 if start < i {
33 dst.Write(src[start:i])
34 }
35 dst.WriteString(`\u202`)
36 dst.WriteByte(hex[src[i+2]&0xF])
37 start = i + 3
38 }
39 v := scan.step(&scan, c)
40 if v >= scanSkipSpace {
41 if v == scanError {
42 break
43 }
44 if start < i {
45 dst.Write(src[start:i])
46 }
47 start = i + 1
48 }
49 }
50 if scan.eof() == scanError {
51 dst.Truncate(origLen)
52 return scan.err
53 }
54 if start < len(src) {
55 dst.Write(src[start:])
56 }
57 return nil
58 }
59
60 func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
61 dst.WriteByte('\n')
62 dst.WriteString(prefix)
63 for i := 0; i < depth; i++ {
64 dst.WriteString(indent)
65 }
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79 func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
80 origLen := dst.Len()
81 var scan scanner
82 scan.reset()
83 needIndent := false
84 depth := 0
85 for _, c := range src {
86 scan.bytes++
87 v := scan.step(&scan, c)
88 if v == scanSkipSpace {
89 continue
90 }
91 if v == scanError {
92 break
93 }
94 if needIndent && v != scanEndObject && v != scanEndArray {
95 needIndent = false
96 depth++
97 newline(dst, prefix, indent, depth)
98 }
99
100
101
102 if v == scanContinue {
103 dst.WriteByte(c)
104 continue
105 }
106
107
108 switch c {
109 case '{', '[':
110
111 needIndent = true
112 dst.WriteByte(c)
113
114 case ',':
115 dst.WriteByte(c)
116 newline(dst, prefix, indent, depth)
117
118 case ':':
119 dst.WriteByte(c)
120 dst.WriteByte(' ')
121
122 case '}', ']':
123 if needIndent {
124
125 needIndent = false
126 } else {
127 depth--
128 newline(dst, prefix, indent, depth)
129 }
130 dst.WriteByte(c)
131
132 default:
133 dst.WriteByte(c)
134 }
135 }
136 if scan.eof() == scanError {
137 dst.Truncate(origLen)
138 return scan.err
139 }
140 return nil
141 }
142
View as plain text