* Fix bug in BinaryReader where it wasn't correctly reading in all the data

This commit is contained in:
Antidote 2013-01-29 13:46:05 -08:00
parent 8adb9c0e98
commit 1e2065b352
10 changed files with 672 additions and 640 deletions

View File

@ -12,11 +12,11 @@
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __BINARYREADER_HPP__
#define __BINARYREADER_HPP__
#include "Stream.hpp"
#include <string>
#ifndef __BINARYREADER_HPP__
#define __BINARYREADER_HPP__
#include "Stream.hpp"
#include <string>
/*! \class BinaryReader
* \brief A Stream class for reading binary data
@ -25,9 +25,9 @@
* all work is done using a memory buffer, and not read directly from the disk
* this allows for fast, flexible code as well as the ability to quickly modify data
* \sa Stream
*/
class BinaryReader : public Stream
{
*/
class BinaryReader : public Stream
{
public:
/*! \brief This constructor takes an existing buffer to read from.
*
@ -38,12 +38,12 @@ public:
/*! \brief This constructor takes an existing Stream to read from.
*
* \param stream The stream to read data from
*/
*/
BinaryReader(const Stream& stream);
/*! \brief This constructor creates an instance from a file on disk.
*
* \param filename The file to create the stream from
*/
*/
BinaryReader(const std::string& filename);
@ -64,7 +64,7 @@ public:
*
* \return Uint16 The value at the current address
* \throw IOException when address is out of range
*/
*/
Uint16 readUInt16();
/*! \brief Reads a Int32 and swaps to proper endianness depending on platform
@ -74,7 +74,7 @@ public:
*
* \return Int32 The value at the current address
* \throw IOException when address is out of range
*/
*/
Int32 readInt32();
/*! \brief Reads a Uint32 and swaps to proper endianness depending on platform
@ -84,7 +84,7 @@ public:
*
* \return Uint32 The value at the current address
* \throw IOException when address is out of range
*/
*/
Uint32 readUInt32();
/*! \brief Reads a Int64 and swaps to proper endianness depending on platform
@ -94,7 +94,7 @@ public:
*
* \return Int64 The value at the current address
* \throw IOException when address is out of range
*/
*/
Int64 readInt64();
/*! \brief Reads a Uint64 and swaps to proper endianness depending on platform
@ -104,7 +104,7 @@ public:
*
* \return Uint64 The value at the current address
* \throw IOException when address is out of range
*/
*/
Uint64 readUInt64();
/*! \brief Reads a float and swaps to proper endianness depending on platform
@ -114,7 +114,7 @@ public:
*
* \return float The value at the current address
* \throw IOException when address is out of range
*/
*/
float readFloat();
/*! \brief Reads a double and swaps to proper endianness depending on platform
@ -124,26 +124,26 @@ public:
*
* \return double The value at the current address
* \throw IOException when address is out of range
*/
*/
double readDouble();
/*! \brief Reads a bool and advances the current position
*
* \return bool The value at the current address
* \throw IOException when address is out of range
*/
*/
bool readBool();
/*! \brief Reads a Unicode string and advances the position in the file
*
* \return std::string The value at the current address
* \throw IOException when address is out of range
*/
*/
std::string readUnicode();
private:
protected:
/*! \brief Overload of isOpenForWriting in Stream
*
* \return false
*/
*/
bool isOpenForWriting();
/*! \brief Overload of writeByte in Stream
*
@ -153,9 +153,9 @@ private:
/*! \brief Overload of writeBytes in Stream
*
* \throw IOException
*/
void writeBytes(Int8*, Int64);
std::string m_filename;
};
#endif
*/
void writeBytes(Int8*, Int64);
std::string m_filename;
};
#endif

View File

