• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef VTTScanner_h
31 #define VTTScanner_h
32 
33 #include "platform/ParsingUtilities.h"
34 #include "wtf/text/WTFString.h"
35 
36 namespace blink {
37 
38 // Helper class for "scanning" an input string and performing parsing of
39 // "micro-syntax"-like constructs.
40 //
41 // There's two primary operations: match and scan.
42 //
43 // The 'match' operation matches an explicitly or implicitly specified sequence
44 // against the characters ahead of the current input pointer, and returns true
45 // if the sequence can be matched.
46 //
47 // The 'scan' operation performs a 'match', and if the match is successful it
48 // advance the input pointer past the matched sequence.
49 class VTTScanner {
50     WTF_MAKE_NONCOPYABLE(VTTScanner);
51 public:
52     explicit VTTScanner(const String& line);
53 
54     typedef const LChar* Position;
55 
56     class Run {
57     public:
Run(Position start,Position end,bool is8Bit)58         Run(Position start, Position end, bool is8Bit)
59             : m_start(start), m_end(end), m_is8Bit(is8Bit) { }
60 
start()61         Position start() const { return m_start; }
end()62         Position end() const { return m_end; }
63 
isEmpty()64         bool isEmpty() const { return m_start == m_end; }
65         size_t length() const;
66 
67     private:
68         Position m_start;
69         Position m_end;
70         bool m_is8Bit;
71     };
72 
73     // Check if the input pointer points at the specified position.
isAt(Position checkPosition)74     bool isAt(Position checkPosition) const { return position() == checkPosition; }
75     // Check if the input pointer points at the end of the input.
isAtEnd()76     bool isAtEnd() const { return position() == end(); }
77     // Match the character |c| against the character at the input pointer (~lookahead).
match(char c)78     bool match(char c) const { return !isAtEnd() && currentChar() == c; }
79     // Scan the character |c|.
80     bool scan(char);
81     // Scan the first |charactersCount| characters of the string |characters|.
82     bool scan(const LChar* characters, size_t charactersCount);
83 
84     // Scan the literal |characters|.
85     template<unsigned charactersCount>
86     bool scan(const char (&characters)[charactersCount]);
87 
88     // Skip (advance the input pointer) as long as the specified
89     // |characterPredicate| returns true, and the input pointer is not passed
90     // the end of the input.
91     template<bool characterPredicate(UChar)>
92     void skipWhile();
93 
94     // Like skipWhile, but using a negated predicate.
95     template<bool characterPredicate(UChar)>
96     void skipUntil();
97 
98     // Return the run of characters for which the specified
99     // |characterPredicate| returns true. The start of the run will be the
100     // current input pointer.
101     template<bool characterPredicate(UChar)>
102     Run collectWhile();
103 
104     // Like collectWhile, but using a negated predicate.
105     template<bool characterPredicate(UChar)>
106     Run collectUntil();
107 
108     // Scan the string |toMatch|, using the specified |run| as the sequence to
109     // match against.
110     bool scanRun(const Run&, const String& toMatch);
111 
112     // Skip to the end of the specified |run|.
113     void skipRun(const Run&);
114 
115     // Return the String made up of the characters in |run|, and advance the
116     // input pointer to the end of the run.
117     String extractString(const Run&);
118 
119     // Return a String constructed from the rest of the input (between input
120     // pointer and end of input), and advance the input pointer accordingly.
121     String restOfInputAsString();
122 
123     // Scan a set of ASCII digits from the input. Return the number of digits
124     // scanned, and set |number| to the computed value. If the digits make up a
125     // number that does not fit the 'int' type, |number| is set to INT_MAX.
126     // Note: Does not handle sign.
127     unsigned scanDigits(int& number);
128 
129     // Scan a floating point value on one of the forms: \d+\.? \d+\.\d+ \.\d+
130     bool scanFloat(float& number);
131 
132 protected:
position()133     Position position() const { return m_data.characters8; }
end()134     Position end() const { return m_end.characters8; }
135     void seekTo(Position);
136     UChar currentChar() const;
137     void advance(unsigned amount = 1);
138     // Adapt a UChar-predicate to an LChar-predicate.
139     // (For use with skipWhile/Until from ParsingUtilities.h).
140     template<bool characterPredicate(UChar)>
LCharPredicateAdapter(LChar c)141     static inline bool LCharPredicateAdapter(LChar c) { return characterPredicate(c); }
142     union {
143         const LChar* characters8;
144         const UChar* characters16;
145     } m_data;
146     union {
147         const LChar* characters8;
148         const UChar* characters16;
149     } m_end;
150     bool m_is8Bit;
151 };
152 
length()153 inline size_t VTTScanner::Run::length() const
154 {
155     if (m_is8Bit)
156         return m_end - m_start;
157     return reinterpret_cast<const UChar*>(m_end) - reinterpret_cast<const UChar*>(m_start);
158 }
159 
160 template<unsigned charactersCount>
scan(const char (& characters)[charactersCount])161 inline bool VTTScanner::scan(const char (&characters)[charactersCount])
162 {
163     return scan(reinterpret_cast<const LChar*>(characters), charactersCount - 1);
164 }
165 
166 template<bool characterPredicate(UChar)>
skipWhile()167 inline void VTTScanner::skipWhile()
168 {
169     if (m_is8Bit)
170         ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
171     else
172         ::skipWhile<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
173 }
174 
175 template<bool characterPredicate(UChar)>
skipUntil()176 inline void VTTScanner::skipUntil()
177 {
178     if (m_is8Bit)
179         ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
180     else
181         ::skipUntil<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
182 }
183 
184 template<bool characterPredicate(UChar)>
collectWhile()185 inline VTTScanner::Run VTTScanner::collectWhile()
186 {
187     if (m_is8Bit) {
188         const LChar* current = m_data.characters8;
189         ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
190         return Run(position(), current, m_is8Bit);
191     }
192     const UChar* current = m_data.characters16;
193     ::skipWhile<UChar, characterPredicate>(current, m_end.characters16);
194     return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
195 }
196 
197 template<bool characterPredicate(UChar)>
collectUntil()198 inline VTTScanner::Run VTTScanner::collectUntil()
199 {
200     if (m_is8Bit) {
201         const LChar* current = m_data.characters8;
202         ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
203         return Run(position(), current, m_is8Bit);
204     }
205     const UChar* current = m_data.characters16;
206     ::skipUntil<UChar, characterPredicate>(current, m_end.characters16);
207     return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
208 }
209 
seekTo(Position position)210 inline void VTTScanner::seekTo(Position position)
211 {
212     ASSERT(position <= end());
213     m_data.characters8 = position;
214 }
215 
currentChar()216 inline UChar VTTScanner::currentChar() const
217 {
218     ASSERT(position() < end());
219     return m_is8Bit ? *m_data.characters8 : *m_data.characters16;
220 }
221 
advance(unsigned amount)222 inline void VTTScanner::advance(unsigned amount)
223 {
224     ASSERT(position() < end());
225     if (m_is8Bit)
226         m_data.characters8 += amount;
227     else
228         m_data.characters16 += amount;
229 }
230 
231 }
232 
233 #endif
234