made stream classes STL-customizable with a traits class

This commit is contained in:
Jack Andersen 2015-08-24 17:42:24 -10:00
parent 92898661cc
commit fe1a489820
19 changed files with 1705 additions and 1783 deletions

View File

@ -32,10 +32,6 @@ endif()
add_library(AthenaCore add_library(AthenaCore
src/Athena/Utility.cpp src/Athena/Utility.cpp
src/Athena/FileReader.cpp
src/Athena/FileWriter.cpp
src/Athena/MemoryReader.cpp
src/Athena/MemoryWriter.cpp
src/Athena/Global.cpp src/Athena/Global.cpp
src/Athena/Checksums.cpp src/Athena/Checksums.cpp
src/Athena/Compression.cpp src/Athena/Compression.cpp

View File

@ -563,9 +563,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
for (int p=0 ; p<2 ; ++p) for (int p=0 ; p<2 ; ++p)
{ {
if (p) if (p)
fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::io::IStreamWriter& " ATHENA_DNA_WRITER ") const\n{\n"; fileOut << "void " << decl->getQualifiedNameAsString() << "::write(IStreamWriter& " ATHENA_DNA_WRITER ") const\n{\n";
else else
fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::io::IStreamReader& " ATHENA_DNA_READER ")\n{\n"; fileOut << "void " << decl->getQualifiedNameAsString() << "::read(IStreamReader& " ATHENA_DNA_READER ")\n{\n";
if (baseDNA.size()) if (baseDNA.size())
{ {
@ -1338,9 +1338,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
for (int p=0 ; p<2 ; ++p) for (int p=0 ; p<2 ; ++p)
{ {
if (p) if (p)
fileOut << "void " << decl->getQualifiedNameAsString() << "::toYAML(Athena::io::YAMLDocWriter& " ATHENA_YAML_WRITER ") const\n{\n"; fileOut << "void " << decl->getQualifiedNameAsString() << "::toYAML(YAMLDocWriter& " ATHENA_YAML_WRITER ") const\n{\n";
else else
fileOut << "void " << decl->getQualifiedNameAsString() << "::fromYAML(Athena::io::YAMLDocReader& " ATHENA_YAML_READER ")\n{\n"; fileOut << "void " << decl->getQualifiedNameAsString() << "::fromYAML(YAMLDocReader& " ATHENA_YAML_READER ")\n{\n";
if (baseDNA.size()) if (baseDNA.size())
{ {

View File

@ -20,16 +20,16 @@ namespace io
/* forward-declaration dance for recursively-derived types */ /* forward-declaration dance for recursively-derived types */
template <size_t sizeVar, Endian VE> template <size_t sizeVar, Endian VE, typename STLTRAITS>
struct Buffer; struct Buffer;
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct String; struct String;
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct WString; struct WString;
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct WStringAsString; struct WStringAsString;
/** /**
@ -40,9 +40,17 @@ struct WStringAsString;
* with all read/write calls necessary to marshal the DNA structure to/from * with all read/write calls necessary to marshal the DNA structure to/from
* a streamed medium * a streamed medium
*/ */
template <Endian DNAE> template <Endian DNAE, typename STLTRAITS = StlTraits>
struct DNA struct DNA
{ {
using IStreamReader = IStreamReader<STLTRAITS>;
using IStreamWriter = IStreamWriter<STLTRAITS>;
using StlTraits = STLTRAITS;
using StlString = typename STLTRAITS::String;
using StlWString = typename STLTRAITS::WString;
template<typename T> using StlVector = typename STLTRAITS::template Vector<T>;
virtual void read(IStreamReader&)=0; virtual void read(IStreamReader&)=0;
virtual void write(IStreamWriter&) const=0; virtual void write(IStreamWriter&) const=0;
@ -50,19 +58,19 @@ struct DNA
using Value = T; using Value = T;
template <typename T, size_t cntVar, Endian VE = DNAE> template <typename T, size_t cntVar, Endian VE = DNAE>
using Vector = std::vector<T>; using Vector = typename STLTRAITS::template Vector<T>;
template <size_t sizeVar> template <size_t sizeVar>
using Buffer = struct Athena::io::Buffer<sizeVar, DNAE>; using Buffer = struct Athena::io::Buffer<sizeVar, DNAE, STLTRAITS>;
template <atInt32 sizeVar = -1> template <atInt32 sizeVar = -1>
using String = struct Athena::io::String<sizeVar, DNAE>; using String = struct Athena::io::String<sizeVar, DNAE, STLTRAITS>;
template <atInt32 sizeVar = -1, Endian VE = DNAE> template <atInt32 sizeVar = -1, Endian VE = DNAE>
using WString = struct Athena::io::WString<sizeVar, VE>; using WString = struct Athena::io::WString<sizeVar, VE, STLTRAITS>;
template <atInt32 sizeVar = -1> template <atInt32 sizeVar = -1>
using WStringAsString = struct Athena::io::WStringAsString<sizeVar, DNAE>; using WStringAsString = struct Athena::io::WStringAsString<sizeVar, DNAE, STLTRAITS>;
template <off_t offset, SeekOrigin direction> template <off_t offset, SeekOrigin direction>
struct Seek {}; struct Seek {};
@ -73,78 +81,78 @@ struct DNA
struct Delete {}; struct Delete {};
}; };
template <size_t sizeVar, Endian VE> template <size_t sizeVar, Endian VE, typename STLTRAITS>
struct Buffer : public DNA<VE>, public std::unique_ptr<atUint8[]> struct Buffer : public DNA<VE, STLTRAITS>, public std::unique_ptr<atUint8[]>
{ {
typename DNA<VE>::Delete expl; typename DNA<VE>::Delete expl;
inline void read(IStreamReader& reader) inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
{ {
reset(new atUint8[sizeVar]); reset(new atUint8[sizeVar]);
reader.readUBytesToBuf(get(), sizeVar); reader.readUBytesToBuf(get(), sizeVar);
} }
inline void write(IStreamWriter& writer) const inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
{ {
writer.writeUBytes(get(), sizeVar); writer.writeUBytes(get(), sizeVar);
} }
}; };
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct String : public DNA<VE>, public std::string struct String : public DNA<VE, STLTRAITS>, public STLTRAITS::String
{ {
typename DNA<VE>::Delete expl; typename DNA<VE>::Delete expl;
inline void read(IStreamReader& reader) inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
{this->assign(std::move(reader.readString(sizeVar)));} {this->assign(std::move(reader.readString(sizeVar)));}
inline void write(IStreamWriter& writer) const inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
{writer.writeString(*this, sizeVar);} {writer.writeString(*this, sizeVar);}
inline std::string& operator=(const std::string& __str) inline typename STLTRAITS::String& operator=(const typename STLTRAITS::String& __str)
{return this->assign(__str);} {return this->assign(__str);}
inline std::string& operator=(std::string&& __str) inline typename STLTRAITS::String& operator=(typename STLTRAITS::String&& __str)
{this->swap(__str); return *this;} {this->swap(__str); return *this;}
}; };
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct WString : public DNA<VE>, public std::wstring struct WString : public DNA<VE, STLTRAITS>, public STLTRAITS::WString
{ {
typename DNA<VE>::Delete expl; typename DNA<VE>::Delete expl;
inline void read(IStreamReader& reader) inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
{ {
reader.setEndian(VE); reader.setEndian(VE);
this->assign(std::move(reader.readWString(sizeVar))); this->assign(std::move(reader.readWString(sizeVar)));
} }
inline void write(IStreamWriter& writer) const inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
{ {
writer.setEndian(VE); writer.setEndian(VE);
writer.writeWString(*this, sizeVar); writer.writeWString(*this, sizeVar);
} }
inline std::wstring& operator=(const std::wstring& __str) inline typename STLTRAITS::WString& operator=(const typename STLTRAITS::WString& __str)
{return this->assign(__str);} {return this->assign(__str);}
inline std::wstring& operator=(std::wstring&& __str) inline typename STLTRAITS::WString& operator=(typename STLTRAITS::WString&& __str)
{this->swap(__str); return *this;} {this->swap(__str); return *this;}
}; };
template <atInt32 sizeVar, Endian VE> template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
struct WStringAsString : public DNA<VE>, public std::string struct WStringAsString : public DNA<VE, STLTRAITS>, public STLTRAITS::String
{ {
typename DNA<VE>::Delete expl; typename DNA<VE>::Delete expl;
inline void read(IStreamReader& reader) inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
{*this = reader.readWStringAsString(sizeVar);} {*this = reader.readWStringAsString(sizeVar);}
inline void write(IStreamWriter& writer) const inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
{writer.writeStringAsWString(*this, sizeVar);} {writer.writeStringAsWString(*this, sizeVar);}
inline std::string& operator=(const std::string& __str) inline typename STLTRAITS::String& operator=(const typename STLTRAITS::String& __str)
{return this->assign(__str);} {return this->assign(__str);}
inline std::string& operator=(std::string&& __str) inline typename STLTRAITS::String& operator=(typename STLTRAITS::String&& __str)
{this->swap(__str); return *this;} {this->swap(__str); return *this;}
}; };
/** Macro to automatically declare read/write methods in subclasses */ /** Macro to automatically declare read/write methods in subclasses */
#define DECL_DNA \ #define DECL_DNA \
void read(Athena::io::IStreamReader&); \ void read(IStreamReader&); \
void write(Athena::io::IStreamWriter&) const; \ void write(IStreamWriter&) const; \
/** Macro to automatically declare read/write methods and prevent outputting implementation */ /** Macro to automatically declare read/write methods and prevent outputting implementation */
#define DECL_EXPLICIT_DNA \ #define DECL_EXPLICIT_DNA \
void read(Athena::io::IStreamReader&); \ void read(IStreamReader&); \
void write(Athena::io::IStreamWriter&) const; \ void write(IStreamWriter&) const; \
Delete __dna_delete; Delete __dna_delete;
/** Macro to supply count variable to atdna and mute it for other compilers */ /** Macro to supply count variable to atdna and mute it for other compilers */

File diff suppressed because it is too large Load Diff

View File

@ -6,36 +6,210 @@
#include <stdio.h> #include <stdio.h>
#include "Athena/IStreamReader.hpp" #include "Athena/IStreamReader.hpp"
#if _WIN32
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h"
#endif
namespace Athena namespace Athena
{ {
namespace io namespace io
{ {
class FileReader : public IStreamReader template<typename STLTRAITS = StlTraits>
class FileReader : public IStreamReader<STLTRAITS>
{ {
public: public:
FileReader(const std::string& filename, atInt32 cacheSize = (32 * 1024)); inline const typename STLTRAITS::String& filename() const
#if _WIN32
FileReader(const std::wstring& filename, atInt32 cacheSize = (32 * 1024));
#endif
virtual ~FileReader();
inline const std::string& filename() const
{return m_filename;} {return m_filename;}
void open(); FileReader(const typename STLTRAITS::String& filename, atInt32 cacheSize = (32 * 1024))
void close(); : m_filename(filename),
inline bool isOpen() const m_fileHandle(nullptr),
{return m_fileHandle != NULL;} m_cacheData(nullptr),
bool save(); m_offset(0)
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); {
atUint64 position() const; open();
atUint64 length() const; setCacheSize(cacheSize);
atUint64 readUBytesToBuf(void* buf, atUint64 len); }
#if _WIN32
FileReader::FileReader(const typename STLTRAITS::WString& filename, atInt32 cacheSize = (32 * 1024))
: m_wfilename(filename),
m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0)
{
open();
setCacheSize(cacheSize);
}
#endif
virtual ~FileReader()
{
if (isOpen())
close();
}
void open()
{
#if _WIN32
if (m_wfilename.size())
m_fileHandle = _wfopen(m_wfilename.c_str(), L"rb");
else
m_fileHandle = fopen(m_filename.c_str(), "rb");
#else
m_fileHandle = fopen(m_filename.c_str(), "rb");
#endif
if (!m_fileHandle)
{
atError("File not found '%s'", m_filename.c_str());
IStream::setError();
return;
}
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void close()
{
if (!m_fileHandle)
{
atError("Cannot close an unopened stream");
IStream::setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
inline bool isOpen() const {return m_fileHandle != NULL;}
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)
{
// check block position
if (m_blockSize > 0)
{
atUint64 oldOff = m_offset;
switch(origin)
{
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length())
{
oldOff = m_offset;
atError("Unable to seek in file");
return;
}
size_t block = m_offset / m_blockSize;
if (block != m_curBlock)
{
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
}
else if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
atError("Unable to seek in file");
}
atUint64 position() const
{
if (!isOpen())
{
atError("File not open");
return 0;
}
if (m_blockSize > 0)
return m_offset;
else
return ftello64(m_fileHandle);
}
atUint64 length() const
{
if (!isOpen())
{
atError("File not open");
return 0;
}
return utility::fileSize(m_filename);
}
atUint64 readUBytesToBuf(void* buf, atUint64 len)
{
if (!isOpen())
{
atError("File not open for reading");
IStream::setError();
return 0;
}
if (m_blockSize <= 0)
return fread(buf, 1, len, m_fileHandle);
else
{
size_t block = m_offset / m_blockSize;
atUint64 cacheOffset = m_offset % m_blockSize;
atUint64 cacheSize;
atUint64 rem = len;
atUint8* dst = (atUint8*)buf;
while (rem)
{
if (block != m_curBlock)
{
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memcpy(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
}
m_offset += len;
return dst - (atUint8*)buf;
}
}
void setCacheSize(const atInt32 blockSize)
{
m_blockSize = blockSize;
if (m_blockSize > length())
m_blockSize = (atInt32)length();
m_curBlock = -1;
if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]);
}
void setCacheSize(const atInt32 blockSize);
protected: protected:
std::string m_filename; typename STLTRAITS::String m_filename;
#if _WIN32 #if _WIN32
std::wstring m_wfilename; typename STLTRAITS::WString m_wfilename;
#endif #endif
FILE* m_fileHandle; FILE* m_fileHandle;
std::unique_ptr<atUint8[]> m_cacheData; std::unique_ptr<atUint8[]> m_cacheData;

View File

@ -4,32 +4,136 @@
#include "Athena/IStreamWriter.hpp" #include "Athena/IStreamWriter.hpp"
#include <stdio.h> #include <stdio.h>
#if _WIN32
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h"
#endif
namespace Athena namespace Athena
{ {
namespace io namespace io
{ {
class FileWriter : public IStreamWriter template<typename STLTRAITS = StlTraits>
class FileWriter : public IStreamWriter<STLTRAITS>
{ {
public: public:
FileWriter(const std::string& filename, bool overwrite = true); inline bool isOpen() const {return m_fileHandle != NULL;}
#if _WIN32
FileWriter(const std::wstring& filename, bool overwrite = true);
#endif
virtual ~FileWriter();
void open(bool overwrite = true); FileWriter(const std::string& filename, bool overwrite = true)
void close(); : m_filename(filename),
inline bool isOpen() const m_fileHandle(NULL),
{return m_fileHandle != NULL;} m_bytePosition(0)
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); {
atUint64 position() const; open(overwrite);
atUint64 length() const; }
void writeUBytes(const atUint8* data, atUint64 len);
#if _WIN32
FileWriter(const std::wstring& filename, bool overwrite = true)
: m_wfilename(filename),
m_fileHandle(NULL),
m_bytePosition(0)
{
open(overwrite);
}
#endif
virtual ~FileWriter()
{
if (isOpen())
close();
}
void open(bool overwrite = true)
{
#if _WIN32
if (m_wfilename.size())
{
if (overwrite)
m_fileHandle = _wfopen(m_wfilename.c_str(), L"w+b");
else
m_fileHandle = _wfopen(m_wfilename.c_str(), L"r+b");
}
else
{
if (overwrite)
m_fileHandle = fopen(m_filename.c_str(), "w+b");
else
m_fileHandle = fopen(m_filename.c_str(), "r+b");
}
#else
if (overwrite)
m_fileHandle = fopen(m_filename.c_str(), "w+b");
else
m_fileHandle = fopen(m_filename.c_str(), "r+b");
#endif
if (!m_fileHandle)
{
atError("Unable to open file '%s'", m_filename.c_str());
IStream::setError();
return;
}
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void close()
{
if (!m_fileHandle)
{
atError("Cannot close an unopened stream");
IStream::setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)
{
if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
{
atError("Unable to seek in file");
IStream::setError();
}
}
atUint64 position() const
{
return ftello64(m_fileHandle);
}
atUint64 length() const
{
return utility::fileSize(m_filename);
}
void writeUBytes(const atUint8* data, atUint64 len)
{
if (!isOpen())
{
atError("File not open for writing");
IStream::setError();
return;
}
if (fwrite(data, 1, len, m_fileHandle) != len)
{
atError("Unable to write to stream");
IStream::setError();
}
}
private: private:
std::string m_filename; typename STLTRAITS::String m_filename;
#if _WIN32 #if _WIN32
std::wstring m_wfilename; typename STLTRAITS::WString m_wfilename;
#endif #endif
FILE* m_fileHandle; FILE* m_fileHandle;
atUint8 m_currentByte; atUint8 m_currentByte;

View File

@ -60,6 +60,13 @@ typedef struct stat64 stat64_t;
namespace Athena namespace Athena
{ {
struct StlTraits
{
template<typename T> using Vector = std::vector<T>;
using String = std::string;
using WString = std::wstring;
};
namespace error namespace error
{ {
enum Level enum Level

View File

@ -1,8 +1,7 @@
#ifndef ISTREAMREADER_HPP #ifndef ISTREAMREADER_HPP
#define ISTREAMREADER_HPP #define ISTREAMREADER_HPP
#include <locale> #include <memory>
#include <codecvt>
#include <functional> #include <functional>
#include "IStream.hpp" #include "IStream.hpp"
@ -10,6 +9,7 @@ namespace Athena
{ {
namespace io namespace io
{ {
template<typename STLTRAITS = StlTraits>
class IStreamReader : public IStream class IStreamReader : public IStream
{ {
public: public:
@ -589,9 +589,9 @@ public:
* \return std::string The value at the current address * \return std::string The value at the current address
* \throw IOException when address is out of range * \throw IOException when address is out of range
*/ */
inline std::string readWStringAsString(atInt32 fixedLen = -1) inline typename STLTRAITS::String readWStringAsString(atInt32 fixedLen = -1)
{ {
std::wstring tmp; typename STLTRAITS::String retval;
atUint16 chr = readUint16(); atUint16 chr = readUint16();
atInt32 i; atInt32 i;
@ -603,20 +603,21 @@ public:
if (!chr) if (!chr)
break; break;
tmp.push_back(chr); char mb[4];
int c = std::wctomb(mb, chr);
retval.append(mb, c);
chr = readUint16(); chr = readUint16();
} }
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv; return retval;
return conv.to_bytes(tmp);
} }
inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1) inline typename STLTRAITS::String readWStringAsStringLittle(atInt32 fixedLen = -1)
{ {
std::wstring tmp; typename STLTRAITS::String retval;
atUint16 chr = readUint16Little(); atUint16 chr = readUint16Little();
atInt32 i; atInt32 i;
@ -628,20 +629,21 @@ public:
if (!chr) if (!chr)
break; break;
tmp.push_back(chr); char mb[4];
int c = std::wctomb(mb, chr);
retval.append(mb, c);
chr = readUint16Little(); chr = readUint16Little();
} }
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv; return retval;
return conv.to_bytes(tmp);
} }
inline std::string readWStringAsStringBig(atInt32 fixedLen = -1) inline typename STLTRAITS::String readWStringAsStringBig(atInt32 fixedLen = -1)
{ {
std::wstring tmp; typename STLTRAITS::String retval;
atUint16 chr = readUint16Big(); atUint16 chr = readUint16Big();
atInt32 i; atInt32 i;
@ -653,15 +655,16 @@ public:
if (!chr) if (!chr)
break; break;
tmp.push_back(chr); char mb[4];
int c = std::wctomb(mb, chr);
retval.append(mb, c);
chr = readUint16Big(); chr = readUint16Big();
} }
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv; return retval;
return conv.to_bytes(tmp);
} }
/*! \brief Reads a string and advances the position in the file /*! \brief Reads a string and advances the position in the file
@ -670,9 +673,9 @@ public:
* \return std::string The value at the current address * \return std::string The value at the current address
* \throw IOException when address is out of range * \throw IOException when address is out of range
*/ */
inline std::string readString(atInt32 fixedLen = -1) inline typename STLTRAITS::String readString(atInt32 fixedLen = -1)
{ {
std::string ret; typename STLTRAITS::String ret;
atUint8 chr = readByte(); atUint8 chr = readByte();
atInt32 i; atInt32 i;
@ -692,18 +695,18 @@ public:
return ret; return ret;
} }
template <class T> template <class T>
inline std::string readVal(typename std::enable_if<std::is_same<T, std::string>::value>::type* = 0) inline typename STLTRAITS::String readVal(typename std::enable_if<std::is_same<T, typename STLTRAITS::String>::value>::type* = 0)
{return readString();} {return readString();}
/*! \brief Reads a wstring and advances the position in the file /*! \brief Reads a wstring and advances the position in the file
* *
* \param fixedLen If non-negative, this is a fixed-length string read * \param fixedLen If non-negative, this is a fixed-length string read
* \return std::wstring The value at the current address * \return The value at the current address
* \throw IOException when address is out of range * \throw IOException when address is out of range
*/ */
inline std::wstring readWString(atInt32 fixedLen = -1) inline typename STLTRAITS::WString readWString(atInt32 fixedLen = -1)
{ {
std::wstring ret; typename STLTRAITS::WString ret;
atUint16 chr = readUint16(); atUint16 chr = readUint16();
atInt32 i; atInt32 i;
@ -723,12 +726,12 @@ public:
return ret; return ret;
} }
template <class T> template <class T>
inline std::wstring readVal(typename std::enable_if<std::is_same<T, std::wstring>::value>::type* = 0) inline typename STLTRAITS::WString readVal(typename std::enable_if<std::is_same<T, typename STLTRAITS::WString>::value>::type* = 0)
{return readWString();} {return readWString();}
inline std::wstring readWStringLittle(atInt32 fixedLen = -1) inline typename STLTRAITS::WString readWStringLittle(atInt32 fixedLen = -1)
{ {
std::wstring ret; typename STLTRAITS::WString ret;
atUint16 chr = readUint16Little(); atUint16 chr = readUint16Little();
atInt32 i; atInt32 i;
@ -748,12 +751,12 @@ public:
return ret; return ret;
} }
template <class T> template <class T>
inline std::wstring readValLittle(typename std::enable_if<std::is_same<T, std::wstring>::value>::type* = 0) inline typename STLTRAITS::WString readValLittle(typename std::enable_if<std::is_same<T, typename STLTRAITS::WString>::value>::type* = 0)
{return readWStringLittle();} {return readWStringLittle();}
inline std::wstring readWStringBig(atInt32 fixedLen = -1) inline typename STLTRAITS::WString readWStringBig(atInt32 fixedLen = -1)
{ {
std::wstring ret; typename STLTRAITS::WString ret;
atUint16 chr = readUint16Big(); atUint16 chr = readUint16Big();
atInt32 i; atInt32 i;
@ -773,11 +776,11 @@ public:
return ret; return ret;
} }
template <class T> template <class T>
inline std::wstring readValBig(typename std::enable_if<std::is_same<T, std::wstring>::value>::type* = 0) inline typename STLTRAITS::WString readValBig(typename std::enable_if<std::is_same<T, typename STLTRAITS::WString>::value>::type* = 0)
{return readWStringBig();} {return readWStringBig();}
template<class T> template<class T>
void enumerate(std::vector<T>& vector, size_t count, void enumerate(typename STLTRAITS::template Vector<T>& vector, size_t count,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -790,7 +793,7 @@ public:
} }
template<class T> template<class T>
void enumerateLittle(std::vector<T>& vector, size_t count, void enumerateLittle(typename STLTRAITS::template Vector<T>& vector, size_t count,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -803,7 +806,7 @@ public:
} }
template<class T> template<class T>
void enumerateBig(std::vector<T>& vector, size_t count, void enumerateBig(typename STLTRAITS::template Vector<T>& vector, size_t count,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -816,7 +819,7 @@ public:
} }
template<class T> template<class T>
void enumerate(std::vector<T>& vector, size_t count, void enumerate(typename STLTRAITS::template Vector<T>& vector, size_t count,
typename std::enable_if<!std::is_arithmetic<T>::value && typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value && !std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value && !std::is_same<T, atVec3f>::value &&
@ -832,7 +835,8 @@ public:
} }
template<class T> template<class T>
void enumerate(std::vector<T>& vector, size_t count, std::function<void(IStreamReader&, T&)> readf) void enumerate(typename STLTRAITS::template Vector<T>& vector,
size_t count, std::function<void(IStreamReader&, T&)> readf)
{ {
vector.clear(); vector.clear();
vector.reserve(count); vector.reserve(count);

View File

@ -9,6 +9,7 @@ namespace Athena
{ {
namespace io namespace io
{ {
template<typename STLTRAITS = StlTraits>
class IStreamWriter : public IStream class IStreamWriter : public IStream
{ {
public: public:
@ -436,116 +437,107 @@ public:
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to * \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
inline void writeStringAsWString(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWString(const typename STLTRAITS::String& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
std::wstring tmp = conv.from_bytes(tmpStr);
if (fixedLen < 0) if (fixedLen < 0)
{ {
for (atUint16 chr : tmp) while (*buf)
{ {
if (chr != 0xFEFF) wchar_t wc;
writeUint16(chr); buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
if (wc != 0xFEFF)
writeUint16(wc);
} }
writeUint16(0); writeUint16(0);
} }
else else
{ {
auto it = tmp.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i) for (atInt32 i=0 ; i<fixedLen ; ++i)
{ {
atUint16 chr; wchar_t wc = 0;
if (it == tmp.end()) if (*buf)
chr = 0; buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
else
chr = *it++;
if (chr == 0xFEFF) if (wc == 0xFEFF)
{ {
--i; --i;
continue; continue;
} }
writeUint16(chr); writeUint16(wc);
} }
} }
} }
inline void writeStringAsWStringLittle(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWStringLittle(const typename STLTRAITS::String& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
std::wstring tmp = conv.from_bytes(tmpStr);
if (fixedLen < 0) if (fixedLen < 0)
{ {
for (atUint16 chr : tmp) while (*buf)
{ {
if (chr != 0xFEFF) wchar_t wc;
writeUint16Little(chr); buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
if (wc != 0xFEFF)
writeUint16Little(wc);
} }
writeUint16Little(0); writeUint16Little(0);
} }
else else
{ {
auto it = tmp.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i) for (atInt32 i=0 ; i<fixedLen ; ++i)
{ {
atUint16 chr; wchar_t wc = 0;
if (it == tmp.end()) if (*buf)
chr = 0; buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
else
chr = *it++;
if (chr == 0xFEFF) if (wc == 0xFEFF)
{ {
--i; --i;
continue; continue;
} }
writeUint16Little(chr); writeUint16Little(wc);
} }
} }
} }
inline void writeStringAsWStringBig(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWStringBig(const typename STLTRAITS::String& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
std::wstring tmp = conv.from_bytes(tmpStr);
if (fixedLen < 0) if (fixedLen < 0)
{ {
for (atUint16 chr : tmp) while (*buf)
{ {
if (chr != 0xFEFF) wchar_t wc;
writeUint16Big(chr); buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
if (wc != 0xFEFF)
writeUint16Big(wc);
} }
writeUint16Big(0); writeUint16Big(0);
} }
else else
{ {
auto it = tmp.begin();
for (atInt32 i=0 ; i<fixedLen ; ++i) for (atInt32 i=0 ; i<fixedLen ; ++i)
{ {
atUint16 chr; wchar_t wc = 0;
if (it == tmp.end()) if (*buf)
chr = 0; buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
else
chr = *it++;
if (chr == 0xFEFF) if (wc == 0xFEFF)
{ {
--i; --i;
continue; continue;
} }
writeUint16Big(chr); writeUint16Big(wc);
} }
} }
} }
@ -556,7 +548,7 @@ public:
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to * \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
inline void writeString(const std::string& str, atInt32 fixedLen = -1) inline void writeString(const typename STLTRAITS::String& str, atInt32 fixedLen = -1)
{ {
if (fixedLen < 0) if (fixedLen < 0)
{ {
@ -583,7 +575,7 @@ public:
} }
} }
} }
inline void writeVal(const std::string& val) {return writeString(val);} inline void writeVal(const typename STLTRAITS::String& val) {return writeString(val);}
/*! \brief Writes an wstring to the buffer and advances the buffer. /*! \brief Writes an wstring to the buffer and advances the buffer.
* *
@ -591,7 +583,7 @@ public:
* \param str The string to write to the buffer * \param str The string to write to the buffer
* \param fixedLen If not -1, the number of characters to zero-fill string to * \param fixedLen If not -1, the number of characters to zero-fill string to
*/ */
inline void writeWString(const std::wstring& str, atInt32 fixedLen = -1) inline void writeWString(const typename STLTRAITS::WString& str, atInt32 fixedLen = -1)
{ {
if (fixedLen < 0) if (fixedLen < 0)
{ {
@ -618,9 +610,9 @@ public:
} }
} }
} }
inline void writeVal(const std::wstring& val) {return writeWString(val);} inline void writeVal(const typename STLTRAITS::WString& val) {return writeWString(val);}
inline void writeWStringLittle(const std::wstring& str, atInt32 fixedLen = -1) inline void writeWStringLittle(const typename STLTRAITS::WString& str, atInt32 fixedLen = -1)
{ {
if (fixedLen < 0) if (fixedLen < 0)
{ {
@ -647,9 +639,9 @@ public:
} }
} }
} }
inline void writeValLittle(const std::wstring& val) {return writeWStringLittle(val);} inline void writeValLittle(const typename STLTRAITS::WString& val) {return writeWStringLittle(val);}
inline void writeWStringBig(const std::wstring& str, atInt32 fixedLen = -1) inline void writeWStringBig(const typename STLTRAITS::WString& str, atInt32 fixedLen = -1)
{ {
if (fixedLen < 0) if (fixedLen < 0)
{ {
@ -676,7 +668,7 @@ public:
} }
} }
} }
inline void writeValBig(const std::wstring& val) {return writeWStringBig(val);} inline void writeValBig(const typename STLTRAITS::WString& val) {return writeWStringBig(val);}
inline void fill(atUint8 val, atUint64 length) inline void fill(atUint8 val, atUint64 length)
{for (atUint64 l=0 ; l<length ; ++l) writeUBytes(&val, 1);} {for (atUint64 l=0 ; l<length ; ++l) writeUBytes(&val, 1);}
@ -684,7 +676,7 @@ public:
{fill((atUint8)val, length);} {fill((atUint8)val, length);}
template <class T> template <class T>
void enumerate(const std::vector<T>& vector, void enumerate(const typename STLTRAITS::template Vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -695,7 +687,7 @@ public:
} }
template <class T> template <class T>
void enumerateLittle(const std::vector<T>& vector, void enumerateLittle(const typename STLTRAITS::template Vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -706,7 +698,7 @@ public:
} }
template <class T> template <class T>
void enumerateBig(const std::vector<T>& vector, void enumerateBig(const typename STLTRAITS::template Vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value || typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value || std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value || std::is_same<T, atVec3f>::value ||
@ -717,7 +709,7 @@ public:
} }
template <class T> template <class T>
void enumerate(const std::vector<T>& vector, void enumerate(const typename STLTRAITS::template Vector<T>& vector,
typename std::enable_if<!std::is_arithmetic<T>::value && typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value && !std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value && !std::is_same<T, atVec3f>::value &&

View File

@ -18,10 +18,16 @@ namespace io
* this allows for fast, flexible code as well as the ability to quickly modify data * this allows for fast, flexible code as well as the ability to quickly modify data
* \sa Stream * \sa Stream
*/ */
class MemoryReader : public IStreamReader template<typename STLTRAITS = StlTraits>
class MemoryReader : public IStreamReader<STLTRAITS>
{ {
using base = IStreamReader<STLTRAITS>;
public: public:
virtual ~MemoryReader(); virtual ~MemoryReader()
{
if (m_owns)
delete[] m_data;
}
/*! \brief This constructor references an existing buffer to read from. /*! \brief This constructor references an existing buffer to read from.
* *
@ -29,28 +35,82 @@ public:
* \param length The length of the existing buffer * \param length The length of the existing buffer
* \param takeOwnership Memory will be freed with the reader if set * \param takeOwnership Memory will be freed with the reader if set
*/ */
MemoryReader(const atUint8* data, atUint64 length, bool takeOwnership=false); MemoryReader(const atUint8* data, atUint64 length, bool takeOwnership=false)
: m_data(data),
m_length(length),
m_position(0),
m_owns(takeOwnership)
{
if (!data)
{
atError("data cannot be NULL");
IStream::setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
IStream::setError();
return;
}
}
/*! \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
* \param origin The Origin to seek \sa SeekOrigin * \param origin The Origin to seek \sa SeekOrigin
*/ */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 position, SeekOrigin origin = SeekOrigin::Current)
{
switch (origin)
{
case SeekOrigin::Begin:
if ((position < 0 || (atInt64)position > (atInt64)m_length))
{
atError("Position %0.8X outside stream bounds ", position);
IStream::setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length))
{
atError("Position %0.8X outside stream bounds ", position);
IStream::setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length))
{
atError("Position %0.8X outside stream bounds ", position);
IStream::setError();
return;
}
m_position = m_length - position;
break;
}
}
/*! \brief Returns the current position in the stream. /*! \brief Returns the current position in the stream.
* *
* \return Int64 The current position in the stream. * \return Int64 The current position in the stream.
*/ */
inline atUint64 position() const inline atUint64 position() const {return m_position;}
{return m_position;}
/*! \brief Returns whether or not the stream is at the end. /*! \brief Returns whether or not the stream is at the end.
* *
* \return bool True if at end; False otherwise. * \return bool True if at end; False otherwise.
*/ */
inline atUint64 length() const inline atUint64 length() const {return m_length;}
{return m_length;}
/*! \brief Sets the buffer to the given one, deleting the current one.<br /> /*! \brief Sets the buffer to the given one, deleting the current one.<br />
@ -63,7 +123,15 @@ public:
* \param takeOwnership Memory will be freed with the reader if set * \param takeOwnership Memory will be freed with the reader if set
* \throw IOException * \throw IOException
*/ */
void setData(const atUint8* data, atUint64 length, bool takeOwnership=false); void setData(const atUint8* data, atUint64 length, bool takeOwnership=false)
{
if (m_owns && m_data)
delete[] m_data;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_owns = takeOwnership;
}
/*! \brief Returns a copy of the current buffer.<br /> /*! \brief Returns a copy of the current buffer.<br />
@ -73,14 +141,32 @@ public:
* as Stream now owns the address, this is done to keep memory usage down. * as Stream now owns the address, this is done to keep memory usage down.
* \return Uint8* The copy of the buffer. * \return Uint8* The copy of the buffer.
*/ */
atUint8* data() const; atUint8* data() const
{
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
/*! \brief Reads a specified number of bytes to user-allocated buffer /*! \brief Reads a specified number of bytes to user-allocated buffer
* \param buf User-allocated buffer pointer * \param buf User-allocated buffer pointer
* \param len Length to read * \param length Length to read
* \return Number of bytes read * \return Number of bytes read
*/ */
atUint64 readUBytesToBuf(void* buf, atUint64 len); atUint64 readUBytesToBuf(void* buf, atUint64 length)
{
if (m_position + length > m_length)
{
atError("Position %0.8X outside stream bounds ", m_position);
IStream::setError();
return 0;
}
memcpy(buf, (const atUint8*)(m_data + m_position), length);
m_position += length;
return length;
}
protected: protected:
const atUint8* m_data; const atUint8* m_data;
@ -89,29 +175,105 @@ protected:
bool m_owns; bool m_owns;
}; };
class MemoryCopyReader : public MemoryReader template<typename STLTRAITS = StlTraits>
class MemoryCopyReader : public MemoryReader<STLTRAITS>
{ {
using base = MemoryReader<STLTRAITS>;
public: public:
/*! \brief This constructor copies an existing buffer to read from. /*! \brief This constructor copies 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
*/ */
MemoryCopyReader(const atUint8* data, atUint64 length); MemoryCopyReader(const atUint8* data, atUint64 length)
: base(data, length, false)
{
if (!data)
{
atError("data cannot be NULL");
IStream::setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
IStream::setError();
return;
}
m_dataCopy.reset(new atUint8[base::m_length]);
base::m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, base::m_length);
}
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
MemoryCopyReader(const std::string& filename) MemoryCopyReader(const std::string& filename)
: MemoryReader(NULL, 0), : base(NULL, 0),
m_filepath(filename) m_filepath(filename)
{loadData();} {loadData();}
void setData(const atUint8* data, atUint64 length); void setData(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
base::m_data = m_dataCopy.get();
memcpy(m_dataCopy.get(), data, length);
base::m_length = length;
base::m_position = 0;
}
protected: protected:
void loadData(); void loadData()
{
FILE* in;
atUint64 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in)
{
atError("Unable to open file '%s'", m_filepath.c_str());
IStream::setError();
return;
}
rewind(in);
length = utility::fileSize(m_filepath);
m_dataCopy.reset(new atUint8[length]);
base::m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do
{
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0)
{
atError("Error reading data from disk");
IStream::setError();
return;
}
else if (ret == 0)
break;
done += ret;
}
while (done < length);
fclose(in);
base::m_length = length;
base::m_position = 0;
}
std::unique_ptr<atUint8[]> m_dataCopy; std::unique_ptr<atUint8[]> m_dataCopy;
std::string m_filepath; //!< Path to the target file std::string m_filepath; //!< Path to the target file
}; };

View File

@ -19,7 +19,8 @@ namespace io
* this allows for fast, flexible code as well as the ability to quickly modify data * this allows for fast, flexible code as well as the ability to quickly modify data
* \sa Stream * \sa Stream
*/ */
class MemoryWriter : public IStreamWriter template<typename STLTRAITS = StlTraits>
class MemoryWriter : public IStreamWriter<STLTRAITS>
{ {
public: public:
@ -28,14 +29,90 @@ public:
* \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, atUint64 length); explicit MemoryWriter(atUint8* data, atUint64 length)
: m_data((atUint8*)data),
m_length(length),
m_position(0)
{
if (!data)
{
atError("data cannot be NULL");
IStream::setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
IStream::setError();
return;
}
}
/*! \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
* \param origin The Origin to seek \sa SeekOrigin * \param origin The Origin to seek \sa SeekOrigin
*/ */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 position, SeekOrigin origin = SeekOrigin::Current)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
IStream::setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0))
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if (m_position + position > m_length)
{
atError("data exceeds available buffer space");
IStream::setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0)
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
IStream::setError();
return;
}
m_position = m_length - position;
break;
}
}
/*! \brief Returns the current position in the stream. /*! \brief Returns the current position in the stream.
@ -63,7 +140,12 @@ public:
* \param length The length of the new buffer. * \param length The length of the new buffer.
* \throw IOException * \throw IOException
*/ */
void setData(atUint8* data, atUint64 length); void setData(atUint8* data, atUint64 length)
{
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
}
/*! \brief Returns a copy of the current buffer.<br /> /*! \brief Returns a copy of the current buffer.<br />
@ -73,7 +155,13 @@ public:
* as Stream now owns the address, this is done to keep memory usage down. * as Stream now owns the address, this is done to keep memory usage down.
* \return Uint8* The copy of the buffer. * \return Uint8* The copy of the buffer.
*/ */
atUint8* data() const; atUint8* data() const
{
atUint8* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
/*! \brief Sets the target file /*! \brief Sets the target file
* *
@ -93,7 +181,52 @@ public:
* *
* \param filename If not empty, the filename to save to * \param filename If not empty, the filename to save to
*/ */
void save(const std::string& filename = ""); void save(const std::string& filename = "")
{
if (filename.empty() && m_filepath.empty())
{
atError("No file specified, cannot save.");
IStream::setError();
return;
}
if (!filename.empty())
m_filepath = filename;
FILE* out = fopen(m_filepath.c_str(), "wb");
if (!out)
{
atError("Unable to open file '%s'", m_filepath.c_str());
IStream::setError();
return;
}
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do
{
if (blocksize > m_length - done)
blocksize = m_length - done;
atInt64 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0)
{
atError("Error writing data to disk");
IStream::setError();
return;
}
else if (ret == 0)
break;
done += blocksize;
}
while (done < m_length);
fclose(out);
}
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length /*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
* however it's undefined behavior to try and write a buffer which is smaller than the given length. * however it's undefined behavior to try and write a buffer which is smaller than the given length.
@ -101,7 +234,26 @@ public:
* \param data The buffer to write * \param data The buffer to write
* \param length The amount to write * \param length The amount to write
*/ */
void writeUBytes(const atUint8* data, atUint64 len); void writeUBytes(const atUint8* data, atUint64 length)
{
if (!data)
{
atError("data cannnot be NULL");
IStream::setError();
return;
}
if (m_position + length > m_length)
{
atError("data length exceeds available buffer space");
IStream::setError();
return;
}
memcpy((atInt8*)(m_data + m_position), data, length);
m_position += length;
}
protected: protected:
MemoryWriter() {} MemoryWriter() {}
@ -111,8 +263,10 @@ protected:
std::string m_filepath; //!< Path to the target file std::string m_filepath; //!< Path to the target file
}; };
class MemoryCopyWriter : public MemoryWriter template<typename STLTRAITS = StlTraits>
class MemoryCopyWriter : public MemoryWriter<STLTRAITS>
{ {
using base = MemoryWriter<STLTRAITS>;
public: public:
/*! \brief This constructor copies an existing buffer to write to. /*! \brief This constructor copies an existing buffer to write to.
@ -120,20 +274,100 @@ public:
* \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 MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10); explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10)
{
base::m_data = data;
base::m_length = length;
base::m_position = 0;
if (length == 0)
{
atError("length cannot be 0");
IStream::setError();
return;
}
base::m_dataCopy.reset(new atUint8[length]);
base::m_data = m_dataCopy.get();
if (data)
memcpy(base::m_data, data, length);
}
/*! \brief This constructor creates an instance from a file on disk. /*! \brief This constructor creates an instance from a file on disk.
* *
* \param filename The file to create the stream from * \param filename The file to create the stream from
*/ */
MemoryCopyWriter(const std::string& filename); MemoryCopyWriter(const std::string& filename)
: base(NULL, 0)
{
base::m_filepath = filename;
base::m_length = 0x10;
base::m_position = 0;
m_dataCopy.reset(new atUint8[base::m_length]);
base::m_data = m_dataCopy.get();
if (!base::m_data)
{
atError("Could not allocate memory!");
IStream::setError();
return;
}
memset(base::m_data, 0, base::m_length);
}
/*! \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
* \param origin The Origin to seek \sa SeekOrigin * \param origin The Origin to seek \sa SeekOrigin
*/ */
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); void seek(atInt64 position, SeekOrigin origin = SeekOrigin::Current)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if ((atUint64)position > base::m_length)
resize(position);
base::m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)base::m_position + position) < 0))
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if (base::m_position + position > base::m_length)
resize(base::m_position + position);
base::m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)base::m_length - position) < 0)
{
atError("Position outside stream bounds");
IStream::setError();
return;
}
if ((atUint64)position > base::m_length)
resize(position);
base::m_position = base::m_length - position;
break;
}
}
/*! \brief Sets the buffer to the given one, deleting the current one.<br /> /*! \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 * <b>BEWARE:</b> As this deletes the current buffer it WILL cause a loss of data
@ -144,7 +378,14 @@ 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(const atUint8* data, atUint64 length)
{
m_dataCopy.reset(new atUint8[length]);
base::m_data = m_dataCopy.get();
memcpy(base::m_data, data, length);
base::m_length = length;
base::m_position = 0;
}
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length /*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
* however it's undefined behavior to try and write a buffer which is smaller than the given length. * however it's undefined behavior to try and write a buffer which is smaller than the given length.
@ -152,12 +393,46 @@ public:
* \param data The buffer to write * \param data The buffer to write
* \param length The amount to write * \param length The amount to write
*/ */
void writeUBytes(const atUint8* data, atUint64 len); void writeUBytes(const atUint8* data, atUint64 length)
{
if (!data)
{
atError("data cannnot be NULL");
IStream::setError();
return;
}
if (base::m_position + length > base::m_length)
resize(base::m_position + length);
memcpy((atInt8*)(base::m_data + base::m_position), data, length);
base::m_position += length;
}
protected: protected:
std::unique_ptr<atUint8[]> m_dataCopy; std::unique_ptr<atUint8[]> m_dataCopy;
private: private:
void resize(atUint64 newSize); void resize(atUint64 newSize)
{
if (newSize < base::m_length)
{
atError("New size cannot be less to the old size.");
return;
}
// Allocate and copy new buffer
atUint8* newArray = new atUint8[newSize];
memset(newArray, 0, newSize);
if (m_dataCopy)
memcpy(newArray, m_dataCopy.get(), base::m_length);
m_dataCopy.reset(newArray);
// Swap the pointer and size out for the new ones.
base::m_data = newArray;
base::m_length = newSize;
}
}; };
} }

View File

@ -39,330 +39,12 @@ void HandleYAMLEmitterError(yaml_emitter_t* emitter)
atError("YAML error: %s: %s", ErrorString(emitter->error), emitter->problem?emitter->problem:""); atError("YAML error: %s: %s", ErrorString(emitter->error), emitter->problem?emitter->problem:"");
} }
int YAMLStdStringReader(YAMLStdStringReaderState* reader, const char* AT_BASE64_CHARS =
unsigned char* buffer, size_t size, size_t* size_read)
{
size_t diff = reader->end - reader->begin;
if (!diff)
{
*size_read = 0;
}
else if (diff < size)
{
memcpy(buffer, &*reader->begin, diff);
*size_read = diff;
}
else
{
memcpy(buffer, &*reader->begin, size);
*size_read = size;
}
return 1;
}
int YAMLStdStringWriter(std::string* str, unsigned char *buffer, size_t size)
{
str->append((char*)buffer, size);
return 1;
}
static inline void InsertNode(std::vector<YAMLNode*>& nodeStack,
std::unique_ptr<YAMLNode>& mapKey,
std::unique_ptr<YAMLNode>& retVal,
std::unique_ptr<YAMLNode>&& newNode)
{
if (nodeStack.empty())
{
retVal = std::move(newNode);
return;
}
YAMLNode* parent = nodeStack.back();
if (parent->m_type == YAML_SEQUENCE_NODE)
{
parent->m_seqChildren.emplace_back(std::move(newNode));
}
else if (parent->m_type == YAML_MAPPING_NODE)
{
if (!mapKey)
mapKey = std::move(newNode);
else
{
parent->m_mapChildren.emplace_back(std::move(mapKey->m_scalarString), std::move(newNode));
mapKey.reset(nullptr);
}
}
}
std::unique_ptr<YAMLNode> YAMLDocReader::ParseEvents(yaml_parser_t* doc)
{
yaml_event_t event;
if (!yaml_parser_parse(doc, &event))
{
HandleYAMLParserError(doc);
return std::unique_ptr<YAMLNode>();
}
std::vector<YAMLNode*> nodeStack;
std::unique_ptr<YAMLNode> mapKey;
std::unique_ptr<YAMLNode> retVal;
int result;
for (result = yaml_parser_parse(doc, &event);
event.type != YAML_STREAM_END_EVENT;
result = yaml_parser_parse(doc, &event))
{
if (!result)
{
HandleYAMLParserError(doc);
return std::unique_ptr<YAMLNode>();
}
switch (event.type)
{
case YAML_SCALAR_EVENT:
{
if (nodeStack.empty())
{
atWarning("YAML parser stack empty; skipping scalar node");
break;
}
std::unique_ptr<YAMLNode> newScalar(new YAMLNode(YAML_SCALAR_NODE));
newScalar->m_scalarString.assign((char*)event.data.scalar.value, event.data.scalar.length);
if (nodeStack.empty())
retVal = std::move(newScalar);
else
InsertNode(nodeStack, mapKey, retVal, std::move(newScalar));
break;
}
case YAML_SEQUENCE_START_EVENT:
{
YAMLNode* newSeq = new YAMLNode(YAML_SEQUENCE_NODE);
InsertNode(nodeStack, mapKey, retVal, std::unique_ptr<YAMLNode>(newSeq));
nodeStack.emplace_back(newSeq);
break;
}
case YAML_SEQUENCE_END_EVENT:
{
nodeStack.pop_back();
break;
}
case YAML_MAPPING_START_EVENT:
{
YAMLNode* newMap = new YAMLNode(YAML_MAPPING_NODE);
InsertNode(nodeStack, mapKey, retVal, std::unique_ptr<YAMLNode>(newMap));
nodeStack.emplace_back(newMap);
break;
}
case YAML_MAPPING_END_EVENT:
{
nodeStack.pop_back();
break;
}
case YAML_DOCUMENT_END_EVENT:
{
yaml_event_delete(&event);
return retVal;
}
default:
break;
}
yaml_event_delete(&event);
}
return std::unique_ptr<YAMLNode>();
}
static inline bool EmitKeyScalar(yaml_emitter_t* doc, const char* val)
{
yaml_event_t event;
if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val,
strlen(val), true, true, YAML_PLAIN_SCALAR_STYLE))
return false;
return yaml_emitter_emit(doc, &event);
}
static inline yaml_scalar_style_t ScalarStyle(const YAMLNode& node)
{
for (const auto& ch : node.m_scalarString)
if (ch == '\n')
return YAML_LITERAL_SCALAR_STYLE;
return YAML_ANY_SCALAR_STYLE;
}
static inline yaml_sequence_style_t SequenceStyle(const YAMLNode& node)
{
size_t count = 0;
for (const auto& item : node.m_seqChildren)
{
if (item->m_type != YAML_SCALAR_NODE)
return YAML_BLOCK_SEQUENCE_STYLE;
size_t strLen = item->m_scalarString.size();
size_t thisCount = strLen / 10;
if (!thisCount)
thisCount = 1;
count += thisCount;
}
return (count > 6) ? YAML_BLOCK_SEQUENCE_STYLE : YAML_FLOW_SEQUENCE_STYLE;
}
static inline yaml_mapping_style_t MappingStyle(const YAMLNode& node)
{
size_t count = 0;
for (const auto& item : node.m_mapChildren)
{
if (item.second->m_type != YAML_SCALAR_NODE)
return YAML_BLOCK_MAPPING_STYLE;
size_t strLen = item.second->m_scalarString.size();
size_t thisCount = strLen / 10;
if (!thisCount)
thisCount = 1;
count += thisCount;
}
return (count > 6) ? YAML_BLOCK_MAPPING_STYLE : YAML_FLOW_MAPPING_STYLE;
}
bool YAMLDocWriter::RecursiveFinish(yaml_emitter_t* doc, const YAMLNode& node)
{
yaml_event_t event;
if (node.m_type == YAML_SCALAR_NODE)
{
if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)node.m_scalarString.c_str(),
node.m_scalarString.length(), true, true, ScalarStyle(node)) ||
!yaml_emitter_emit(doc, &event))
goto err;
}
else if (node.m_type == YAML_SEQUENCE_NODE)
{
if (!yaml_sequence_start_event_initialize(&event, nullptr, nullptr, 1, SequenceStyle(node)) ||
!yaml_emitter_emit(doc, &event))
goto err;
for (const auto& item : node.m_seqChildren)
{
if (!RecursiveFinish(doc, *item))
goto err;
}
if (!yaml_sequence_end_event_initialize(&event) ||
!yaml_emitter_emit(doc, &event))
goto err;
}
else if (node.m_type == YAML_MAPPING_NODE)
{
if (!yaml_mapping_start_event_initialize(&event, nullptr, nullptr, true, MappingStyle(node)) ||
!yaml_emitter_emit(doc, &event))
goto err;
for (const auto& item : node.m_mapChildren)
{
if (!EmitKeyScalar(doc, item.first.c_str()))
goto err;
if (!RecursiveFinish(doc, *item.second))
goto err;
}
event.type = YAML_MAPPING_END_EVENT;
if (!yaml_mapping_end_event_initialize(&event) ||
!yaml_emitter_emit(doc, &event))
goto err;
}
return true;
err:
HandleYAMLEmitterError(doc);
return false;
}
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz"
"0123456789+/"; "0123456789+/";
static inline bool is_base64(unsigned char c)
{
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(const atUint8* bytes_to_encode, size_t in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
ret.reserve(in_len * 4 / 3);
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
std::unique_ptr<atUint8[]> base64_decode(const std::string& encoded_string)
{
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::unique_ptr<atUint8[]> ret(new atUint8[in_len * 3 / 4]);
atUint8* retBuf = ret.get();
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
*retBuf++ = char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) *retBuf++ = char_array_3[j];
}
return ret;
}
} }
} }