@ -13,36 +13,37 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __EXCEPTION_HPP__
#define __EXCEPTION_HPP__
#include <string>
#ifndef __EXCEPTION_HPP__
#define __EXCEPTION_HPP__
#include <string>
/*! \class Exception
* \brief The baseclass for all Exceptions.
*
* <b>Do Not</b> use Exception directly, instead create an appropriate
* Exception class and inherit from this baseclass.
*/
class Exception
{
*/
class Exception
{
public:
/*! \brief The constructor for an Exception
* \param message The error message to throw
*/
Exception(const std::string& message) :
m_message(message)
{};
*/
inline Exception(const std::string& message) :
m_message(message)
{
};
/*! \brief Returns the Error message of the exception
* \return std::string The error message
*/
std::string message() const
{
return m_message;
};
protected:
std::string m_message;
};
#endif
*/
inline std::string message() const
{
return m_message;
};
protected:
std::string m_message;
};
#endif

View File

@ -13,10 +13,10 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __FILENOTFOUNDEXCEPTION_HPP__
#define __FILENOTFOUNDEXCEPTION_HPP__
#include "Exception.hpp"
#ifndef __FILENOTFOUNDEXCEPTION_HPP__
#define __FILENOTFOUNDEXCEPTION_HPP__
#include "Exception.hpp"
/*! \class FileNotFoundException
* \brief An excpeption thrown when a file could not be found at the given path.
@ -25,24 +25,24 @@
* <br />
* It is <b>NOT</b> appropriate to use <b>throw new</b> so avoid doing so,
* keeping things on the stack as much as possible is very important for speed.
*/
class FileNotFoundException : public Exception
{
*/
class FileNotFoundException : public Exception
{
public:
/*! \brief The constructor for an FileNotFoundException
* \param filename The path of the offending file.
*/
FileNotFoundException(const std::string& filename) :
Exception("FileNotFoundException:\nCouldn't not find \"" + filename + "\", please check that it exists."),
m_filename(filename)
{}
*/
inline FileNotFoundException(const std::string& filename) :
Exception("FileNotFoundException:\nCouldn't not find \"" + filename + "\", please check that it exists."),
m_filename(filename)
{}
/*! \brief Returns the path of the offending file.
* \return std::string The filename of the file including the path.
*/
std::string filename() const { return m_filename; }
private:
std::string m_filename;
};
#endif
*/
inline std::string filename() const { return m_filename; }
private:
std::string m_filename;
};
#endif

View File

@ -13,11 +13,11 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __INVALID_OPERATION_EXCEPTION_HPP__
#define __INVALID_OPERATION_EXCEPTION_HPP__
#include <string>
#include <Exception.hpp>
#ifndef __INVALID_OPERATION_EXCEPTION_HPP__
#define __INVALID_OPERATION_EXCEPTION_HPP__
#include <string>
#include <Exception.hpp>
/*! \class InvalidOperationException
* \brief An excpeption thrown on Invalid Operations calls.
@ -27,16 +27,16 @@
* <br />
* It is <b>NOT</b> appropriate to use <b>throw new</b> so avoid doing so,
* keeping things on the stack as much as possible is very important for speed.
*/
class InvalidOperationException : public Exception
{
*/
class InvalidOperationException : public Exception
{
public:
/*! \brief The constructor for an InvalidOperationException
* \param error The error message to throw
*/
InvalidOperationException(const std::string& error)
: Exception("InvalidOperationException:\n" + error)
{
}
};
#endif // __INVALID_OPERATION_EXCEPTION_HPP__
*/
inline InvalidOperationException(const std::string& error)
: Exception("InvalidOperationException:\n" + error)
{
}
};
#endif // __INVALID_OPERATION_EXCEPTION_HPP__

View File

@ -37,7 +37,34 @@
* return 0;
* }
* \endcode
* \section example_sec BinaryReader example
* \code
* #include "BinaryReader.hpp"
* #include "FileNotFoundException.hpp"
* #include "Exception.hpp"
* int main()
* {
* try
* {
* BinaryReader writer("test.bin");
* std::cout << reader.readByte() << std::endl;
* std::cout << reader.readInt32() << std::endl;
* }
* catch (FileNotFoundException e)
* {
* std::cout << e.message() << std::endl;
* }
* catch (Exception e)
* {
* std::cout << e.message() << std::endl;
* }
* catch(...)
* {
* }
* return 0;
* }
* \endcode
* \section Credits
* Chibi Zelda: AnimeWaterFall on Deviantart
* Chibi Zelda: <a href="http://animewaterfall.deviantart.com/art/Chibi-Zelda-331611090">AnimeWaterFall</a> on Deviantart
*/
#endif // __MAINPAGE_HPP__

