mirror of
https://github.com/libAthena/athena.git
synced 2025-06-09 08:03:35 +00:00
* Add support for cached reads
This commit is contained in:
parent
a19dcad876
commit
a7c180db00
@ -12,7 +12,7 @@ namespace io
|
|||||||
class FileReader : public IStreamReader
|
class FileReader : public IStreamReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileReader(const std::string& filename);
|
FileReader(const std::string& filename, atUint32 cacheSize = (32 * 1024));
|
||||||
virtual ~FileReader();
|
virtual ~FileReader();
|
||||||
inline const std::string& filename() const
|
inline const std::string& filename() const
|
||||||
{return m_filename;}
|
{return m_filename;}
|
||||||
@ -27,10 +27,14 @@ public:
|
|||||||
atUint64 length() const;
|
atUint64 length() const;
|
||||||
atUint64 readUBytesToBuf(void* buf, atUint64 len);
|
atUint64 readUBytesToBuf(void* buf, atUint64 len);
|
||||||
|
|
||||||
|
void setCacheSize(const atUint32 blockSize);
|
||||||
protected:
|
protected:
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
FILE* m_fileHandle;
|
FILE* m_fileHandle;
|
||||||
atUint8 m_currentByte;
|
std::unique_ptr<atUint8[]> m_cacheData;
|
||||||
|
atUint32 m_blockSize;
|
||||||
|
atInt32 m_curBlock;
|
||||||
|
atUint64 m_offset;
|
||||||
};
|
};
|
||||||
} // io
|
} // io
|
||||||
} // Athena
|
} // Athena
|
||||||
|
@ -14,10 +14,13 @@ namespace Athena
|
|||||||
{
|
{
|
||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
FileReader::FileReader(const std::string& filename)
|
FileReader::FileReader(const std::string& filename, atUint32 cacheSize)
|
||||||
: m_filename(filename),
|
: m_filename(filename),
|
||||||
m_fileHandle(NULL)
|
m_fileHandle(nullptr),
|
||||||
|
m_cacheData(nullptr),
|
||||||
|
m_offset(0)
|
||||||
{
|
{
|
||||||
|
setCacheSize(cacheSize);
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +53,37 @@ void FileReader::close()
|
|||||||
|
|
||||||
void FileReader::seek(atInt64 pos, SeekOrigin origin)
|
void FileReader::seek(atInt64 pos, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
|
// check block position
|
||||||
|
if (m_blockSize > 0)
|
||||||
|
{
|
||||||
|
atUint64 oldOff = m_offset;
|
||||||
|
switch(origin)
|
||||||
|
{
|
||||||
|
case SeekOrigin::Begin:
|
||||||
|
m_offset = pos;
|
||||||
|
break;
|
||||||
|
case SeekOrigin::Current:
|
||||||
|
m_offset += pos;
|
||||||
|
break;
|
||||||
|
case SeekOrigin::End:
|
||||||
|
m_offset = length() - pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m_offset > length())
|
||||||
|
{
|
||||||
|
oldOff = m_offset;
|
||||||
|
THROW_INVALID_OPERATION_EXCEPTION("Unable to seek in file");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t block = m_offset / m_blockSize;
|
||||||
|
if (block != m_curBlock)
|
||||||
|
{
|
||||||
|
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
|
||||||
|
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
|
||||||
|
m_curBlock = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
|
||||||
THROW_INVALID_OPERATION_EXCEPTION("Unable to seek in file");
|
THROW_INVALID_OPERATION_EXCEPTION("Unable to seek in file");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +92,9 @@ atUint64 FileReader::position() const
|
|||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open");
|
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open");
|
||||||
|
|
||||||
|
if (m_blockSize > 0)
|
||||||
|
return m_offset;
|
||||||
|
else
|
||||||
return ftello64(m_fileHandle);
|
return ftello64(m_fileHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +111,46 @@ atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
|
|||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
THROW_INVALID_OPERATION_EXCEPTION_RETURN(0, "File not open for reading");
|
||||||
|
|
||||||
|
if (m_blockSize <= 0)
|
||||||
return fread(buf, 1, len, m_fileHandle);
|
return fread(buf, 1, len, m_fileHandle);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t block = m_offset / m_blockSize;
|
||||||
|
atUint64 cacheOffset = m_offset % m_blockSize;
|
||||||
|
atUint64 cacheSize;
|
||||||
|
atUint64 rem = len;
|
||||||
|
atUint8* dst = (atUint8*)buf;
|
||||||
|
|
||||||
|
while (rem)
|
||||||
|
{
|
||||||
|
if (block != m_curBlock)
|
||||||
|
{
|
||||||
|
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
|
||||||
|
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
|
||||||
|
m_curBlock = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheSize = rem;
|
||||||
|
if (cacheSize + cacheOffset > m_blockSize)
|
||||||
|
cacheSize = m_blockSize - cacheOffset;
|
||||||
|
|
||||||
|
memcpy(dst, m_cacheData.get() + cacheOffset, cacheSize);
|
||||||
|
dst += cacheSize;
|
||||||
|
rem -= cacheSize;
|
||||||
|
cacheOffset = 0;
|
||||||
|
++block;
|
||||||
|
}
|
||||||
|
m_offset += len;
|
||||||
|
return dst - (atUint8*)buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileReader::setCacheSize(const atUint32 blockSize)
|
||||||
|
{
|
||||||
|
m_blockSize = blockSize;
|
||||||
|
m_curBlock = -1;
|
||||||
|
if (m_blockSize > 0)
|
||||||
|
m_cacheData.reset(new atUint8[m_blockSize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // io
|
} // io
|
||||||
|
Loading…
x
Reference in New Issue
Block a user