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. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class ALTTPFileReader : protected MemoryReader class ALTTPFileReader : protected MemoryCopyReader
{ {
MEMORYREADER_BASE(); MEMORYCOPYREADER_BASE();
public: public:
/*! \brief This constructor takes an existing buffer to read from. /*! \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. * all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class ALTTPFileWriter : protected MemoryWriter class ALTTPFileWriter : protected MemoryCopyWriter
{ {
MEMORYWRITER_BASE(); MEMORYCOPYWRITER_BASE();
public: public:
/*! \brief This constructor takes an existing buffer to write to. /*! \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. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class MCFileReader : public MemoryReader class MCFileReader : public MemoryCopyReader
{ {
MEMORYREADER_BASE(); MEMORYCOPYREADER_BASE();
public: public:
/*! /*!
* \brief This constructor takes an existing buffer to read from. * \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. * all work is done using a memory buffer, and not written directly from the disk.
* \sa BinaryWriter * \sa BinaryWriter
*/ */
class MCFileWriter : protected MemoryWriter class MCFileWriter : protected MemoryCopyWriter
{ {
MEMORYWRITER_BASE(); MEMORYCOPYWRITER_BASE();
public: public:
/*! /*!
* \brief This constructor takes an existing buffer to write to. * \brief This constructor takes an existing buffer to write to.

View File

@ -20,21 +20,13 @@ namespace io
class MemoryReader : public IStreamReader class MemoryReader : public IStreamReader
{ {
public: public:
~MemoryReader(); /*! \brief This constructor references an existing buffer to read from.
/*! \brief This constructor takes an existing buffer to read from.
* *
* \param data The existing buffer * \param data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
MemoryReader(const atUint8* data, atUint64 length); 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 /> /*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default. * It seeks relative to the current position by default.
* \param position where in the buffer to seek * \param position where in the buffer to seek
@ -78,16 +70,46 @@ public:
*/ */
atUint8* data() const; 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); atUint64 readUBytesToBuf(void* buf, atUint64 len);
protected: protected:
void loadData(); const atUint8* m_data;
atUint8* m_data;
atUint64 m_length; atUint64 m_length;
std::string m_filepath; //!< Path to the target file
atUint64 m_position; 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();
std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file
};
} // io } // io
} // Athena } // Athena
@ -98,4 +120,11 @@ private: \
#endif // MEMORYREADER_BASE #endif // MEMORYREADER_BASE
#ifndef MEMORYCOPYREADER_BASE
#define MEMORYCOPYREADER_BASE() \
private: \
typedef Athena::io::MemoryCopyReader base
#endif // MEMORYCOPYREADER_BASE
#endif // MEMORYREADER_HPP #endif // MEMORYREADER_HPP

View File

