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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/scanner/utf8_bytes_scanner.dart

Issue 137343002: Handle BOMs in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 6 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
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 scanner; 5 part of scanner;
6 6
7 /** 7 /**
8 * Scanner that reads from a UTF-8 encoded list of bytes and creates tokens 8 * Scanner that reads from a UTF-8 encoded list of bytes and creates tokens
9 * that points to substrings. 9 * that points to substrings.
10 */ 10 */
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 * string text of the source file is decoded. 62 * string text of the source file is decoded.
63 * 63 *
64 * The list of UTF-8 bytes [file.slowUtf8Bytes()] is expected to return an 64 * The list of UTF-8 bytes [file.slowUtf8Bytes()] is expected to return an
65 * array whose last element is '0' to signal the end of the file. If this 65 * array whose last element is '0' to signal the end of the file. If this
66 * is not the case, the entire array is copied before scanning. 66 * is not the case, the entire array is copied before scanning.
67 */ 67 */
68 Utf8BytesScanner(SourceFile file, {bool includeComments: false}) 68 Utf8BytesScanner(SourceFile file, {bool includeComments: false})
69 : bytes = file.slowUtf8Bytes(), 69 : bytes = file.slowUtf8Bytes(),
70 super(file, includeComments) { 70 super(file, includeComments) {
71 ensureZeroTermination(); 71 ensureZeroTermination();
72 // Skip a leading BOM.
73 if (_containsBomAt(0)) byteOffset += 3;
72 } 74 }
73 75
74 /** 76 /**
75 * Creates a new Utf8BytesScanner from a list of UTF-8 bytes. 77 * Creates a new Utf8BytesScanner from a list of UTF-8 bytes.
76 * 78 *
77 * The last element of the list is expected to be '0' to signal the end of 79 * The last element of the list is expected to be '0' to signal the end of
78 * the file. If this is not the case, the entire array is copied before 80 * the file. If this is not the case, the entire array is copied before
79 * scanning. 81 * scanning.
80 */ 82 */
81 Utf8BytesScanner.fromBytes(this.bytes, {bool includeComments: false}) 83 Utf8BytesScanner.fromBytes(this.bytes, {bool includeComments: false})
82 : super(null, includeComments) { 84 : super(null, includeComments) {
83 ensureZeroTermination(); 85 ensureZeroTermination();
84 } 86 }
85 87
86 void ensureZeroTermination() { 88 void ensureZeroTermination() {
87 if (bytes.isEmpty || bytes[bytes.length - 1] != 0) { 89 if (bytes.isEmpty || bytes[bytes.length - 1] != 0) {
88 // TODO(lry): abort instead of copying the array, or warn? 90 // TODO(lry): abort instead of copying the array, or warn?
89 var newBytes = new Uint8List(bytes.length + 1); 91 var newBytes = new Uint8List(bytes.length + 1);
90 for (int i = 0; i < bytes.length; i++) { 92 for (int i = 0; i < bytes.length; i++) {
91 newBytes[i] = bytes[i]; 93 newBytes[i] = bytes[i];
92 } 94 }
93 newBytes[bytes.length] = 0; 95 newBytes[bytes.length] = 0;
94 bytes = newBytes; 96 bytes = newBytes;
95 } 97 }
96 } 98 }
97 99
100 bool _containsBomAt(int offset) {
101 const BOM_UTF8 = const [0xEF, 0xBB, 0xBF];
102
103 return offset + 3 < bytes.length &&
104 bytes[offset] == BOM_UTF8[0] &&
105 bytes[offset + 1] == BOM_UTF8[1] &&
106 bytes[offset + 2] == BOM_UTF8[2];
107 }
108
98 int advance() => bytes[++byteOffset]; 109 int advance() => bytes[++byteOffset];
99 110
100 int peek() => bytes[byteOffset + 1]; 111 int peek() => bytes[byteOffset + 1];
101 112
102 /** 113 /**
103 * Returns the unicode code point starting at the byte offset [startOffset] 114 * Returns the unicode code point starting at the byte offset [startOffset]
104 * with the byte [nextByte]. If [advance] is true the current [byteOffset] 115 * with the byte [nextByte]. If [advance] is true the current [byteOffset]
105 * is advanced to the last byte of the code point. 116 * is advanced to the last byte of the code point.
106 */ 117 */
107 int nextCodePoint(int startOffset, int nextByte, bool advance) { 118 int nextCodePoint(int startOffset, int nextByte, bool advance) {
108 // The number of 1s in the first byte indicate the number of bytes, at 119 // The number of 1s in the first byte indicate the number of bytes, at
109 // least 2. 120 // least 2.
110 int numBytes = 2; 121 int numBytes = 2;
111 int bit = 0x20; 122 int bit = 0x20;
112 while ((nextByte & bit) != 0) { 123 while ((nextByte & bit) != 0) {
113 numBytes++; 124 numBytes++;
114 bit >>= 1; 125 bit >>= 1;
115 } 126 }
116 int end = startOffset + numBytes; 127 int end = startOffset + numBytes;
117 if (advance) { 128 if (advance) {
118 byteOffset = end - 1; 129 byteOffset = end - 1;
119 } 130 }
120 // TODO(lry): measurably slow, decode creates first a Utf8Decoder and a 131 // TODO(lry): measurably slow, decode creates first a Utf8Decoder and a
121 // _Utf8Decoder instance. Also the sublist is eagerly allocated. 132 // _Utf8Decoder instance. Also the sublist is eagerly allocated.
122 String codePoint = UTF8.decode(bytes.sublist(startOffset, end)); 133 String codePoint = UTF8.decode(bytes.sublist(startOffset, end));
134 if (codePoint.length == 0) {
135 // The UTF-8 decoder discards leading BOM characters.
136 // TODO(floitsch): don't just assume that removed characters were the
137 // BOM.
138 assert(_containsBomAt(startOffset));
139 codePoint = new String.fromCharCode(UNICODE_BOM_CHARACTER_RUNE);
140 }
123 if (codePoint.length == 1) { 141 if (codePoint.length == 1) {
124 if (advance) { 142 if (advance) {
125 utf8Slack += (numBytes - 1); 143 utf8Slack += (numBytes - 1);
126 scanSlack = numBytes - 1; 144 scanSlack = numBytes - 1;
127 scanSlackOffset = byteOffset; 145 scanSlackOffset = byteOffset;
128 } 146 }
129 return codePoint.codeUnitAt(0); 147 return codePoint.codeUnitAt(0);
130 } else if (codePoint.length == 2) { 148 } else if (codePoint.length == 2) {
131 if (advance) { 149 if (advance) {
132 utf8Slack += (numBytes - 2); 150 utf8Slack += (numBytes - 2);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 204
187 void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly, 205 void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly,
188 [int extraOffset = 0]) { 206 [int extraOffset = 0]) {
189 tail.next = new StringToken.fromUtf8Bytes( 207 tail.next = new StringToken.fromUtf8Bytes(
190 info, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart); 208 info, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
191 tail = tail.next; 209 tail = tail.next;
192 } 210 }
193 211
194 bool atEndOfFile() => byteOffset >= bytes.length - 1; 212 bool atEndOfFile() => byteOffset >= bytes.length - 1;
195 } 213 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698