|
@@ -0,0 +1,287 @@
|
|
|
+#include<regex>
|
|
|
+#include"fail_reason.hpp"
|
|
|
+#include"tokenizer.hpp"
|
|
|
+using namespace std;
|
|
|
+namespace brynhild {
|
|
|
+ namespace core {
|
|
|
+ class FileReader {
|
|
|
+ private:
|
|
|
+ Tokenizer tokenizer;
|
|
|
+ bool validState;
|
|
|
+ bool strict;
|
|
|
+ FailReason reason;
|
|
|
+
|
|
|
+ public:
|
|
|
+ FileReader(const std::string& filename,bool strict=true)
|
|
|
+ : tokenizer(filename), validState(true),strict(strict),reason(NONE) {}
|
|
|
+
|
|
|
+ FileReader& operator>>(std::string& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ value = word;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(int& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = std::stoi(word);
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ validState = false;
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ validState = false;
|
|
|
+ reason = FILE_EOF;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(char& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word) && word.length() == 1) {
|
|
|
+ value = word[0];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) throw std::runtime_error("Read operation failed: Expected a single character.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(short& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = static_cast<short>(std::stoi(word));
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(float& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = static_cast<float>(std::stof(word));
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(double& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = static_cast<double>(std::stod(word));
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(long& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = static_cast<long>(std::stol(word));
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ FileReader& operator>>(long long& value) {
|
|
|
+ if (!validState) {
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: Invalid state.");
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string word;
|
|
|
+ if (tokenizer.getNextWord(word)) {
|
|
|
+ try {
|
|
|
+ value = static_cast<long long>(std::stoll(word));
|
|
|
+ }
|
|
|
+ catch (const std::exception& e) {
|
|
|
+ reason = TYPE_INCOMPATIABLE;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ reason = FILE_EOF;
|
|
|
+ validState = false;
|
|
|
+ if (strict) {
|
|
|
+ throw std::runtime_error("Read operation failed: No more data.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ size_t getCurrentLine() const {
|
|
|
+ if (tokenizer.isEOF) {
|
|
|
+ return tokenizer.getCurrentLine() - 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return tokenizer.getCurrentLine();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ size_t getCurrentOffset() const {
|
|
|
+ if (tokenizer.isEOF) {
|
|
|
+ return tokenizer.lines[getCurrentLine() - 1].length() + 1;
|
|
|
+ }
|
|
|
+ return tokenizer.getCurrentOffset() - tokenizer.lastWord.length();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool isValid() const {
|
|
|
+ return validState;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool good() const {
|
|
|
+ return validState;
|
|
|
+ }
|
|
|
+
|
|
|
+ FailReason getReason() const{
|
|
|
+ return reason;
|
|
|
+ }
|
|
|
+
|
|
|
+ string getReasonString() const{
|
|
|
+ switch (reason)
|
|
|
+ {
|
|
|
+ case brynhild::core::NONE:
|
|
|
+ return "NONE ERROR";
|
|
|
+ break;
|
|
|
+ case brynhild::core::FILE_EOF:
|
|
|
+ return "FILE_EOF";
|
|
|
+ break;
|
|
|
+ case brynhild::core::TYPE_INCOMPATIABLE:
|
|
|
+ return "TYPE_INCOMPATIABLE";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return "INVALID REASON";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+}
|