added buffer-copying subclass to MemoryReader/Writer

This commit is contained in:
Jack Andersen 2015-07-07 20:03:08 -10:00
parent 8a397a1622
commit ec38ba088e
19 changed files with 159 additions and 94 deletions

View File

@ -35,9 +35,9 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class ALTTPFileReader : protected MemoryReader
class ALTTPFileReader : protected MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
/*! \brief This constructor takes an existing buffer to read from.

View File

@ -34,9 +34,9 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader
*/
class ALTTPFileWriter : protected MemoryWriter
class ALTTPFileWriter : protected MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
/*! \brief This constructor takes an existing buffer to write to.

View File

@ -34,9 +34,9 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class MCFileReader : public MemoryReader
class MCFileReader : public MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
/*!
* \brief This constructor takes an existing buffer to read from.

View File

@ -35,9 +35,9 @@ namespace io
* all work is done using a memory buffer, and not written directly from the disk.
* \sa BinaryWriter
*/
class MCFileWriter : protected MemoryWriter
class MCFileWriter : protected MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
/*!
* \brief This constructor takes an existing buffer to write to.

View File

@ -20,21 +20,13 @@ namespace io
class MemoryReader : public IStreamReader
{
public:
~MemoryReader();
/*! \brief This constructor takes an existing buffer to read from.
/*! \brief This constructor references an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MemoryReader(const atUint8* data, atUint64 length);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryReader(const std::string& filename);
/*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* \param position where in the buffer to seek
@ -78,14 +70,44 @@ public:
*/
atUint8* data() const;
/*! \brief Reads a specified number of bytes to user-allocated buffer
* \param buf User-allocated buffer pointer
* \param len Length to read
* \return Number of bytes read
*/
atUint64 readUBytesToBuf(void* buf, atUint64 len);
protected:
const atUint8* m_data;
atUint64 m_length;
atUint64 m_position;
};
class MemoryCopyReader : public MemoryReader
{
public:
/*! \brief This constructor copies an existing buffer to read from.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
MemoryCopyReader(const atUint8* data, atUint64 length);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryCopyReader(const std::string& filename)
: MemoryReader(NULL, 0),
m_filepath(filename)
{loadData();}
void setData(const atUint8* data, atUint64 length);
protected:
void loadData();
atUint8* m_data;
atUint64 m_length;
std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file
atUint64 m_position;
};
} // io
@ -98,4 +120,11 @@ private: \
#endif // MEMORYREADER_BASE
#ifndef MEMORYCOPYREADER_BASE
#define MEMORYCOPYREADER_BASE() \
private: \
typedef Athena::io::MemoryCopyReader base
#endif // MEMORYCOPYREADER_BASE
#endif // MEMORYREADER_HPP

View File

@ -21,22 +21,14 @@ namespace io
class MemoryWriter : public IStreamWriter
{
public:
~MemoryWriter();
/*! \brief This constructor takes an existing buffer to write to.
/*! \brief This constructor references an existing buffer to write to in-place.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
explicit MemoryWriter(atUint8* data = nullptr, atUint64 length = 0x10);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryWriter(const std::string& filename, std::function<void(int)> progressFun = nullptr);
/*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default.
* \param position where in the buffer to seek
@ -70,7 +62,7 @@ public:
* \param length The length of the new buffer.
* \throw IOException
*/
void setData(const atUint8* data, atUint64 length);
void setData(atUint8* data, atUint64 length);
/*! \brief Returns a copy of the current buffer.<br />
@ -113,11 +105,35 @@ public:
protected:
atUint8* m_data;
atUint64 m_length;
std::string m_filepath; //!< Path to the target file
atUint64 m_position;
std::string m_filepath; //!< Path to the target file
private:
void resize(atUint64 newSize);
};
class MemoryCopyWriter : public MemoryWriter
{
public:
/*! \brief This constructor copies an existing buffer to write to.
*
* \param data The existing buffer
* \param length The length of the existing buffer
*/
explicit MemoryCopyWriter(atUint8* data, atUint64 length);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
MemoryCopyWriter(const std::string& filename);
void setData(const atUint8* data, atUint64 length);
protected:
std::unique_ptr<atUint8[]> m_dataCopy;
};
}
}
@ -126,4 +142,11 @@ private:
private: \
typedef Athena::io::MemoryWriter base
#endif // BINARYWRITER_BASE
#ifndef MEMORYCOPYWRITER_BASE
#define MEMORYCOPYWRITER_BASE() \
private: \
typedef Athena::io::MemoryCopyWriter base
#endif // BINARYWRITER_BASE
#endif // MEMORYWRITER_HPP

