athena/src/athena/MemoryReader.cpp

164 lines
3.9 KiB
C++

#include "athena/MemoryReader.hpp"
#include <algorithm>
#include <cstdio>
#include <cstring>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace athena::io {
MemoryReader::MemoryReader(const void* data, atUint64 length, bool takeOwnership, bool globalErr)
: m_data(data), m_length(length), m_position(0), m_owns(takeOwnership), m_globalErr(globalErr) {
if (!data) {
if (m_globalErr)
atError(FMT_STRING("data cannot be NULL"));
setError();
return;
}
}
MemoryReader::~MemoryReader() {
if (m_owns)
delete[] static_cast<const atUint8*>(m_data);
}
MemoryCopyReader::MemoryCopyReader(const void* data, atUint64 length) : MemoryReader(data, length, false) {
if (!data) {
if (m_globalErr)
atError(FMT_STRING("data cannot be NULL"));
setError();
return;
}
m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, m_length);
}
void MemoryReader::seek(atInt64 position, SeekOrigin origin) {
switch (origin) {
case SeekOrigin::Begin:
if ((position < 0 || atInt64(position) > atInt64(m_length))) {
if (m_globalErr)
atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position);
m_position = m_length;
setError();
return;
}
m_position = atUint64(position);
break;
case SeekOrigin::Current:
if (((atInt64(m_position) + position) < 0 || (m_position + atUint64(position)) > m_length)) {
if (m_globalErr)
atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position);
m_position = (position < 0 ? 0 : m_length);
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) {
if (m_globalErr)
atFatal(FMT_STRING("Position {:08X} outside stream bounds "), position);
m_position = m_length;
setError();
return;
}
m_position = m_length - position;
break;
}
}
void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership) {
if (m_owns)
delete[] static_cast<const atUint8*>(m_data);
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_owns = takeOwnership;
}
void MemoryCopyReader::setData(const atUint8* data, atUint64 length) {
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memmove(m_dataCopy.get(), data, length);
m_length = length;
m_position = 0;
}
atUint8* MemoryReader::data() const {
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memmove(ret, m_data, m_length);
return ret;
}
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) {
if (m_position >= m_length) {
if (m_globalErr)
atError(FMT_STRING("Position {:08X} outside stream bounds "), m_position);
m_position = m_length;
setError();
return 0;
}
length = std::min(length, m_length - m_position);
memmove(buf, static_cast<const atUint8*>(m_data) + m_position, length);
m_position += length;
return length;
}
void MemoryCopyReader::loadData() {
FILE* in;
atUint64 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in) {
if (m_globalErr)
atError(FMT_STRING("Unable to open file '%s'"), m_filepath);
setError();
return;
}
rewind(in);
length = utility::fileSize(m_filepath);
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do {
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0) {
if (m_globalErr)
atError(FMT_STRING("Error reading data from disk"));
setError();
return;
} else if (ret == 0)
break;
done += ret;
} while (done < length);
fclose(in);
m_length = length;
m_position = 0;
}
} // namespace athena::io