diff --git a/src/lib/utility/text/TextAccess.cpp b/src/lib/utility/text/TextAccess.cpp index 04a85b66..1ec2bcaa 100644 --- a/src/lib/utility/text/TextAccess.cpp +++ b/src/lib/utility/text/TextAccess.cpp @@ -4,6 +4,48 @@ #include "logging.h" +namespace +{ + std::istream& safeGetline(std::istream& is, std::string& t) + { + t.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is, true); + std::streambuf* sb = is.rdbuf(); + + while (true) + { + int c = sb->sbumpc(); + switch (c) + { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') + { + sb->sbumpc(); + } + return is; + case std::streambuf::traits_type::eof(): + // Also handle the case when the last line has no line ending + if (t.empty()) + { + is.setstate(std::ios::eofbit); + } + return is; + default: + t += (char)c; + } + } + } +} + std::shared_ptr TextAccess::createFromFile(const FilePath& filePath) { std::shared_ptr result(new TextAccess()); @@ -93,7 +135,7 @@ std::vector TextAccess::readFile(const FilePath& filePath) while (!srcFile.eof()) { std::string line; - std::getline(srcFile, line); + safeGetline(srcFile, line); result.push_back(line + '\n'); } srcFile.close();