| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "core/html/track/vtt/VTTParser.h" | 32 #include "core/html/track/vtt/VTTParser.h" |
| 33 | 33 |
| 34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
| 35 #include "core/dom/ProcessingInstruction.h" | 35 #include "core/dom/ProcessingInstruction.h" |
| 36 #include "core/dom/Text.h" | 36 #include "core/dom/Text.h" |
| 37 #include "core/html/track/vtt/VTTElement.h" | 37 #include "core/html/track/vtt/VTTElement.h" |
| 38 #include "core/html/track/vtt/VTTScanner.h" |
| 38 #include "platform/text/SegmentedString.h" | 39 #include "platform/text/SegmentedString.h" |
| 39 #include "wtf/text/WTFString.h" | 40 #include "wtf/text/WTFString.h" |
| 40 | 41 |
| 41 namespace WebCore { | 42 namespace WebCore { |
| 42 | 43 |
| 43 const double secondsPerHour = 3600; | 44 const double secondsPerHour = 3600; |
| 44 const double secondsPerMinute = 60; | 45 const double secondsPerMinute = 60; |
| 45 const double secondsPerMillisecond = 0.001; | 46 const double secondsPerMillisecond = 0.001; |
| 46 const unsigned fileIdentifierLength = 6; | 47 const unsigned fileIdentifierLength = 6; |
| 47 | 48 |
| 48 static unsigned scanDigits(const String& input, unsigned* position) | 49 static unsigned scanDigits(const String& input, unsigned* position) |
| 49 { | 50 { |
| 50 unsigned startPosition = *position; | 51 unsigned startPosition = *position; |
| 51 while (*position < input.length() && isASCIIDigit(input[*position])) | 52 while (*position < input.length() && isASCIIDigit(input[*position])) |
| 52 (*position)++; | 53 (*position)++; |
| 53 return *position - startPosition; | 54 return *position - startPosition; |
| 54 } | 55 } |
| 55 | 56 |
| 56 unsigned VTTParser::collectDigitsToInt(const String& input, unsigned* position,
int& number) | 57 unsigned VTTParser::collectDigitsToInt(const String& input, unsigned* position,
int& number) |
| 57 { | 58 { |
| 58 unsigned startPosition = *position; | 59 VTTLegacyScanner inputScanner(input, position); |
| 59 unsigned numDigits = scanDigits(input, position); | 60 return inputScanner.scanDigits(number); |
| 60 if (!numDigits) { | |
| 61 number = 0; | |
| 62 return 0; | |
| 63 } | |
| 64 bool validNumber; | |
| 65 if (input.is8Bit()) | |
| 66 number = charactersToInt(input.characters8() + startPosition, numDigits,
&validNumber); | |
| 67 else | |
| 68 number = charactersToInt(input.characters16() + startPosition, numDigits
, &validNumber); | |
| 69 | |
| 70 // Since we know that scanDigits only scanned valid (ASCII) digits (and | |
| 71 // hence that's what got passed to charactersToInt()), the remaining | |
| 72 // failure mode for charactersToInt() is overflow, so if |validNumber| is | |
| 73 // not true, then set |number| to the maximum int value. | |
| 74 if (!validNumber) | |
| 75 number = std::numeric_limits<int>::max(); | |
| 76 return numDigits; | |
| 77 } | 61 } |
| 78 | 62 |
| 79 String VTTParser::collectWord(const String& input, unsigned* position) | 63 String VTTParser::collectWord(const String& input, unsigned* position) |
| 80 { | 64 { |
| 81 StringBuilder string; | 65 StringBuilder string; |
| 82 while (*position < input.length() && !isASpace(input[*position])) | 66 while (*position < input.length() && !isASpace(input[*position])) |
| 83 string.append(input[(*position)++]); | 67 string.append(input[(*position)++]); |
| 84 return string.toString(); | 68 return string.toString(); |
| 85 } | 69 } |
| 86 | 70 |
| 87 void VTTParser::skipWhiteSpace(const String& line, unsigned* position) | |
| 88 { | |
| 89 while (*position < line.length() && isASpace(line[*position])) | |
| 90 (*position)++; | |
| 91 } | |
| 92 | |
| 93 bool VTTParser::parseFloatPercentageValue(const String& value, float& percentage
) | 71 bool VTTParser::parseFloatPercentageValue(const String& value, float& percentage
) |
| 94 { | 72 { |
| 95 // '%' must be present and at the end of the setting value. | 73 // '%' must be present and at the end of the setting value. |
| 96 if (value.isEmpty() || value[value.length() - 1] != '%') | 74 if (value.isEmpty() || value[value.length() - 1] != '%') |
| 97 return false; | 75 return false; |
| 98 | 76 |
| 99 unsigned position = 0; | 77 unsigned position = 0; |
| 100 unsigned digitsBeforeDot = scanDigits(value, &position); | 78 unsigned digitsBeforeDot = scanDigits(value, &position); |
| 101 unsigned digitsAfterDot = 0; | 79 unsigned digitsAfterDot = 0; |
| 102 if (value[position] == '.') { | 80 if (value[position] == '.') { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 VTTParser::ParseState VTTParser::collectCueId(const String& line) | 278 VTTParser::ParseState VTTParser::collectCueId(const String& line) |
| 301 { | 279 { |
| 302 if (line.contains("-->")) | 280 if (line.contains("-->")) |
| 303 return collectTimingsAndSettings(line); | 281 return collectTimingsAndSettings(line); |
| 304 m_currentId = line; | 282 m_currentId = line; |
| 305 return TimingsAndSettings; | 283 return TimingsAndSettings; |
| 306 } | 284 } |
| 307 | 285 |
| 308 VTTParser::ParseState VTTParser::collectTimingsAndSettings(const String& line) | 286 VTTParser::ParseState VTTParser::collectTimingsAndSettings(const String& line) |
| 309 { | 287 { |
| 288 VTTScanner input(line); |
| 289 |
| 310 // Collect WebVTT cue timings and settings. (5.3 WebVTT cue timings and sett
ings parsing.) | 290 // Collect WebVTT cue timings and settings. (5.3 WebVTT cue timings and sett
ings parsing.) |
| 311 // Steps 1 - 3 - Let input be the string being parsed and position be a poin
ter into input. | 291 // Steps 1 - 3 - Let input be the string being parsed and position be a poin
ter into input. |
| 312 unsigned position = 0; | 292 input.skipWhile<isASpace>(); |
| 313 skipWhiteSpace(line, &position); | |
| 314 | 293 |
| 315 // Steps 4 - 5 - Collect a WebVTT timestamp. If that fails, then abort and r
eturn failure. Otherwise, let cue's text track cue start time be the collected t
ime. | 294 // Steps 4 - 5 - Collect a WebVTT timestamp. If that fails, then abort and r
eturn failure. Otherwise, let cue's text track cue start time be the collected t
ime. |
| 316 if (!collectTimeStamp(line, &position, m_currentStartTime)) | 295 if (!collectTimeStamp(input, m_currentStartTime)) |
| 317 return BadCue; | 296 return BadCue; |
| 318 if (position >= line.length()) | 297 input.skipWhile<isASpace>(); |
| 319 return BadCue; | |
| 320 | |
| 321 skipWhiteSpace(line, &position); | |
| 322 | 298 |
| 323 // Steps 6 - 9 - If the next three characters are not "-->", abort and retur
n failure. | 299 // Steps 6 - 9 - If the next three characters are not "-->", abort and retur
n failure. |
| 324 if (line.find("-->", position) == kNotFound) | 300 if (!input.scan("-->")) |
| 325 return BadCue; | 301 return BadCue; |
| 326 position += 3; | 302 input.skipWhile<isASpace>(); |
| 327 if (position >= line.length()) | |
| 328 return BadCue; | |
| 329 | |
| 330 skipWhiteSpace(line, &position); | |
| 331 | 303 |
| 332 // Steps 10 - 11 - Collect a WebVTT timestamp. If that fails, then abort and
return failure. Otherwise, let cue's text track cue end time be the collected t
ime. | 304 // Steps 10 - 11 - Collect a WebVTT timestamp. If that fails, then abort and
return failure. Otherwise, let cue's text track cue end time be the collected t
ime. |
| 333 if (!collectTimeStamp(line, &position, m_currentEndTime)) | 305 if (!collectTimeStamp(input, m_currentEndTime)) |
| 334 return BadCue; | 306 return BadCue; |
| 335 skipWhiteSpace(line, &position); | 307 input.skipWhile<isASpace>(); |
| 336 | 308 |
| 337 // Step 12 - Parse the WebVTT settings for the cue (conducted in TextTrackCu
e). | 309 // Step 12 - Parse the WebVTT settings for the cue (conducted in TextTrackCu
e). |
| 338 m_currentSettings = line.substring(position, line.length()-1); | 310 m_currentSettings = input.restOfInputAsString(); |
| 339 return CueText; | 311 return CueText; |
| 340 } | 312 } |
| 341 | 313 |
| 342 VTTParser::ParseState VTTParser::collectCueText(const String& line) | 314 VTTParser::ParseState VTTParser::collectCueText(const String& line) |
| 343 { | 315 { |
| 344 // Step 34. | 316 // Step 34. |
| 345 if (line.isEmpty()) { | 317 if (line.isEmpty()) { |
| 346 createNewCue(); | 318 createNewCue(); |
| 347 return Id; | 319 return Id; |
| 348 } | 320 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 break; | 435 break; |
| 464 } | 436 } |
| 465 } | 437 } |
| 466 | 438 |
| 467 // Step 12.5.11 | 439 // Step 12.5.11 |
| 468 m_regionList.append(region); | 440 m_regionList.append(region); |
| 469 } | 441 } |
| 470 | 442 |
| 471 bool VTTParser::collectTimeStamp(const String& line, unsigned* position, double&
timeStamp) | 443 bool VTTParser::collectTimeStamp(const String& line, unsigned* position, double&
timeStamp) |
| 472 { | 444 { |
| 445 VTTLegacyScanner input(line, position); |
| 446 return collectTimeStamp(input, timeStamp); |
| 447 } |
| 448 |
| 449 bool VTTParser::collectTimeStamp(VTTScanner& input, double& timeStamp) |
| 450 { |
| 473 // Collect a WebVTT timestamp (5.3 WebVTT cue timings and settings parsing.) | 451 // Collect a WebVTT timestamp (5.3 WebVTT cue timings and settings parsing.) |
| 474 // Steps 1 - 4 - Initial checks, let most significant units be minutes. | 452 // Steps 1 - 4 - Initial checks, let most significant units be minutes. |
| 475 enum Mode { Minutes, Hours }; | 453 enum Mode { Minutes, Hours }; |
| 476 Mode mode = Minutes; | 454 Mode mode = Minutes; |
| 477 | 455 |
| 478 // Steps 5 - 7 - Collect a sequence of characters that are 0-9. | 456 // Steps 5 - 7 - Collect a sequence of characters that are 0-9. |
| 479 // If not 2 characters or value is greater than 59, interpret as hours. | 457 // If not 2 characters or value is greater than 59, interpret as hours. |
| 480 int value1; | 458 int value1; |
| 481 unsigned value1Digits = collectDigitsToInt(line, position, value1); | 459 unsigned value1Digits = input.scanDigits(value1); |
| 482 if (!value1Digits) | 460 if (!value1Digits) |
| 483 return false; | 461 return false; |
| 484 if (value1Digits != 2 || value1 > 59) | 462 if (value1Digits != 2 || value1 > 59) |
| 485 mode = Hours; | 463 mode = Hours; |
| 486 | 464 |
| 487 // Steps 8 - 11 - Collect the next sequence of 0-9 after ':' (must be 2 char
s). | 465 // Steps 8 - 11 - Collect the next sequence of 0-9 after ':' (must be 2 char
s). |
| 488 if (*position >= line.length() || line[(*position)++] != ':') | |
| 489 return false; | |
| 490 int value2; | 466 int value2; |
| 491 if (collectDigitsToInt(line, position, value2) != 2) | 467 if (!input.scan(':') || input.scanDigits(value2) != 2) |
| 492 return false; | 468 return false; |
| 493 | 469 |
| 494 // Step 12 - Detect whether this timestamp includes hours. | 470 // Step 12 - Detect whether this timestamp includes hours. |
| 495 int value3; | 471 int value3; |
| 496 if (mode == Hours || (*position < line.length() && line[*position] == ':'))
{ | 472 if (mode == Hours || input.match(':')) { |
| 497 if (*position >= line.length() || line[(*position)++] != ':') | 473 if (!input.scan(':') || input.scanDigits(value3) != 2) |
| 498 return false; | |
| 499 if (collectDigitsToInt(line, position, value3) != 2) | |
| 500 return false; | 474 return false; |
| 501 } else { | 475 } else { |
| 502 value3 = value2; | 476 value3 = value2; |
| 503 value2 = value1; | 477 value2 = value1; |
| 504 value1 = 0; | 478 value1 = 0; |
| 505 } | 479 } |
| 506 | 480 |
| 507 // Steps 13 - 17 - Collect next sequence of 0-9 after '.' (must be 3 chars). | 481 // Steps 13 - 17 - Collect next sequence of 0-9 after '.' (must be 3 chars). |
| 508 if (*position >= line.length() || line[(*position)++] != '.') | |
| 509 return false; | |
| 510 int value4; | 482 int value4; |
| 511 if (collectDigitsToInt(line, position, value4) != 3) | 483 if (!input.scan('.') || input.scanDigits(value4) != 3) |
| 512 return false; | 484 return false; |
| 513 if (value2 > 59 || value3 > 59) | 485 if (value2 > 59 || value3 > 59) |
| 514 return false; | 486 return false; |
| 515 | 487 |
| 516 // Steps 18 - 19 - Calculate result. | 488 // Steps 18 - 19 - Calculate result. |
| 517 timeStamp = (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3
+ (value4 * secondsPerMillisecond); | 489 timeStamp = (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3
+ (value4 * secondsPerMillisecond); |
| 518 return true; | 490 return true; |
| 519 } | 491 } |
| 520 | 492 |
| 521 static VTTNodeType tokenToNodeType(VTTToken& token) | 493 static VTTNodeType tokenToNodeType(VTTToken& token) |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 m_currentNode->parserAppendChild(ProcessingInstruction::create(docum
ent, "timestamp", charactersString)); | 590 m_currentNode->parserAppendChild(ProcessingInstruction::create(docum
ent, "timestamp", charactersString)); |
| 619 break; | 591 break; |
| 620 } | 592 } |
| 621 default: | 593 default: |
| 622 break; | 594 break; |
| 623 } | 595 } |
| 624 } | 596 } |
| 625 | 597 |
| 626 } | 598 } |
| 627 | 599 |
| OLD | NEW |