From a5e7be56c195e0f313ef7602148b59355662f4ce Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 19 Feb 2024 18:27:24 -0600 Subject: [PATCH] Add seek to file streams --- src/io/streams.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/io/streams.hpp | 4 +--- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/io/streams.cpp b/src/io/streams.cpp index 17d03e0ad..3d4baffd2 100644 --- a/src/io/streams.cpp +++ b/src/io/streams.cpp @@ -166,3 +166,63 @@ void FileStream::close() file_ = nullptr; } + +static int portable_fseek64(FILE* file, int64_t offset, int origin) +{ +#ifdef _MSC_VER + return _fseeki64(file, offset, origin); +#elif __APPLE__ + return fseeko(file, offset, origin); +#else + return fseeko64(file, offset, origin); +#endif +} + +static int64_t portable_ftell64(FILE* file) +{ +#ifdef _MSC_VER + return _ftelli64(file); +#elif __APPLE__ + return ftello(file); +#else + return ftello64(file); +#endif +} + +StreamSize FileStream::seek(SeekFrom seek_from, StreamOffset offset) +{ + if (!file_) + { + throw std::domain_error("FileStream is empty"); + } + + int origin; + switch (seek_from) + { + case SeekFrom::kStart: + origin = SEEK_SET; + break; + case SeekFrom::kCurrent: + origin = SEEK_CUR; + break; + case SeekFrom::kEnd: + origin = SEEK_END; + break; + default: + throw std::invalid_argument("invalid SeekFrom"); + } + + if (portable_fseek64((FILE*)(file_), offset, origin) != 0) + { + int err = errno; + throw make_exception_from_errno(err); + } + + StreamOffset newpos = portable_ftell64((FILE*)(file_)); + if (newpos < 0) + { + int err = errno; + throw make_exception_from_errno(err); + } + return newpos; +} diff --git a/src/io/streams.hpp b/src/io/streams.hpp index c4456d2d4..a91b0ebbc 100644 --- a/src/io/streams.hpp +++ b/src/io/streams.hpp @@ -616,9 +616,7 @@ public: StreamSize read(tcb::span buffer); StreamSize write(tcb::span buffer); - - // not bothering with seeking for now -- apparently 64-bit file positions is not available in ansi c - // StreamSize seek(SeekFrom seek_from, StreamOffset offset); + StreamSize seek(SeekFrom seek_from, StreamOffset offset); void close(); };