UNPKG

shaka-player

Version:
181 lines (154 loc) 4.07 kB
/*! @license * Shaka Player * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ goog.provide('shaka.util.TextParser'); goog.require('goog.asserts'); /** * Reads elements from strings. */ shaka.util.TextParser = class { /** * @param {string} data */ constructor(data) { /** * @const * @private {string} */ this.data_ = data || ''; /** @private {number} */ this.position_ = 0; } /** @return {boolean} Whether it is at the end of the string. */ atEnd() { return this.position_ == this.data_.length; } /** * Reads a line from the parser. This will read but not return the newline. * Returns null at the end. * * @return {?string} */ readLine() { return this.readRegexReturnCapture_(/(.*?)(\n|$)/gm, 1); } /** * Reads a word from the parser. This will not read or return any whitespace * before or after the word (including newlines). Returns null at the end. * * @return {?string} */ readWord() { return this.readRegexReturnCapture_(/[^ \t\n]*/gm, 0); } /** * Skips any continuous whitespace from the parser. Returns null at the end. */ skipWhitespace() { this.readRegex(/[ \t]+/gm); } /** * Reads the given regular expression from the parser. This requires the * match to be at the current position; there is no need to include a head * anchor. * This requires that the regex have the global flag to be set so that it can * set lastIndex to start the search at the current position. Returns null at * the end or if the regex does not match the current position. * * @param {!RegExp} regex * @return {Array<string>} */ readRegex(regex) { const index = this.indexOf_(regex); if (this.atEnd() || index == null || index.position != this.position_) { return null; } this.position_ += index.length; return index.results; } /** * Reads a regex from the parser and returns the given capture. * * @param {!RegExp} regex * @param {number} index * @return {?string} * @private */ readRegexReturnCapture_(regex, index) { if (this.atEnd()) { return null; } const ret = this.readRegex(regex); if (!ret) { return null; } else { return ret[index]; } } /** * Returns the index info about a regular expression match. * * @param {!RegExp} regex * @return {?{position: number, length: number, results: !Array<string>}} * @private */ indexOf_(regex) { // The global flag is required to use lastIndex. goog.asserts.assert(regex.global, 'global flag should be set'); regex.lastIndex = this.position_; const results = regex.exec(this.data_); if (results == null) { return null; } else { return { position: results.index, length: results[0].length, results: results, }; } } /** * Parses a time. * * @return {?number} */ parseTime() { const results = this.readRegex(shaka.util.TextParser.timeFormat_); if (results == null) { return null; } // This capture is optional, but will still be in the array as undefined, // in which case it is 0. const hours = Number(results[1]) || 0; const minutes = Number(results[2]); const seconds = Number(results[3]); const milliseconds = Number(results[6]) || 0; if (minutes > 59 || seconds > 59) { return null; } return (milliseconds / 1000) + seconds + (minutes * 60) + (hours * 3600); } /** * Parses a time from string. * * @param {?string} time * @return {?number} */ static parseTime(time) { if (!time) { return null; } const parser = new shaka.util.TextParser(time); return parser.parseTime(); } }; /** * @const * @private {!RegExp} * @example 00:00.000 or 00:00:00.000 or 0:00:00.000 or * 00:00.00 or 00:00:00.00 or 0:00:00.00 or 00:00:00 */ shaka.util.TextParser.timeFormat_ = /(?:(\d{1,}):)?(\d{2}):(\d{2})((\.(\d{1,3})))?/g;