summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.h
blob: aa097e780ec360de1ca32ee224ad2b1ef2fcf2a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * 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.
 */

#ifndef VTTScanner_h
#define VTTScanner_h

#include "platform/ParsingUtilities.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

// Helper class for "scanning" an input string and performing parsing of
// "micro-syntax"-like constructs.
//
// There's two primary operations: match and scan.
//
// The 'match' operation matches an explicitly or implicitly specified sequence
// against the characters ahead of the current input pointer, and returns true
// if the sequence can be matched.
//
// The 'scan' operation performs a 'match', and if the match is successful it
// advance the input pointer past the matched sequence.
class VTTScanner {
    WTF_MAKE_NONCOPYABLE(VTTScanner);
public:
    explicit VTTScanner(const String& line);

    typedef const LChar* Position;

    class Run {
    public:
        Run(Position start, Position end, bool is8Bit)
            : m_start(start), m_end(end), m_is8Bit(is8Bit) { }

        Position start() const { return m_start; }
        Position end() const { return m_end; }

        bool isEmpty() const { return m_start == m_end; }
        size_t length() const;

    private:
        Position m_start;
        Position m_end;
        bool m_is8Bit;
    };

    // Check if the input pointer points at the specified position.
    bool isAt(Position checkPosition) const { return position() == checkPosition; }
    // Check if the input pointer points at the end of the input.
    bool isAtEnd() const { return position() == end(); }
    // Match the character |c| against the character at the input pointer (~lookahead).
    bool match(char c) const { return !isAtEnd() && currentChar() == c; }
    // Scan the character |c|.
    bool scan(char);
    // Scan the first |charactersCount| characters of the string |characters|.
    bool scan(const LChar* characters, size_t charactersCount);

    // Scan the literal |characters|.
    template<unsigned charactersCount>
    bool scan(const char (&characters)[charactersCount]);

    // Skip (advance the input pointer) as long as the specified
    // |characterPredicate| returns true, and the input pointer is not passed
    // the end of the input.
    template<bool characterPredicate(UChar)>
    void skipWhile();

    // Like skipWhile, but using a negated predicate.
    template<bool characterPredicate(UChar)>
    void skipUntil();

    // Return the run of characters for which the specified
    // |characterPredicate| returns true. The start of the run will be the
    // current input pointer.
    template<bool characterPredicate(UChar)>
    Run collectWhile();

    // Like collectWhile, but using a negated predicate.
    template<bool characterPredicate(UChar)>
    Run collectUntil();

    // Scan the string |toMatch|, using the specified |run| as the sequence to
    // match against.
    bool scanRun(const Run&, const String& toMatch);

    // Skip to the end of the specified |run|.
    void skipRun(const Run&);

    // Return the String made up of the characters in |run|, and advance the
    // input pointer to the end of the run.
    String extractString(const Run&);

    // Return a String constructed from the rest of the input (between input
    // pointer and end of input), and advance the input pointer accordingly.
    String restOfInputAsString();

    // Scan a set of ASCII digits from the input. Return the number of digits
    // scanned, and set |number| to the computed value. If the digits make up a
    // number that does not fit the 'int' type, |number| is set to INT_MAX.
    // Note: Does not handle sign.
    unsigned scanDigits(int& number);

    // Scan a floating point value on one of the forms: \d+\.? \d+\.\d+ \.\d+
    bool scanFloat(float& number);

protected:
    Position position() const { return m_data.characters8; }
    Position end() const { return m_end.characters8; }
    void seekTo(Position);
    UChar currentChar() const;
    void advance(unsigned amount = 1);
    // Adapt a UChar-predicate to an LChar-predicate.
    // (For use with skipWhile/Until from ParsingUtilities.h).
    template<bool characterPredicate(UChar)>
    static inline bool LCharPredicateAdapter(LChar c) { return characterPredicate(c); }
    union {
        const LChar* characters8;
        const UChar* characters16;
    } m_data;
    union {
        const LChar* characters8;
        const UChar* characters16;
    } m_end;
    bool m_is8Bit;
};

inline size_t VTTScanner::Run::length() const
{
    if (m_is8Bit)
        return m_end - m_start;
    return reinterpret_cast<const UChar*>(m_end) - reinterpret_cast<const UChar*>(m_start);
}

template<unsigned charactersCount>
inline bool VTTScanner::scan(const char (&characters)[charactersCount])
{
    return scan(reinterpret_cast<const LChar*>(characters), charactersCount - 1);
}

template<bool characterPredicate(UChar)>
inline void VTTScanner::skipWhile()
{
    if (m_is8Bit)
        ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
    else
        ::skipWhile<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
}

template<bool characterPredicate(UChar)>
inline void VTTScanner::skipUntil()
{
    if (m_is8Bit)
        ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
    else
        ::skipUntil<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
}

template<bool characterPredicate(UChar)>
inline VTTScanner::Run VTTScanner::collectWhile()
{
    if (m_is8Bit) {
        const LChar* current = m_data.characters8;
        ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
        return Run(position(), current, m_is8Bit);
    }
    const UChar* current = m_data.characters16;
    ::skipWhile<UChar, characterPredicate>(current, m_end.characters16);
    return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
}

template<bool characterPredicate(UChar)>
inline VTTScanner::Run VTTScanner::collectUntil()
{
    if (m_is8Bit) {
        const LChar* current = m_data.characters8;
        ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
        return Run(position(), current, m_is8Bit);
    }
    const UChar* current = m_data.characters16;
    ::skipUntil<UChar, characterPredicate>(current, m_end.characters16);
    return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
}

inline void VTTScanner::seekTo(Position position)
{
    ASSERT(position <= end());
    m_data.characters8 = position;
}

inline UChar VTTScanner::currentChar() const
{
    ASSERT(position() < end());
    return m_is8Bit ? *m_data.characters8 : *m_data.characters16;
}

inline void VTTScanner::advance(unsigned amount)
{
    ASSERT(position() < end());
    if (m_is8Bit)
        m_data.characters8 += amount;
    else
        m_data.characters16 += amount;
}

}

#endif