blob: a6ded6dd91d3ace7aff13bd8d8919db79d9e8b80 [file] [log] [blame]
/*
* Copyright (c) 2013, Opera Software ASA. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Opera Software ASA nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h"
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
namespace blink {
VTTScanner::VTTScanner(const String& line) : is_8bit_(line.Is8Bit()) {
if (is_8bit_) {
data_.characters8 = line.Characters8();
end_.characters8 = data_.characters8 + line.length();
} else {
data_.characters16 = line.Characters16();
end_.characters16 = data_.characters16 + line.length();
}
}
bool VTTScanner::Scan(char c) {
if (!Match(c))
return false;
Advance();
return true;
}
bool VTTScanner::Scan(const LChar* characters, wtf_size_t characters_count) {
wtf_size_t match_length =
is_8bit_
? static_cast<wtf_size_t>(end_.characters8 - data_.characters8)
: static_cast<wtf_size_t>(end_.characters16 - data_.characters16);
if (match_length < characters_count)
return false;
bool matched;
if (is_8bit_)
matched = WTF::Equal(data_.characters8, characters, characters_count);
else
matched = WTF::Equal(data_.characters16, characters, characters_count);
if (matched)
Advance(characters_count);
return matched;
}
bool VTTScanner::ScanRun(const Run& run, const String& to_match) {
DCHECK_EQ(run.Start(), GetPosition());
DCHECK_LE(run.Start(), end());
DCHECK_GE(run.end(), run.Start());
DCHECK_LE(run.end(), end());
wtf_size_t match_length = run.length();
if (to_match.length() > match_length)
return false;
bool matched;
if (is_8bit_)
matched = WTF::Equal(to_match.Impl(), data_.characters8, match_length);
else
matched = WTF::Equal(to_match.Impl(), data_.characters16, match_length);
if (matched)
SeekTo(run.end());
return matched;
}
void VTTScanner::SkipRun(const Run& run) {
DCHECK_LE(run.Start(), end());
DCHECK_GE(run.end(), run.Start());
DCHECK_LE(run.end(), end());
SeekTo(run.end());
}
String VTTScanner::ExtractString(const Run& run) {
DCHECK_EQ(run.Start(), GetPosition());
DCHECK_LE(run.Start(), end());
DCHECK_GE(run.end(), run.Start());
DCHECK_LE(run.end(), end());
String s;
if (is_8bit_)
s = String(data_.characters8, run.length());
else
s = String(data_.characters16, run.length());
SeekTo(run.end());
return s;
}
String VTTScanner::RestOfInputAsString() {
Run rest(GetPosition(), end(), is_8bit_);
return ExtractString(rest);
}
unsigned VTTScanner::ScanDigits(unsigned& number) {
Run run_of_digits = CollectWhile<IsASCIIDigit>();
if (run_of_digits.IsEmpty()) {
number = 0;
return 0;
}
bool valid_number;
wtf_size_t num_digits = run_of_digits.length();
if (is_8bit_) {
number = CharactersToUInt(data_.characters8, num_digits,
WTF::NumberParsingOptions::kNone, &valid_number);
} else {
number = CharactersToUInt(data_.characters16, num_digits,
WTF::NumberParsingOptions::kNone, &valid_number);
}
// Since we know that scanDigits only scanned valid (ASCII) digits (and
// hence that's what got passed to charactersToUInt()), the remaining
// failure mode for charactersToUInt() is overflow, so if |validNumber| is
// not true, then set |number| to the maximum unsigned value.
if (!valid_number)
number = std::numeric_limits<unsigned>::max();
// Consume the digits.
SeekTo(run_of_digits.end());
return num_digits;
}
bool VTTScanner::ScanDouble(double& number) {
Run integer_run = CollectWhile<IsASCIIDigit>();
SeekTo(integer_run.end());
Run decimal_run(GetPosition(), GetPosition(), is_8bit_);
if (Scan('.')) {
decimal_run = CollectWhile<IsASCIIDigit>();
SeekTo(decimal_run.end());
}
// At least one digit required.
if (integer_run.IsEmpty() && decimal_run.IsEmpty()) {
// Restore to starting position.
SeekTo(integer_run.Start());
return false;
}
size_t length_of_double =
Run(integer_run.Start(), GetPosition(), is_8bit_).length();
bool valid_number;
if (is_8bit_) {
number = CharactersToDouble(integer_run.Start(), length_of_double,
&valid_number);
} else {
number =
CharactersToDouble(reinterpret_cast<const UChar*>(integer_run.Start()),
length_of_double, &valid_number);
}
if (number == std::numeric_limits<double>::infinity())
return false;
if (!valid_number)
number = std::numeric_limits<double>::max();
return true;
}
bool VTTScanner::ScanPercentage(double& percentage) {
Position saved_position = GetPosition();
if (!ScanDouble(percentage))
return false;
if (Scan('%'))
return true;
// Restore scanner position.
SeekTo(saved_position);
return false;
}
} // namespace blink