1/*
2 * Copyright (c) 2013, Opera Software ASA. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of Opera Software ASA nor the names of its
13 *    contributors may be used to endorse or promote products derived
14 *    from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 * OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "config.h"
31#include "VTTScanner.h"
32
33namespace WebCore {
34
35VTTScanner::VTTScanner(const String& line)
36    : m_is8Bit(line.is8Bit())
37{
38    if (m_is8Bit) {
39        m_data.characters8 = line.characters8();
40        m_end.characters8 = m_data.characters8 + line.length();
41    } else {
42        m_data.characters16 = line.characters16();
43        m_end.characters16 = m_data.characters16 + line.length();
44    }
45}
46
47bool VTTScanner::scan(char c)
48{
49    if (!match(c))
50        return false;
51    advance();
52    return true;
53}
54
55bool VTTScanner::scan(const LChar* characters, size_t charactersCount)
56{
57    unsigned matchLength = m_is8Bit ? m_end.characters8 - m_data.characters8 : m_end.characters16 - m_data.characters16;
58    if (matchLength < charactersCount)
59        return false;
60    bool matched;
61    if (m_is8Bit)
62        matched = WTF::equal(m_data.characters8, characters, charactersCount);
63    else
64        matched = WTF::equal(m_data.characters16, characters, charactersCount);
65    if (matched)
66        advance(charactersCount);
67    return matched;
68}
69
70bool VTTScanner::scanRun(const Run& run, const String& toMatch)
71{
72    ASSERT(run.start() == position());
73    ASSERT(run.start() <= end());
74    ASSERT(run.end() >= run.start());
75    ASSERT(run.end() <= end());
76    size_t matchLength = run.length();
77    if (toMatch.length() > matchLength)
78        return false;
79    bool matched;
80    if (m_is8Bit)
81        matched = WTF::equal(toMatch.impl(), m_data.characters8, matchLength);
82    else
83        matched = WTF::equal(toMatch.impl(), m_data.characters16, matchLength);
84    if (matched)
85        seekTo(run.end());
86    return matched;
87}
88
89void VTTScanner::skipRun(const Run& run)
90{
91    ASSERT(run.start() <= end());
92    ASSERT(run.end() >= run.start());
93    ASSERT(run.end() <= end());
94    seekTo(run.end());
95}
96
97String VTTScanner::extractString(const Run& run)
98{
99    ASSERT(run.start() == position());
100    ASSERT(run.start() <= end());
101    ASSERT(run.end() >= run.start());
102    ASSERT(run.end() <= end());
103    String s;
104    if (m_is8Bit)
105        s = String(m_data.characters8, run.length());
106    else
107        s = String(m_data.characters16, run.length());
108    seekTo(run.end());
109    return s;
110}
111
112String VTTScanner::restOfInputAsString()
113{
114    Run rest(position(), end(), m_is8Bit);
115    return extractString(rest);
116}
117
118unsigned VTTScanner::scanDigits(int& number)
119{
120    Run runOfDigits = collectWhile<isASCIIDigit>();
121    if (runOfDigits.isEmpty()) {
122        number = 0;
123        return 0;
124    }
125    bool validNumber;
126    size_t numDigits = runOfDigits.length();
127    if (m_is8Bit)
128        number = charactersToIntStrict(m_data.characters8, numDigits, &validNumber);
129    else
130        number = charactersToIntStrict(m_data.characters16, numDigits, &validNumber);
131
132    // Since we know that scanDigits only scanned valid (ASCII) digits (and
133    // hence that's what got passed to charactersToInt()), the remaining
134    // failure mode for charactersToInt() is overflow, so if |validNumber| is
135    // not true, then set |number| to the maximum int value.
136    if (!validNumber)
137        number = std::numeric_limits<int>::max();
138    // Consume the digits.
139    seekTo(runOfDigits.end());
140    return numDigits;
141}
142
143bool VTTScanner::scanFloat(float& number, bool* isNegative)
144{
145    bool negative = scan('-');
146    Run integerRun = collectWhile<isASCIIDigit>();
147
148    seekTo(integerRun.end());
149    Run decimalRun(position(), position(), m_is8Bit);
150    if (scan('.')) {
151        decimalRun = collectWhile<isASCIIDigit>();
152        seekTo(decimalRun.end());
153    }
154
155    // At least one digit required.
156    if (integerRun.isEmpty() && decimalRun.isEmpty()) {
157        // Restore to starting position.
158        seekTo(integerRun.start());
159        return false;
160    }
161
162    size_t lengthOfFloat = Run(integerRun.start(), position(), m_is8Bit).length();
163    bool validNumber;
164    if (m_is8Bit)
165        number = charactersToFloat(integerRun.start(), lengthOfFloat, &validNumber);
166    else
167        number = charactersToFloat(reinterpret_cast<const UChar*>(integerRun.start()), lengthOfFloat, &validNumber);
168
169    if (!validNumber)
170        number = std::numeric_limits<float>::max();
171    else if (negative)
172        number = -number;
173
174    if (isNegative)
175        *isNegative = negative;
176
177    return true;
178}
179
180}
181