Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: sdk/lib/convert/json.dart

Issue 2754013002: Format all dart: library files (Closed)
Patch Set: Format all dart: library files Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sdk/lib/convert/html_escape.dart ('k') | sdk/lib/convert/latin1.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.convert; 5 part of dart.convert;
6 6
7 /** 7 /**
8 * Error thrown by JSON serialization if an object cannot be serialized. 8 * Error thrown by JSON serialization if an object cannot be serialized.
9 * 9 *
10 * The [unsupportedObject] field holds that object that failed to be serialized. 10 * The [unsupportedObject] field holds that object that failed to be serialized.
11 * 11 *
12 * If an object isn't directly serializable, the serializer calls the `toJson` 12 * If an object isn't directly serializable, the serializer calls the `toJson`
13 * method on the object. If that call fails, the error will be stored in the 13 * method on the object. If that call fails, the error will be stored in the
14 * [cause] field. If the call returns an object that isn't directly 14 * [cause] field. If the call returns an object that isn't directly
15 * serializable, the [cause] is null. 15 * serializable, the [cause] is null.
16 */ 16 */
17 class JsonUnsupportedObjectError extends Error { 17 class JsonUnsupportedObjectError extends Error {
18 /** The object that could not be serialized. */ 18 /** The object that could not be serialized. */
19 final unsupportedObject; 19 final unsupportedObject;
20 /** The exception thrown when trying to convert the object. */ 20 /** The exception thrown when trying to convert the object. */
21 final cause; 21 final cause;
22 22
23 JsonUnsupportedObjectError(this.unsupportedObject, { this.cause }); 23 JsonUnsupportedObjectError(this.unsupportedObject, {this.cause});
24 24
25 String toString() { 25 String toString() {
26 if (cause != null) { 26 if (cause != null) {
27 return "Converting object to an encodable object failed."; 27 return "Converting object to an encodable object failed.";
28 } else { 28 } else {
29 return "Converting object did not return an encodable object."; 29 return "Converting object did not return an encodable object.";
30 } 30 }
31 } 31 }
32 } 32 }
33 33
34
35 /** 34 /**
36 * Reports that an object could not be stringified due to cyclic references. 35 * Reports that an object could not be stringified due to cyclic references.
37 * 36 *
38 * An object that references itself cannot be serialized by [stringify]. 37 * An object that references itself cannot be serialized by [stringify].
39 * When the cycle is detected, a [JsonCyclicError] is thrown. 38 * When the cycle is detected, a [JsonCyclicError] is thrown.
40 */ 39 */
41 class JsonCyclicError extends JsonUnsupportedObjectError { 40 class JsonCyclicError extends JsonUnsupportedObjectError {
42 /** The first object that was detected as part of a cycle. */ 41 /** The first object that was detected as part of a cycle. */
43 JsonCyclicError(Object object): super(object); 42 JsonCyclicError(Object object) : super(object);
44 String toString() => "Cyclic error in JSON stringify"; 43 String toString() => "Cyclic error in JSON stringify";
45 } 44 }
46 45
47
48 /** 46 /**
49 * An instance of the default implementation of the [JsonCodec]. 47 * An instance of the default implementation of the [JsonCodec].
50 * 48 *
51 * This instance provides a convenient access to the most common JSON 49 * This instance provides a convenient access to the most common JSON
52 * use cases. 50 * use cases.
53 * 51 *
54 * Examples: 52 * Examples:
55 * 53 *
56 * var encoded = JSON.encode([1, 2, { "a": null }]); 54 * var encoded = JSON.encode([1, 2, { "a": null }]);
57 * var decoded = JSON.decode('["foo", { "bar": 499 }]'); 55 * var decoded = JSON.decode('["foo", { "bar": 499 }]');
58 */ 56 */
59 const JsonCodec JSON = const JsonCodec(); 57 const JsonCodec JSON = const JsonCodec();
60 58
61 typedef _Reviver(var key, var value); 59 typedef _Reviver(var key, var value);
62 typedef _ToEncodable(var o); 60 typedef _ToEncodable(var o);
63 61
64
65 /** 62 /**
66 * A [JsonCodec] encodes JSON objects to strings and decodes strings to 63 * A [JsonCodec] encodes JSON objects to strings and decodes strings to
67 * JSON objects. 64 * JSON objects.
68 * 65 *
69 * Examples: 66 * Examples:
70 * 67 *
71 * var encoded = JSON.encode([1, 2, { "a": null }]); 68 * var encoded = JSON.encode([1, 2, { "a": null }]);
72 * var decoded = JSON.decode('["foo", { "bar": 499 }]'); 69 * var decoded = JSON.decode('["foo", { "bar": 499 }]');
73 */ 70 */
74 class JsonCodec extends Codec<Object, String> { 71 class JsonCodec extends Codec<Object, String> {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 * The converter works more efficiently if the given [sink] is a 248 * The converter works more efficiently if the given [sink] is a
252 * [StringConversionSink]. 249 * [StringConversionSink].
253 * 250 *
254 * Returns a chunked-conversion sink that accepts at most one object. It is 251 * Returns a chunked-conversion sink that accepts at most one object. It is
255 * an error to invoke `add` more than once on the returned sink. 252 * an error to invoke `add` more than once on the returned sink.
256 */ 253 */
257 ChunkedConversionSink<Object> startChunkedConversion(Sink<String> sink) { 254 ChunkedConversionSink<Object> startChunkedConversion(Sink<String> sink) {
258 if (sink is! StringConversionSink) { 255 if (sink is! StringConversionSink) {
259 sink = new StringConversionSink.from(sink); 256 sink = new StringConversionSink.from(sink);
260 } else if (sink is _Utf8EncoderSink) { 257 } else if (sink is _Utf8EncoderSink) {
261 return new _JsonUtf8EncoderSink(sink._sink, _toEncodable, 258 return new _JsonUtf8EncoderSink(
262 JsonUtf8Encoder._utf8Encode(indent), 259 sink._sink,
263 JsonUtf8Encoder.DEFAULT_BUFFER_SIZE); 260 _toEncodable,
261 JsonUtf8Encoder._utf8Encode(indent),
262 JsonUtf8Encoder.DEFAULT_BUFFER_SIZE);
264 } 263 }
265 return new _JsonEncoderSink(sink, _toEncodable, indent); 264 return new _JsonEncoderSink(sink, _toEncodable, indent);
266 } 265 }
267 266
268 // Override the base class's bind, to provide a better type. 267 // Override the base class's bind, to provide a better type.
269 Stream<String> bind(Stream<Object> stream) => super.bind(stream); 268 Stream<String> bind(Stream<Object> stream) => super.bind(stream);
270 269
271 Converter<Object, T> fuse<T>(Converter<String, T> other) { 270 Converter<Object, T> fuse<T>(Converter<String, T> other) {
272 if (other is Utf8Encoder) { 271 if (other is Utf8Encoder) {
273 return new JsonUtf8Encoder(indent, _toEncodable) 272 return new JsonUtf8Encoder(indent, _toEncodable)
274 as dynamic/*=Converter<Object, T>*/; 273 as dynamic/*=Converter<Object, T>*/;
275 } 274 }
276 return super.fuse<T>(other); 275 return super.fuse<T>(other);
277 } 276 }
278 } 277 }
279 278
280 /** 279 /**
281 * Encoder that encodes a single object as a UTF-8 encoded JSON string. 280 * Encoder that encodes a single object as a UTF-8 encoded JSON string.
282 * 281 *
283 * This encoder works equivalently to first converting the object to 282 * This encoder works equivalently to first converting the object to
284 * a JSON string, and then UTF-8 encoding the string, but without 283 * a JSON string, and then UTF-8 encoding the string, but without
285 * creating an intermediate string. 284 * creating an intermediate string.
286 */ 285 */
287 class JsonUtf8Encoder extends Converter<Object, List<int>> 286 class JsonUtf8Encoder extends Converter<Object, List<int>>
288 implements ChunkedConverter<Object, List<int>, Object, List<int>> { 287 implements ChunkedConverter<Object, List<int>, Object, List<int>> {
289
290 /** Default buffer size used by the JSON-to-UTF-8 encoder. */ 288 /** Default buffer size used by the JSON-to-UTF-8 encoder. */
291 static const int DEFAULT_BUFFER_SIZE = 256; 289 static const int DEFAULT_BUFFER_SIZE = 256;
292 /** Indentation used in pretty-print mode, `null` if not pretty. */ 290 /** Indentation used in pretty-print mode, `null` if not pretty. */
293 final List<int> _indent; 291 final List<int> _indent;
294 /** Function called with each un-encodable object encountered. */ 292 /** Function called with each un-encodable object encountered. */
295 final _ToEncodable _toEncodable; 293 final _ToEncodable _toEncodable;
296 /** UTF-8 buffer size. */ 294 /** UTF-8 buffer size. */
297 final int _bufferSize; 295 final int _bufferSize;
298 296
299 /** 297 /**
(...skipping 14 matching lines...) Expand all
314 * 312 *
315 * The JSON encoder handles numbers, strings, booleans, null, lists and maps 313 * The JSON encoder handles numbers, strings, booleans, null, lists and maps
316 * directly. 314 * directly.
317 * 315 *
318 * Any other object is attempted converted by [toEncodable] to an object that 316 * Any other object is attempted converted by [toEncodable] to an object that
319 * is of one of the convertible types. 317 * is of one of the convertible types.
320 * 318 *
321 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the 319 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
322 * object. 320 * object.
323 */ 321 */
324 JsonUtf8Encoder([String indent, 322 JsonUtf8Encoder(
325 toEncodable(object), 323 [String indent,
326 int bufferSize = DEFAULT_BUFFER_SIZE]) 324 toEncodable(object),
325 int bufferSize = DEFAULT_BUFFER_SIZE])
327 : _indent = _utf8Encode(indent), 326 : _indent = _utf8Encode(indent),
328 _toEncodable = toEncodable, 327 _toEncodable = toEncodable,
329 _bufferSize = bufferSize; 328 _bufferSize = bufferSize;
330 329
331 static List<int> _utf8Encode(String string) { 330 static List<int> _utf8Encode(String string) {
332 if (string == null) return null; 331 if (string == null) return null;
333 if (string.isEmpty) return new Uint8List(0); 332 if (string.isEmpty) return new Uint8List(0);
334 checkAscii: { 333 checkAscii:
334 {
335 for (int i = 0; i < string.length; i++) { 335 for (int i = 0; i < string.length; i++) {
336 if (string.codeUnitAt(i) >= 0x80) break checkAscii; 336 if (string.codeUnitAt(i) >= 0x80) break checkAscii;
337 } 337 }
338 return string.codeUnits; 338 return string.codeUnits;
339 } 339 }
340 return UTF8.encode(string); 340 return UTF8.encode(string);
341 } 341 }
342 342
343 /** Convert [object] into UTF-8 encoded JSON. */ 343 /** Convert [object] into UTF-8 encoded JSON. */
344 List<int> convert(Object object) { 344 List<int> convert(Object object) {
345 List<List<int>> bytes = []; 345 List<List<int>> bytes = [];
346 // The `stringify` function always converts into chunks. 346 // The `stringify` function always converts into chunks.
347 // Collect the chunks into the `bytes` list, then combine them afterwards. 347 // Collect the chunks into the `bytes` list, then combine them afterwards.
348 void addChunk(Uint8List chunk, int start, int end) { 348 void addChunk(Uint8List chunk, int start, int end) {
349 if (start > 0 || end < chunk.length) { 349 if (start > 0 || end < chunk.length) {
350 int length = end - start; 350 int length = end - start;
351 chunk = new Uint8List.view(chunk.buffer, 351 chunk = new Uint8List.view(
352 chunk.offsetInBytes + start, 352 chunk.buffer, chunk.offsetInBytes + start, length);
353 length);
354 } 353 }
355 bytes.add(chunk); 354 bytes.add(chunk);
356 } 355 }
357 _JsonUtf8Stringifier.stringify(object, 356
358 _indent, 357 _JsonUtf8Stringifier.stringify(
359 _toEncodable, 358 object, _indent, _toEncodable, _bufferSize, addChunk);
360 _bufferSize,
361 addChunk);
362 if (bytes.length == 1) return bytes[0]; 359 if (bytes.length == 1) return bytes[0];
363 int length = 0; 360 int length = 0;
364 for (int i = 0; i < bytes.length; i++) { 361 for (int i = 0; i < bytes.length; i++) {
365 length += bytes[i].length; 362 length += bytes[i].length;
366 } 363 }
367 Uint8List result = new Uint8List(length); 364 Uint8List result = new Uint8List(length);
368 for (int i = 0, offset = 0; i < bytes.length; i++) { 365 for (int i = 0, offset = 0; i < bytes.length; i++) {
369 var byteList = bytes[i]; 366 var byteList = bytes[i];
370 int end = offset + byteList.length; 367 int end = offset + byteList.length;
371 result.setRange(offset, end, byteList); 368 result.setRange(offset, end, byteList);
(...skipping 10 matching lines...) Expand all
382 * The argument [sink] will receive byte lists in sizes depending on the 379 * The argument [sink] will receive byte lists in sizes depending on the
383 * `bufferSize` passed to the constructor when creating this encoder. 380 * `bufferSize` passed to the constructor when creating this encoder.
384 */ 381 */
385 ChunkedConversionSink<Object> startChunkedConversion(Sink<List<int>> sink) { 382 ChunkedConversionSink<Object> startChunkedConversion(Sink<List<int>> sink) {
386 ByteConversionSink byteSink; 383 ByteConversionSink byteSink;
387 if (sink is ByteConversionSink) { 384 if (sink is ByteConversionSink) {
388 byteSink = sink; 385 byteSink = sink;
389 } else { 386 } else {
390 byteSink = new ByteConversionSink.from(sink); 387 byteSink = new ByteConversionSink.from(sink);
391 } 388 }
392 return new _JsonUtf8EncoderSink(byteSink, _toEncodable, 389 return new _JsonUtf8EncoderSink(
393 _indent, _bufferSize); 390 byteSink, _toEncodable, _indent, _bufferSize);
394 } 391 }
395 392
396 // Override the base class's bind, to provide a better type. 393 // Override the base class's bind, to provide a better type.
397 Stream<List<int>> bind(Stream<Object> stream) { 394 Stream<List<int>> bind(Stream<Object> stream) {
398 return super.bind(stream); 395 return super.bind(stream);
399 } 396 }
400 } 397 }
401 398
402 /** 399 /**
403 * Implements the chunked conversion from object to its JSON representation. 400 * Implements the chunked conversion from object to its JSON representation.
(...skipping 18 matching lines...) Expand all
422 void add(Object o) { 419 void add(Object o) {
423 if (_isDone) { 420 if (_isDone) {
424 throw new StateError("Only one call to add allowed"); 421 throw new StateError("Only one call to add allowed");
425 } 422 }
426 _isDone = true; 423 _isDone = true;
427 ClosableStringSink stringSink = _sink.asStringSink(); 424 ClosableStringSink stringSink = _sink.asStringSink();
428 _JsonStringStringifier.printOn(o, stringSink, _toEncodable, _indent); 425 _JsonStringStringifier.printOn(o, stringSink, _toEncodable, _indent);
429 stringSink.close(); 426 stringSink.close();
430 } 427 }
431 428
432 void close() { /* do nothing */ } 429 void close() {/* do nothing */}
433 } 430 }
434 431
435 /** 432 /**
436 * Sink returned when starting a chunked conversion from object to bytes. 433 * Sink returned when starting a chunked conversion from object to bytes.
437 */ 434 */
438 class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> { 435 class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
439 /** The byte sink receiveing the encoded chunks. */ 436 /** The byte sink receiveing the encoded chunks. */
440 final ByteConversionSink _sink; 437 final ByteConversionSink _sink;
441 final List<int> _indent; 438 final List<int> _indent;
442 final _ToEncodable _toEncodable; 439 final _ToEncodable _toEncodable;
443 final int _bufferSize; 440 final int _bufferSize;
444 bool _isDone = false; 441 bool _isDone = false;
445 _JsonUtf8EncoderSink(this._sink, this._toEncodable, this._indent, 442 _JsonUtf8EncoderSink(
446 this._bufferSize); 443 this._sink, this._toEncodable, this._indent, this._bufferSize);
447 444
448 /** Callback called for each slice of result bytes. */ 445 /** Callback called for each slice of result bytes. */
449 void _addChunk(Uint8List chunk, int start, int end) { 446 void _addChunk(Uint8List chunk, int start, int end) {
450 _sink.addSlice(chunk, start, end, false); 447 _sink.addSlice(chunk, start, end, false);
451 } 448 }
452 449
453 void add(Object object) { 450 void add(Object object) {
454 if (_isDone) { 451 if (_isDone) {
455 throw new StateError("Only one call to add allowed"); 452 throw new StateError("Only one call to add allowed");
456 } 453 }
457 _isDone = true; 454 _isDone = true;
458 _JsonUtf8Stringifier.stringify(object, _indent, _toEncodable, 455 _JsonUtf8Stringifier.stringify(
459 _bufferSize, 456 object, _indent, _toEncodable, _bufferSize, _addChunk);
460 _addChunk);
461 _sink.close(); 457 _sink.close();
462 } 458 }
463 459
464 void close() { 460 void close() {
465 if (!_isDone) { 461 if (!_isDone) {
466 _isDone = true; 462 _isDone = true;
467 _sink.close(); 463 _sink.close();
468 } 464 }
469 } 465 }
470 } 466 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 */ 502 */
507 external StringConversionSink startChunkedConversion(Sink<Object> sink); 503 external StringConversionSink startChunkedConversion(Sink<Object> sink);
508 504
509 // Override the base class's bind, to provide a better type. 505 // Override the base class's bind, to provide a better type.
510 Stream<Object> bind(Stream<String> stream) => super.bind(stream); 506 Stream<Object> bind(Stream<String> stream) => super.bind(stream);
511 } 507 }
512 508
513 // Internal optimized JSON parsing implementation. 509 // Internal optimized JSON parsing implementation.
514 external _parseJson(String source, reviver(key, value)); 510 external _parseJson(String source, reviver(key, value));
515 511
516
517 // Implementation of encoder/stringifier. 512 // Implementation of encoder/stringifier.
518 513
519 dynamic _defaultToEncodable(dynamic object) => object.toJson(); 514 dynamic _defaultToEncodable(dynamic object) => object.toJson();
520 515
521 /** 516 /**
522 * JSON encoder that traverses an object structure and writes JSON source. 517 * JSON encoder that traverses an object structure and writes JSON source.
523 * 518 *
524 * This is an abstract implementation that doesn't decide on the output 519 * This is an abstract implementation that doesn't decide on the output
525 * format, but writes the JSON through abstract methods like [writeString]. 520 * format, but writes the JSON through abstract methods like [writeString].
526 */ 521 */
527 abstract class _JsonStringifier { 522 abstract class _JsonStringifier {
528 // Character code constants. 523 // Character code constants.
529 static const int BACKSPACE = 0x08; 524 static const int BACKSPACE = 0x08;
530 static const int TAB = 0x09; 525 static const int TAB = 0x09;
531 static const int NEWLINE = 0x0a; 526 static const int NEWLINE = 0x0a;
532 static const int CARRIAGE_RETURN = 0x0d; 527 static const int CARRIAGE_RETURN = 0x0d;
533 static const int FORM_FEED = 0x0c; 528 static const int FORM_FEED = 0x0c;
534 static const int QUOTE = 0x22; 529 static const int QUOTE = 0x22;
535 static const int CHAR_0 = 0x30; 530 static const int CHAR_0 = 0x30;
536 static const int BACKSLASH = 0x5c; 531 static const int BACKSLASH = 0x5c;
537 static const int CHAR_b = 0x62; 532 static const int CHAR_b = 0x62;
538 static const int CHAR_f = 0x66; 533 static const int CHAR_f = 0x66;
539 static const int CHAR_n = 0x6e; 534 static const int CHAR_n = 0x6e;
540 static const int CHAR_r = 0x72; 535 static const int CHAR_r = 0x72;
541 static const int CHAR_t = 0x74; 536 static const int CHAR_t = 0x74;
542 static const int CHAR_u = 0x75; 537 static const int CHAR_u = 0x75;
543 538
544 /** List of objects currently being traversed. Used to detect cycles. */ 539 /** List of objects currently being traversed. Used to detect cycles. */
545 final List _seen = new List(); 540 final List _seen = new List();
546 /** Function called for each un-encodable object encountered. */ 541 /** Function called for each un-encodable object encountered. */
547 final _ToEncodable _toEncodable; 542 final _ToEncodable _toEncodable;
548 543
549 _JsonStringifier(toEncodable(o)) 544 _JsonStringifier(toEncodable(o))
550 : _toEncodable = toEncodable ?? _defaultToEncodable; 545 : _toEncodable = toEncodable ?? _defaultToEncodable;
551 546
552 /** Append a string to the JSON output. */ 547 /** Append a string to the JSON output. */
(...skipping 15 matching lines...) Expand all
568 int offset = 0; 563 int offset = 0;
569 final int length = s.length; 564 final int length = s.length;
570 for (int i = 0; i < length; i++) { 565 for (int i = 0; i < length; i++) {
571 int charCode = s.codeUnitAt(i); 566 int charCode = s.codeUnitAt(i);
572 if (charCode > BACKSLASH) continue; 567 if (charCode > BACKSLASH) continue;
573 if (charCode < 32) { 568 if (charCode < 32) {
574 if (i > offset) writeStringSlice(s, offset, i); 569 if (i > offset) writeStringSlice(s, offset, i);
575 offset = i + 1; 570 offset = i + 1;
576 writeCharCode(BACKSLASH); 571 writeCharCode(BACKSLASH);
577 switch (charCode) { 572 switch (charCode) {
578 case BACKSPACE: 573 case BACKSPACE:
579 writeCharCode(CHAR_b); 574 writeCharCode(CHAR_b);
580 break; 575 break;
581 case TAB: 576 case TAB:
582 writeCharCode(CHAR_t); 577 writeCharCode(CHAR_t);
583 break; 578 break;
584 case NEWLINE: 579 case NEWLINE:
585 writeCharCode(CHAR_n); 580 writeCharCode(CHAR_n);
586 break; 581 break;
587 case FORM_FEED: 582 case FORM_FEED:
588 writeCharCode(CHAR_f); 583 writeCharCode(CHAR_f);
589 break; 584 break;
590 case CARRIAGE_RETURN: 585 case CARRIAGE_RETURN:
591 writeCharCode(CHAR_r); 586 writeCharCode(CHAR_r);
592 break; 587 break;
593 default: 588 default:
594 writeCharCode(CHAR_u); 589 writeCharCode(CHAR_u);
595 writeCharCode(CHAR_0); 590 writeCharCode(CHAR_0);
596 writeCharCode(CHAR_0); 591 writeCharCode(CHAR_0);
597 writeCharCode(hexDigit((charCode >> 4) & 0xf)); 592 writeCharCode(hexDigit((charCode >> 4) & 0xf));
598 writeCharCode(hexDigit(charCode & 0xf)); 593 writeCharCode(hexDigit(charCode & 0xf));
599 break; 594 break;
600 } 595 }
601 } else if (charCode == QUOTE || charCode == BACKSLASH) { 596 } else if (charCode == QUOTE || charCode == BACKSLASH) {
602 if (i > offset) writeStringSlice(s, offset, i); 597 if (i > offset) writeStringSlice(s, offset, i);
603 offset = i + 1; 598 offset = i + 1;
604 writeCharCode(BACKSLASH); 599 writeCharCode(BACKSLASH);
605 writeCharCode(charCode); 600 writeCharCode(charCode);
606 } 601 }
607 } 602 }
608 if (offset == 0) { 603 if (offset == 0) {
609 writeString(s); 604 writeString(s);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 bool writeJsonValue(object) { 666 bool writeJsonValue(object) {
672 if (object is num) { 667 if (object is num) {
673 if (!object.isFinite) return false; 668 if (!object.isFinite) return false;
674 writeNumber(object); 669 writeNumber(object);
675 return true; 670 return true;
676 } else if (identical(object, true)) { 671 } else if (identical(object, true)) {
677 writeString('true'); 672 writeString('true');
678 return true; 673 return true;
679 } else if (identical(object, false)) { 674 } else if (identical(object, false)) {
680 writeString('false'); 675 writeString('false');
681 return true; 676 return true;
682 } else if (object == null) { 677 } else if (object == null) {
683 writeString('null'); 678 writeString('null');
684 return true; 679 return true;
685 } else if (object is String) { 680 } else if (object is String) {
686 writeString('"'); 681 writeString('"');
687 writeStringContent(object); 682 writeStringContent(object);
688 writeString('"'); 683 writeString('"');
689 return true; 684 return true;
690 } else if (object is List) { 685 } else if (object is List) {
691 _checkCycle(object); 686 _checkCycle(object);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 } else { 850 } else {
856 stringifier = 851 stringifier =
857 new _JsonStringStringifierPretty(output, toEncodable, indent); 852 new _JsonStringStringifierPretty(output, toEncodable, indent);
858 } 853 }
859 stringifier.writeObject(object); 854 stringifier.writeObject(object);
860 } 855 }
861 856
862 void writeNumber(num number) { 857 void writeNumber(num number) {
863 _sink.write(number.toString()); 858 _sink.write(number.toString());
864 } 859 }
860
865 void writeString(String string) { 861 void writeString(String string) {
866 _sink.write(string); 862 _sink.write(string);
867 } 863 }
864
868 void writeStringSlice(String string, int start, int end) { 865 void writeStringSlice(String string, int start, int end) {
869 _sink.write(string.substring(start, end)); 866 _sink.write(string.substring(start, end));
870 } 867 }
868
871 void writeCharCode(int charCode) { 869 void writeCharCode(int charCode) {
872 _sink.writeCharCode(charCode); 870 _sink.writeCharCode(charCode);
873 } 871 }
874 } 872 }
875 873
876 class _JsonStringStringifierPretty extends _JsonStringStringifier 874 class _JsonStringStringifierPretty extends _JsonStringStringifier
877 with _JsonPrettyPrintMixin { 875 with _JsonPrettyPrintMixin {
878 final String _indent; 876 final String _indent;
879 877
880 _JsonStringStringifierPretty(StringSink sink, toEncodable(o), this._indent) 878 _JsonStringStringifierPretty(StringSink sink, toEncodable(o), this._indent)
881 : super(sink, toEncodable); 879 : super(sink, toEncodable);
882 880
883 void writeIndentation(int count) { 881 void writeIndentation(int count) {
884 for (int i = 0; i < count; i++) writeString(_indent); 882 for (int i = 0; i < count; i++) writeString(_indent);
885 } 883 }
886 } 884 }
887 885
(...skipping 20 matching lines...) Expand all
908 * Convert [object] to UTF-8 encoded JSON. 906 * Convert [object] to UTF-8 encoded JSON.
909 * 907 *
910 * Calls [addChunk] with slices of UTF-8 code units. 908 * Calls [addChunk] with slices of UTF-8 code units.
911 * These will typically have size [bufferSize], but may be shorter. 909 * These will typically have size [bufferSize], but may be shorter.
912 * The buffers are not reused, so the [addChunk] call may keep and reuse the 910 * The buffers are not reused, so the [addChunk] call may keep and reuse the
913 * chunks. 911 * chunks.
914 * 912 *
915 * If [indent] is non-`null`, the result will be "pretty-printed" with extra 913 * If [indent] is non-`null`, the result will be "pretty-printed" with extra
916 * newlines and indentation, using [indent] as the indentation. 914 * newlines and indentation, using [indent] as the indentation.
917 */ 915 */
918 static void stringify(Object object, 916 static void stringify(Object object, List<int> indent, toEncodable(o),
919 List<int> indent, 917 int bufferSize, void addChunk(Uint8List chunk, int start, int end)) {
920 toEncodable(o),
921 int bufferSize,
922 void addChunk(Uint8List chunk, int start, int end)) {
923 _JsonUtf8Stringifier stringifier; 918 _JsonUtf8Stringifier stringifier;
924 if (indent != null) { 919 if (indent != null) {
925 stringifier = new _JsonUtf8StringifierPretty(toEncodable, indent, 920 stringifier = new _JsonUtf8StringifierPretty(
926 bufferSize, addChunk); 921 toEncodable, indent, bufferSize, addChunk);
927 } else { 922 } else {
928 stringifier = new _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk); 923 stringifier = new _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk);
929 } 924 }
930 stringifier.writeObject(object); 925 stringifier.writeObject(object);
931 stringifier.flush(); 926 stringifier.flush();
932 } 927 }
933 928
934 /** 929 /**
935 * Must be called at the end to push the last chunk to the [addChunk] 930 * Must be called at the end to push the last chunk to the [addChunk]
936 * callback. 931 * callback.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 index = 0; 1021 index = 0;
1027 } 1022 }
1028 buffer[index++] = byte; 1023 buffer[index++] = byte;
1029 } 1024 }
1030 } 1025 }
1031 1026
1032 /** 1027 /**
1033 * Pretty-printing version of [_JsonUtf8Stringifier]. 1028 * Pretty-printing version of [_JsonUtf8Stringifier].
1034 */ 1029 */
1035 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier 1030 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier
1036 with _JsonPrettyPrintMixin { 1031 with _JsonPrettyPrintMixin {
1037 final List<int> indent; 1032 final List<int> indent;
1038 _JsonUtf8StringifierPretty( 1033 _JsonUtf8StringifierPretty(toEncodable(o), this.indent, bufferSize,
1039 toEncodable(o), this.indent, 1034 void addChunk(Uint8List buffer, int start, int end))
1040 bufferSize, void addChunk(Uint8List buffer, int start, int end))
1041 : super(toEncodable, bufferSize, addChunk); 1035 : super(toEncodable, bufferSize, addChunk);
1042 1036
1043 void writeIndentation(int count) { 1037 void writeIndentation(int count) {
1044 List<int> indent = this.indent; 1038 List<int> indent = this.indent;
1045 int indentLength = indent.length; 1039 int indentLength = indent.length;
1046 if (indentLength == 1) { 1040 if (indentLength == 1) {
1047 int char = indent[0]; 1041 int char = indent[0];
1048 while (count > 0) { 1042 while (count > 0) {
1049 writeByte(char); 1043 writeByte(char);
1050 count -= 1; 1044 count -= 1;
1051 } 1045 }
1052 return; 1046 return;
1053 } 1047 }
1054 while (count > 0) { 1048 while (count > 0) {
1055 count--; 1049 count--;
1056 int end = index + indentLength; 1050 int end = index + indentLength;
1057 if (end <= buffer.length) { 1051 if (end <= buffer.length) {
1058 buffer.setRange(index, end, indent); 1052 buffer.setRange(index, end, indent);
1059 index = end; 1053 index = end;
1060 } else { 1054 } else {
1061 for (int i = 0; i < indentLength; i++) { 1055 for (int i = 0; i < indentLength; i++) {
1062 writeByte(indent[i]); 1056 writeByte(indent[i]);
1063 } 1057 }
1064 } 1058 }
1065 } 1059 }
1066 } 1060 }
1067 } 1061 }
OLDNEW
« no previous file with comments | « sdk/lib/convert/html_escape.dart ('k') | sdk/lib/convert/latin1.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698