#ifndef VTTScanner_h
#define VTTScanner_h
#include "platform/ParsingUtilities.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
class VTTScanner {
WTF_MAKE_NONCOPYABLE(VTTScanner);
public:
explicit VTTScanner(const String& line);
typedef const LChar* Position;
class Run {
public:
Run(Position start, Position end, bool is8Bit)
: m_start(start), m_end(end), m_is8Bit(is8Bit) { }
Position start() const { return m_start; }
Position end() const { return m_end; }
bool isEmpty() const { return m_start == m_end; }
size_t length() const;
private:
Position m_start;
Position m_end;
bool m_is8Bit;
};
bool isAt(Position checkPosition) const { return position() == checkPosition; }
bool isAtEnd() const { return position() == end(); }
bool match(char c) const { return !isAtEnd() && currentChar() == c; }
bool scan(char);
bool scan(const LChar* characters, size_t charactersCount);
template<unsigned charactersCount>
bool scan(const char (&characters)[charactersCount]);
template<bool characterPredicate(UChar)>
void skipWhile();
template<bool characterPredicate(UChar)>
void skipUntil();
template<bool characterPredicate(UChar)>
Run collectWhile();
template<bool characterPredicate(UChar)>
Run collectUntil();
bool scanRun(const Run&, const String& toMatch);
void skipRun(const Run&);
String extractString(const Run&);
String restOfInputAsString();
unsigned scanDigits(int& number);
bool scanFloat(float& number);
protected:
Position position() const { return m_data.characters8; }
Position end() const { return m_end.characters8; }
void seekTo(Position);
UChar currentChar() const;
void advance(unsigned amount = 1);
template<bool characterPredicate(UChar)>
static inline bool LCharPredicateAdapter(LChar c) { return characterPredicate(c); }
union {
const LChar* characters8;
const UChar* characters16;
} m_data;
union {
const LChar* characters8;
const UChar* characters16;
} m_end;
bool m_is8Bit;
};
inline size_t VTTScanner::Run::length() const
{
if (m_is8Bit)
return m_end - m_start;
return reinterpret_cast<const UChar*>(m_end) - reinterpret_cast<const UChar*>(m_start);
}
template<unsigned charactersCount>
inline bool VTTScanner::scan(const char (&characters)[charactersCount])
{
return scan(reinterpret_cast<const LChar*>(characters), charactersCount - 1);
}
template<bool characterPredicate(UChar)>
inline void VTTScanner::skipWhile()
{
if (m_is8Bit)
::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
else
::skipWhile<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
}
template<bool characterPredicate(UChar)>
inline void VTTScanner::skipUntil()
{
if (m_is8Bit)
::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8);
else
::skipUntil<UChar, characterPredicate>(m_data.characters16, m_end.characters16);
}
template<bool characterPredicate(UChar)>
inline VTTScanner::Run VTTScanner::collectWhile()
{
if (m_is8Bit) {
const LChar* current = m_data.characters8;
::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
return Run(position(), current, m_is8Bit);
}
const UChar* current = m_data.characters16;
::skipWhile<UChar, characterPredicate>(current, m_end.characters16);
return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
}
template<bool characterPredicate(UChar)>
inline VTTScanner::Run VTTScanner::collectUntil()
{
if (m_is8Bit) {
const LChar* current = m_data.characters8;
::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8);
return Run(position(), current, m_is8Bit);
}
const UChar* current = m_data.characters16;
::skipUntil<UChar, characterPredicate>(current, m_end.characters16);
return Run(position(), reinterpret_cast<Position>(current), m_is8Bit);
}
inline void VTTScanner::seekTo(Position position)
{
ASSERT(position <= end());
m_data.characters8 = position;
}
inline UChar VTTScanner::currentChar() const
{
ASSERT(position() < end());
return m_is8Bit ? *m_data.characters8 : *m_data.characters16;
}
inline void VTTScanner::advance(unsigned amount)
{
ASSERT(position() < end());
if (m_is8Bit)
m_data.characters8 += amount;
else
m_data.characters16 += amount;
}
}
#endif