View File

@ -12,10 +12,10 @@
//
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#ifndef __STREAM_HPP__
#define __STREAM_HPP__
#include "Types.hpp"
#ifndef __STREAM_HPP__
#define __STREAM_HPP__
#include "Types.hpp"
/*! \class Stream
* \brief Stream is the main class all streams inherit from
@ -28,10 +28,11 @@
* <br />
* Stream can also be used by itself though it's not advised as it's not feature filled.<br />
* It's highly suggested to use of the more advanced Streams such as BinaryReader.
*/
class Stream
{
*/
class Stream
{
public:
//! \brief Default buffer block size.
static const Uint32 BLOCKSZ;
/*! \enum Endian
@ -47,50 +48,50 @@ public:
/*! \enum SeekOrigin
* \brief Specifies how to seek in a stream.
*/
*/
enum SeekOrigin
{
Beginning = 0, //!< Tells the Stream to seek from the Beginning of the buffer.
Current, //!< Tells the Stream to seek from the Current position of the buffer.
End //!< Tells the Stream to seek from the End of the buffer.
};
};
/*! \brief The default constructor
*/
*/
Stream();
/*! \brief This constructor takes an existing buffer to read from.
*
* \param bytes The existing buffer
* \param length The length of the existing buffer
*/
*/
Stream(const Uint8* bytes, Uint64 length);
/*! \brief This constructor creates a buffer from the given length.
*
* \param length The length of the existing buffer
*/
*/
Stream(Int64 length);
/*! \brief This constructor takes an existing Stream to read from.
*
* \param stream The stream to read data from
*/
*/
Stream(Stream* stream);
/*! \brief The destructor cleans up memory and sets everything back
* to the default settings.
*/
virtual ~Stream();
*/
virtual ~Stream();
/*! \brief Writes a bit at the current position and advances the position by one bit.
* \param val the value to write
* \throw IOException
*/
*/
virtual void writeBit(bool val);
/*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write
* \throw IOException
*/
*/
virtual void writeByte(Int8 byte);
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
@ -99,27 +100,27 @@ public:
* \param data The buffer to write
* \param length The amount to write
* \throw IOException
*/
*/
virtual void writeBytes(Int8* data, Int64 length);
/*! \brief Reads a bit at the current position and advances the current position
*
* \return bool The value at the current position
* \throw IOException
*/
*/
virtual bool readBit();
/*! \brief Reads a byte at the current position and advances the current position
*
* \return Int8 The value at the current position
* \throw IOException
*/
*/
virtual Int8 readByte();
/*! \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.
* \throw IOException
*/
*/
virtual Int8* readBytes(Int64 length);
/*! \brief Sets the buffers position relative to the specified position.<br />
@ -127,15 +128,15 @@ public:
* \param position where in the buffer to seek
* \param origin The Origin to seek \sa SeekOrigin
* \throw IOException
*/
*/
void seek(Int64 position, SeekOrigin origin = Current);
/*! \brief Resizes the buffer to the given length.<br />
* The new size must be greater than the current length to avoid loss of data.
* \param newSize The amount to resize by.
* \throw IOException
*/
void resize(Uint64 newSize);
*/
void resize(Uint64 newSize);
/*! \brief Sets the buffer to the given one, deleting the current one.<br />
* <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data
@ -161,44 +162,44 @@ public:
/*! \brief Returns the length of the Stream.
*
* \return Int64 The length of the stream.
*/
*/
Int64 length();
/*! \brief Returns the current position in the stream.
*
* \return Int64 The current position in the stream.
*/
*/
Int64 position();
/*! \brief Returns whether or not the stream is at the end.
*
* \return bool True if at end; False otherwise.
*/
*/
bool atEnd();
/*! \brief Sets whether the Stream resizes when the at the end of the buffer.
*
* \param val True for resizing; False for no resizing.
*/
*/
void setAutoResizing(bool val);
/*! \brief Retuns whether or not the Stream currenty autoresizes.
*
* \return True for resizing; False otherwise.
*/
bool autoResizing() const;
*/
bool autoResizing() const;
/*! \brief Retuns whether or not the Stream is open for reading.
*
* \return True if open for reading; False otherwise.
*/
*/
virtual bool isOpenForReading() const;
/*! \brief Retuns whether or not the Stream is open for writing
*
* \return True if open for writing; False otherwise.
*/
*/
virtual bool isOpenForWriting() const;
/*! \brief Sets the Endianss of the stream
@ -225,14 +226,14 @@ public:
* \return bool True for LittleEndian; False for BigEndian
*/
bool isLittleEndian() const;
protected:
Uint32 m_bitPosition; //!< The current position in the current byte
Uint64 m_position; //!< The current position in the Stream
protected:
Uint32 m_bitPosition; //!< The current position in the current byte
Uint64 m_position; //!< The current position in the Stream
Uint64 m_length; //!< The length of the Stream
Endian m_endian; //!< The Endianess of the Stream
Uint8* m_data; //!< The Stream buffer
bool m_autoResize; //!< Whether the stream is autoresizing
};
#endif // __STREAM_HPP__
Endian m_endian; //!< The Endianess of the Stream
Uint8* m_data; //!< The Stream buffer
bool m_autoResize; //!< Whether the stream is autoresizing
};
#endif // __STREAM_HPP__

