void WebVTTParser::parseBytes(const char* data, unsigned length) { // 4.8.10.13.3 WHATWG WebVTT Parser algorithm. // 1-3 - Initial setup. unsigned position = 0; while (position < length) { String line = collectNextLine(data, length, &position); switch (m_state) { case Initial: // Buffer up at least 9 bytes before proceeding with checking for the file identifier. m_identifierData.append(data, length); if (m_identifierData.size() < bomLength + fileIdentifierLength) return; // 4-12 - Collect the first line and check for "WEBVTT". if (!hasRequiredFileIdentifier()) { if (m_client) m_client->fileFailedToParse(); return; } m_state = Header; m_identifierData.clear(); break; case Header: // 13-18 - Allow a header (comment area) under the WEBVTT line. if (line.isEmpty()) m_state = Id; break; case Id: // 19-29 - Allow any number of line terminators, then initialize new cue values. if (line.isEmpty()) break; resetCueValues(); // 30-39 - Check if this line contains an optional identifier or timing data. m_state = collectCueId(line); break; case TimingsAndSettings: // 40 - Collect cue timings and settings. m_state = collectTimingsAndSettings(line); break; case CueText: // 41-53 - Collect the cue text, create a cue, and add it to the output. m_state = collectCueText(line, length, position); break; case BadCue: // 54-62 - Collect and discard the remaining cue. m_state = ignoreBadCue(line); break; } } }
void VTTParser::parse() { // WebVTT parser algorithm. (5.1 WebVTT file parsing.) // Steps 1 - 3 - Initial setup. String line; while (m_lineReader.getLine(line)) { switch (m_state) { case Initial: // Steps 4 - 9 - Check for a valid WebVTT signature. if (!hasRequiredFileIdentifier(line)) { if (m_client) m_client->fileFailedToParse(); return; } m_state = Header; break; case Header: // Steps 10 - 14 - Allow a header (comment area) under the WEBVTT line. collectMetadataHeader(line); if (line.isEmpty()) { if (m_client && m_regionList.size()) m_client->newRegionsParsed(); m_state = Id; break; } // Step 15 - Break out of header loop if the line could be a timestamp line. if (line.contains("-->")) m_state = recoverCue(line); // Step 16 - Line is not the empty string and does not contain "-->". break; case Id: // Steps 17 - 20 - Allow any number of line terminators, then initialize new cue values. if (line.isEmpty()) break; // Step 21 - Cue creation (start a new cue). resetCueValues(); // Steps 22 - 25 - Check if this line contains an optional identifier or timing data. m_state = collectCueId(line); break; case TimingsAndSettings: // Steps 26 - 27 - Discard current cue if the line is empty. if (line.isEmpty()) { m_state = Id; break; } // Steps 28 - 29 - Collect cue timings and settings. m_state = collectTimingsAndSettings(line); break; case CueText: // Steps 31 - 41 - Collect the cue text, create a cue, and add it to the output. m_state = collectCueText(line); break; case BadCue: // Steps 42 - 48 - Discard lines until an empty line or a potential timing line is seen. m_state = ignoreBadCue(line); break; } } }