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
)