mirror of
https://github.com/bkaradzic/bx.git
synced 2026-09-14 22:34:35 +00:00
174 lines
3.4 KiB
C++
174 lines
3.4 KiB
C++
/*
|
|
* Copyright 2010-2026 Branimir Karadzic. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
|
|
*/
|
|
|
|
#include <bx/scanner.h>
|
|
|
|
namespace bx
|
|
{
|
|
bool Scanner::seek(const StringView& _to)
|
|
{
|
|
if (contain(m_input, _to) )
|
|
{
|
|
moveTo(_to);
|
|
return true;
|
|
}
|
|
|
|
BX_TRACE("StringView '%S' is not a view into input string!", &_to);
|
|
return false;
|
|
}
|
|
|
|
uint32_t Scanner::getColumn() const
|
|
{
|
|
return uint32_t(between(getCursor(Cursor::LineStart) ).getLength() ) + 1;
|
|
}
|
|
|
|
StringView Scanner::getCursor(Cursor _which) const
|
|
{
|
|
const char* ptr = m_tail.getPtr();
|
|
|
|
if (Cursor::LineStart == _which)
|
|
{
|
|
while (ptr > m_input.getPtr()
|
|
&& '\n' != ptr[-1])
|
|
{
|
|
--ptr;
|
|
}
|
|
}
|
|
else if (Cursor::LineEnd == _which)
|
|
{
|
|
const char* term = m_input.getTerm();
|
|
while (ptr < term
|
|
&& '\n' != *ptr)
|
|
{
|
|
++ptr;
|
|
}
|
|
}
|
|
|
|
return StringView(ptr, ptr);
|
|
}
|
|
|
|
StringView Scanner::moveTo(const StringView& _to)
|
|
{
|
|
if (BX_LIKELY(!_to.isEmpty() ) )
|
|
{
|
|
if (BX_LIKELY(overlap(m_tail, _to) ) )
|
|
{
|
|
const StringView result(m_tail.getPtr(), _to.getTerm() );
|
|
|
|
m_tail.set(_to.getTerm(), m_tail.getTerm() );
|
|
m_line += countLines(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
const StringView result(_to.getPtr(), m_tail.getPtr() );
|
|
|
|
m_tail.set(_to.getPtr(), m_tail.getTerm() );
|
|
m_line -= countLines(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
if (_to.getPtr() != m_tail.getPtr()
|
|
&& contain(m_input, _to) )
|
|
{
|
|
moveBy(int32_t(_to.getPtr() - m_tail.getPtr() ) );
|
|
}
|
|
|
|
return getCursor();
|
|
}
|
|
|
|
StringView Scanner::strFunc(Class _class) const
|
|
{
|
|
switch (_class)
|
|
{
|
|
case Class::Space:
|
|
return strLTrimSpace(m_tail);
|
|
|
|
case Class::NonSpace:
|
|
return strLTrimNonSpace(m_tail);
|
|
|
|
case Class::Identifier:
|
|
{
|
|
const StringView word = strWord(m_tail);
|
|
return word.isEmpty()
|
|
? m_tail
|
|
: StringView(word.getTerm(), m_tail.getTerm() )
|
|
;
|
|
}
|
|
|
|
case Class::EndOfLine:
|
|
return strFindEol(m_tail);
|
|
|
|
case Class::NewLine:
|
|
return strFindNl(m_tail);
|
|
|
|
default:
|
|
BX_ASSERT(false, "Bug, _class can't be %d!", _class);
|
|
BX_UNREACHABLE;
|
|
}
|
|
}
|
|
|
|
StringView Scanner::moveBy(int32_t _bytes)
|
|
{
|
|
const int32_t len = m_tail.getLength();
|
|
_bytes = clamp(_bytes, len - m_input.getLength(), len);
|
|
|
|
if (BX_LIKELY(0 < _bytes) )
|
|
{
|
|
const StringView result(m_tail.getPtr(), m_tail.getPtr() + _bytes);
|
|
|
|
m_tail.set(result.getTerm(), m_tail.getTerm() );
|
|
m_line += countLines(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
const StringView result(m_tail.getPtr() + _bytes, m_tail.getPtr() );
|
|
|
|
m_tail.set(result.getPtr(), m_tail.getTerm() );
|
|
m_line -= countLines(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32_t Scanner::countLines(const StringView& _str)
|
|
{
|
|
uint32_t line = 0;
|
|
|
|
StringView str = strFindEol(_str);
|
|
|
|
while (!str.isEmpty() )
|
|
{
|
|
++line;
|
|
str = strFindEol(strFindNl(str) );
|
|
}
|
|
|
|
return line;
|
|
}
|
|
|
|
StringView LineReader::next()
|
|
{
|
|
if (!m_scanner.isDone() )
|
|
{
|
|
++m_line;
|
|
|
|
const StringView cursor = m_scanner.getCursor();
|
|
m_scanner.acceptUntil(Scanner::Class::EndOfLine);
|
|
|
|
const StringView line = m_scanner.between(cursor);
|
|
m_scanner.accept(Scanner::Class::NewLine);
|
|
|
|
// A line terminator is `\n` or `\r\n`, and `Class::EndOfLine` already
|
|
// excludes it. Only malformed input (`\r` at the end of input, or
|
|
// `\r\r\n`) can leave a trailing `\r` behind.
|
|
return strRTrim(line, "\r");
|
|
}
|
|
|
|
return m_scanner.getCursor();
|
|
}
|
|
|
|
} // namespace bx
|