Merge pull request #25 from libAthena/smart-ptrs

Refactored readBytes() and readUBytes() to return std::unique_ptr
This commit is contained in:
Jack Andersen 2015-08-05 12:58:32 -10:00
commit 9ed090b126
17 changed files with 100 additions and 134 deletions

View File

@ -97,13 +97,13 @@ public:
* \brief setInventory
* \param inv
*/
void setInventory(ALTTPInventory* inv);
void setInventory(const ALTTPInventory& inv);
/*!
* \brief inventory
* \return
*/
ALTTPInventory* inventory() const;
const ALTTPInventory& inventory() const;
/*!
* \brief setRupeeMax
@ -641,7 +641,7 @@ public:
private:
std::vector<ALTTPRoomFlags*> m_roomFlags;
std::vector<ALTTPOverworldEvent*> m_overworldEvents;
ALTTPInventory* m_inventory;
ALTTPInventory m_inventory;
atUint16 m_rupeeMax;
atUint16 m_rupeeCurrent;
ALTTPDungeonItemFlags m_compasses;

View File

@ -89,14 +89,23 @@ public:
*
* \return Uint8* The buffer at the current position from the given length.
*/
inline atInt8* readBytes(atUint64 length)
{atInt8* buf = new atInt8[length]; readUBytesToBuf(buf, length); return buf;}
inline std::unique_ptr<atInt8[]> readBytes(atUint64 length)
{
atInt8* buf = new atInt8[length];
readUBytesToBuf(buf, length);
return std::unique_ptr<atInt8[]>(buf);
}
/*! \brief Reads a byte at the current position and advances the current position.
*
* \return Int8* The buffer at the current position from the given length.
*/
inline atUint8* readUBytes(atUint64 length) {return (atUint8*)readBytes(length);}
inline std::unique_ptr<atUint8[]> readUBytes(atUint64 length)
{
atUint8* buf = new atUint8[length];
readUBytesToBuf(buf, length);
return std::unique_ptr<atUint8[]>(buf);
}
inline atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);}
virtual atUint64 readUBytesToBuf(void* buf, atUint64 len)=0;

View File

@ -9,7 +9,7 @@ namespace Athena
class MCSlot : public ZQuestFile
{
public:
MCSlot(atUint8* data, atUint32 length);
MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length);
};
} // Athena

View File

@ -34,7 +34,7 @@
Seeds
};
SkywardSwordQuest(atUint8* data, atUint32 len);
SkywardSwordQuest(std::unique_ptr<atUint8[]>&& data, atUint32 len);
void setPlayerName(const std::string& name);
std::string playerName() const;
@ -56,7 +56,7 @@
std::string currentArea();
std::string currentLocationCopy();
void setSkipData(const atUint8* data);
void setSkipData(std::unique_ptr<atUint8[]>&& data);
atUint8* skipData() const;
@ -67,7 +67,7 @@
void setNew(bool isNew);
bool isNew() const;
private:
atUint8* m_skipData;
std::unique_ptr<atUint8[]> m_skipData;
};

View File

