Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / json / indent.go
blob000da42f6fb0d53a2b35fc803f1c84df6ca34485
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.
5 package json
7 import (
8 "bytes"
9 "os"
12 // Compact appends to dst the JSON-encoded src with
13 // insignificant space characters elided.
14 func Compact(dst *bytes.Buffer, src []byte) os.Error {
15 origLen := dst.Len()
16 var scan scanner
17 scan.reset()
18 start := 0
19 for i, c := range src {
20 v := scan.step(&scan, int(c))
21 if v >= scanSkipSpace {
22 if v == scanError {
23 break
25 if start < i {
26 dst.Write(src[start:i])
28 start = i + 1
31 if scan.eof() == scanError {
32 dst.Truncate(origLen)
33 return scan.err
35 if start < len(src) {
36 dst.Write(src[start:])
38 return nil
41 func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
42 dst.WriteByte('\n')
43 dst.WriteString(prefix)
44 for i := 0; i < depth; i++ {
45 dst.WriteString(indent)
49 // Indent appends to dst an indented form of the JSON-encoded src.
50 // Each element in a JSON object or array begins on a new,
51 // indented line beginning with prefix followed by one or more
52 // copies of indent according to the indentation nesting.
53 // The data appended to dst has no trailing newline, to make it easier
54 // to embed inside other formatted JSON data.
55 func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) os.Error {
56 origLen := dst.Len()
57 var scan scanner
58 scan.reset()
59 needIndent := false
60 depth := 0
61 for _, c := range src {
62 v := scan.step(&scan, int(c))
63 if v == scanSkipSpace {
64 continue
66 if v == scanError {
67 break
69 if needIndent && v != scanEndObject && v != scanEndArray {
70 needIndent = false
71 depth++
72 newline(dst, prefix, indent, depth)
75 // Emit semantically uninteresting bytes
76 // (in particular, punctuation in strings) unmodified.
77 if v == scanContinue {
78 dst.WriteByte(c)
79 continue
82 // Add spacing around real punctuation.
83 switch c {
84 case '{', '[':
85 // delay indent so that empty object and array are formatted as {} and [].
86 needIndent = true
87 dst.WriteByte(c)
89 case ',':
90 dst.WriteByte(c)
91 newline(dst, prefix, indent, depth)
93 case ':':
94 dst.WriteByte(c)
95 dst.WriteByte(' ')
97 case '}', ']':
98 if needIndent {
99 // suppress indent in empty object/array
100 needIndent = false
101 } else {
102 depth--
103 newline(dst, prefix, indent, depth)
105 dst.WriteByte(c)
107 default:
108 dst.WriteByte(c)
111 if scan.eof() == scanError {
112 dst.Truncate(origLen)
113 return scan.err
115 return nil