View File

@ -1319,7 +1319,7 @@ MAKEINDEX_CMD_NAME = makeindex
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
COMPACT_LATEX = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and

View File

@ -28,3 +28,6 @@ SOURCES += \
src/BinaryWriter.cpp \
src/BinaryReader.cpp
system("exec doxygen libzelda.conf")
system("cd doc/latex && make")
system("cd ../../")

View File

@ -13,43 +13,43 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "BinaryReader.hpp"
#include "IOException.hpp"
#include "FileNotFoundException.hpp"
#include "utility.hpp"
#include "utf8.h"
#include <stdio.h>
#include <stdlib.h>
#include "BinaryReader.hpp"
#include "IOException.hpp"
#include "FileNotFoundException.hpp"
#include "utility.hpp"
#include "utf8.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
BinaryReader::BinaryReader(const Stream& stream) :
Stream(stream)
{
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const Uint8* data, Uint64 length) :
Stream(data, length)
{
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const std::string& filename)
: m_filename(filename)
#include <iostream>
BinaryReader::BinaryReader(const Stream& stream) :
Stream(stream)
{
Stream::setAutoResizing(false);
FILE* in;
int length;
in = fopen(filename.c_str(), "rb");
if (!in)
throw FileNotFoundException(filename);
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const Uint8* data, Uint64 length) :
Stream(data, length)
{
Stream::setAutoResizing(false);
}
BinaryReader::BinaryReader(const std::string& filename)
: m_filename(filename)
{
Stream::setAutoResizing(false);
FILE* in;
int length;
in = fopen(filename.c_str(), "rb");
if (!in)
throw FileNotFoundException(filename);
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
m_data = new Uint8[length];
Uint32 done = 0;
@ -68,203 +68,203 @@ BinaryReader::BinaryReader(const std::string& filename)
done += blocksize;
std::cout << "Read " << done << " bytes" << std::endl;
}while (done < m_length);
fclose(in);
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
void BinaryReader::writeByte(Int8)
{
throw IOException("BinaryReader::writeByte() -> Stream not open for writing");
}
void BinaryReader::writeBytes(Int8*, Int64)
{
throw IOException("BinaryReader::writeBytes() -> Stream not open for writing");
}
Int16 BinaryReader::readInt16()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length)
throw IOException("BinaryReader::readInt16() -> Position outside stream bounds");
Int16 ret = *(Int16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap16(ret);
return ret;
}
Uint16 BinaryReader::readUInt16()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint16) > m_length)
throw IOException("BinaryReader::readUint16() -> Position outside stream bounds");
Uint16 ret = *(Uint16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapU16(ret);
return ret;
}
Int32 BinaryReader::readInt32()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length)
throw IOException("BinaryReader::readUint32() -> Position outside stream bounds");
Int32 ret = *(Int32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap32(ret);
return ret;
}
Uint32 BinaryReader::readUInt32()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint32) > m_length)
throw IOException("BinaryReader::readUint32() -> Position outside stream bounds");
Uint32 ret = *(Uint32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapU32(ret);
return ret;
}
Int64 BinaryReader::readInt64()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length)
throw IOException("BinaryReader::readInt64() -> Position outside stream bounds");
Int64 ret = *(Int64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap64(ret);
return ret;
}
Uint64 BinaryReader::readUInt64()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length)
throw IOException("BinaryReader::readUInt64() -> Position outside stream bounds");
Uint64 ret = *(Uint64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap64(ret);
return ret;
}
float BinaryReader::readFloat()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length)
throw IOException("BinaryReader::readFloat() -> Position outside stream bounds");
float ret = *(float*)(m_data + m_position);
}while (done < length);
fclose(in);
m_length = length;
m_position = 0;
m_bitPosition = 0;
}
void BinaryReader::writeByte(Int8)
{
throw IOException("BinaryReader::writeByte() -> Stream not open for writing");
}
void BinaryReader::writeBytes(Int8*, Int64)
{
throw IOException("BinaryReader::writeBytes() -> Stream not open for writing");
}
Int16 BinaryReader::readInt16()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int16) > m_length)
throw IOException("BinaryReader::readInt16() -> Position outside stream bounds");
Int16 ret = *(Int16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap16(ret);
return ret;
}
Uint16 BinaryReader::readUInt16()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint16) > m_length)
throw IOException("BinaryReader::readUint16() -> Position outside stream bounds");
Uint16 ret = *(Uint16*)(m_data + m_position);
m_position += 2;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapU16(ret);
return ret;
}
Int32 BinaryReader::readInt32()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int32) > m_length)
throw IOException("BinaryReader::readUint32() -> Position outside stream bounds");
Int32 ret = *(Int32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapFloat(ret);
return ret;
}
double BinaryReader::readDouble()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length)
throw IOException("BinaryReader::readDouble() -> Position outside stream bounds");
double ret = *(double*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapDouble(ret);
return ret;
}
bool BinaryReader::readBool()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length)
throw IOException("BinaryReader::readBool() -> Position outside stream bounds");
bool ret = *(bool*)(m_data + m_position);
m_position += 1;
return ret;
}
std::string BinaryReader::readUnicode()
{
std::string ret;
std::vector<short> tmp;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap32(ret);
return ret;
}
Uint32 BinaryReader::readUInt32()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint32) > m_length)
throw IOException("BinaryReader::readUint32() -> Position outside stream bounds");
Uint32 ret = *(Uint32*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapU32(ret);
return ret;
}
Int64 BinaryReader::readInt64()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Int64) > m_length)
throw IOException("BinaryReader::readInt64() -> Position outside stream bounds");
Int64 ret = *(Int64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap64(ret);
return ret;
}
Uint64 BinaryReader::readUInt64()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(Uint64) > m_length)
throw IOException("BinaryReader::readUInt64() -> Position outside stream bounds");
Uint64 ret = *(Uint64*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swap64(ret);
return ret;
}
float BinaryReader::readFloat()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(float) > m_length)
throw IOException("BinaryReader::readFloat() -> Position outside stream bounds");
float ret = *(float*)(m_data + m_position);
m_position += 4;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapFloat(ret);
return ret;
}
double BinaryReader::readDouble()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(double) > m_length)
throw IOException("BinaryReader::readDouble() -> Position outside stream bounds");
double ret = *(double*)(m_data + m_position);
m_position += 8;
if ((!isSystemBigEndian() && m_endian == Stream::BigEndian) || (isSystemBigEndian() && m_endian == Stream::LittleEndian))
ret = swapDouble(ret);
return ret;
}
bool BinaryReader::readBool()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + sizeof(bool) > m_length)
throw IOException("BinaryReader::readBool() -> Position outside stream bounds");
bool ret = *(bool*)(m_data + m_position);
m_position += 1;
return ret;
}
std::string BinaryReader::readUnicode()
{
std::string ret;
std::vector<short> tmp;
for(;;)
{
short chr = readUInt16();
if (chr)
tmp.push_back(chr);
else
break;
else
break;
};
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
return ret;
}
bool BinaryReader::isOpenForWriting()
{
return false;
}
utf8::utf16to8(tmp.begin(), tmp.end(), back_inserter(ret));
return ret;
}
bool BinaryReader::isOpenForWriting()
{
return false;
}