View File

@ -24,9 +24,9 @@ namespace Athena
class SkywardSwordFile;
namespace io
{
class SkywardSwordFileReader : public MemoryReader
class SkywardSwordFileReader : public MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
SkywardSwordFileReader(atUint8* data, atUint64 length);

View File

@ -26,9 +26,9 @@ class SkywardSwordFile;
namespace io
{
class SkywardSwordFileWriter : public MemoryWriter
class SkywardSwordFileWriter : public MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
SkywardSwordFileWriter(atUint8* data, atUint64 len);
SkywardSwordFileWriter(const std::string& filename);

View File

@ -29,9 +29,9 @@ class SpriteFile;
namespace io
{
class SpriteFileReader : public MemoryReader
class SpriteFileReader : public MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
SpriteFileReader(atUint8* data, atUint64 length);
SpriteFileReader(const std::string& filepath);

View File

@ -29,9 +29,9 @@ class SpriteFile;
namespace io
{
class SpriteFileWriter : public MemoryWriter
class SpriteFileWriter : public MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
SpriteFileWriter(atUint8* data, atUint64 length);

View File

@ -37,9 +37,9 @@ namespace io
* all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader
*/
class WiiSaveReader : protected MemoryReader
class WiiSaveReader : protected MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
/*! \brief This constructor takes an existing buffer to read from.
*

View File

@ -36,9 +36,9 @@ namespace io
* all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader
*/
class WiiSaveWriter : protected MemoryWriter
class WiiSaveWriter : protected MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
/*! \brief This constructor creates an instance from a file on disk.
*

View File

@ -29,9 +29,9 @@ namespace io
/*!
* \brief The ZQuestFileReader class
*/
class ZQuestFileReader : protected MemoryReader
class ZQuestFileReader : protected MemoryCopyReader
{
MEMORYREADER_BASE();
MEMORYCOPYREADER_BASE();
public:
/*!

View File

@ -29,9 +29,9 @@ namespace io
/*!
* \brief The ZQuestFileWriter class
*/
class ZQuestFileWriter : protected MemoryWriter
class ZQuestFileWriter : protected MemoryCopyWriter
{
MEMORYWRITER_BASE();
MEMORYCOPYWRITER_BASE();
public:
/*!

View File

@ -39,7 +39,7 @@ MCFile* MCFileReader::readFile()
base::m_position = 0;
if (isScrambled)
MCFile::unscramble(base::m_data, base::m_length);
MCFile::unscramble(base::m_dataCopy.get(), base::m_length);
return nullptr;
}

View File

@ -19,7 +19,8 @@ namespace Athena
namespace io
{
MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
: m_length(length),
: m_data(data),
m_length(length),
m_position(0)
{
if (!data)
@ -27,24 +28,20 @@ MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
m_data = new atUint8[m_length];
memcpy(m_data, data, m_length);
}
MemoryReader::MemoryReader(const std::string& filename)
: m_data(NULL),
m_length(0),
m_filepath(filename),
m_position(0)
MemoryCopyReader::MemoryCopyReader(const atUint8* data, atUint64 length)
: MemoryReader(data, length)
{
loadData();
}
if (!data)
THROW_INVALID_DATA_EXCEPTION("data cannot be NULL");
MemoryReader::~MemoryReader()
{
delete[] m_data;
m_data = NULL;
if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, m_length);
}
void MemoryReader::seek(atInt64 position, SeekOrigin origin)
@ -76,14 +73,20 @@ void MemoryReader::seek(atInt64 position, SeekOrigin origin)
void MemoryReader::setData(const atUint8* data, atUint64 length)
{
if (m_data)
delete[] m_data;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
}
void MemoryCopyReader::setData(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, length);
m_length = length;
m_position = 0;
}
atUint8* MemoryReader::data() const
{
atUint8* ret = new atUint8[m_length];
@ -94,9 +97,6 @@ atUint8* MemoryReader::data() const
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
{
if (!m_data)
loadData();
if (m_position + length > m_length)
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position);
@ -105,7 +105,7 @@ atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
return length;
}
void MemoryReader::loadData()
void MemoryCopyReader::loadData()
{
FILE* in;
atUint64 length;
@ -117,7 +117,8 @@ void MemoryReader::loadData()
rewind(in);
length = utility::fileSize(m_filepath);
m_data = new atUint8[length];
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
@ -127,7 +128,7 @@ void MemoryReader::loadData()
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_data + done, 1, blocksize, in);
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0)
THROW_IO_EXCEPTION("Error reading data from disk");

View File

@ -23,18 +23,33 @@ MemoryWriter::MemoryWriter(atUint8* data, atUint64 length)
m_length(length),
m_position(0)
{
if (!m_data && m_length > 0)
m_data = new atUint8[m_length];
if (!data)
THROW_INVALID_DATA_EXCEPTION("data cannot be NULL");
if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
}
MemoryWriter::MemoryWriter(const std::string& filename, std::function<void(int)> progressFun)
: m_length(0),
m_filepath(filename),
m_position(0)
MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length)
: MemoryWriter(data, length)
{
if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
if (data)
memcpy(m_data, data, length);
}
MemoryCopyWriter::MemoryCopyWriter(const std::string& filename)
: MemoryWriter(NULL, 0)
{
m_filepath = filename;
m_length = 0x10;
m_position = 0;
m_data = new atUint8[m_length];
m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
if (!m_data)
THROW_IO_EXCEPTION("Could not allocate memory!");
@ -42,12 +57,6 @@ MemoryWriter::MemoryWriter(const std::string& filename, std::function<void(int)>
memset(m_data, 0, m_length);
}
MemoryWriter::~MemoryWriter()
{
delete[] m_data;
m_data = nullptr;
}
void MemoryWriter::seek(atInt64 position, SeekOrigin origin)
{
switch (origin)
@ -84,16 +93,22 @@ void MemoryWriter::seek(atInt64 position, SeekOrigin origin)
}
}
void MemoryWriter::setData(const atUint8* data, atUint64 length)
void MemoryWriter::setData(atUint8* data, atUint64 length)
{
if (m_data)
delete[] m_data;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
}
void MemoryCopyWriter::setData(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
memcpy(m_data, data, length);
m_length = length;
m_position = 0;
}
atUint8* MemoryWriter::data() const
{
atUint8* ret = new atUint8[m_length];
@ -105,9 +120,6 @@ atUint8* MemoryWriter::data() const
void MemoryWriter::save(const std::string& filename)
{
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (filename.empty() && m_filepath.empty())
THROW_INVALID_OPERATION_EXCEPTION("No file specified, cannot save.");

View File

@ -16,7 +16,7 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe
atUint32 encodeSize = (srcLength << 8) | (0x10);
encodeSize = Athena::utility::LittleUint32(encodeSize); //File size needs to be written as little endian always
Athena::io::MemoryWriter outbuf("tmp");
Athena::io::MemoryCopyWriter outbuf("tmp");
outbuf.writeUint32(encodeSize);
atUint8* ptrStart = (atUint8*)src;

View File

@ -13,7 +13,7 @@ LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimum
atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength)
{
Athena::io::MemoryWriter outbuff("tmp");
Athena::io::MemoryCopyWriter outbuff("tmp");
if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
{