@ -17,6 +17,7 @@
#ifndef WIIIMAGE_HPP
#define WIIIMAGE_HPP
#include <memory>
#include "Athena/Types.hpp"
namespace Athena
@ -38,12 +39,7 @@ public:
* \param height
* \param data
*/
WiiImage(atUint32 width, atUint32 height, atUint8* data);
/*!
* \brief ~WiiImage
*/
~WiiImage();
WiiImage(atUint32 width, atUint32 height, std::unique_ptr<atUint8[]>&& data);
/*!
* \brief setWidth
@ -90,7 +86,7 @@ public:
private:
atUint32 m_width;
atUint32 m_height;
atUint8* m_data;
std::unique_ptr<atUint8[]> m_data;
};
} // zelda

View File

@ -21,6 +21,7 @@
#include "Athena/Global.hpp"
#include <string>
#include <vector>
#include <memory>
#define ZQUEST_VERSION_CHECK(major, minor, revision) \
(major | (minor << 8) | (revision << 16))
@ -98,8 +99,7 @@ public:
* \param data
* \param length
*/
ZQuestFile(Game game, Endian endian, atUint8* data, atUint32 length, const std::string& gameString = std::string());
~ZQuestFile();
ZQuestFile(Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length, const std::string& gameString = std::string());
/*!
* \brief setGame
@ -130,7 +130,7 @@ public:
* \param data The data to assign
* \param length The length of the data
*/
void setData(atUint8* data, atUint32 length);
void setData(std::unique_ptr<atUint8[]>&& data, atUint32 length);
/*!
* \brief data
@ -156,7 +156,7 @@ protected:
Game m_game;
std::string m_gameString;
Endian m_endian;
atUint8* m_data;
std::unique_ptr<atUint8[]> m_data;
atUint32 m_length;
// Game strings support

View File

@ -68,7 +68,7 @@ ALTTPFile* ALTTPFileReader::readFile()
quest->setOverworldEvents(owEvents);
quest->setInventory((ALTTPInventory*)base::readBytes(sizeof(ALTTPInventory)));
quest->setInventory(*(ALTTPInventory*)base::readBytes(sizeof(ALTTPInventory)).get());
quest->setRupeeMax(base::readUint16());
quest->setRupeeCurrent(base::readUint16());
quest->setCompasses(readDungeonFlags());
@ -109,8 +109,8 @@ ALTTPFile* ALTTPFileReader::readFile()
abilities.Read = (abilitiesByte >> 6) & 1;
abilities.Unknown2 = (abilitiesByte >> 7) & 1;
quest->setAbilityFlags(abilities);
quest->setCrystals((ALTTPCrystals&)*base::readBytes(sizeof(ALTTPCrystals)));
quest->setMagicUsage((ALTTPMagicUsage&)*base::readBytes(sizeof(ALTTPMagicUsage)));
quest->setCrystals(*(ALTTPCrystals*)base::readBytes(sizeof(ALTTPCrystals)).get());
quest->setMagicUsage(*(ALTTPMagicUsage*)base::readBytes(sizeof(ALTTPMagicUsage)).get());
j = 0x10;
@ -122,11 +122,11 @@ ALTTPFile* ALTTPFileReader::readFile()
quest->setDungeonKeys(dungeonKeys);
base::seek(0x039);
quest->setProgressIndicator((ALTTPProgressIndicator)base::readByte());
quest->setProgressFlags1((ALTTPProgressFlags1&)*base::readBytes(sizeof(ALTTPProgressFlags1)));
quest->setProgressFlags1(*(ALTTPProgressFlags1*)base::readBytes(sizeof(ALTTPProgressFlags1)).get());
quest->setMapIcon((ALTTPMapIcon)base::readByte());
quest->setStartLocation((ALTTPStartLocation)base::readByte());
quest->setProgressFlags2((ALTTPProgressFlags2&)*base::readBytes(sizeof(ALTTPProgressFlags2)));
quest->setLightDarkWorldIndicator((ALTTPLightDarkWorldIndicator&)*base::readBytes(1));
quest->setProgressFlags2(*(ALTTPProgressFlags2*)base::readBytes(sizeof(ALTTPProgressFlags2)).get());
quest->setLightDarkWorldIndicator(*(ALTTPLightDarkWorldIndicator*)base::readBytes(1).get());
base::seek(1);
quest->setTagAlong((ALTTPTagAlong)base::readByte());

View File

@ -56,7 +56,7 @@ void ALTTPFileWriter::writeFile(ALTTPFile* file)
writeOverworldEvent(quest->overworldEvent(j));
}
base::writeBytes((atInt8*)quest->inventory(), sizeof(ALTTPInventory));
base::writeBytes((atInt8*)&quest->inventory(), sizeof(ALTTPInventory));
base::writeUint16(quest->rupeeMax());
base::writeUint16(quest->rupeeCurrent());
writeDungeonItems(quest->compasses());

View File

@ -79,12 +79,12 @@ ALTTPOverworldEvent* ALTTPQuest::overworldEvent(atUint32 id) const
return m_overworldEvents[id];
}
void ALTTPQuest::setInventory(ALTTPInventory* inv)
void ALTTPQuest::setInventory(const ALTTPInventory& inv)
{
m_inventory = inv;
}
ALTTPInventory* ALTTPQuest::inventory() const
const ALTTPInventory& ALTTPQuest::inventory() const
{
return m_inventory;
}

View File

@ -122,8 +122,7 @@ std::unique_ptr<YAMLNode> YAMLDocReader::ParseEvents(yaml_parser_t* doc)
if (nodeStack.empty())
{
atWarning("YAML parser stack empty; skipping scalar node");
yaml_event_delete(&event);
continue;
break;
}
std::unique_ptr<YAMLNode> newScalar(new YAMLNode(YAML_SCALAR_NODE));
newScalar->m_scalarString.assign((char*)event.data.scalar.value, event.data.scalar.length);
@ -236,7 +235,7 @@ bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node)
goto err;
for (const auto& item : node.m_seqChildren)
{
if (!RecursiveFinish(doc, *item.get()))
if (!RecursiveFinish(doc, *item))
goto err;
}
if (!yaml_sequence_end_event_initialize(&event) ||
@ -252,7 +251,7 @@ bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node)
{
if (!EmitKeyScalar(doc, item.first.c_str()))
goto err;
if (!RecursiveFinish(doc, *item.second.get()))
if (!RecursiveFinish(doc, *item.second))
goto err;
}
event.type = YAML_MAPPING_END_EVENT;

View File

@ -3,8 +3,8 @@
namespace Athena
{
MCSlot::MCSlot(atUint8* data, atUint32 length)
: ZQuestFile(ZQuestFile::MC, Endian::LittleEndian, data, length)
MCSlot::MCSlot(std::unique_ptr<atUint8[]>&& data, atUint32 length)
: ZQuestFile(ZQuestFile::MC, Endian::LittleEndian, std::move(data), length)
{
}

View File

@ -71,7 +71,7 @@ SkywardSwordFile* SkywardSwordFileReader::read()
for (int i = 0; i < 3; i++)
{
SkywardSwordQuest* q = new SkywardSwordQuest((atUint8*)base::readBytes(0x53C0), 0x53C0);
SkywardSwordQuest* q = new SkywardSwordQuest(base::readUBytes(0x53C0), 0x53C0);
atUint64 pos = base::position();
// seek to the skip data for this particular quest
base::seek(0xFB60 + (i * 0x24), SeekOrigin::Begin);

View File

@ -54,26 +54,19 @@ union AmmoValues
atUint32 value;
};
SkywardSwordQuest::SkywardSwordQuest(atUint8* data, atUint32 len)
: ZQuestFile(ZQuestFile::SS, Endian::BigEndian, data, len),
m_skipData(nullptr)
SkywardSwordQuest::SkywardSwordQuest(std::unique_ptr<atUint8[]>&& data, atUint32 len)
: ZQuestFile(ZQuestFile::SS, Endian::BigEndian, std::move(data), len)
{
}
void SkywardSwordQuest::setSkipData(const atUint8* data)
void SkywardSwordQuest::setSkipData(std::unique_ptr<atUint8[]>&& data)
{
if (m_skipData)
{
delete[] m_skipData;
m_skipData = nullptr;
}
m_skipData = (atUint8*)data;
m_skipData = std::move(data);
}
atUint8* SkywardSwordQuest::skipData() const
{
return m_skipData;
return m_skipData.get();
}
void SkywardSwordQuest::setPlayerName(const std::string& name)
@ -86,7 +79,7 @@ void SkywardSwordQuest::setPlayerName(const std::string& name)
for (atUint32 i = 0; i < 8; i++)
{
atUint16& c = *(atUint16*)(m_data + priv::NAME_OFFSET + (i * 2));
atUint16& c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2));
if (i >= val.size())
{
@ -105,7 +98,7 @@ std::string SkywardSwordQuest::playerName() const
for (atUint32 i = 0; i < 8; i++)
{
atUint16 c = *(atUint16*)(m_data + priv::NAME_OFFSET + (i * 2));
atUint16 c = *(atUint16*)(m_data.get() + priv::NAME_OFFSET + (i * 2));
if (c == 0)
break;
@ -120,20 +113,20 @@ std::string SkywardSwordQuest::playerName() const
void SkywardSwordQuest::setRupeeCount(atUint16 value)
{
atUint16& tmp = *(atUint16*)(m_data + priv::RUPEE_COUNT_OFFSET);
atUint16& tmp = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET);
tmp = value;
utility::BigUint16(tmp);
}
atUint16 SkywardSwordQuest::rupeeCount()
{
atUint16 ret = *(atUint16*)(m_data + priv::RUPEE_COUNT_OFFSET);
atUint16 ret = *(atUint16*)(m_data.get() + priv::RUPEE_COUNT_OFFSET);
return utility::BigUint16(ret);
}
void SkywardSwordQuest::setAmmoCount(SkywardSwordQuest::AmmoType type, atUint32 count)
{
AmmoValues& values = *(AmmoValues*)(m_data + priv::AMMO_COUNT_OFFSET);
AmmoValues& values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET);
utility::BigUint32(values.value);
switch (type)
@ -156,7 +149,7 @@ void SkywardSwordQuest::setAmmoCount(SkywardSwordQuest::AmmoType type, atUint32
atUint32 SkywardSwordQuest::ammoCount(AmmoType type)
{
AmmoValues values = *(AmmoValues*)(m_data + priv::AMMO_COUNT_OFFSET);
AmmoValues values = *(AmmoValues*)(m_data.get() + priv::AMMO_COUNT_OFFSET);
utility::BigUint32(values.value);
switch (type)
@ -177,12 +170,12 @@ atUint32 SkywardSwordQuest::ammoCount(AmmoType type)
void SkywardSwordQuest::setMaxHP(atUint16 val)
{
*(atUint16*)(m_data + priv::MAX_HP_OFFSET) = utility::BigUint16(val);
*(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET) = utility::BigUint16(val);
}
atUint16 SkywardSwordQuest::maxHP()
{
atUint16 ret = *(atUint16*)(m_data + priv::MAX_HP_OFFSET);
atUint16 ret = *(atUint16*)(m_data.get() + priv::MAX_HP_OFFSET);
return utility::BigUint16(ret);
}
@ -193,12 +186,12 @@ float SkywardSwordQuest::maxHearts()
void SkywardSwordQuest::setSpawnHP(atUint16 val)
{
*(atUint16*)(m_data + priv::SPAWN_HP_OFFSET) = utility::BigUint16(val);
*(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET) = utility::BigUint16(val);
}
atUint16 SkywardSwordQuest::spawnHP()
{
atUint16 ret = *(atUint16*)(m_data + priv::SPAWN_HP_OFFSET);
atUint16 ret = *(atUint16*)(m_data.get() + priv::SPAWN_HP_OFFSET);
return utility::BigUint16(ret);
}
@ -209,12 +202,12 @@ float SkywardSwordQuest::spawnHearts()
void SkywardSwordQuest::setCurrentHP(atUint16 val)
{
*(atUint16*)(m_data + priv::CURRENT_HP_OFFSET) = utility::BigUint16(val);
*(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET) = utility::BigUint16(val);
}
atUint16 SkywardSwordQuest::currentHP()
{
atUint16 ret = *(atUint16*)(m_data + priv::CURRENT_HP_OFFSET);
atUint16 ret = *(atUint16*)(m_data.get() + priv::CURRENT_HP_OFFSET);
return utility::BigUint16(ret);
}
@ -225,22 +218,22 @@ float SkywardSwordQuest::currentHearts()
std::string SkywardSwordQuest::currentLocation()
{
return std::string((char*)m_data + priv::CURRENT_LOCATION_OFFSET);
return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_OFFSET);
}
std::string SkywardSwordQuest::currentArea()
{
return std::string((char*)m_data + priv::CURRENT_AREA_OFFSET);
return std::string((char*)m_data.get() + priv::CURRENT_AREA_OFFSET);
}
std::string SkywardSwordQuest::currentLocationCopy()
{
return std::string((char*)m_data + priv::CURRENT_LOCATION_COPY_OFFSET);
return std::string((char*)m_data.get() + priv::CURRENT_LOCATION_COPY_OFFSET);
}
atUint32 SkywardSwordQuest::slotChecksum()
{
atUint32 ret = *(atUint32*)(m_data + priv::CHECKSUM_OFFSET);
atUint32 ret = *(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET);
utility::BigUint32(ret);
return ret;
@ -248,7 +241,7 @@ atUint32 SkywardSwordQuest::slotChecksum()
atUint32 SkywardSwordQuest::skipChecksum()
{
atUint32 ret = *(atUint32*)(m_skipData + priv::SKIP_CHECKSUM_OFFSET);
atUint32 ret = *(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET);
utility::BigUint32(ret);
return ret;
@ -256,23 +249,23 @@ atUint32 SkywardSwordQuest::skipChecksum()
void SkywardSwordQuest::fixChecksums()
{
atUint32 checksum = Checksums::crc32(m_data, priv::CHECKSUM_OFFSET);
atUint32 checksum = Checksums::crc32(m_data.get(), priv::CHECKSUM_OFFSET);
utility::BigUint32(checksum);
*(atUint32*)(m_data + priv::CHECKSUM_OFFSET) = checksum;
*(atUint32*)(m_data.get() + priv::CHECKSUM_OFFSET) = checksum;
checksum = Checksums::crc32(m_skipData, priv::SKIP_CHECKSUM_OFFSET);
checksum = Checksums::crc32(m_skipData.get(), priv::SKIP_CHECKSUM_OFFSET);
utility::BigUint32(checksum);
*(atUint32*)(m_skipData + priv::SKIP_CHECKSUM_OFFSET) = checksum;
*(atUint32*)(m_skipData.get() + priv::SKIP_CHECKSUM_OFFSET) = checksum;
}
void SkywardSwordQuest::setNew(bool isNew)
{
*(bool*)(m_data + priv::ISNEW_OFFSET) = isNew;
*(bool*)(m_data.get() + priv::ISNEW_OFFSET) = isNew;
}
bool SkywardSwordQuest::isNew() const
{
return *(bool*)(m_data + priv::ISNEW_OFFSET);
return *(bool*)(m_data.get() + priv::ISNEW_OFFSET);
}
} // zelda

View File

@ -22,24 +22,16 @@
namespace Athena
{
WiiImage::WiiImage(atUint32 width, atUint32 height, atUint8* data) :
WiiImage::WiiImage(atUint32 width, atUint32 height, std::unique_ptr<atUint8[]>&& data) :
m_width(width),
m_height(height),
m_data(data)
m_data(std::move(data))
{
}
WiiImage::~WiiImage()
{
if (m_data)
delete[] m_data;
m_data = NULL;
}
atUint8* WiiImage::data()
{
return m_data;
return m_data.get();
}
atUint32 WiiImage::width() const
@ -72,7 +64,7 @@ atUint8* WiiImage::toRGBA()
{
for (x = x1; x < (x1 + 4); x++)
{
atUint16 oldpixel = *(atUint16*)(m_data + ((iv++) * 2));
atUint16 oldpixel = *(atUint16*)(m_data.get() + ((iv++) * 2));
//if((x >= m_width) || (y >= m_height))
// continue;
oldpixel = utility::swapU16(oldpixel);

View File

@ -125,7 +125,7 @@ WiiBanner* WiiSaveReader::readBanner()
{
atUint8* dec = new atUint8[0xF0C0];
memset(dec, 0, 0xF0C0);
atUint8* data = (atUint8*)base::readBytes(0xF0C0);
std::unique_ptr<atUint8[]> data = base::readUBytes(0xF0C0);
atUint8* oldData = base::data();
atUint64 oldPos = base::position();
atUint64 oldLen = base::length();
@ -140,7 +140,7 @@ WiiBanner* WiiSaveReader::readBanner()
std::cout << "Decrypting: banner.bin...";
std::unique_ptr<IAES> aes = NewAES();
aes->setKey(SD_KEY);
aes->decrypt(tmpIV, data, dec, 0xF0C0);
aes->decrypt(tmpIV, data.get(), dec, 0xF0C0);
std::cout << "done" << std::endl;
memset(md5, 0, 16);
@ -260,10 +260,10 @@ WiiBanner* WiiSaveReader::readBanner()
WiiImage* WiiSaveReader::readImage(atUint32 width, atUint32 height)
{
atUint8* image = (atUint8*)base::readBytes(width * height * 2);
std::unique_ptr<atUint8[]> image = base::readUBytes(width * height * 2);
if (!utility::isEmpty((atInt8*)image, width * height * 2))
return new WiiImage(width, height, image);
if (!utility::isEmpty((atInt8*)image.get(), width * height * 2))
return new WiiImage(width, height, std::move(image));
return NULL;
}
@ -276,7 +276,6 @@ WiiFile* WiiSaveReader::readFile()
atUint8 attributes;
atUint8 type;
std::string name;
atUint8* filedata;
WiiFile* ret;
atUint32 magic = base::readUint32();
@ -291,27 +290,26 @@ WiiFile* WiiSaveReader::readFile()
permissions = base::readByte();
attributes = base::readByte();
type = (WiiFile::Type)base::readByte();
name = std::string((const char*)base::readBytes(0x45));
name = std::string((const char*)base::readBytes(0x45).get());
ret = new WiiFile(std::string(name));
ret->setPermissions(permissions);
ret->setAttributes(attributes);
ret->setType((WiiFile::Type)type);
atUint8* iv = (atUint8*)base::readBytes(0x10);
std::unique_ptr<atUint8[]> iv = base::readUBytes(0x10);
base::seek(0x20);
if (type == WiiFile::File)
{
// Read file data
int roundedLen = (fileLen + 63) & ~63;
filedata = (atUint8*)base::readBytes(roundedLen);
std::unique_ptr<atUint8[]> filedata = base::readUBytes(roundedLen);
// Decrypt file
std::cout << "Decrypting: " << ret->filename() << "...";
atUint8* decData = new atUint8[roundedLen];
std::unique_ptr<IAES> aes = NewAES();
aes->setKey(SD_KEY);
aes->decrypt(iv, filedata, decData, roundedLen);
delete filedata;
aes->decrypt(iv.get(), filedata.get(), decData, roundedLen);
ret->setData(decData);
ret->setLength(fileLen);
std::cout << "done" << std::endl;
@ -325,18 +323,18 @@ void WiiSaveReader::readCerts(atUint32 totalSize)
{
std::cout << "Reading certs..." << std::endl;
atUint32 dataSize = totalSize - 0x340;
atUint8* sig = (atUint8*)base::readBytes(0x40);
atUint8* ngCert = (atUint8*)base::readBytes(0x180);
atUint8* apCert = (atUint8*)base::readBytes(0x180);
std::unique_ptr<atUint8[]> sig = base::readUBytes(0x40);
std::unique_ptr<atUint8[]> ngCert = base::readUBytes(0x180);
std::unique_ptr<atUint8[]> apCert = base::readUBytes(0x180);
base::seek(0xF0C0, SeekOrigin::Begin);
atUint8* data = (atUint8*)base::readBytes(dataSize);
std::unique_ptr<atUint8[]> data = base::readUBytes(dataSize);
atUint8* hash;
hash = getSha1(data, dataSize);
hash = getSha1(data.get(), dataSize);
atUint8* hash2 = getSha1(hash, 20);
std::cout << "validating..." << std::endl;
std::cout << (check_ec(ngCert, apCert, sig, hash2) ? "ok" : "invalid") << "...";
std::cout << (check_ec(ngCert.get(), apCert.get(), sig.get(), hash2) ? "ok" : "invalid") << "...";
std::cout << "done" << std::endl;
}

View File

@ -56,17 +56,16 @@ const atUint32 ZQuestFile::Magic = 'Z' | ('Q' << 8) | ('S' << 16) | (('0' + ZQ
ZQuestFile::ZQuestFile()
: m_game(NoGame),
m_endian(Endian::LittleEndian),
m_data(NULL),
m_length(0)
{
initGameStrings();
}
ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, atUint8* data, atUint32 length, const std::string& gameString)
ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, std::unique_ptr<atUint8[]>&& data, atUint32 length, const std::string& gameString)
: m_game(game),
m_gameString(gameString),
m_endian(endian),
m_data(data),
m_data(std::move(data)),
m_length(length)
{
initGameStrings();
@ -75,13 +74,6 @@ ZQuestFile::ZQuestFile(ZQuestFile::Game game, Endian endian, atUint8* data, atUi
m_gameString = GameStrings[m_game];
}
ZQuestFile::~ZQuestFile()
{
delete[] m_data;
m_data = NULL;
m_length = 0;
}
void ZQuestFile::setGame(ZQuestFile::Game game)
{
m_game = game;
@ -107,24 +99,15 @@ Endian ZQuestFile::endian() const
return m_endian;
}
void ZQuestFile::setData(atUint8* data, atUint32 length)
void ZQuestFile::setData(std::unique_ptr<atUint8[]>&& data, atUint32 length)
{
// ensure we're not overwritting our data without freeing first
// or assigning unnecessisarily
if (!m_data || m_data != data)
{
delete[] m_data;
m_data = new atUint8[length];
// Why is this memcpy needed?
// I get SIGABRT without it, need to research
memcpy(m_data, data, length);
m_length = length;
}
m_data = std::move(data);
m_length = length;
}
atUint8* ZQuestFile::data() const
{
return m_data;
return m_data.get();
}

View File

@ -45,7 +45,6 @@ ZQuestFile* ZQuestFileReader::read()
std::string gameString;
atUint16 BOM;
atUint32 checksum = 0;
atUint8* data;
magic = base::readUint32();
@ -68,7 +67,7 @@ ZQuestFile* ZQuestFileReader::read()
if (version >= ZQUEST_VERSION_CHECK(2, 0, 0))
{
gameString = std::string((const char*)base::readBytes(0x0A), 0x0A);
gameString = std::string((const char*)base::readBytes(0x0A).get(), 0x0A);
for (size_t i = 0; i < ZQuestFile::gameStringList().size(); i++)
{
@ -90,13 +89,12 @@ ZQuestFile* ZQuestFileReader::read()
base::seek(0x0A);
}
data = (atUint8*)base::readBytes(compressedLen); // compressedLen is always the total file size
std::unique_ptr<atUint8[]> data = base::readUBytes(compressedLen); // compressedLen is always the total file size
if (version >= ZQUEST_VERSION_CHECK(2, 0, 0))
{
if (checksum != Athena::Checksums::crc32(data, compressedLen))
if (checksum != Athena::Checksums::crc32(data.get(), compressedLen))
{
delete[] data;
atError("Checksum mismatch, data corrupt");
return nullptr;
}
@ -110,21 +108,19 @@ ZQuestFile* ZQuestFileReader::read()
if (compressedLen != uncompressedLen)
{
atUint8* dst = new atUint8[uncompressedLen];
atUint32 dstLen = io::Compression::decompressZlib(data, compressedLen, dst, uncompressedLen);
atUint32 dstLen = io::Compression::decompressZlib(data.get(), compressedLen, dst, uncompressedLen);
if (dstLen != uncompressedLen)
{
delete[] dst;
delete[] data;
atError("Error decompressing data");
return nullptr;
}
delete[] data;
data = dst;
data.reset(dst);
}
return new ZQuestFile(game, BOM == 0xFEFF ? Endian::BigEndian : Endian::LittleEndian, data, uncompressedLen, gameString);
return new ZQuestFile(game, BOM == 0xFEFF ? Endian::BigEndian : Endian::LittleEndian, std::move(data), uncompressedLen, gameString);
}
} // io