1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // Compact appends to dst the JSON-encoded src with
10 // insignificant space characters elided.
11 func Compact(dst *bytes.Buffer, src []byte) error {
12 return compact(dst, src, false)
15 func compact(dst *bytes.Buffer, src []byte, escape bool) error {
20 for i, c := range src {
21 if escape && (c == '<' || c == '>' || c == '&') {
23 dst.Write(src[start:i])
25 dst.WriteString(`\u00`)
26 dst.WriteByte(hex[c>>4])
27 dst.WriteByte(hex[c&0xF])
30 // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
31 if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
33 dst.Write(src[start:i])
35 dst.WriteString(`\u202`)
36 dst.WriteByte(hex[src[i+2]&0xF])
39 v := scan.step(&scan, c)
40 if v >= scanSkipSpace {
45 dst.Write(src[start:i])
50 if scan.eof() == scanError {
55 dst.Write(src[start:])
60 func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
62 dst.WriteString(prefix)
63 for i := 0; i < depth; i++ {
64 dst.WriteString(indent)
68 // Indent appends to dst an indented form of the JSON-encoded src.
69 // Each element in a JSON object or array begins on a new,
70 // indented line beginning with prefix followed by one or more
71 // copies of indent according to the indentation nesting.
72 // The data appended to dst does not begin with the prefix nor
73 // any indentation, to make it easier to embed inside other formatted JSON data.
74 // Although leading space characters (space, tab, carriage return, newline)
75 // at the beginning of src are dropped, trailing space characters
76 // at the end of src are preserved and copied to dst.
77 // For example, if src has no trailing spaces, neither will dst;
78 // if src ends in a trailing newline, so will dst.
79 func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
85 for _, c := range src {
87 v := scan.step(&scan, c)
88 if v == scanSkipSpace {
94 if needIndent && v != scanEndObject && v != scanEndArray {
97 newline(dst, prefix, indent, depth)
100 // Emit semantically uninteresting bytes
101 // (in particular, punctuation in strings) unmodified.
102 if v == scanContinue {
107 // Add spacing around real punctuation.
110 // delay indent so that empty object and array are formatted as {} and [].
116 newline(dst, prefix, indent, depth)
124 // suppress indent in empty object/array
128 newline(dst, prefix, indent, depth)
136 if scan.eof() == scanError {
137 dst.Truncate(origLen)