#pragma once #include <cctype> #include <fstream> #include <string> class SimpleParser { std::ifstream localStream{}; std::ifstream ∈ // buffer will always contain at least 1 char, or eof==true std::string buffer; size_t pos; bool eof; bool eol; void bufferSaturate() { while (!eof && pos >= buffer.size()) { eof = !std::getline(in, buffer); eol = true; pos = 0; } } char bufferPeek() { if (eof) { return -1; } return buffer[pos]; } void bufferNextChar() { if (!eof) { eol = false; pos++; bufferSaturate(); } } char bufferGet() { auto const c = bufferPeek(); bufferNextChar(); return c; } public: SimpleParser(std::ifstream &); SimpleParser(char const *); bool isEof() const; bool isEol() const; int64_t getInt64(); std::string getToken(char const terminate = '\0'); std::string getAlNum(); std::string getLine(); char getChar(); char peekChar(); void skipWhitespace(); bool skipChar(char const); bool skipToken(std::string const &); }; SimpleParser::SimpleParser(std::ifstream &stream) : in(stream), buffer(""), pos(0), eof(false), eol(false) { bufferSaturate(); eol = false; } SimpleParser::SimpleParser(char const *infile) : localStream(std::ifstream(infile)), in(localStream), buffer(""), pos(0), eof(false), eol(false) { bufferSaturate(); eol = false; } int64_t SimpleParser::getInt64() { skipWhitespace(); size_t processed; int64_t const value = std::stoll(buffer.substr(pos), &processed); eol = false; pos += processed; bufferSaturate(); return value; } std::string SimpleParser::getToken(char const terminate) { skipWhitespace(); auto end = pos; while (end < buffer.size() && !std::isspace(buffer[end]) && buffer[end] != terminate) { ++end; } auto token = buffer.substr(pos, end - pos); eol = false; pos = end; bufferSaturate(); return token; } std::string SimpleParser::getAlNum() { skipWhitespace(); auto end = pos; while (end < buffer.size() && std::isalnum(buffer[end])) { ++end; } auto token = buffer.substr(pos, end - pos); eol = false; pos = end; bufferSaturate(); return token; } std::string SimpleParser::getLine() { skipWhitespace(); auto end = buffer.size(); auto token = buffer.substr(pos, end - pos); pos = end; bufferSaturate(); return token; } bool SimpleParser::isEof() const { return eof; } bool SimpleParser::isEol() const { return eol; } char SimpleParser::getChar() { skipWhitespace(); if (!eof) { auto const c = buffer[pos]; bufferNextChar(); return c; } return -1; } char SimpleParser::peekChar() { skipWhitespace(); if (!eof) { return buffer[pos]; } return -1; } void SimpleParser::skipWhitespace() { while (!eof && std::isspace(buffer[pos])) { bufferNextChar(); } } bool SimpleParser::skipChar(char const c) { skipWhitespace(); if (!eof && buffer[pos] == c) { bufferNextChar(); return true; } return false; } // If token follows in the input, skip over it and return true bool SimpleParser::skipToken(std::string const &token) { skipWhitespace(); if (buffer.find(token.data(), pos, token.size()) == pos) { pos += token.size(); bufferSaturate(); return true; } return false; }