diff --git a/include/BinaryReader.hpp b/include/BinaryReader.hpp index 2357c1c..5810351 100644 --- a/include/BinaryReader.hpp +++ b/include/BinaryReader.hpp @@ -52,6 +52,17 @@ public: */ BinaryReader(const std::string& filename); + /*! \brief Sets the target file + * + * \sa Endian + * \param filepath The path to write to. + */ + void setFilepath(const std::string& filepath); + + /*! \brief Returns the target file + * + */ + std::string filepath() const; /*! \brief Reads a Int16 and swaps to proper endianness depending on platform * and Stream settings, and advances the current position diff --git a/include/BinaryWriter.hpp b/include/BinaryWriter.hpp index 8531a32..3ecdfac 100644 --- a/include/BinaryWriter.hpp +++ b/include/BinaryWriter.hpp @@ -47,12 +47,25 @@ public: * \param stream The stream to write data to */ BinaryWriter(const Stream& stream); + /*! \brief This constructor creates an instance from a file on disk. * * \param filename The file to create the stream from */ BinaryWriter(const std::string& filename); + /*! \brief Sets the target file + * + * \sa Endian + * \param filepath The path to write to. + */ + void setFilepath(const std::string& filepath); + + /*! \brief Returns the target file + * + */ + std::string filepath() const; + /*! \brief Saves the file to the specified file. * * \param filename If not empty, the filename to save to @@ -145,6 +158,7 @@ public: * \param str The string to write to the buffer */ void writeString(const std::string& str); + protected: Int8 readByte(); Int8* readBytes(Int64); diff --git a/include/Stream.hpp b/include/Stream.hpp index 38ad3a8..2d6e36e 100644 --- a/include/Stream.hpp +++ b/include/Stream.hpp @@ -176,19 +176,19 @@ public: * * \return Int64 The length of the stream. */ - Int64 length(); + Int64 length() const; /*! \brief Returns the current position in the stream. * * \return Int64 The current position in the stream. */ - Int64 position(); + Int64 position() const; /*! \brief Returns whether or not the stream is at the end. * * \return bool True if at end; False otherwise. */ - bool atEnd(); + bool atEnd() const; /*! \brief Sets whether the Stream resizes when the at the end of the buffer. * diff --git a/include/TextStream.hpp b/include/TextStream.hpp index 80386c4..094302f 100644 --- a/include/TextStream.hpp +++ b/include/TextStream.hpp @@ -40,11 +40,11 @@ public: */ enum TextMode { - Open, //!< The file is opened if it exists. - Create, //!< Create the file if it does not exist. + Open = 0x01, //!< The file is opened if it exists. + Create = 0x02, //!< Create the file if it does not exist. OpenOrCreate = Open|Create, //!< If the file does not exist when opening the file it is created - Truncate, //!< All the data currently that is in the file is erased. - Append //!< After opening the file the current line is set to the end of the buffer + Truncate = 0x04, //!< All the data currently that is in the file is erased. + Append = 0x08 //!< After opening the file the current line is set to the end of the buffer }; /*! \enum AccessMode @@ -57,8 +57,9 @@ public: ReadWrite //!< The Stream can be read from or written to. }; + TextStream(); /*! \brief This constructor opens the file and loads all the lines. */ - TextStream(const std::string& filename, TextMode fileMode = Open, AccessMode accessMode = ReadWrite); + TextStream(const std::string& filename, Uint32 fileMode = Open, AccessMode accessMode = ReadWrite); /*! \brief Creates a new buffer and saves all lines to the specified file. * \param filename The file, including path to save to. @@ -144,14 +145,20 @@ public: * * \return TextMode The mode to set. */ - TextMode textMode() const; + Uint32 textMode() const; + + + /*! \brief Empties the stream. + * + */ + void truncate(); bool isOpenForReading() const; bool isOpenForWriting() const; private: void loadLines(); std::string m_filename; - TextMode m_textmode; + Uint32 m_textmode; AccessMode m_accessmode; std::vector m_lines; diff --git a/include/utility.hpp b/include/utility.hpp index 95a8a51..1e38cba 100644 --- a/include/utility.hpp +++ b/include/utility.hpp @@ -17,6 +17,7 @@ #define __UTILITY_H__ #include +#include #include "Types.hpp" namespace zelda @@ -27,9 +28,9 @@ namespace utility bool isEmpty(Int8*, Uint32); Uint16 swapU16(Uint16 val ); -Int16 swap16 (Int16 val ); -Uint32 swapU32(Uint32 val); -Int32 swap32 (Int32 val ); +Int16 swap16 (Int16 val ); +Uint32 swapU32(Uint32 val); +Int32 swap32 (Int32 val ); Uint64 swapU64(Uint64 val); Int64 swap64 (Int64 val); @@ -40,6 +41,14 @@ bool isSystemBigEndian(); void fillRandom(Uint8 * rndArea, Uint8 count); +std::vector split(const std::string &s, char delim); +void tolower(std::string& str); +void toupper(std::string& str); +std::string sprintf(const char* fmt, ...); +bool parseBool(const std::string& boolean, bool &valid); + +int countChar(const std::string& str, const char chr, int& lastOccur); + } // utility } // zelda diff --git a/libzelda.pro b/libzelda.pro index a63375c..a789bae 100644 --- a/libzelda.pro +++ b/libzelda.pro @@ -1,6 +1,6 @@ CONFIG += staticlib TEMPLATE=lib -DESTDIR = ./ +DESTDIR = ./lib CONFIG(debug, debug|release){ DEFINES += DEBUG @@ -9,7 +9,7 @@ CONFIG(debug, debug|release){ CONFIG(release, release|debug){ DEFINES -= DEBUG - TARGET=zelda + unix:TARGET=zelda } QMAKE_CXXFLAGS += -std=c++0x diff --git a/libzelda_wii.cbp b/libzelda_wii.cbp new file mode 100644 index 0000000..b92fa23 --- /dev/null +++ b/libzelda_wii.cbp @@ -0,0 +1,146 @@ + + + + + + diff --git a/src/BinaryReader.cpp b/src/BinaryReader.cpp index c49e2f0..6b08300 100644 --- a/src/BinaryReader.cpp +++ b/src/BinaryReader.cpp @@ -24,6 +24,10 @@ #include #include +#ifdef HW_RVL +#include +#endif // HW_RVL + namespace zelda { namespace io @@ -55,7 +59,11 @@ BinaryReader::BinaryReader(const std::string& filename) fseek(in, 0, SEEK_END); length = ftell(in); fseek(in, 0, SEEK_SET); +#ifdef HW_RVL + m_data = (Uint8*)memalign(32, length); +#else m_data = new Uint8[length]; +#endif Uint32 done = 0; Uint32 blocksize = BLOCKSZ; @@ -101,7 +109,7 @@ Int16 BinaryReader::readInt16() if (m_position + sizeof(Int16) > m_length) throw error::IOException("BinaryReader::readInt16 -> Position outside stream bounds"); Int16 ret = *(Int16*)(m_data + m_position); - m_position += 2; + m_position += sizeof(Int16); if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian)) ret = utility::swap16(ret); @@ -118,7 +126,7 @@ Uint16 BinaryReader::readUInt16() if (m_position + sizeof(Uint16) > m_length) throw error::IOException("BinaryReader::readUint16 -> Position outside stream bounds"); Uint16 ret = *(Uint16*)(m_data + m_position); - m_position += 2; + m_position += sizeof(Uint16); if ((!utility::isSystemBigEndian() && m_endian == BigEndian) || (utility::isSystemBigEndian() && m_endian == LittleEndian)) ret = utility::swapU16(ret); diff --git a/src/BinaryWriter.cpp b/src/BinaryWriter.cpp index 7907f71..ab16c9e 100644 --- a/src/BinaryWriter.cpp +++ b/src/BinaryWriter.cpp @@ -25,6 +25,10 @@ #include #include +#ifdef HW_RVL +#include +#endif // HW_RVL + namespace zelda { namespace io @@ -44,12 +48,27 @@ BinaryWriter::BinaryWriter(const std::string& filename) m_length = 0x10; m_bitPosition = 0; m_position = 0; +#ifdef HW_RVL + m_data = (Uint8*)memalign(32, m_length); +#else m_data = new Uint8[m_length]; +#endif + if (!m_data) throw error::IOException("BinaryWriter::BinaryWriter -> Could not allocate memory!"); memset(m_data, 0, m_length); } +void BinaryWriter::setFilepath(const std::string& filepath) +{ + m_filepath = filepath; +} + +std::string BinaryWriter::filepath() const +{ + return m_filepath; +} + void BinaryWriter::save(const std::string& filename) { if (filename.empty() && m_filepath.empty()) diff --git a/src/Stream.cpp b/src/Stream.cpp index decdae5..4bca8e6 100644 --- a/src/Stream.cpp +++ b/src/Stream.cpp @@ -19,6 +19,10 @@ #include #include +#ifdef HW_RVL +#include +#endif // HW_RVL + namespace zelda { namespace io @@ -49,7 +53,12 @@ Stream::Stream(const Uint8* data, Uint64 length) : m_data = (Uint8*)data; else { +#ifdef HW_RVL + m_data = (Uint8*)memalign(32, m_length); +#else m_data = new Uint8[m_length]; +#endif + memset(m_data, 0, m_length); } } @@ -59,7 +68,11 @@ Stream::Stream(Int64 length) : m_position(0), m_length(length) { +#ifdef HW_RVL + m_data = (Uint8*)memalign(32, m_length); +#else m_data = new Uint8[m_length]; +#endif memset(m_data, 0, m_length); } @@ -68,6 +81,7 @@ Stream::Stream(Stream* stream) if (m_data) delete[] m_data; + m_data = NULL; m_data = stream->m_data; m_position = stream->m_position; m_length = stream->m_length; @@ -76,7 +90,11 @@ Stream::Stream(Stream* stream) Stream::~Stream() { if (m_data) +#ifdef HW_RVL + free(m_data); +#else delete[] m_data; +#endif m_data = NULL; m_position = 0; @@ -196,7 +214,13 @@ Int8* Stream::readBytes(Int64 length) if (m_position + length > m_length) throw error::IOException("Stream::readBytes -> Position passed stream bounds: " + m_position); - Int8* ret = new Int8[length]; + Int8* ret; +#ifdef HW_RVL + ret = (Int8*)memalign(32, length); +#else + ret = new Int8[length]; +#endif + memcpy(ret, (const Int8*)(m_data + m_position), length); m_position += length; return ret; @@ -250,13 +274,22 @@ void Stream::resize(Uint64 newSize) throw error::InvalidOperationException("Stream::resize() -> New size cannot be less to the old size."); // Allocate and copy new buffer - Uint8* newArray = new Uint8[newSize]; +#ifdef HW_RVL + Uint8* newArray = (Uint8*)memalign(32, newSize); +#else + Uint8* newArray = new Uint8[newSize]; +#endif + memset(newArray, 0, newSize); memcpy(newArray, m_data, m_length); // Delete the old one - delete[] m_data; +#ifdef HW_RVL + free(m_data); +#else + delete[] m_data; +#endif // Swap the pointer and size out for the new ones. m_data = newArray; @@ -266,7 +299,11 @@ void Stream::resize(Uint64 newSize) void Stream::setData(const Uint8* data, Uint64 length) { if (m_data) +#ifdef HW_RVL + free(m_data); +#else delete[] m_data; +#endif m_data = (Uint8*)data; m_length = length; @@ -281,17 +318,17 @@ Uint8* Stream::data() const return ret; } -Int64 Stream::length() +Int64 Stream::length() const { return m_length; } -Int64 Stream::position() +Int64 Stream::position() const { return m_position; } -bool Stream::atEnd() +bool Stream::atEnd() const { return m_position >= m_length; } diff --git a/src/TextStream.cpp b/src/TextStream.cpp index 1db2aca..94f1b9d 100644 --- a/src/TextStream.cpp +++ b/src/TextStream.cpp @@ -23,7 +23,7 @@ namespace zelda { namespace io { -TextStream::TextStream(const std::string& filename, TextMode fileMode, AccessMode accessMode) : +TextStream::TextStream(const std::string& filename, Uint32 fileMode, AccessMode accessMode) : m_filename(filename), m_textmode(fileMode), m_accessmode(accessMode), @@ -69,6 +69,10 @@ TextStream::TextStream(const std::string& filename, TextMode fileMode, AccessMod loadLines(); } +TextStream::TextStream() + : Stream() +{} + void TextStream::save(const std::string& filename) { if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) @@ -78,7 +82,10 @@ void TextStream::save(const std::string& filename) // We need a new buffer to write the new lines if (m_data) + { delete[] m_data; + m_data = NULL; + } m_position = 0; m_length = 1; @@ -90,6 +97,8 @@ void TextStream::save(const std::string& filename) for (std::string s : m_lines) writeBytes((Int8*)s.c_str(), s.size()); + writeByte('\n'); + FILE* out = fopen(m_filename.c_str(), "wb"); if(out) @@ -117,14 +126,14 @@ void TextStream::writeLine(const std::string& str) { if (m_accessmode != WriteOnly && m_accessmode != ReadWrite) throw error::InvalidOperationException("TextStream::writeLine -> Stream not open for writing"); - else if (m_currentLine > m_lines.size()) + else if (m_currentLine >= m_lines.size()) { - m_lines.push_back(str); + m_lines.push_back(str + "\n"); m_currentLine++; return; } - m_lines[m_currentLine++] = str; + m_lines[m_currentLine++] = str + "\n"; } void TextStream::writeLines(std::vector strings) @@ -211,11 +220,16 @@ void TextStream::setTextMode(TextMode mode) m_textmode = mode; } -TextStream::TextMode TextStream::textMode() const +Uint32 TextStream::textMode() const { return m_textmode; } +void TextStream::truncate() +{ + m_lines.clear(); +} + bool TextStream::isOpenForReading() const { return ((m_accessmode == ReadOnly || m_accessmode == ReadWrite) && m_accessmode != WriteOnly); @@ -229,35 +243,43 @@ bool TextStream::isOpenForWriting() const // PRIVATE FUNCTIONS void TextStream::loadLines() { - while (!atEnd()) + try { - std::string line; - Uint8 c; - for (;;) - { - c = readByte(); - if (c == '\r' || c == '\n') + while (!atEnd()) + { + std::string line; + Uint8 c; + for (;;) { - m_currentLine++; - line.push_back(c); - if (*(Uint8*)(m_data + m_position + 1) == '\n') + c = readByte(); + + if (c == '\r' || c == '\n') + { + m_currentLine++; + line.push_back(c); + if (*(Uint8*)(m_data + m_position + 1) == '\n') + { + line.push_back('\n'); + m_position++; // advance position past the new line character + } + break; + } + + if (c == '\0') { line.push_back('\n'); - m_position++; // advance position past the new line character + break; } - break; + line.push_back(c); } - if (c == '\0') - { - line.push_back('\n'); - break; - } - line.push_back(c); + m_lines.push_back(line); } - - m_lines.push_back(line); + } + catch(...) + { + // The stream MAY throw an out of range error but we're not concerned with it } } diff --git a/src/utility.cpp b/src/utility.cpp index 3f172a7..d0d3362 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include namespace zelda { @@ -111,5 +114,96 @@ double swapDouble(double val) return (double)((Uint64)retVal); } + +std::vector &split(const std::string &s, char delim, std::vector &elems) +{ + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + elems.push_back(item); + return elems; +} + + +std::vector split(const std::string &s, char delim) +{ + std::vector elems; + split(s, delim, elems); + return elems; +} + +void tolower(std::string& str) +{ + std::transform(str.begin(), str.end(), str.begin(), ::tolower); +} + +void toupper(std::string& str) +{ + std::transform(str.begin(), str.end(), str.begin(), ::toupper); +} + +std::string sprintf(const char* fmt, ...) +{ + int size = 512; + char* buffer = 0; + buffer = new char[size]; + va_list vl; + va_start(vl, fmt); + int nsize = vsnprintf(buffer, size, fmt, vl); + if(size<=nsize) + { //fail delete buffer and try again + delete[] buffer; + buffer = 0; + buffer = new char[nsize+1]; //+1 for /0 + nsize = vsnprintf(buffer, size, fmt, vl); + } + std::string ret(buffer); + va_end(vl); + delete[] buffer; + return ret; +} + +bool parseBool(const std::string& boolean, bool &valid) +{ + std::string val = boolean; + // compare must be case insensitive + // This is the cleanest solution since I only need to do it once + std::transform(val.begin(), val.end(), val.begin(), ::tolower); + + // Check for true first + if (!val.compare("true") || !val.compare("1") || !val.compare("yes")) + return (valid = true); + + // Now false + if (!val.compare("false") || !val.compare("0") || !val.compare("no")) + { + valid = true; + return false; + } + + // Well that could've gone better + + return (valid = false); +} + +int countChar(const std::string &str, const char chr, int &lastOccur) +{ + int ret = 0; + + int index = 0; + for (char c : str) + { + if (c == chr) + { + lastOccur = index; + ret++; + } + index++; + } + + return ret; +} + + } // utility } // zelda