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

Side by Side Diff: runtime/lib/convert_patch.dart

Issue 853613003: Optimize creation of ASCII strings in UTF-8 JSON parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comment. More documentation. Created 5 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 import "dart:_internal" show POWERS_OF_TEN; 5 import "dart:_internal" show POWERS_OF_TEN;
6 6
7 // JSON conversion. 7 // JSON conversion.
8 8
9 patch _parseJson(String json, reviver(var key, var value)) { 9 patch _parseJson(String json, reviver(var key, var value)) {
10 _BuildJsonListener listener; 10 _BuildJsonListener listener;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 // Grows to the exact size asked for. 209 // Grows to the exact size asked for.
210 void ensureCapacity(int newCapacity) { 210 void ensureCapacity(int newCapacity) {
211 Uint8List list = this.list; 211 Uint8List list = this.list;
212 if (newCapacity <= list.length) return; 212 if (newCapacity <= list.length) return;
213 Uint8List newList = new Uint8List(newCapacity); 213 Uint8List newList = new Uint8List(newCapacity);
214 newList.setRange(0, list.length, list, 0); 214 newList.setRange(0, list.length, list, 0);
215 this.list = newList; 215 this.list = newList;
216 } 216 }
217 217
218 String getString() { 218 String getString() {
219 var list = this.list; 219 String result = new String.fromCharCodes(list, 0, length);
220 if (length < list.length) {
221 list = new Uint8List.view(list.buffer, 0, length);
222 }
223 String result = new String.fromCharCodes(list);
224 return result; 220 return result;
225 } 221 }
226 222
227 // TODO(lrn): See if parsing of numbers can be abstracted to something 223 // TODO(lrn): See if parsing of numbers can be abstracted to something
228 // not only working on strings, but also on char-code lists, without lossing 224 // not only working on strings, but also on char-code lists, without lossing
229 // performance. 225 // performance.
230 int parseInt() => int.parse(getString()); 226 int parseInt() => int.parse(getString());
231 double parseDouble() => double.parse(getString()); 227 double parseDouble() => double.parse(getString());
232 } 228 }
233 229
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 537
542 /** 538 /**
543 * Extracts a literal string from a slice of the current chunk. 539 * Extracts a literal string from a slice of the current chunk.
544 * 540 *
545 * No interpretation of the content is performed, except for converting 541 * No interpretation of the content is performed, except for converting
546 * the source format to string. 542 * the source format to string.
547 * This can be implemented more or less efficiently depending on the 543 * This can be implemented more or less efficiently depending on the
548 * underlying source. 544 * underlying source.
549 * 545 *
550 * This is used for string literals that contain no escapes. 546 * This is used for string literals that contain no escapes.
547 *
548 * The [bits] integer is an upper bound on the code point in the range
549 * from `start` to `end`.
550 * Usually found by doing bitwise or of all the values.
551 * The function may choose to optimize depending on the value.
551 */ 552 */
552 String getString(int start, int end); 553 String getString(int start, int end, int bits);
553 554
554 /** 555 /**
555 * Parse a slice of the current chunk as an integer. 556 * Parse a slice of the current chunk as an integer.
556 * 557 *
557 * The format is expected to be correct. 558 * The format is expected to be correct.
558 */ 559 */
559 int parseInt(int start, int end) { 560 int parseInt(int start, int end) {
560 return int.parse(getString(start, end)); 561 const int asciiBits = 0x7f; // Integer literals are ASCII only.
562 return int.parse(getString(start, end, asciiBits));
561 } 563 }
562 564
563 /** 565 /**
564 * Parse a slice of the current chunk as a double. 566 * Parse a slice of the current chunk as a double.
565 * 567 *
566 * The format is expected to be correct. 568 * The format is expected to be correct.
567 * This is used by [parseNumber] when the double value cannot be 569 * This is used by [parseNumber] when the double value cannot be
568 * built exactly during parsing. 570 * built exactly during parsing.
569 */ 571 */
570 double parseDouble(int start, int end) { 572 double parseDouble(int start, int end) {
571 return double.parse(getString(start, end)); 573 const int asciiBits = 0x7f; // Double literals are ASCII only.
574 return double.parse(getString(start, end, asciiBits));
572 } 575 }
573 576
574 /** 577 /**
575 * Create a _NumberBuffer containing the digits from [start] to [chunkEnd]. 578 * Create a _NumberBuffer containing the digits from [start] to [chunkEnd].
576 * 579 *
577 * This creates a number buffer and initializes it with the part of the 580 * This creates a number buffer and initializes it with the part of the
578 * number literal ending the current chunk 581 * number literal ending the current chunk
579 */ 582 */
580 void createNumberBuffer(int start) { 583 void createNumberBuffer(int start) {
581 assert(start >= 0); 584 assert(start >= 0);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 * Parses a string value. 967 * Parses a string value.
965 * 968 *
966 * Initial [position] is right after the initial quote. 969 * Initial [position] is right after the initial quote.
967 * Returned position right after the final quote. 970 * Returned position right after the final quote.
968 */ 971 */
969 int parseString(int position) { 972 int parseString(int position) {
970 // Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"' 973 // Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"'
971 // Initial position is right after first '"'. 974 // Initial position is right after first '"'.
972 int start = position; 975 int start = position;
973 int end = chunkEnd; 976 int end = chunkEnd;
977 int bits = 0;
974 while (position < end) { 978 while (position < end) {
975 int char = getChar(position++); 979 int char = getChar(position++);
980 bits |= char; // Includes final '"', but that never matters.
976 // BACKSLASH is larger than QUOTE and SPACE. 981 // BACKSLASH is larger than QUOTE and SPACE.
977 if (char > BACKSLASH) { 982 if (char > BACKSLASH) {
978 continue; 983 continue;
979 } 984 }
980 if (char == BACKSLASH) { 985 if (char == BACKSLASH) {
981 beginString(); 986 beginString();
982 int sliceEnd = position - 1; 987 int sliceEnd = position - 1;
983 if (start < sliceEnd) addSliceToString(start, sliceEnd); 988 if (start < sliceEnd) addSliceToString(start, sliceEnd);
984 return parseStringToBuffer(position - 1); 989 return parseStringToBuffer(sliceEnd);
985 } 990 }
986 if (char == QUOTE) { 991 if (char == QUOTE) {
987 listener.handleString(getString(start, position - 1)); 992 listener.handleString(getString(start, position - 1, bits));
988 return position; 993 return position;
989 } 994 }
990 if (char < SPACE) { 995 if (char < SPACE) {
991 fail(position - 1, "Control character in string"); 996 fail(position - 1, "Control character in string");
992 } 997 }
993 } 998 }
994 beginString(); 999 beginString();
995 if (start < end) addSliceToString(start, end); 1000 if (start < end) addSliceToString(start, end);
996 return chunkString(STR_PLAIN); 1001 return chunkString(STR_PLAIN);
997 } 1002 }
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 * Chunked JSON parser that parses [String] chunks. 1320 * Chunked JSON parser that parses [String] chunks.
1316 */ 1321 */
1317 class _JsonStringParser extends _ChunkedJsonParser { 1322 class _JsonStringParser extends _ChunkedJsonParser {
1318 String chunk; 1323 String chunk;
1319 int chunkEnd; 1324 int chunkEnd;
1320 1325
1321 _JsonStringParser(_JsonListener listener) : super(listener); 1326 _JsonStringParser(_JsonListener listener) : super(listener);
1322 1327
1323 int getChar(int position) => chunk.codeUnitAt(position); 1328 int getChar(int position) => chunk.codeUnitAt(position);
1324 1329
1325 String getString(int start, int end) { 1330 String getString(int start, int end, int bits) {
1326 return chunk.substring(start, end); 1331 return chunk.substring(start, end);
1327 } 1332 }
1328 1333
1329 void beginString() { 1334 void beginString() {
1330 this.buffer = new StringBuffer(); 1335 this.buffer = new StringBuffer();
1331 } 1336 }
1332 1337
1333 void addSliceToString(int start, int end) { 1338 void addSliceToString(int start, int end) {
1334 StringBuffer buffer = this.buffer; 1339 StringBuffer buffer = this.buffer;
1335 buffer.write(chunk.substring(start, end)); 1340 buffer.write(chunk.substring(start, end));
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1661 class _JsonUtf8Parser extends _ChunkedJsonParser { 1666 class _JsonUtf8Parser extends _ChunkedJsonParser {
1662 final bool allowMalformed; 1667 final bool allowMalformed;
1663 List<int> chunk; 1668 List<int> chunk;
1664 int chunkEnd; 1669 int chunkEnd;
1665 1670
1666 _JsonUtf8Parser(_JsonListener listener, this.allowMalformed) 1671 _JsonUtf8Parser(_JsonListener listener, this.allowMalformed)
1667 : super(listener); 1672 : super(listener);
1668 1673
1669 int getChar(int position) => chunk[position]; 1674 int getChar(int position) => chunk[position];
1670 1675
1671 String getString(int start, int end) { 1676 String getString(int start, int end, int bits) {
1677 const int maxAsciiChar = 0x7f;
1678 if (bits <= maxAsciiChar) {
1679 return new String.fromCharCodes(chunk, start, end);
1680 }
1672 beginString(); 1681 beginString();
1673 if (start < end) addSliceToString(start, end); 1682 if (start < end) addSliceToString(start, end);
1674 String result = endString(); 1683 String result = endString();
1675 return result; 1684 return result;
1676 } 1685 }
1677 1686
1678 void beginString() { 1687 void beginString() {
1679 this.buffer = new _Utf8StringBuffer(allowMalformed); 1688 this.buffer = new _Utf8StringBuffer(allowMalformed);
1680 } 1689 }
1681 1690
(...skipping 12 matching lines...) Expand all
1694 this.buffer = null; 1703 this.buffer = null;
1695 return buffer.toString(); 1704 return buffer.toString();
1696 } 1705 }
1697 1706
1698 void copyCharsToList(int start, int end, List target, int offset) { 1707 void copyCharsToList(int start, int end, List target, int offset) {
1699 int length = end - start; 1708 int length = end - start;
1700 target.setRange(offset, offset + length, chunk, start); 1709 target.setRange(offset, offset + length, chunk, start);
1701 } 1710 }
1702 1711
1703 double parseDouble(int start, int end) { 1712 double parseDouble(int start, int end) {
1704 String string = getString(start, end); 1713 String string = getString(start, end, 0x7f);
1705 return _parseDouble(string, 0, string.length); 1714 return _parseDouble(string, 0, string.length);
1706 } 1715 }
1707 } 1716 }
1708 1717
1709 double _parseDouble(String source, int start, int end) 1718 double _parseDouble(String source, int start, int end)
1710 native "Double_parse"; 1719 native "Double_parse";
1711 1720
1712 /** 1721 /**
1713 * Implements the chunked conversion from a UTF-8 encoding of JSON 1722 * Implements the chunked conversion from a UTF-8 encoding of JSON
1714 * to its corresponding object. 1723 * to its corresponding object.
(...skipping 30 matching lines...) Expand all
1745 _parser.parse(start); 1754 _parser.parse(start);
1746 } 1755 }
1747 1756
1748 void close() { 1757 void close() {
1749 _parser.close(); 1758 _parser.close();
1750 var decoded = _parser.result; 1759 var decoded = _parser.result;
1751 _sink.add(decoded); 1760 _sink.add(decoded);
1752 _sink.close(); 1761 _sink.close();
1753 } 1762 }
1754 } 1763 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698