string called by `any` or `object`(for map keys) after reading `"`
()
| 242 | |
| 243 | // string called by `any` or `object`(for map keys) after reading `"` |
| 244 | func (d *Decoder) string() (string, error) { |
| 245 | d.scratch.reset() |
| 246 | |
| 247 | var c = d.next() |
| 248 | |
| 249 | scan: |
| 250 | for { |
| 251 | switch { |
| 252 | case c == '"': |
| 253 | return string(d.scratch.bytes()), nil |
| 254 | case c == '\\': |
| 255 | c = d.next() |
| 256 | goto scan_esc |
| 257 | case c < 0x20: |
| 258 | return "", d.mkError(ErrSyntax, "in string literal") |
| 259 | // Coerce to well-formed UTF-8. |
| 260 | default: |
| 261 | d.scratch.add(c) |
| 262 | if d.remaining() == 0 { |
| 263 | return "", d.mkError(ErrSyntax, "in string literal") |
| 264 | } |
| 265 | c = d.next() |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | scan_esc: |
| 270 | switch c { |
| 271 | case '"', '\\', '/', '\'': |
| 272 | d.scratch.add(c) |
| 273 | case 'u': |
| 274 | goto scan_u |
| 275 | case 'b': |
| 276 | d.scratch.add('\b') |
| 277 | case 'f': |
| 278 | d.scratch.add('\f') |
| 279 | case 'n': |
| 280 | d.scratch.add('\n') |
| 281 | case 'r': |
| 282 | d.scratch.add('\r') |
| 283 | case 't': |
| 284 | d.scratch.add('\t') |
| 285 | default: |
| 286 | return "", d.mkError(ErrSyntax, "in string escape code") |
| 287 | } |
| 288 | c = d.next() |
| 289 | goto scan |
| 290 | |
| 291 | scan_u: |
| 292 | r := d.u4() |
| 293 | if r < 0 { |
| 294 | return "", d.mkError(ErrSyntax, "in unicode escape sequence") |
| 295 | } |
| 296 | |
| 297 | // check for proceeding surrogate pair |
| 298 | c = d.next() |
| 299 | if !utf16.IsSurrogate(r) || c != '\\' { |
| 300 | d.scratch.addRune(r) |
| 301 | goto scan |