OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ | 3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ |
4 * Copyright (C) 2013 Google, Inc. All Rights Reserved. | 4 * Copyright (C) 2013 Google, Inc. All Rights Reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 reset(); | 46 reset(); |
47 } | 47 } |
48 | 48 |
49 ALWAYS_INLINE UChar nextInputCharacter() const { return m_nextInputCharacter
; } | 49 ALWAYS_INLINE UChar nextInputCharacter() const { return m_nextInputCharacter
; } |
50 | 50 |
51 // Returns whether we succeeded in peeking at the next character. | 51 // Returns whether we succeeded in peeking at the next character. |
52 // The only way we can fail to peek is if there are no more | 52 // The only way we can fail to peek is if there are no more |
53 // characters in |source| (after collapsing \r\n, etc). | 53 // characters in |source| (after collapsing \r\n, etc). |
54 ALWAYS_INLINE bool peek(SegmentedString& source) | 54 ALWAYS_INLINE bool peek(SegmentedString& source) |
55 { | 55 { |
56 PeekAgain: | |
57 m_nextInputCharacter = source.currentChar(); | 56 m_nextInputCharacter = source.currentChar(); |
58 | 57 |
59 // Every branch in this function is expensive, so we have a | 58 // Every branch in this function is expensive, so we have a |
60 // fast-reject branch for characters that don't require special | 59 // fast-reject branch for characters that don't require special |
61 // handling. Please run the parser benchmark whenever you touch | 60 // handling. Please run the parser benchmark whenever you touch |
62 // this function. It's very hot. | 61 // this function. It's very hot. |
63 static const UChar specialCharacterMask = '\n' | '\r' | '\0'; | 62 static const UChar specialCharacterMask = '\n' | '\r' | '\0'; |
64 if (m_nextInputCharacter & ~specialCharacterMask) { | 63 if (m_nextInputCharacter & ~specialCharacterMask) { |
65 m_skipNextNewLine = false; | 64 m_skipNextNewLine = false; |
66 return true; | 65 return true; |
67 } | 66 } |
| 67 return processNextInputCharacter(source); |
| 68 } |
| 69 |
| 70 // Returns whether there are more characters in |source| after advancing. |
| 71 ALWAYS_INLINE bool advance(SegmentedString& source) |
| 72 { |
| 73 source.advanceAndUpdateLineNumber(); |
| 74 if (source.isEmpty()) |
| 75 return false; |
| 76 return peek(source); |
| 77 } |
| 78 |
| 79 bool skipNextNewLine() const { return m_skipNextNewLine; } |
| 80 |
| 81 void reset(bool skipNextNewLine = false) |
| 82 { |
| 83 m_nextInputCharacter = '\0'; |
| 84 m_skipNextNewLine = skipNextNewLine; |
| 85 } |
| 86 |
| 87 private: |
| 88 bool processNextInputCharacter(SegmentedString& source) |
| 89 { |
| 90 ProcessAgain: |
| 91 ASSERT(m_nextInputCharacter == source.currentChar()); |
68 | 92 |
69 if (m_nextInputCharacter == '\n' && m_skipNextNewLine) { | 93 if (m_nextInputCharacter == '\n' && m_skipNextNewLine) { |
70 m_skipNextNewLine = false; | 94 m_skipNextNewLine = false; |
71 source.advancePastNewlineAndUpdateLineNumber(); | 95 source.advancePastNewlineAndUpdateLineNumber(); |
72 if (source.isEmpty()) | 96 if (source.isEmpty()) |
73 return false; | 97 return false; |
74 m_nextInputCharacter = source.currentChar(); | 98 m_nextInputCharacter = source.currentChar(); |
75 } | 99 } |
76 if (m_nextInputCharacter == '\r') { | 100 if (m_nextInputCharacter == '\r') { |
77 m_nextInputCharacter = '\n'; | 101 m_nextInputCharacter = '\n'; |
78 m_skipNextNewLine = true; | 102 m_skipNextNewLine = true; |
79 } else { | 103 } else { |
80 m_skipNextNewLine = false; | 104 m_skipNextNewLine = false; |
81 // FIXME: The spec indicates that the surrogate pair range as well a
s | 105 // FIXME: The spec indicates that the surrogate pair range as well a
s |
82 // a number of specific character values are parse errors and should
be replaced | 106 // a number of specific character values are parse errors and should
be replaced |
83 // by the replacement character. We suspect this is a problem with t
he spec as doing | 107 // by the replacement character. We suspect this is a problem with t
he spec as doing |
84 // that filtering breaks surrogate pair handling and causes us not t
o match Minefield. | 108 // that filtering breaks surrogate pair handling and causes us not t
o match Minefield. |
85 if (m_nextInputCharacter == '\0' && !shouldTreatNullAsEndOfFileMarke
r(source)) { | 109 if (m_nextInputCharacter == '\0' && !shouldTreatNullAsEndOfFileMarke
r(source)) { |
86 if (m_tokenizer->shouldSkipNullCharacters()) { | 110 if (m_tokenizer->shouldSkipNullCharacters()) { |
87 source.advancePastNonNewline(); | 111 source.advancePastNonNewline(); |
88 if (source.isEmpty()) | 112 if (source.isEmpty()) |
89 return false; | 113 return false; |
90 goto PeekAgain; | 114 m_nextInputCharacter = source.currentChar(); |
| 115 goto ProcessAgain; |
91 } | 116 } |
92 m_nextInputCharacter = 0xFFFD; | 117 m_nextInputCharacter = 0xFFFD; |
93 } | 118 } |
94 } | 119 } |
95 return true; | 120 return true; |
96 } | 121 } |
97 | 122 |
98 // Returns whether there are more characters in |source| after advancing. | |
99 ALWAYS_INLINE bool advance(SegmentedString& source) | |
100 { | |
101 source.advanceAndUpdateLineNumber(); | |
102 if (source.isEmpty()) | |
103 return false; | |
104 return peek(source); | |
105 } | |
106 | |
107 bool skipNextNewLine() const { return m_skipNextNewLine; } | |
108 | |
109 void reset(bool skipNextNewLine = false) | |
110 { | |
111 m_nextInputCharacter = '\0'; | |
112 m_skipNextNewLine = skipNextNewLine; | |
113 } | |
114 | |
115 private: | |
116 bool shouldTreatNullAsEndOfFileMarker(SegmentedString& source) const | 123 bool shouldTreatNullAsEndOfFileMarker(SegmentedString& source) const |
117 { | 124 { |
118 return source.isClosed() && source.length() == 1; | 125 return source.isClosed() && source.length() == 1; |
119 } | 126 } |
120 | 127 |
121 Tokenizer* m_tokenizer; | 128 Tokenizer* m_tokenizer; |
122 | 129 |
123 // http://www.whatwg.org/specs/web-apps/current-work/#next-input-character | 130 // http://www.whatwg.org/specs/web-apps/current-work/#next-input-character |
124 UChar m_nextInputCharacter; | 131 UChar m_nextInputCharacter; |
125 bool m_skipNextNewLine; | 132 bool m_skipNextNewLine; |
126 }; | 133 }; |
127 | 134 |
128 } | 135 } |
129 | 136 |
130 #endif // InputStreamPreprocessor_h | 137 #endif // InputStreamPreprocessor_h |
131 | 138 |
OLD | NEW |