InputStreamPreprocessor.h [plain text]
#pragma once
#include "SegmentedString.h"
#include <wtf/unicode/CharacterNames.h>
namespace WebCore {
template <typename Tokenizer>
class InputStreamPreprocessor {
public:
explicit InputStreamPreprocessor(Tokenizer& tokenizer)
: m_tokenizer(tokenizer)
{
}
ALWAYS_INLINE UChar nextInputCharacter() const { return m_nextInputCharacter; }
ALWAYS_INLINE bool peek(SegmentedString& source, bool skipNullCharacters = false)
{
if (UNLIKELY(source.isEmpty()))
return false;
m_nextInputCharacter = source.currentCharacter();
constexpr UChar specialCharacterMask = '\n' | '\r' | '\0';
if (LIKELY(m_nextInputCharacter & ~specialCharacterMask)) {
m_skipNextNewLine = false;
return true;
}
return processNextInputCharacter(source, skipNullCharacters);
}
ALWAYS_INLINE bool advance(SegmentedString& source, bool skipNullCharacters = false)
{
source.advance();
return peek(source, skipNullCharacters);
}
ALWAYS_INLINE bool advancePastNonNewline(SegmentedString& source, bool skipNullCharacters = false)
{
source.advancePastNonNewline();
return peek(source, skipNullCharacters);
}
private:
bool processNextInputCharacter(SegmentedString& source, bool skipNullCharacters)
{
ProcessAgain:
ASSERT(m_nextInputCharacter == source.currentCharacter());
if (m_nextInputCharacter == '\n' && m_skipNextNewLine) {
m_skipNextNewLine = false;
source.advancePastNewline();
if (source.isEmpty())
return false;
m_nextInputCharacter = source.currentCharacter();
}
if (m_nextInputCharacter == '\r') {
m_nextInputCharacter = '\n';
m_skipNextNewLine = true;
return true;
}
m_skipNextNewLine = false;
if (m_nextInputCharacter || isAtEndOfFile(source))
return true;
if (skipNullCharacters && !m_tokenizer.neverSkipNullCharacters()) {
source.advancePastNonNewline();
if (source.isEmpty())
return false;
m_nextInputCharacter = source.currentCharacter();
goto ProcessAgain;
}
m_nextInputCharacter = replacementCharacter;
return true;
}
static bool isAtEndOfFile(SegmentedString& source)
{
return source.isClosed() && source.length() == 1;
}
Tokenizer& m_tokenizer;
UChar m_nextInputCharacter { 0 };
bool m_skipNextNewLine { false };
};
}