diff --git a/system/jlib/jfile.cpp b/system/jlib/jfile.cpp index df468594f7d..ceac0fb3391 100644 --- a/system/jlib/jfile.cpp +++ b/system/jlib/jfile.cpp @@ -7591,45 +7591,43 @@ IAPICopyClient * createApiCopyClient(IStorageApiInfo * source, IStorageApiInfo * } +// NB: This implementation is not thread-safe. +// Therefore it should only be used by use cases that are single threaded class CBlockedFileIO : public CSimpleInterfaceOf { Owned io; - offset_t fileSize = 0; size32_t blockSize = 0; + size32_t readLen = 0; void *buffer = nullptr; offset_t lastReadPos = (offset_t)-1; MemoryBuffer mb; public: CBlockedFileIO(IFileIO *_io, size32_t _blockSize) : io(_io), blockSize(_blockSize) { - fileSize = io->size(); buffer = mb.reserveTruncate(blockSize); } virtual size32_t read(offset_t pos, size32_t len, void *data) override { - if (len > blockSize || pos+len > fileSize || len==0) + if (len > blockSize) return io->read(pos, len, data); size32_t totalCopied = 0; byte *dest = (byte *) data; while (len) { - offset_t readPos = (pos / blockSize) * blockSize; - size32_t readLen; - if (readPos + blockSize <= fileSize) - readLen = blockSize; - else - readLen = fileSize - readPos; - if (readPos != lastReadPos) // NB: if readLen < blockSize then last block, won't ever read more for that block. + offset_t readPos = (pos / blockSize) * blockSize; // NB: could be beyond end of file + if (readPos != lastReadPos) { - size32_t read = io->read(readPos, readLen, buffer); - assertex(read == readLen); + readLen = io->read(readPos, blockSize, buffer); // NB: can be less than blockSize (and 0 if beyodn end of file) lastReadPos = readPos; } + size32_t endPos = readPos+readLen; size32_t copyNow; - if (pos+len <= readPos+readLen) + if (pos+len <= endPos) // common case hopefully copyNow = len; - else - copyNow = readPos+readLen-pos; + else if (pos < endPos) + copyNow = endPos-pos; + else // nothing to copy + break; memcpy(dest, ((byte *)buffer) + pos-readPos, copyNow); len -= copyNow; pos += copyNow; @@ -7638,7 +7636,7 @@ class CBlockedFileIO : public CSimpleInterfaceOf } return totalCopied; } - virtual offset_t size() override { return fileSize; } + virtual offset_t size() override { return io->size(); } virtual size32_t write(offset_t pos, size32_t len, const void * data) override { throwUnexpected(); } virtual offset_t appendFile(IFile *file, offset_t pos=0, offset_t len=(offset_t)-1) override { throwUnexpected(); } virtual void setSize(offset_t size) override { throwUnexpected(); }