View File

@ -117,7 +117,7 @@ bool FileInfo::touch() const
#if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO)) #if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO))
stat64_t st; stat64_t st;
if (stat64(m_path.c_str(), &st) < 0) { if (stat64(m_path.c_str(), &st) < 0) {
(void)Athena::io::FileWriter(m_path); (void)Athena::io::FileWriter<>(m_path);
return true; return true;
} }
if (utimes(m_path.c_str(), NULL) < 0) { if (utimes(m_path.c_str(), NULL) < 0) {

View File

@ -1,195 +0,0 @@
#include "Athena/FileReader.hpp"
#if _WIN32
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h"
#endif
namespace Athena
{
namespace io
{
FileReader::FileReader(const std::string& filename, atInt32 cacheSize)
: m_filename(filename),
m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0)
{
open();
setCacheSize(cacheSize);
}
#if _WIN32
FileReader::FileReader(const std::wstring& filename, atInt32 cacheSize)
: m_wfilename(filename),
m_fileHandle(nullptr),
m_cacheData(nullptr),
m_offset(0)
{
open();
setCacheSize(cacheSize);
}
#endif
FileReader::~FileReader()
{
if (isOpen())
close();
}
void FileReader::open()
{
#if _WIN32
if (m_wfilename.size())
m_fileHandle = _wfopen(m_wfilename.c_str(), L"rb");
else
m_fileHandle = fopen(m_filename.c_str(), "rb");
#else
m_fileHandle = fopen(m_filename.c_str(), "rb");
#endif
if (!m_fileHandle)
{
atError("File not found '%s'", m_filename.c_str());
setError();
return;
}
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void FileReader::close()
{
if (!m_fileHandle)
{
atError("Cannot close an unopened stream");
setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
void FileReader::seek(atInt64 pos, SeekOrigin origin)
{
// check block position
if (m_blockSize > 0)
{
atUint64 oldOff = m_offset;
switch(origin)
{
case SeekOrigin::Begin:
m_offset = pos;
break;
case SeekOrigin::Current:
m_offset += pos;
break;
case SeekOrigin::End:
m_offset = length() - pos;
break;
}
if (m_offset > length())
{
oldOff = m_offset;
atError("Unable to seek in file");
return;
}
size_t block = m_offset / m_blockSize;
if (block != m_curBlock)
{
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
}
else if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
atError("Unable to seek in file");
}
atUint64 FileReader::position() const
{
if (!isOpen())
{
atError("File not open");
return 0;
}
if (m_blockSize > 0)
return m_offset;
else
return ftello64(m_fileHandle);
}
atUint64 FileReader::length() const
{
if (!isOpen())
{
atError("File not open");
return 0;
}
return utility::fileSize(m_filename);
}
atUint64 FileReader::readUBytesToBuf(void* buf, atUint64 len)
{
if (!isOpen())
{
atError("File not open for reading");
setError();
return 0;
}
if (m_blockSize <= 0)
return fread(buf, 1, len, m_fileHandle);
else
{
size_t block = m_offset / m_blockSize;
atUint64 cacheOffset = m_offset % m_blockSize;
atUint64 cacheSize;
atUint64 rem = len;
atUint8* dst = (atUint8*)buf;
while (rem)
{
if (block != m_curBlock)
{
fseeko64(m_fileHandle, block * m_blockSize, SEEK_SET);
fread(m_cacheData.get(), 1, m_blockSize, m_fileHandle);
m_curBlock = (atInt32)block;
}
cacheSize = rem;
if (cacheSize + cacheOffset > m_blockSize)
cacheSize = m_blockSize - cacheOffset;
memcpy(dst, m_cacheData.get() + cacheOffset, cacheSize);
dst += cacheSize;
rem -= cacheSize;
cacheOffset = 0;
++block;
}
m_offset += len;
return dst - (atUint8*)buf;
}
}
void FileReader::setCacheSize(const atInt32 blockSize)
{
m_blockSize = blockSize;
if (m_blockSize > length())
m_blockSize = (atInt32)length();
m_curBlock = -1;
if (m_blockSize > 0)
m_cacheData.reset(new atUint8[m_blockSize]);
}
} // io
} // Athena

View File

@ -1,124 +0,0 @@
#include "Athena/FileWriter.hpp"
#if _WIN32
#include "win32_largefilewrapper.h"
#elif __APPLE__
#include "osx_largefilewrapper.h"
#endif
namespace Athena
{
namespace io
{
FileWriter::FileWriter(const std::string& filename, bool overwrite)
: m_filename(filename),
m_fileHandle(NULL),
m_bytePosition(0)
{
open(overwrite);
}
#if _WIN32
FileWriter::FileWriter(const std::wstring& filename, bool overwrite)
: m_wfilename(filename),
m_fileHandle(NULL),
m_bytePosition(0)
{
open(overwrite);
}
#endif
FileWriter::~FileWriter()
{
if (isOpen())
close();
}
void FileWriter::open(bool overwrite)
{
#if _WIN32
if (m_wfilename.size())
{
if (overwrite)
m_fileHandle = _wfopen(m_wfilename.c_str(), L"w+b");
else
m_fileHandle = _wfopen(m_wfilename.c_str(), L"r+b");
}
else
{
if (overwrite)
m_fileHandle = fopen(m_filename.c_str(), "w+b");
else
m_fileHandle = fopen(m_filename.c_str(), "r+b");
}
#else
if (overwrite)
m_fileHandle = fopen(m_filename.c_str(), "w+b");
else
m_fileHandle = fopen(m_filename.c_str(), "r+b");
#endif
if (!m_fileHandle)
{
atError("Unable to open file '%s'", m_filename.c_str());
setError();
return;
}
// ensure we're at the beginning of the file
rewind(m_fileHandle);
}
void FileWriter::close()
{
if (!m_fileHandle)
{
atError("Cannot close an unopened stream");
setError();
return;
}
fclose(m_fileHandle);
m_fileHandle = NULL;
return;
}
void FileWriter::seek(atInt64 pos, SeekOrigin origin)
{
if (fseeko64(m_fileHandle, pos, (int)origin) != 0)
{
atError("Unable to seek in file");
setError();
}
}
atUint64 FileWriter::position() const
{
return ftello64(m_fileHandle);
}
atUint64 FileWriter::length() const
{
return utility::fileSize(m_filename);
}
void FileWriter::writeUBytes(const atUint8* data, atUint64 len)
{
if (!isOpen())
{
atError("File not open for writing");
setError();
return;
}
if (fwrite(data, 1, len, m_fileHandle) != len)
{
atError("Unable to write to stream");
setError();
}
}
}
} // Athena

View File

@ -1,196 +0,0 @@
#include "Athena/MemoryReader.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <cstring>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace Athena
{
namespace io
{
MemoryReader::MemoryReader(const atUint8* data, atUint64 length, bool takeOwnership)
: m_data(data),
m_length(length),
m_position(0),
m_owns(takeOwnership)
{
if (!data)
{
atError("data cannot be NULL");
setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
setError();
return;
}
}
MemoryReader::~MemoryReader()
{
if (m_owns)
delete[] m_data;
}
MemoryCopyReader::MemoryCopyReader(const atUint8* data, atUint64 length)
: MemoryReader(data, length, false)
{
if (!data)
{
atError("data cannot be NULL");
setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
setError();
return;
}
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)
{
switch (origin)
{
case SeekOrigin::Begin:
if ((position < 0 || (atInt64)position > (atInt64)m_length))
{
atError("Position %0.8X outside stream bounds ", position);
setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0 || (m_position + position) > m_length))
{
atError("Position %0.8X outside stream bounds ", position);
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if ((((atInt64)m_length - position < 0) || (m_length - position) > m_length))
{
atError("Position %0.8X outside stream bounds ", position);
setError();
return;
}
m_position = m_length - position;
break;
}
}
void MemoryReader::setData(const atUint8* data, atUint64 length, bool takeOwnership)
{
if (m_owns && m_data)
delete[] m_data;
m_data = (atUint8*)data;
m_length = length;
m_position = 0;
m_owns = takeOwnership;
}
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* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
atUint64 MemoryReader::readUBytesToBuf(void* buf, atUint64 length)
{
if (m_position + length > m_length)
{
atError("Position %0.8X outside stream bounds ", m_position);
setError();
return 0;
}
memcpy(buf, (const atUint8*)(m_data + m_position), length);
m_position += length;
return length;
}
void MemoryCopyReader::loadData()
{
FILE* in;
atUint64 length;
in = fopen(m_filepath.c_str(), "rb");
if (!in)
{
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
}
rewind(in);
length = utility::fileSize(m_filepath);
m_dataCopy.reset(new atUint8[length]);
m_data = m_dataCopy.get();
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do
{
if (blocksize > length - done)
blocksize = length - done;
atInt64 ret = fread(m_dataCopy.get() + done, 1, blocksize, in);
if (ret < 0)
{
atError("Error reading data from disk");
setError();
return;
}
else if (ret == 0)
break;
done += ret;
}
while (done < length);
fclose(in);
m_length = length;
m_position = 0;
}
}
}

View File

@ -1,315 +0,0 @@
#include "Athena/MemoryWriter.hpp"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#ifdef HW_RVL
#include <malloc.h>
#endif // HW_RVL
namespace Athena
{
namespace io
{
MemoryWriter::MemoryWriter(atUint8* data, atUint64 length)
: m_data((atUint8*)data),
m_length(length),
m_position(0)
{
if (!data)
{
atError("data cannot be NULL");
setError();
return;
}
if (length == 0)
{
atError("length cannot be 0");
setError();
return;
}
}
MemoryCopyWriter::MemoryCopyWriter(atUint8* data, atUint64 length)
{
m_data = data;
m_length = length;
m_position = 0;
if (length == 0)
{
atError("length cannot be 0");
setError();
return;
}
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_position = 0;
m_dataCopy.reset(new atUint8[m_length]);
m_data = m_dataCopy.get();
if (!m_data)
{
atError("Could not allocate memory!");
setError();
return;
}
memset(m_data, 0, m_length);
}
void MemoryWriter::seek(atInt64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0))
{
atError("Position outside stream bounds");
setError();
return;
}
if (m_position + position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
{
atError("data exceeds available buffer space");
setError();
return;
}
m_position = m_length - position;
break;
}
}
void MemoryCopyWriter::seek(atInt64 position, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin::Begin:
if (position < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
resize(position);
m_position = position;
break;
case SeekOrigin::Current:
if ((((atInt64)m_position + position) < 0))
{
atError("Position outside stream bounds");
setError();
return;
}
if (m_position + position > m_length)
resize(m_position + position);
m_position += position;
break;
case SeekOrigin::End:
if (((atInt64)m_length - position) < 0)
{
atError("Position outside stream bounds");
setError();
return;
}
if ((atUint64)position > m_length)
resize(position);
m_position = m_length - position;
break;
}
}
void MemoryWriter::setData(atUint8* data, atUint64 length)
{
m_data = (atUint8*)data;
m_length = length;
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* ret = new atUint8[m_length];
memset(ret, 0, m_length);
memcpy(ret, m_data, m_length);
return ret;
}
void MemoryWriter::save(const std::string& filename)
{
if (filename.empty() && m_filepath.empty())
{
atError("No file specified, cannot save.");
setError();
return;
}
if (!filename.empty())
m_filepath = filename;
FILE* out = fopen(m_filepath.c_str(), "wb");
if (!out)
{
atError("Unable to open file '%s'", m_filepath.c_str());
setError();
return;
}
atUint64 done = 0;
atUint64 blocksize = BLOCKSZ;
do
{
if (blocksize > m_length - done)
blocksize = m_length - done;
atInt64 ret = fwrite(m_data + done, 1, blocksize, out);
if (ret < 0)
{
atError("Error writing data to disk");
setError();
return;
}
else if (ret == 0)
break;
done += blocksize;
}
while (done < m_length);
fclose(out);
}
void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length)
{
if (!data)
{
atError("data cannnot be NULL");
setError();
return;
}
if (m_position + length > m_length)
{
atError("data length exceeds available buffer space");
setError();
return;
}
memcpy((atInt8*)(m_data + m_position), data, length);
m_position += length;
}
void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length)
{
if (!data)
{
atError("data cannnot be NULL");
setError();
return;
}
if (m_position + length > m_length)
resize(m_position + length);
memcpy((atInt8*)(m_data + m_position), data, length);
m_position += length;
}
void MemoryCopyWriter::resize(atUint64 newSize)
{
if (newSize < m_length)
{
atError("New size cannot be less to the old size.");
return;
}
// Allocate and copy new buffer
atUint8* newArray = new atUint8[newSize];
memset(newArray, 0, newSize);
if (m_dataCopy)
memcpy(newArray, m_dataCopy.get(), m_length);
m_dataCopy.reset(newArray);
// Swap the pointer and size out for the new ones.
m_data = newArray;
m_length = newSize;
}
} // io
} // Athena

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::MemoryCopyWriter 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::MemoryCopyWriter 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
{ {