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

Side by Side Diff: third_party/WebKit/Source/platform/inspector_protocol/Parser.cpp

Issue 1779033003: DevTools: always use 16bit strings for inspector protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebaselined Created 4 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/inspector_protocol/Parser.h" 5 #include "platform/inspector_protocol/Parser.h"
6 6
7 #include "platform/inspector_protocol/String16.h" 7 #include "platform/inspector_protocol/String16.h"
8 #include "platform/inspector_protocol/Values.h" 8 #include "platform/inspector_protocol/Values.h"
9 9
10 namespace blink { 10 namespace blink {
(...skipping 15 matching lines...) Expand all
26 NullToken, 26 NullToken,
27 ListSeparator, 27 ListSeparator,
28 ObjectPairSeparator, 28 ObjectPairSeparator,
29 InvalidToken, 29 InvalidToken,
30 }; 30 };
31 31
32 const char* const nullString = "null"; 32 const char* const nullString = "null";
33 const char* const trueString = "true"; 33 const char* const trueString = "true";
34 const char* const falseString = "false"; 34 const char* const falseString = "false";
35 35
36 template<typename CharType> 36 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEn d, const char* token)
37 bool parseConstToken(const CharType* start, const CharType* end, const CharType* * tokenEnd, const char* token)
38 { 37 {
39 while (start < end && *token != '\0' && *start++ == *token++) { } 38 while (start < end && *token != '\0' && *start++ == *token++) { }
40 if (*token != '\0') 39 if (*token != '\0')
41 return false; 40 return false;
42 *tokenEnd = start; 41 *tokenEnd = start;
43 return true; 42 return true;
44 } 43 }
45 44
46 template<typename CharType> 45 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
47 bool readInt(const CharType* start, const CharType* end, const CharType** tokenE nd, bool canHaveLeadingZeros)
48 { 46 {
49 if (start == end) 47 if (start == end)
50 return false; 48 return false;
51 bool haveLeadingZero = '0' == *start; 49 bool haveLeadingZero = '0' == *start;
52 int length = 0; 50 int length = 0;
53 while (start < end && '0' <= *start && *start <= '9') { 51 while (start < end && '0' <= *start && *start <= '9') {
54 ++start; 52 ++start;
55 ++length; 53 ++length;
56 } 54 }
57 if (!length) 55 if (!length)
58 return false; 56 return false;
59 if (!canHaveLeadingZeros && length > 1 && haveLeadingZero) 57 if (!canHaveLeadingZeros && length > 1 && haveLeadingZero)
60 return false; 58 return false;
61 *tokenEnd = start; 59 *tokenEnd = start;
62 return true; 60 return true;
63 } 61 }
64 62
65 template<typename CharType> 63 bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenE nd)
66 bool parseNumberToken(const CharType* start, const CharType* end, const CharType ** tokenEnd)
67 { 64 {
68 // We just grab the number here. We validate the size in DecodeNumber. 65 // We just grab the number here. We validate the size in DecodeNumber.
69 // According to RFC4627, a valid number is: [minus] int [frac] [exp] 66 // According to RFC4627, a valid number is: [minus] int [frac] [exp]
70 if (start == end) 67 if (start == end)
71 return false; 68 return false;
72 CharType c = *start; 69 UChar c = *start;
73 if ('-' == c) 70 if ('-' == c)
74 ++start; 71 ++start;
75 72
76 if (!readInt(start, end, &start, false)) 73 if (!readInt(start, end, &start, false))
77 return false; 74 return false;
78 if (start == end) { 75 if (start == end) {
79 *tokenEnd = start; 76 *tokenEnd = start;
80 return true; 77 return true;
81 } 78 }
82 79
(...skipping 22 matching lines...) Expand all
105 return false; 102 return false;
106 } 103 }
107 if (!readInt(start, end, &start, true)) 104 if (!readInt(start, end, &start, true))
108 return false; 105 return false;
109 } 106 }
110 107
111 *tokenEnd = start; 108 *tokenEnd = start;
112 return true; 109 return true;
113 } 110 }
114 111
115 template<typename CharType> 112 bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
116 bool readHexDigits(const CharType* start, const CharType* end, const CharType** tokenEnd, int digits)
117 { 113 {
118 if (end - start < digits) 114 if (end - start < digits)
119 return false; 115 return false;
120 for (int i = 0; i < digits; ++i) { 116 for (int i = 0; i < digits; ++i) {
121 CharType c = *start++; 117 UChar c = *start++;
122 if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))) 118 if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
123 return false; 119 return false;
124 } 120 }
125 *tokenEnd = start; 121 *tokenEnd = start;
126 return true; 122 return true;
127 } 123 }
128 124
129 template<typename CharType> 125 bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenE nd)
130 bool parseStringToken(const CharType* start, const CharType* end, const CharType ** tokenEnd)
131 { 126 {
132 while (start < end) { 127 while (start < end) {
133 CharType c = *start++; 128 UChar c = *start++;
134 if ('\\' == c) { 129 if ('\\' == c) {
135 c = *start++; 130 c = *start++;
136 // Make sure the escaped char is valid. 131 // Make sure the escaped char is valid.
137 switch (c) { 132 switch (c) {
138 case 'x': 133 case 'x':
139 if (!readHexDigits(start, end, &start, 2)) 134 if (!readHexDigits(start, end, &start, 2))
140 return false; 135 return false;
141 break; 136 break;
142 case 'u': 137 case 'u':
143 if (!readHexDigits(start, end, &start, 4)) 138 if (!readHexDigits(start, end, &start, 4))
(...skipping 13 matching lines...) Expand all
157 return false; 152 return false;
158 } 153 }
159 } else if ('"' == c) { 154 } else if ('"' == c) {
160 *tokenEnd = start; 155 *tokenEnd = start;
161 return true; 156 return true;
162 } 157 }
163 } 158 }
164 return false; 159 return false;
165 } 160 }
166 161
167 template<typename CharType> 162 bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
168 bool skipComment(const CharType* start, const CharType* end, const CharType** co mmentEnd)
169 { 163 {
170 if (start == end) 164 if (start == end)
171 return false; 165 return false;
172 166
173 if (*start != '/' || start + 1 >= end) 167 if (*start != '/' || start + 1 >= end)
174 return false; 168 return false;
175 ++start; 169 ++start;
176 170
177 if (*start == '/') { 171 if (*start == '/') {
178 // Single line comment, read to newline. 172 // Single line comment, read to newline.
179 for (++start; start < end; ++start) { 173 for (++start; start < end; ++start) {
180 if (*start == '\n' || *start == '\r') { 174 if (*start == '\n' || *start == '\r') {
181 *commentEnd = start + 1; 175 *commentEnd = start + 1;
182 return true; 176 return true;
183 } 177 }
184 } 178 }
185 *commentEnd = end; 179 *commentEnd = end;
186 // Comment reaches end-of-input, which is fine. 180 // Comment reaches end-of-input, which is fine.
187 return true; 181 return true;
188 } 182 }
189 183
190 if (*start == '*') { 184 if (*start == '*') {
191 CharType previous = '\0'; 185 UChar previous = '\0';
192 // Block comment, read until end marker. 186 // Block comment, read until end marker.
193 for (++start; start < end; previous = *start++) { 187 for (++start; start < end; previous = *start++) {
194 if (previous == '*' && *start == '/') { 188 if (previous == '*' && *start == '/') {
195 *commentEnd = start + 1; 189 *commentEnd = start + 1;
196 return true; 190 return true;
197 } 191 }
198 } 192 }
199 // Block comment must close before end-of-input. 193 // Block comment must close before end-of-input.
200 return false; 194 return false;
201 } 195 }
202 196
203 return false; 197 return false;
204 } 198 }
205 199
206 template<typename CharType> 200 void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar ** whitespaceEnd)
207 void skipWhitespaceAndComments(const CharType* start, const CharType* end, const CharType** whitespaceEnd)
208 { 201 {
209 while (start < end) { 202 while (start < end) {
210 if (isSpaceOrNewline(*start)) { 203 if (isSpaceOrNewline(*start)) {
211 ++start; 204 ++start;
212 } else if (*start == '/') { 205 } else if (*start == '/') {
213 const CharType* commentEnd; 206 const UChar* commentEnd;
214 if (!skipComment(start, end, &commentEnd)) 207 if (!skipComment(start, end, &commentEnd))
215 break; 208 break;
216 start = commentEnd; 209 start = commentEnd;
217 } else { 210 } else {
218 break; 211 break;
219 } 212 }
220 } 213 }
221 *whitespaceEnd = start; 214 *whitespaceEnd = start;
222 } 215 }
223 216
224 template<typename CharType> 217 Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
225 Token parseToken(const CharType* start, const CharType* end, const CharType** to kenStart, const CharType** tokenEnd)
226 { 218 {
227 skipWhitespaceAndComments(start, end, tokenStart); 219 skipWhitespaceAndComments(start, end, tokenStart);
228 start = *tokenStart; 220 start = *tokenStart;
229 221
230 if (start == end) 222 if (start == end)
231 return InvalidToken; 223 return InvalidToken;
232 224
233 switch (*start) { 225 switch (*start) {
234 case 'n': 226 case 'n':
235 if (parseConstToken(start, end, tokenEnd, nullString)) 227 if (parseConstToken(start, end, tokenEnd, nullString))
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return Number; 268 return Number;
277 break; 269 break;
278 case '"': 270 case '"':
279 if (parseStringToken(start + 1, end, tokenEnd)) 271 if (parseStringToken(start + 1, end, tokenEnd))
280 return StringLiteral; 272 return StringLiteral;
281 break; 273 break;
282 } 274 }
283 return InvalidToken; 275 return InvalidToken;
284 } 276 }
285 277
286 template<typename CharType> 278 inline int hexToInt(UChar c)
287 inline int hexToInt(CharType c)
288 { 279 {
289 if ('0' <= c && c <= '9') 280 if ('0' <= c && c <= '9')
290 return c - '0'; 281 return c - '0';
291 if ('A' <= c && c <= 'F') 282 if ('A' <= c && c <= 'F')
292 return c - 'A' + 10; 283 return c - 'A' + 10;
293 if ('a' <= c && c <= 'f') 284 if ('a' <= c && c <= 'f')
294 return c - 'a' + 10; 285 return c - 'a' + 10;
295 ASSERT_NOT_REACHED(); 286 ASSERT_NOT_REACHED();
296 return 0; 287 return 0;
297 } 288 }
298 289
299 template<typename CharType> 290 bool decodeString(const UChar* start, const UChar* end, String16Builder* output)
300 bool decodeUTF8(const CharType* start, const CharType* end, const CharType** utf 8charEnd, String16Builder* output)
301 {
302 UChar utf16[4] = {0};
303 char utf8[6] = {0};
304 size_t utf8count = 0;
305
306 while (start < end) {
307 if (start + 1 >= end || *start != '\\' || *(start + 1) != 'x')
308 return false;
309 start += 2;
310
311 // Accumulate one more utf8 character and try converting to utf16.
312 if (start + 1 >= end)
313 return false;
314 utf8[utf8count++] = (hexToInt(*start) << 4) + hexToInt(*(start + 1));
315 start += 2;
316
317 const char* utf8start = utf8;
318 UChar* utf16start = utf16;
319 String16::ConversionResult conversionResult = String16::convertUTF8ToUTF 16(&utf8start, utf8start + utf8count, &utf16start, utf16start + 4, nullptr, true );
320
321 if (conversionResult == String16::sourceIllegal)
322 return false;
323
324 if (conversionResult == String16::conversionOK) {
325 // Not all utf8 characters were consumed - failed parsing.
326 if (utf8start != utf8 + utf8count)
327 return false;
328
329 size_t utf16length = utf16start - utf16;
330 output->append(utf16, utf16length);
331 *utf8charEnd = start;
332 return true;
333 }
334
335 // Keep accumulating utf8 characters up to buffer length (6 should be en ough).
336 if (utf8count >= 6)
337 return false;
338 }
339
340 return false;
341 }
342
343 template<typename CharType>
344 bool decodeString(const CharType* start, const CharType* end, String16Builder* o utput)
345 { 291 {
346 while (start < end) { 292 while (start < end) {
347 UChar c = *start++; 293 UChar c = *start++;
348 if ('\\' != c) { 294 if ('\\' != c) {
349 output->append(c); 295 output->append(c);
350 continue; 296 continue;
351 } 297 }
352 c = *start++; 298 c = *start++;
353 299
354 if (c == 'x') { 300 if (c == 'x') {
355 // Rewind "\x". 301 // \x is not supported.
356 if (!decodeUTF8(start - 2, end, &start, output)) 302 return false;
357 return false;
358 continue;
359 } 303 }
360 304
361 switch (c) { 305 switch (c) {
362 case '"': 306 case '"':
363 case '/': 307 case '/':
364 case '\\': 308 case '\\':
365 break; 309 break;
366 case 'b': 310 case 'b':
367 c = '\b'; 311 c = '\b';
368 break; 312 break;
(...skipping 20 matching lines...) Expand all
389 start += 4; 333 start += 4;
390 break; 334 break;
391 default: 335 default:
392 return false; 336 return false;
393 } 337 }
394 output->append(c); 338 output->append(c);
395 } 339 }
396 return true; 340 return true;
397 } 341 }
398 342
399 template<typename CharType> 343 bool decodeString(const UChar* start, const UChar* end, String16* output)
400 bool decodeString(const CharType* start, const CharType* end, String16* output)
401 { 344 {
402 if (start == end) { 345 if (start == end) {
403 *output = ""; 346 *output = "";
404 return true; 347 return true;
405 } 348 }
406 if (start > end) 349 if (start > end)
407 return false; 350 return false;
408 String16Builder buffer; 351 String16Builder buffer;
409 buffer.reserveCapacity(end - start); 352 buffer.reserveCapacity(end - start);
410 if (!decodeString(start, end, &buffer)) 353 if (!decodeString(start, end, &buffer))
411 return false; 354 return false;
412 *output = buffer.toString(); 355 *output = buffer.toString();
413 // Validate constructed utf16 string.
414 if (!output->validateUTF8())
415 return false;
416 return true; 356 return true;
417 } 357 }
418 358
419 template<typename CharType> 359 PassOwnPtr<Value> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
420 PassOwnPtr<Value> buildValue(const CharType* start, const CharType* end, const C harType** valueTokenEnd, int depth)
421 { 360 {
422 if (depth > stackLimit) 361 if (depth > stackLimit)
423 return nullptr; 362 return nullptr;
424 363
425 OwnPtr<Value> result; 364 OwnPtr<Value> result;
426 const CharType* tokenStart; 365 const UChar* tokenStart;
427 const CharType* tokenEnd; 366 const UChar* tokenEnd;
428 Token token = parseToken(start, end, &tokenStart, &tokenEnd); 367 Token token = parseToken(start, end, &tokenStart, &tokenEnd);
429 switch (token) { 368 switch (token) {
430 case InvalidToken: 369 case InvalidToken:
431 return nullptr; 370 return nullptr;
432 case NullToken: 371 case NullToken:
433 result = Value::null(); 372 result = Value::null();
434 break; 373 break;
435 case BoolTrue: 374 case BoolTrue:
436 result = FundamentalValue::create(true); 375 result = FundamentalValue::create(true);
437 break; 376 break;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 465
527 default: 466 default:
528 // We got a token that's not a value. 467 // We got a token that's not a value.
529 return nullptr; 468 return nullptr;
530 } 469 }
531 470
532 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd); 471 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd);
533 return result.release(); 472 return result.release();
534 } 473 }
535 474
536 template<typename CharType> 475 PassOwnPtr<Value> parseJSONInternal(const UChar* start, unsigned length)
537 PassOwnPtr<Value> parseJSONInternal(const CharType* start, unsigned length)
538 { 476 {
539 const CharType* end = start + length; 477 const UChar* end = start + length;
540 const CharType *tokenEnd; 478 const UChar *tokenEnd;
541 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, 0); 479 OwnPtr<Value> value = buildValue(start, end, &tokenEnd, 0);
542 if (!value || tokenEnd != end) 480 if (!value || tokenEnd != end)
543 return nullptr; 481 return nullptr;
544 return value.release(); 482 return value.release();
545 } 483 }
546 484
547 } // anonymous namespace 485 } // anonymous namespace
548 486
549 PassOwnPtr<Value> parseJSON(const String16& json) 487 PassOwnPtr<Value> parseJSON(const String16& json)
550 { 488 {
551 if (json.isEmpty()) 489 if (json.isEmpty())
552 return nullptr; 490 return nullptr;
553 if (json.is8Bit())
554 return parseJSONInternal(json.characters8(), json.length());
555 return parseJSONInternal(json.characters16(), json.length()); 491 return parseJSONInternal(json.characters16(), json.length());
556 } 492 }
557 493
558 } // namespace protocol 494 } // namespace protocol
559 } // namespace blink 495 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698