OLD | NEW |
(Empty) | |
| 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 WebCore { |
| 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: |
| 58 Run(Position start, Position end, bool is8Bit) |
| 59 : m_start(start), m_end(end), m_is8Bit(is8Bit) { } |
| 60 |
| 61 Position end() const { return m_end; } |
| 62 |
| 63 bool isEmpty() const { return m_start == m_end; } |
| 64 size_t length() const; |
| 65 |
| 66 private: |
| 67 Position m_start; |
| 68 Position m_end; |
| 69 bool m_is8Bit; |
| 70 }; |
| 71 |
| 72 // Check if the input pointer points at the specified position. |
| 73 bool isAt(Position checkPosition) const { return position() == checkPosition
; } |
| 74 // Check if the input pointer points at the end of the input. |
| 75 bool isAtEnd() const { return position() == end(); } |
| 76 // Match the character |c| against the character at the input pointer (~look
ahead). |
| 77 bool match(char c) const { return !isAtEnd() && currentChar() == c; } |
| 78 // Scan the character |c|. |
| 79 bool scan(char); |
| 80 // Scan the first |charactersCount| characters of the string |characters|. |
| 81 bool scan(const LChar* characters, size_t charactersCount); |
| 82 |
| 83 // Scan the literal |characters|. |
| 84 template<unsigned charactersCount> |
| 85 bool scan(const char (&characters)[charactersCount]); |
| 86 |
| 87 // Skip (advance the input pointer) as long as the specified |
| 88 // |characterPredicate| returns true, and the input pointer is not passed |
| 89 // the end of the input. |
| 90 template<bool characterPredicate(UChar)> |
| 91 void skipWhile(); |
| 92 |
| 93 // Return the run of characters for which the specified |
| 94 // |characterPredicate| returns true. The start of the run will be the |
| 95 // current input pointer. |
| 96 template<bool characterPredicate(UChar)> |
| 97 Run collectWhile(); |
| 98 |
| 99 // Return a String constructed from the rest of the input (between input |
| 100 // pointer and end of input), and advance the input pointer accordingly. |
| 101 String restOfInputAsString(); |
| 102 |
| 103 // Scan a set of ASCII digits from the input. Return the number of digits |
| 104 // scanned, and set |number| to the computed value. If the digits make up a |
| 105 // number that does not fit the 'int' type, |number| is set to INT_MAX. |
| 106 // Note: Does not handle sign. |
| 107 unsigned scanDigits(int& number); |
| 108 |
| 109 protected: |
| 110 Position position() const { return m_data.characters8; } |
| 111 Position end() const { return m_end.characters8; } |
| 112 void seekTo(Position); |
| 113 UChar currentChar() const; |
| 114 void advance(unsigned amount = 1); |
| 115 // Adapt a UChar-predicate to an LChar-predicate. |
| 116 // (For use with skipWhile/Until from ParsingUtilities.h). |
| 117 template<bool characterPredicate(UChar)> |
| 118 static inline bool LCharPredicateAdapter(LChar c) { return characterPredicat
e(c); } |
| 119 union { |
| 120 const LChar* characters8; |
| 121 const UChar* characters16; |
| 122 } m_data; |
| 123 union { |
| 124 const LChar* characters8; |
| 125 const UChar* characters16; |
| 126 } m_end; |
| 127 bool m_is8Bit; |
| 128 }; |
| 129 |
| 130 inline size_t VTTScanner::Run::length() const |
| 131 { |
| 132 if (m_is8Bit) |
| 133 return m_end - m_start; |
| 134 return reinterpret_cast<const UChar*>(m_end) - reinterpret_cast<const UChar*
>(m_start); |
| 135 } |
| 136 |
| 137 template<unsigned charactersCount> |
| 138 inline bool VTTScanner::scan(const char (&characters)[charactersCount]) |
| 139 { |
| 140 return scan(reinterpret_cast<const LChar*>(characters), charactersCount - 1)
; |
| 141 } |
| 142 |
| 143 template<bool characterPredicate(UChar)> |
| 144 inline void VTTScanner::skipWhile() |
| 145 { |
| 146 if (m_is8Bit) |
| 147 ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.ch
aracters8, m_end.characters8); |
| 148 else |
| 149 ::skipWhile<UChar, characterPredicate>(m_data.characters16, m_end.charac
ters16); |
| 150 } |
| 151 |
| 152 template<bool characterPredicate(UChar)> |
| 153 inline VTTScanner::Run VTTScanner::collectWhile() |
| 154 { |
| 155 if (m_is8Bit) { |
| 156 const LChar* current = m_data.characters8; |
| 157 ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(current,
m_end.characters8); |
| 158 return Run(position(), current, m_is8Bit); |
| 159 } |
| 160 const UChar* current = m_data.characters16; |
| 161 ::skipWhile<UChar, characterPredicate>(current, m_end.characters16); |
| 162 return Run(position(), reinterpret_cast<Position>(current), m_is8Bit); |
| 163 } |
| 164 |
| 165 inline void VTTScanner::seekTo(Position position) |
| 166 { |
| 167 ASSERT(position <= end()); |
| 168 m_data.characters8 = position; |
| 169 } |
| 170 |
| 171 inline UChar VTTScanner::currentChar() const |
| 172 { |
| 173 ASSERT(position() < end()); |
| 174 return m_is8Bit ? *m_data.characters8 : *m_data.characters16; |
| 175 } |
| 176 |
| 177 inline void VTTScanner::advance(unsigned amount) |
| 178 { |
| 179 ASSERT(position() < end()); |
| 180 if (m_is8Bit) |
| 181 m_data.characters8 += amount; |
| 182 else |
| 183 m_data.characters16 += amount; |
| 184 } |
| 185 |
| 186 // Wrapper of VTTScanner that allows easy interaction with a parsing model |
| 187 // where a <String, index> tuple is used. |
| 188 class VTTLegacyScanner : public VTTScanner { |
| 189 WTF_MAKE_NONCOPYABLE(VTTLegacyScanner); |
| 190 public: |
| 191 VTTLegacyScanner(const String& line, unsigned* outPosition) |
| 192 : VTTScanner(line) |
| 193 , m_outPosition(outPosition) |
| 194 { |
| 195 ASSERT(outPosition && *outPosition <= line.length()); |
| 196 // Adjust state according to |*outPosition|. |
| 197 advance(*outPosition); |
| 198 // Save the start position to allow adjusting |*outPosition|. |
| 199 if (m_is8Bit) |
| 200 m_start.characters8 = m_data.characters8; |
| 201 else |
| 202 m_start.characters16 = m_data.characters16; |
| 203 } |
| 204 ~VTTLegacyScanner() |
| 205 { |
| 206 // "Export" the updated position. |
| 207 unsigned advancedChars = m_is8Bit ? m_data.characters8 - m_start.charact
ers8 : m_data.characters16 - m_start.characters16; |
| 208 *m_outPosition += advancedChars; |
| 209 } |
| 210 |
| 211 private: |
| 212 unsigned* m_outPosition; |
| 213 union { |
| 214 const LChar* characters8; |
| 215 const UChar* characters16; |
| 216 } m_start; |
| 217 }; |
| 218 |
| 219 } |
| 220 |
| 221 #endif |
OLD | NEW |