#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
namespace solidity::langutil
{
struct SourceLocation;
struct LineColumn;
class CharStream
{
public:
CharStream() = default;
CharStream(std::string _source, std::string _name):
m_source(std::move(_source)), m_name(std::move(_name)) {}
size_t position() const { return m_position; }
bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); }
char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; }
char advanceAndGet(size_t _chars = 1);
char rollback(size_t _amount);
char setPosition(size_t _location);
void reset() { m_position = 0; }
std::string const& source() const noexcept { return m_source; }
std::string const& name() const noexcept { return m_name; }
size_t size() const { return m_source.size(); }
std::string lineAtPosition(int _position) const;
LineColumn translatePositionToLineColumn(int _position) const;
std::optional<int> translateLineColumnToPosition(LineColumn const& _lineColumn) const;
static std::optional<int> translateLineColumnToPosition(std::string const& _text, LineColumn const& _input);
bool prefixMatch(std::string_view _sequence)
{
if (isPastEndOfInput(_sequence.size()))
return false;
for (size_t i = 0; i < _sequence.size(); ++i)
if (_sequence[i] != get(i))
return false;
return true;
}
std::string_view text(SourceLocation const& _location) const;
std::string singleLineSnippet(SourceLocation const& _location) const
{
return singleLineSnippet(m_source, _location);
}
static std::string singleLineSnippet(std::string const& _sourceCode, SourceLocation const& _location);
private:
std::string m_source;
std::string m_name;
size_t m_position{0};
};
}