@ -21,22 +21,14 @@ namespace io
class MemoryWriter : public IStreamWriter class MemoryWriter : public IStreamWriter
{ {
public: 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 data The existing buffer
* \param length The length of the existing buffer * \param length The length of the existing buffer
*/ */
explicit MemoryWriter(atUint8* data = nullptr, atUint64 length = 0x10); 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 /> /*! \brief Sets the buffers position relative to the specified position.<br />
* It seeks relative to the current position by default. * It seeks relative to the current position by default.
* \param position where in the buffer to seek * \param position where in the buffer to seek
@ -70,7 +62,7 @@ public:
* \param length The length of the new buffer. * \param length The length of the new buffer.
* \throw IOException * \throw IOException
*/ */
void setData(const atUint8* data, atUint64 length); void setData(atUint8* data, atUint64 length);
/*! \brief Returns a copy of the current buffer.<br /> /*! \brief Returns a copy of the current buffer.<br />
@ -113,11 +105,35 @@ public:
protected: protected:
atUint8* m_data; atUint8* m_data;
atUint64 m_length; atUint64 m_length;
std::string m_filepath; //!< Path to the target file
atUint64 m_position; atUint64 m_position;
std::string m_filepath; //!< Path to the target file
private: private:
void resize(atUint64 newSize); 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: \ private: \
typedef Athena::io::MemoryWriter base typedef Athena::io::MemoryWriter base
#endif // BINARYWRITER_BASE #endif // BINARYWRITER_BASE
#ifndef MEMORYCOPYWRITER_BASE
#define MEMORYCOPYWRITER_BASE() \
private: \
typedef Athena::io::MemoryCopyWriter base
#endif // BINARYWRITER_BASE
#endif // MEMORYWRITER_HPP #endif // MEMORYWRITER_HPP

View File

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

View File

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

View File

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

View File

@ -29,9 +29,9 @@ class SpriteFile;
namespace io namespace io
{ {
class SpriteFileWriter : public MemoryWriter class SpriteFileWriter : public MemoryCopyWriter
{ {
MEMORYWRITER_BASE(); MEMORYCOPYWRITER_BASE();
public: public:
SpriteFileWriter(atUint8* data, atUint64 length); 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. * all work is done using a memory buffer, and not read directly from the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class WiiSaveReader : protected MemoryReader class WiiSaveReader : protected MemoryCopyReader
{ {
MEMORYREADER_BASE(); MEMORYCOPYREADER_BASE();
public: public:
/*! \brief This constructor takes an existing buffer to read from. /*! \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. * all work is done using a memory buffer, and not written directly to the disk.
* \sa BinaryReader * \sa BinaryReader
*/ */
class WiiSaveWriter : protected MemoryWriter class WiiSaveWriter : protected MemoryCopyWriter
{ {
MEMORYWRITER_BASE(); MEMORYCOPYWRITER_BASE();
public: public:
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *

View File

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

View File

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

View File

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

View File

@ -19,7 +19,8 @@ namespace Athena
namespace io namespace io
{ {
MemoryReader::MemoryReader(const atUint8* data, atUint64 length) MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
: m_length(length), : m_data(data),
m_length(length),
m_position(0) m_position(0)
{ {
if (!data) if (!data)
@ -27,24 +28,20 @@ MemoryReader::MemoryReader(const atUint8* data, atUint64 length)
if (length == 0) if (length == 0)
THROW_INVALID_OPERATION_EXCEPTION("length cannot be 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) MemoryCopyReader::MemoryCopyReader(const atUint8* data, atUint64 length)
: m_data(NULL), : MemoryReader(data, length)
m_length(0),
m_filepath(filename),
m_position(0)
{ {
loadData(); if (!data)
} THROW_INVALID_DATA_EXCEPTION("data cannot be NULL");
MemoryReader::~MemoryReader() if (length == 0)
{ THROW_INVALID_OPERATION_EXCEPTION("length cannot be 0");
delete[] m_data;
m_data = NULL; 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) 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) void MemoryReader::setData(const atUint8* data, atUint64 length)
{ {
if (m_data)
delete[] m_data;
m_data = (atUint8*)data; m_data = (atUint8*)data;
m_length = length; m_length = length;
m_position = 0; 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* MemoryReader::data() const
{ {
atUint8* ret = new atUint8[m_length]; atUint8* ret = new atUint8[m_length];
@ -94,9 +97,6 @@ atUint8* MemoryReader::data() const
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length) atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
{ {
if (!m_data)
loadData();
if (m_position + length > m_length) if (m_position + length > m_length)
THROW_IO_EXCEPTION_RETURN(0, "Position %0.8X outside stream bounds ", m_position); 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; return length;
} }
void MemoryReader::loadData() void MemoryCopyReader::loadData()
{ {
FILE* in; FILE* in;
atUint64 length; atUint64 length;
@ -117,7 +117,8 @@ void MemoryReader::loadData()
rewind(in); rewind(in);
length = utility::fileSize(m_filepath); 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 done = 0;
atUint64 blocksize = BLOCKSZ; atUint64 blocksize = BLOCKSZ;
@ -127,7 +128,7 @@ void MemoryReader::loadData()
if (blocksize > length - done) if (blocksize > length - done)
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) if (ret < 0)
THROW_IO_EXCEPTION("Error reading data from disk"); THROW_IO_EXCEPTION("Error reading data from disk");

View File

@ -23,18 +23,33 @@ MemoryWriter::MemoryWriter(atUint8* data, atUint64 length)
m_length(length), m_length(length),
m_position(0) m_position(0)
{ {
if (!m_data && m_length > 0) if (!data)
m_data = new atUint8[m_length]; 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) MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length)
: m_length(0), : MemoryWriter(data, length)
m_filepath(filename),
m_position(0)
{ {
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_length = 0x10;
m_position = 0; m_position = 0;
m_data = new atUint8[m_length]; m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
if (!m_data) if (!m_data)
THROW_IO_EXCEPTION("Could not allocate memory!"); 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); memset(m_data, 0, m_length);
} }
MemoryWriter::~MemoryWriter()
{
delete[] m_data;
m_data = nullptr;
}
void MemoryWriter::seek(atInt64 position, SeekOrigin origin) void MemoryWriter::seek(atInt64 position, SeekOrigin origin)
{ {
switch (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_data = (atUint8*)data;
m_length = length; m_length = length;
m_position = 0; 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* MemoryWriter::data() const
{ {
atUint8* ret = new atUint8[m_length]; atUint8* ret = new atUint8[m_length];
@ -105,9 +120,6 @@ atUint8* MemoryWriter::data() const
void MemoryWriter::save(const std::string& filename) void MemoryWriter::save(const std::string& filename)
{ {
if (!isOpen())
THROW_INVALID_OPERATION_EXCEPTION("File not open for writing");
if (filename.empty() && m_filepath.empty()) if (filename.empty() && m_filepath.empty())
THROW_INVALID_OPERATION_EXCEPTION("No file specified, cannot save."); 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); atUint32 encodeSize = (srcLength << 8) | (0x10);
encodeSize = Athena::utility::LittleUint32(encodeSize); //File size needs to be written as little endian always 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); outbuf.writeUint32(encodeSize);
atUint8* ptrStart = (atUint8*)src; 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) 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 if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs
{ {