View File

@ -13,296 +13,296 @@
// You should have received a copy of the GNU General Public License
// along with libZelda. If not, see <http://www.gnu.org/licenses/>
#include "Stream.hpp"
#include "IOException.hpp"
#include "InvalidOperationException.hpp"
#include <string.h>
#include <sstream>
#include "Stream.hpp"
#include "IOException.hpp"
#include "InvalidOperationException.hpp"
#include <string.h>
#include <sstream>
const Uint32 Stream::BLOCKSZ = 512;
Stream::Stream() :
m_bitPosition(0),
m_position(0),
m_length(0),
m_endian(Stream::LittleEndian),
m_data(NULL),
m_autoResize(true)
{}
Stream::Stream(const Uint8* data, Uint64 length) :
m_bitPosition(0),
m_position(0),
m_endian(Stream::LittleEndian),
m_autoResize(true)
{
if (length <= 0)
throw InvalidOperationException("Length cannot be <= to 0");
m_length = length;
if (data)
m_data = (Uint8*)data;
else
{
m_data = new Uint8[m_length];
memset(m_data, 0, m_length);
}
}
Stream::Stream(Int64 length) :
m_bitPosition(0),
m_position(0),
m_length(length)
{
m_data = new Uint8[m_length];
memset(m_data, 0, m_length);
}
Stream::Stream(Stream* stream)
{
if (m_data)
delete[] m_data;
m_data = stream->m_data;
m_position = stream->m_position;
m_length = stream->m_length;
}
Stream::~Stream()
{
if (m_data)
delete[] m_data;
m_data = NULL;
m_position = 0;
m_length = 0;
m_endian = LittleEndian;
m_autoResize = false;
}
void Stream::writeBit(bool val)
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw IOException("Stream::writeBit() -> Position outside stream bounds");
*(Uint8*)(m_data + m_position) |= ((Uint32)val << m_bitPosition);
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
}
void Stream::writeByte(Int8 byte)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length && m_autoResize)
resize(m_position + 1);
else if (m_position > m_length)
throw IOException("Stream::writeByte() -> Position outside stream bounds");
*(Int8*)(m_data + m_position) = byte;
m_position++;
}
void Stream::writeBytes(Int8* data, Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (!data)
throw InvalidOperationException("BinaryWriter::writeBytes() -> data cannnot be NULL");
if (m_position + length > m_length && m_autoResize)
resize(m_position + length);
else if (m_position > m_length)
throw IOException("BinaryWriter::writeBytes() -> Position outside stream bounds");
memcpy((Int8*)(m_data + m_position), data, length);
m_position += length;
}
bool Stream::readBit()
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw IOException("BinaryWriter::WriteInt16() -> Position outside stream bounds");
Stream::Stream() :
m_bitPosition(0),
m_position(0),
m_length(0),
m_endian(Stream::LittleEndian),
m_data(NULL),
m_autoResize(true)
{}
bool ret = (*(Uint8*)(m_data + m_position) & (1 << m_bitPosition));
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
return ret;
}
Int8 Stream::readByte()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
throw IOException("Position passed stream bounds");
return *(Int8*)(m_data + m_position++);
}
Int8* Stream::readBytes(Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + length > m_length)
throw IOException("Position passed stream bounds: " + m_position);
Int8* ret = new Int8[length];
memcpy(ret, (const Int8*)(m_data + m_position), length);
m_position += length;
return ret;
}
void Stream::seek(Int64 position, SeekOrigin origin)
{
switch (origin)
{
case Beginning:
if ((position < 0 || (Uint32)position > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << position;
throw IOException("Stream::seek() Beginnning -> Position outside stream bounds: " + ss.str());
}
if ((Uint64)position > m_length)
this->resize(position);
m_position = position;
break;
case Current:
if (((m_position + position) < 0 || (m_position + position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << (m_position + position);
throw IOException("Stream::seek() Current -> Position outside stream bounds: " + ss.str());
}
else if ((m_position + position) > m_length)
this->resize(m_position + position);
m_position += position;
break;
case End:
if (((m_length - position < 0) || (m_length - position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << std::hex << "0x" << (m_length - position);
throw IOException("Stream::seek() End -> Position outside stream bounds " + ss.str());
}
else if ((m_length - position) > m_length)
this->resize(m_length - position);
m_position = m_length - position;
break;
}
}
void Stream::resize(Uint64 newSize)
{
if (newSize < m_length)
throw InvalidOperationException("Stream::Resize() -> New size cannot be less to the old size.");
// Allocate and copy new buffer
Uint8* newArray = new Uint8[newSize];
memset(newArray, 0, newSize);
memcpy(newArray, m_data, m_length);
// Delete the old one
delete[] m_data;
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
void Stream::setData(const Uint8* data, Uint64 length)
{
if (m_data)
delete[] m_data;
m_data = (Uint8*)data;
m_length = length;
m_position = 0;
}
Uint8* Stream::data() const
{
Uint8* ret = new Uint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
Int64 Stream::length()
{
return m_length;
}
Int64 Stream::position()
{
return m_position;
}
bool Stream::atEnd()
{
return m_position >= m_length;
}
void Stream::setAutoResizing(bool val)
{
m_autoResize = val;
}
bool Stream::autoResizing() const
{
return m_autoResize;
}
bool Stream::isOpenForReading() const
{
return true;
}
bool Stream::isOpenForWriting() const
{
return true;
}
void Stream::setEndianess(Endian endian)
{
m_endian = endian;
}
Stream::Endian Stream::endianness() const
{
return m_endian;
}
Stream::Stream(const Uint8* data, Uint64 length) :
m_bitPosition(0),
m_position(0),
m_endian(Stream::LittleEndian),
m_autoResize(true)
{
if (length <= 0)
throw InvalidOperationException("Length cannot be <= to 0");
m_length = length;
if (data)
m_data = (Uint8*)data;
else
{
m_data = new Uint8[m_length];
memset(m_data, 0, m_length);
}
}
Stream::Stream(Int64 length) :
m_bitPosition(0),
m_position(0),
m_length(length)
{
m_data = new Uint8[m_length];
memset(m_data, 0, m_length);
}
Stream::Stream(Stream* stream)
{
if (m_data)
delete[] m_data;
m_data = stream->m_data;
m_position = stream->m_position;
m_length = stream->m_length;
}
Stream::~Stream()
{
if (m_data)
delete[] m_data;
m_data = NULL;
m_position = 0;
m_length = 0;
m_endian = LittleEndian;
m_autoResize = false;
}
void Stream::writeBit(bool val)
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw IOException("Stream::writeBit() -> Position outside stream bounds");
*(Uint8*)(m_data + m_position) |= ((Uint32)val << m_bitPosition);
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
}
void Stream::writeByte(Int8 byte)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length && m_autoResize)
resize(m_position + 1);
else if (m_position > m_length)
throw IOException("Stream::writeByte() -> Position outside stream bounds");
*(Int8*)(m_data + m_position) = byte;
m_position++;
}
void Stream::writeBytes(Int8* data, Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (!data)
throw InvalidOperationException("BinaryWriter::writeBytes() -> data cannnot be NULL");
if (m_position + length > m_length && m_autoResize)
resize(m_position + length);
else if (m_position > m_length)
throw IOException("BinaryWriter::writeBytes() -> Position outside stream bounds");
memcpy((Int8*)(m_data + m_position), data, length);
m_position += length;
}
bool Stream::readBit()
{
if (m_position + sizeof(Uint8) > m_length && m_autoResize)
resize(m_position + sizeof(Uint8));
else if (m_position > m_length)
throw IOException("BinaryWriter::WriteInt16() -> Position outside stream bounds");
bool ret = (*(Uint8*)(m_data + m_position) & (1 << m_bitPosition));
m_bitPosition++;
if (m_bitPosition > 7)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
return ret;
}
Int8 Stream::readByte()
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + 1 > m_length)
throw IOException("Position passed stream bounds");
return *(Int8*)(m_data + m_position++);
}
Int8* Stream::readBytes(Int64 length)
{
if (m_bitPosition > 0)
{
m_bitPosition = 0;
m_position += sizeof(Uint8);
}
if (m_position + length > m_length)
throw IOException("Position passed stream bounds: " + m_position);
Int8* ret = new Int8[length];
memcpy(ret, (const Int8*)(m_data + m_position), length);
m_position += length;
return ret;
}
void Stream::seek(Int64 position, SeekOrigin origin)
{
switch (origin)
{
case Beginning:
if ((position < 0 || (Int64)position > (Int64)m_length) && !m_autoResize)
{
std::stringstream ss;
ss << position;
throw IOException("Stream::seek() Beginnning -> Position outside stream bounds: " + ss.str());
}
if ((Uint64)position > m_length)
this->resize(position);
m_position = position;
break;
case Current:
if ((((Int64)m_position + position) < 0 || (m_position + position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << (m_position + position);
throw IOException("Stream::seek() Current -> Position outside stream bounds: " + ss.str());
}
else if ((m_position + position) > m_length)
this->resize(m_position + position);
m_position += position;
break;
case End:
if ((((Int64)m_length - position < 0) || (m_length - position) > m_length) && !m_autoResize)
{
std::stringstream ss;
ss << std::hex << "0x" << (m_length - position);
throw IOException("Stream::seek() End -> Position outside stream bounds " + ss.str());
}
else if ((m_length - position) > m_length)
this->resize(m_length - position);
m_position = m_length - position;
break;
}
}
void Stream::resize(Uint64 newSize)
{
if (newSize < m_length)
throw InvalidOperationException("Stream::Resize() -> New size cannot be less to the old size.");
// Allocate and copy new buffer
Uint8* newArray = new Uint8[newSize];
memset(newArray, 0, newSize);
memcpy(newArray, m_data, m_length);
// Delete the old one
delete[] m_data;
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
void Stream::setData(const Uint8* data, Uint64 length)
{
if (m_data)
delete[] m_data;
m_data = (Uint8*)data;
m_length = length;
m_position = 0;
}
Uint8* Stream::data() const
{
Uint8* ret = new Uint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
Int64 Stream::length()
{
return m_length;
}
Int64 Stream::position()
{
return m_position;
}
bool Stream::atEnd()
{
return m_position >= m_length;
}
void Stream::setAutoResizing(bool val)
{
m_autoResize = val;
}
bool Stream::autoResizing() const
{
return m_autoResize;
}
bool Stream::isOpenForReading() const
{
return true;
}
bool Stream::isOpenForWriting() const
{
return true;
}
void Stream::setEndianess(Endian endian)
{
m_endian = endian;
}
Stream::Endian Stream::endianness() const
{
return m_endian;
}