From 47054ea88141974ec2ceb8d2a12eaa6187acbbaf Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 1 Jul 2014 20:32:44 -0700 Subject: [PATCH] * Add PHYSFSFileReader class --- Athena.pri | 6 +- include/Athena/PHYSFSFileReader.hpp | 61 +++++++++ include/Athena/Stream.hpp | 4 +- src/Athena/PHYSFSFileReader.cpp | 197 ++++++++++++++++++++++++++++ 4 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 include/Athena/PHYSFSFileReader.hpp create mode 100644 src/Athena/PHYSFSFileReader.cpp diff --git a/Athena.pri b/Athena.pri index 52f33df..e3ac840 100644 --- a/Athena.pri +++ b/Athena.pri @@ -44,7 +44,8 @@ SOURCES += \ $$PWD/src/md5.cpp \ $$PWD/src/sha1.cpp \ $$PWD/src/aes.c \ - $$PWD/src/lzo.c + $$PWD/src/lzo.c \ + Athena/src/Athena/PHYSFSFileReader.cpp win32:SOURCES += $$PWD/src/win32_largefilewrapper.c HEADERS += \ @@ -101,7 +102,8 @@ HEADERS += \ $$PWD/include/Athena/WiiSaveWriter.hpp \ $$PWD/include/Athena/ZQuestFile.hpp \ $$PWD/include/Athena/ZQuestFileReader.hpp \ - $$PWD/include/Athena/ZQuestFileWriter.hpp + $$PWD/include/Athena/ZQuestFileWriter.hpp \ + Athena/include/Athena/PHYSFSFileReader.hpp win32:HEADERS += \ $$PWD/include/win32_largefilewrapper.h diff --git a/include/Athena/PHYSFSFileReader.hpp b/include/Athena/PHYSFSFileReader.hpp new file mode 100644 index 0000000..819fe87 --- /dev/null +++ b/include/Athena/PHYSFSFileReader.hpp @@ -0,0 +1,61 @@ +#ifdef ATHENA_ENABLE_PHYSFS +#ifndef PHYSFSSTREAM_HPP +#define PHYSFSSTREAM_HPP + +#include "Athena/Stream.hpp" +#include + +namespace Athena +{ +namespace io +{ +class PHYSFSFileReader : public Stream +{ +public: + PHYSFSFileReader(const std::string& path); + + void setEndian(Endian); + Endian endian() const; + bool isBigEndian() const; + bool isLittleEndian() const; + atUint8* data(); + + atUint64 length() const; + + atUint64 position() const; + + bool isOpen() const; + + void seek(atInt64 position, SeekOrigin origin); + atInt8 readByte(); + atUint8 readUByte(); + atUint8* readUBytes(atUint64 length); + atInt8* readBytes(atUint64 length); + atUint16 readUint16(); + atInt16 readInt16(); + atUint32 readUint32(); + atInt32 readInt32(); + atUint64 readUint64(); + atInt64 readInt64(); + double readDouble(); + float readFloat(); + bool readBool(); + + bool atEnd() const; + + // TODO: Strings +private: + Endian m_endian; + std::string m_path; + atUint64 m_length; + PHYSFS_File* m_handle; +}; +} +} + +#ifndef PHYSFSFILEREADER_BASE +#define PHYSFSFILEREADER_BASE() \ + typedef Athena::io::PHYSFSFileReader base +#endif +#endif // PHYSFSSTREAM_HPP +#endif // ATHENA_ENABLE_PHYSFS diff --git a/include/Athena/Stream.hpp b/include/Athena/Stream.hpp index 7007825..3c3a9c4 100644 --- a/include/Athena/Stream.hpp +++ b/include/Athena/Stream.hpp @@ -21,7 +21,8 @@ namespace Athena { - +namespace io +{ std::ostream& operator<<(std::ostream& os, Endian& endian); class Stream @@ -78,4 +79,5 @@ protected: virtual void fill(atInt8, atUint64) {THROW_NOT_IMPLEMENTED_EXCEPTION();} }; } +} #endif // STREAM_HPP diff --git a/src/Athena/PHYSFSFileReader.cpp b/src/Athena/PHYSFSFileReader.cpp new file mode 100644 index 0000000..f61b256 --- /dev/null +++ b/src/Athena/PHYSFSFileReader.cpp @@ -0,0 +1,197 @@ +#ifdef ATHENA_ENABLE_PHYSFS +#include "Athena/PHYSFSFileReader.hpp" +#include "Athena/FileNotFoundException.hpp" +#include "Athena/IOException.hpp" + +namespace Athena +{ +namespace io +{ + +PHYSFSFileReader::PHYSFSFileReader(const std::string& path) + : m_path(path), + m_endian(Endian::LittleEndian) +{ + if (!PHYSFS_exists(m_path.c_str())) + THROW_FILE_NOT_FOUND_EXCEPTION(path); + + m_handle = PHYSFS_openRead(path.c_str()); + m_length = PHYSFS_fileLength(m_handle); +} + +atUint8* PHYSFSFileReader::data() +{ + return readUBytes(length()); +} + +atUint64 PHYSFSFileReader::length() const +{ + return m_length; +} + +atUint64 PHYSFSFileReader::position() const +{ + return PHYSFS_tell(m_handle); +} + +bool PHYSFSFileReader::isOpen() const +{ + return (m_handle != nullptr); +} + +void PHYSFSFileReader::seek(atInt64 position, SeekOrigin origin) +{ + atInt64 curPos = PHYSFS_tell(m_handle); + switch (origin) + { + case SeekOrigin::Begin: + if ((position < 0 || (atInt64)position > (atInt64)m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + PHYSFS_seek(m_handle, position); + break; + case SeekOrigin::Current: + if ((((atInt64)curPos + position) < 0 || (curPos + position) > m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + PHYSFS_seek(m_handle, curPos + position); + break; + case SeekOrigin::End: + if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length)) + THROW_IO_EXCEPTION("Position %0.16X outside stream bounds ", position); + PHYSFS_seek(m_handle, m_length - position); + break; + } +} + +atUint8 PHYSFSFileReader::readUByte() +{ + atUint8 val; + + if (!PHYSFS_read(m_handle, &val, 1, 1)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; +} + +atInt8 PHYSFSFileReader::readByte() +{ + return readUByte(); +} + +atUint8* PHYSFSFileReader::readUBytes(atUint64 length) +{ + atUint8* data = new atUint8[length]; + if (PHYSFS_read(m_handle, data, 1, length) == length) + return data; + delete[] data; + THROW_IO_EXCEPTION("Position outside stream bounds"); +} + +atInt8*PHYSFSFileReader::readBytes(atUint64 length) +{ + return (atInt8*)readUBytes(length); +} + +atUint16 PHYSFSFileReader::readUint16() +{ + atUint16 val; + + if (m_endian == Endian::BigEndian) + { + if (!PHYSFS_readUBE16(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } + else if (!PHYSFS_readULE16(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; +} + +atInt16 PHYSFSFileReader::readInt16() +{ + return readUint16(); +} + +atUint32 PHYSFSFileReader::readUint32() +{ + atUint32 val; + + if (m_endian == Endian::BigEndian) + { + if (!PHYSFS_readUBE32(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } + else if (!PHYSFS_readULE32(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; +} + +atInt32 PHYSFSFileReader::readInt32() +{ + return readUint32(); +} + +atUint64 PHYSFSFileReader::readUint64() +{ + atUint64 val; + + if (m_endian == Endian::BigEndian) + { + if (!PHYSFS_readUBE64(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + } + else if (!PHYSFS_readUBE64(m_handle, &val)) + THROW_IO_EXCEPTION("Position outside stream bounds"); + + return val; +} + +atInt64 PHYSFSFileReader::readInt64() +{ + return readUint64(); +} + +double PHYSFSFileReader::readDouble() +{ + return static_cast(readUint64()); +} + +float PHYSFSFileReader::readFloat() +{ + return static_cast(readUint32()); +} + +bool PHYSFSFileReader::readBool() +{ + return (readByte() != 0); +} + +bool PHYSFSFileReader::atEnd() const +{ + return PHYSFS_eof(m_handle); +} + +void PHYSFSFileReader::setEndian(Endian endian) +{ + m_endian = endian; +} + +Endian PHYSFSFileReader::endian() const +{ + return m_endian; +} + +bool PHYSFSFileReader::isBigEndian() const +{ + return m_endian == Endian::BigEndian; +} + +bool PHYSFSFileReader::isLittleEndian() const +{ + return m_endian == Endian::LittleEndian; +} + +} +} + +#endif