Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(8)

Delta Between Two Patch Sets: src/pkg/json/encode.go

Issue 1496042: code review 1496042: json: Add HTMLEscape
Left Patch Set: Created 14 years, 9 months ago
Right Patch Set: code review 1496042: json: Add HTMLEscape Created 14 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/json/decode_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2010 The Go Authors. All rights reserved. 1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package json 5 package json
6 6
7 import ( 7 import (
8 "os" 8 "os"
9 "bytes" 9 "bytes"
10 "reflect" 10 "reflect"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 return nil, err 69 return nil, err
70 } 70 }
71 var buf bytes.Buffer 71 var buf bytes.Buffer
72 err = Indent(&buf, b, prefix, indent) 72 err = Indent(&buf, b, prefix, indent)
73 if err != nil { 73 if err != nil {
74 return nil, err 74 return nil, err
75 } 75 }
76 return buf.Bytes(), nil 76 return buf.Bytes(), nil
77 } 77 }
78 78
79 // HTMLEscape re-encodes <, >, and & characters in JSON data so 79 // MarshalForHTML is like Marshal but applies HTMLEscape to the output.
80 // they may be safely embedded in HTML. For historical reasons, 80 func MarshalForHTML(v interface{}) ([]byte, os.Error) {
81 // browsers don't honor standard HTML escaping within <script> 81 » b, err := Marshal(v)
82 // tags, so an alternative JSON encoding must be used. 82 » if err != nil {
83 func HTMLEscape(json []byte) []byte { 83 » » return nil, err
84 » var b bytes.Buffer 84 » }
85 » for _, c := range json { 85 » var buf bytes.Buffer
86 » » switch c { 86 » HTMLEscape(&buf, b)
87 » » case '<', '>', '&': 87 » return buf.Bytes(), nil
88 » » » b.WriteString(`\u00`) 88 }
89 » » » b.WriteByte(hex[c>>4]) 89
90 » » » b.WriteByte(hex[c&0xF]) 90 // HTMLEscape appends to dst the JSON-encoded src with <, >, and &
91 » » default: 91 // characters inside string literals changed to \u003c, \u003e, \u0026
92 » » » b.WriteByte(c) 92 // so that the JSON will be safe to embed inside HTML <script> tags.
93 » » } 93 // For historical reasons, web browsers don't honor standard HTML
94 » } 94 // escaping within <script> tags, so an alternative JSON encoding must
95 » return b.Bytes() 95 // be used.
96 func HTMLEscape(dst *bytes.Buffer, src []byte) {
97 » // < > & can only appear in string literals,
98 » // so just scan the string one byte at a time.
99 » start := 0
100 » for i, c := range src {
101 » » if c == '<' || c == '>' || c == '&' {
102 » » » if start < i {
103 » » » » dst.Write(src[start:i])
104 » » » }
105 » » » dst.WriteString(`\u00`)
106 » » » dst.WriteByte(hex[c>>4])
107 » » » dst.WriteByte(hex[c&0xF])
108 » » » start = i + 1
109 » » }
110 » }
111 » if start < len(src) {
112 » » dst.Write(src[start:])
113 » }
96 } 114 }
97 115
98 // Marshaler is the interface implemented by objects that 116 // Marshaler is the interface implemented by objects that
99 // can marshal themselves into valid JSON. 117 // can marshal themselves into valid JSON.
100 type Marshaler interface { 118 type Marshaler interface {
101 MarshalJSON() ([]byte, os.Error) 119 MarshalJSON() ([]byte, os.Error)
102 } 120 }
103 121
104 type UnsupportedTypeError struct { 122 type UnsupportedTypeError struct {
105 Type reflect.Type 123 Type reflect.Type
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 switch v := v.(type) { 186 switch v := v.(type) {
169 case *reflect.BoolValue: 187 case *reflect.BoolValue:
170 x := v.Get() 188 x := v.Get()
171 if x { 189 if x {
172 e.WriteString("true") 190 e.WriteString("true")
173 } else { 191 } else {
174 e.WriteString("false") 192 e.WriteString("false")
175 } 193 }
176 194
177 case *reflect.IntValue: 195 case *reflect.IntValue:
178 e.WriteString(strconv.Itoa(v.Get()))
179 case *reflect.Int8Value:
180 e.WriteString(strconv.Itoa(int(v.Get())))
181 case *reflect.Int16Value:
182 e.WriteString(strconv.Itoa(int(v.Get())))
183 case *reflect.Int32Value:
184 e.WriteString(strconv.Itoa(int(v.Get())))
185 case *reflect.Int64Value:
186 e.WriteString(strconv.Itoa64(v.Get())) 196 e.WriteString(strconv.Itoa64(v.Get()))
187 197
188 case *reflect.UintValue: 198 case *reflect.UintValue:
189 e.WriteString(strconv.Uitoa(v.Get()))
190 case *reflect.Uint8Value:
191 e.WriteString(strconv.Uitoa(uint(v.Get())))
192 case *reflect.Uint16Value:
193 e.WriteString(strconv.Uitoa(uint(v.Get())))
194 case *reflect.Uint32Value:
195 e.WriteString(strconv.Uitoa(uint(v.Get())))
196 case *reflect.Uint64Value:
197 e.WriteString(strconv.Uitoa64(v.Get())) 199 e.WriteString(strconv.Uitoa64(v.Get()))
198 case *reflect.UintptrValue:
199 e.WriteString(strconv.Uitoa64(uint64(v.Get())))
200 200
201 case *reflect.FloatValue: 201 case *reflect.FloatValue:
202 » » e.WriteString(strconv.Ftoa(v.Get(), 'g', -1)) 202 » » e.WriteString(strconv.FtoaN(v.Get(), 'g', -1, v.Type().Bits()))
203 » case *reflect.Float32Value:
204 » » e.WriteString(strconv.Ftoa32(v.Get(), 'g', -1))
205 » case *reflect.Float64Value:
206 » » e.WriteString(strconv.Ftoa64(v.Get(), 'g', -1))
207 203
208 case *reflect.StringValue: 204 case *reflect.StringValue:
209 e.string(v.Get()) 205 e.string(v.Get())
210 206
211 case *reflect.StructValue: 207 case *reflect.StructValue:
212 e.WriteByte('{') 208 e.WriteByte('{')
213 t := v.Type().(*reflect.StructType) 209 t := v.Type().(*reflect.StructType)
214 n := v.NumField() 210 n := v.NumField()
215 for i := 0; i < n; i++ { 211 for i := 0; i < n; i++ {
216 if i > 0 { 212 if i > 0 {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 e.WriteByte(hex[c&0xF]) 287 e.WriteByte(hex[c&0xF])
292 case c == '\\' || c == '"': 288 case c == '\\' || c == '"':
293 e.WriteByte('\\') 289 e.WriteByte('\\')
294 fallthrough 290 fallthrough
295 default: 291 default:
296 e.WriteRune(c) 292 e.WriteRune(c)
297 } 293 }
298 } 294 }
299 e.WriteByte('"') 295 e.WriteByte('"')
300 } 296 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b