OSDN Git Service

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