Line data Source code
1 : /* Copyright (C) 2025 Robert Schiwon 2 : * 3 : * This file is part of libjdx. 4 : * 5 : * libjdx is free software: you can redistribute it and/or modify it under the 6 : * terms of the GNU Lesser General Public License as published by the Free 7 : * Software Foundation, either version 3 of the License, or (at your option) any 8 : * later version. 9 : * 10 : * libjdx is distributed in the hope that it will be useful, but WITHOUT ANY 11 : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 : * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 13 : * details. 14 : * 15 : * You should have received a copy of the GNU Lesser General Public License 16 : * along with libjdx. If not, see <https://www.gnu.org/licenses/>. 17 : */ 18 : #include "io/SimpleTextReader.hpp" 19 : 20 : #include <fstream> 21 : #include <sstream> 22 : #include <stdexcept> 23 : 24 114 : libjdx::io::SimpleTextReader::SimpleTextReader( 25 114 : std::unique_ptr<std::istream> streamPtr) 26 114 : : m_streamPtr{std::move(streamPtr)} 27 : { 28 114 : setStreamFlags(); 29 114 : } 30 : 31 23 : libjdx::io::SimpleTextReader::SimpleTextReader(const std::string& filePath) 32 25 : : m_streamPtr{std::make_unique<std::ifstream>(filePath)} 33 : { 34 23 : setStreamFlags(); 35 21 : } 36 : 37 137 : void libjdx::io::SimpleTextReader::setStreamFlags() 38 : { 39 137 : if (m_streamPtr == nullptr) 40 : { 41 0 : throw std::runtime_error("Text reader input stream is null."); 42 : } 43 : // the underlying getline() method sets eofbit at end of file, so do not set 44 : // std::ios::eofbit 45 137 : m_streamPtr->exceptions(std::ios::failbit | std::ios::badbit); 46 135 : } 47 : 48 576 : std::ios::pos_type libjdx::io::SimpleTextReader::tellg() const 49 : { 50 576 : return m_streamPtr->tellg(); 51 : } 52 : 53 290 : void libjdx::io::SimpleTextReader::seekg( 54 : std::ios::pos_type position, std::ios_base::seekdir seekdir) 55 : { 56 290 : m_streamPtr->seekg(position, seekdir); 57 290 : } 58 : 59 2 : std::ios::pos_type libjdx::io::SimpleTextReader::getLength() 60 : { 61 2 : const std::ios::pos_type current = m_streamPtr->tellg(); 62 2 : m_streamPtr->seekg(0, std::ios::end); 63 2 : const std::ios::pos_type length = m_streamPtr->tellg(); 64 2 : m_streamPtr->seekg(current, std::ios::beg); 65 2 : return length; 66 : } 67 : 68 3268 : bool libjdx::io::SimpleTextReader::eof() const 69 : { 70 : // see: 71 : // https://stackoverflow.com/questions/6283632/how-to-know-if-the-next-character-is-eof-in-c 72 3268 : auto c = m_streamPtr->peek(); 73 3268 : if (c == EOF) 74 : { 75 132 : if (m_streamPtr->eof()) 76 : { 77 : // otherwise operations no longer works after eofbit is set 78 132 : m_streamPtr->clear(); 79 132 : return true; 80 : } 81 : throw std::runtime_error( 82 0 : "End of file reached, but std::ios::eofbit not set."); 83 : } 84 3136 : return false; 85 : } 86 : 87 3275 : std::string libjdx::io::SimpleTextReader::readLine() 88 : { 89 3275 : std::string out{}; 90 3275 : if (std::getline(*m_streamPtr, out)) 91 : { 92 3274 : if (m_streamPtr->eof()) 93 : { 94 : // cleat eofbit, so that other operations will still succeed 95 : // other types of errors raise exceptions 96 104 : m_streamPtr->clear(); 97 : } 98 3274 : if (!out.empty() && out.at(out.size() - 1) == '\r') 99 : { 100 : // remove trailing \r in case line ending is \r\n and has not been 101 : // converted to \n by stream already 102 454 : out.erase(out.size() - 1); 103 : } 104 3274 : return out; 105 : } 106 0 : throw std::runtime_error("Error reading line from istream."); 107 : }