| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IOS_THIRD_PARTY_BLINK_SRC_HTML_CHARACTER_PROVIDER_H_ |
| #define IOS_THIRD_PARTY_BLINK_SRC_HTML_CHARACTER_PROVIDER_H_ |
| |
| #include <stddef.h> |
| |
| #include "base/macros.h" |
| #include "ios/third_party/blink/src/html_tokenizer_adapter.h" |
| |
| namespace WebCore { |
| |
| const LChar kEndOfFileMarker = 0; |
| |
| // CharacterProvider provides input characters to WebCore::HTMLTokenizer. |
| // It replaces WebCore::SegmentedString (which sits ontop of WTF::String). |
| class CharacterProvider { |
| public: |
| CharacterProvider() |
| : _totalBytes(0) |
| , _remainingBytes(0) |
| , _singleBytePtr(nullptr) |
| , _doubleBytePtr(nullptr) |
| , _littleEndian(false) |
| { |
| } |
| |
| void setContents(const LChar* str, size_t numberOfBytes) |
| { |
| _totalBytes = numberOfBytes; |
| _remainingBytes = numberOfBytes; |
| _singleBytePtr = str; |
| _doubleBytePtr = nullptr; |
| _littleEndian = false; |
| } |
| |
| void setContents(const UChar* str, size_t numberOfBytes) |
| { |
| _totalBytes = numberOfBytes; |
| _remainingBytes = numberOfBytes; |
| _singleBytePtr = nullptr; |
| _doubleBytePtr = str; |
| _littleEndian = false; |
| } |
| |
| void clear() |
| { |
| _totalBytes = 0; |
| _remainingBytes = 0; |
| _singleBytePtr = nullptr; |
| _doubleBytePtr = nullptr; |
| _littleEndian = false; |
| } |
| |
| bool startsWith(const LChar* str, |
| size_t byteCount, |
| bool caseInsensitive = false) const |
| { |
| if (!str || byteCount > _remainingBytes) |
| return false; |
| |
| for (size_t index = 0; index < byteCount; ++index) { |
| UChar lhs = characterAtIndex(index); |
| UChar rhs = str[index]; |
| |
| if (caseInsensitive) { |
| if (isASCIIUpper(lhs)) |
| lhs = toLowerCase(lhs); |
| |
| if (isASCIIUpper(rhs)) |
| rhs = toLowerCase(rhs); |
| } |
| |
| if (lhs != rhs) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| inline UChar currentCharacter() const |
| { |
| return characterAtIndex(0); |
| } |
| |
| inline UChar nextCharacter() |
| { |
| advanceBytePointer(); |
| return characterAtIndex(0); |
| } |
| |
| inline void next() |
| { |
| advanceBytePointer(); |
| } |
| |
| inline bool isEmpty() const |
| { |
| return !_remainingBytes; |
| } |
| |
| inline size_t remainingBytes() const |
| { |
| return _remainingBytes; |
| } |
| |
| inline size_t bytesProvided() const |
| { |
| return _totalBytes - _remainingBytes; |
| } |
| |
| inline void setLittleEndian() |
| { |
| _littleEndian = true; |
| } |
| |
| private: |
| void advanceBytePointer() |
| { |
| --_remainingBytes; |
| if (!_remainingBytes) |
| return; |
| |
| if (_singleBytePtr) |
| ++_singleBytePtr; |
| else { |
| DCHECK(_doubleBytePtr); |
| ++_doubleBytePtr; |
| } |
| } |
| |
| UChar characterAtIndex(size_t index) const |
| { |
| if (!_remainingBytes) { |
| // There is a quirk in the blink implementation wherein the empty state |
| // is not set on the source until next() has been called when |
| // _remainingBytes is zero. In this case, return kEndOfFileMarker. |
| return kEndOfFileMarker; |
| } |
| |
| ASSERT(_singleBytePtr || _doubleBytePtr); |
| |
| UChar character = kEndOfFileMarker; |
| if (_singleBytePtr) |
| character = _singleBytePtr[index]; |
| else |
| character = _doubleBytePtr[index]; |
| |
| if (_littleEndian) |
| character = ByteSwap(character); |
| |
| return character; |
| } |
| |
| private: |
| size_t _totalBytes; |
| size_t _remainingBytes; |
| const LChar* _singleBytePtr; |
| const UChar* _doubleBytePtr; |
| bool _littleEndian; |
| |
| DISALLOW_COPY_AND_ASSIGN(CharacterProvider); |
| }; |
| |
| } |
| |
| #endif // IOS_THIRD_PARTY_BLINK_SRC_HTML_CHARACTER_PROVIDER_H_ |