| 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 |