mirror of https://github.com/libAthena/athena.git
made stream classes STL-customizable with a traits class
This commit is contained in:
parent
92898661cc
commit
fe1a489820
|
@ -32,10 +32,6 @@ endif()
|
|||
|
||||
add_library(AthenaCore
|
||||
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/Checksums.cpp
|
||||
src/Athena/Compression.cpp
|
||||
|
|
|
@ -563,9 +563,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
|
|||
for (int p=0 ; p<2 ; ++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
|
||||
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())
|
||||
{
|
||||
|
@ -1338,9 +1338,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
|
|||
for (int p=0 ; p<2 ; ++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
|
||||
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())
|
||||
{
|
||||
|
|
|
@ -20,16 +20,16 @@ namespace io
|
|||
|
||||
/* forward-declaration dance for recursively-derived types */
|
||||
|
||||
template <size_t sizeVar, Endian VE>
|
||||
template <size_t sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct Buffer;
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct String;
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct WString;
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct WStringAsString;
|
||||
|
||||
/**
|
||||
|
@ -40,9 +40,17 @@ struct WStringAsString;
|
|||
* with all read/write calls necessary to marshal the DNA structure to/from
|
||||
* a streamed medium
|
||||
*/
|
||||
template <Endian DNAE>
|
||||
template <Endian DNAE, typename STLTRAITS = StlTraits>
|
||||
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 write(IStreamWriter&) const=0;
|
||||
|
||||
|
@ -50,19 +58,19 @@ struct DNA
|
|||
using Value = T;
|
||||
|
||||
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>
|
||||
using Buffer = struct Athena::io::Buffer<sizeVar, DNAE>;
|
||||
using Buffer = struct Athena::io::Buffer<sizeVar, DNAE, STLTRAITS>;
|
||||
|
||||
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>
|
||||
using WString = struct Athena::io::WString<sizeVar, VE>;
|
||||
using WString = struct Athena::io::WString<sizeVar, VE, STLTRAITS>;
|
||||
|
||||
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>
|
||||
struct Seek {};
|
||||
|
@ -73,78 +81,78 @@ struct DNA
|
|||
struct Delete {};
|
||||
};
|
||||
|
||||
template <size_t sizeVar, Endian VE>
|
||||
struct Buffer : public DNA<VE>, public std::unique_ptr<atUint8[]>
|
||||
template <size_t sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct Buffer : public DNA<VE, STLTRAITS>, public std::unique_ptr<atUint8[]>
|
||||
{
|
||||
typename DNA<VE>::Delete expl;
|
||||
inline void read(IStreamReader& reader)
|
||||
inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
|
||||
{
|
||||
reset(new atUint8[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);
|
||||
}
|
||||
};
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
struct String : public DNA<VE>, public std::string
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct String : public DNA<VE, STLTRAITS>, public STLTRAITS::String
|
||||
{
|
||||
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)));}
|
||||
inline void write(IStreamWriter& writer) const
|
||||
inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
|
||||
{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);}
|
||||
inline std::string& operator=(std::string&& __str)
|
||||
inline typename STLTRAITS::String& operator=(typename STLTRAITS::String&& __str)
|
||||
{this->swap(__str); return *this;}
|
||||
};
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
struct WString : public DNA<VE>, public std::wstring
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct WString : public DNA<VE, STLTRAITS>, public STLTRAITS::WString
|
||||
{
|
||||
typename DNA<VE>::Delete expl;
|
||||
inline void read(IStreamReader& reader)
|
||||
inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
|
||||
{
|
||||
reader.setEndian(VE);
|
||||
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.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);}
|
||||
inline std::wstring& operator=(std::wstring&& __str)
|
||||
inline typename STLTRAITS::WString& operator=(typename STLTRAITS::WString&& __str)
|
||||
{this->swap(__str); return *this;}
|
||||
};
|
||||
|
||||
template <atInt32 sizeVar, Endian VE>
|
||||
struct WStringAsString : public DNA<VE>, public std::string
|
||||
template <atInt32 sizeVar, Endian VE, typename STLTRAITS>
|
||||
struct WStringAsString : public DNA<VE, STLTRAITS>, public STLTRAITS::String
|
||||
{
|
||||
typename DNA<VE>::Delete expl;
|
||||
inline void read(IStreamReader& reader)
|
||||
inline void read(typename DNA<VE, STLTRAITS>::IStreamReader& reader)
|
||||
{*this = reader.readWStringAsString(sizeVar);}
|
||||
inline void write(IStreamWriter& writer) const
|
||||
inline void write(typename DNA<VE, STLTRAITS>::IStreamWriter& writer) const
|
||||
{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);}
|
||||
inline std::string& operator=(std::string&& __str)
|
||||
inline typename STLTRAITS::String& operator=(typename STLTRAITS::String&& __str)
|
||||
{this->swap(__str); return *this;}
|
||||
};
|
||||
|
||||
/** Macro to automatically declare read/write methods in subclasses */
|
||||
#define DECL_DNA \
|
||||
void read(Athena::io::IStreamReader&); \
|
||||
void write(Athena::io::IStreamWriter&) const; \
|
||||
void read(IStreamReader&); \
|
||||
void write(IStreamWriter&) const; \
|
||||
|
||||
/** Macro to automatically declare read/write methods and prevent outputting implementation */
|
||||
#define DECL_EXPLICIT_DNA \
|
||||
void read(Athena::io::IStreamReader&); \
|
||||
void write(Athena::io::IStreamWriter&) const; \
|
||||
void read(IStreamReader&); \
|
||||
void write(IStreamWriter&) const; \
|
||||
Delete __dna_delete;
|
||||
|
||||
/** Macro to supply count variable to atdna and mute it for other compilers */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,36 +6,210 @@
|
|||
#include <stdio.h>
|
||||
#include "Athena/IStreamReader.hpp"
|
||||
|
||||
#if _WIN32
|
||||
#include "win32_largefilewrapper.h"
|
||||
#elif __APPLE__
|
||||
#include "osx_largefilewrapper.h"
|
||||
#endif
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class FileReader : public IStreamReader
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class FileReader : public IStreamReader<STLTRAITS>
|
||||
{
|
||||
public:
|
||||
FileReader(const std::string& filename, atInt32 cacheSize = (32 * 1024));
|
||||
#if _WIN32
|
||||
FileReader(const std::wstring& filename, atInt32 cacheSize = (32 * 1024));
|
||||
#endif
|
||||
virtual ~FileReader();
|
||||
inline const std::string& filename() const
|
||||
inline const typename STLTRAITS::String& filename() const
|
||||
{return m_filename;}
|
||||
|
||||
void open();
|
||||
void close();
|
||||
inline bool isOpen() const
|
||||
{return m_fileHandle != NULL;}
|
||||
bool save();
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
atUint64 position() const;
|
||||
atUint64 length() const;
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len);
|
||||
FileReader(const typename STLTRAITS::String& filename, atInt32 cacheSize = (32 * 1024))
|
||||
: m_filename(filename),
|
||||
m_fileHandle(nullptr),
|
||||
m_cacheData(nullptr),
|
||||
m_offset(0)
|
||||
{
|
||||
open();
|
||||
setCacheSize(cacheSize);
|
||||
}
|
||||
|
||||
#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:
|
||||
std::string m_filename;
|
||||
typename STLTRAITS::String m_filename;
|
||||
#if _WIN32
|
||||
std::wstring m_wfilename;
|
||||
typename STLTRAITS::WString m_wfilename;
|
||||
#endif
|
||||
FILE* m_fileHandle;
|
||||
std::unique_ptr<atUint8[]> m_cacheData;
|
||||
|
|
|
@ -4,32 +4,136 @@
|
|||
#include "Athena/IStreamWriter.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
#if _WIN32
|
||||
#include "win32_largefilewrapper.h"
|
||||
#elif __APPLE__
|
||||
#include "osx_largefilewrapper.h"
|
||||
#endif
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class FileWriter : public IStreamWriter
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class FileWriter : public IStreamWriter<STLTRAITS>
|
||||
{
|
||||
public:
|
||||
FileWriter(const std::string& filename, bool overwrite = true);
|
||||
#if _WIN32
|
||||
FileWriter(const std::wstring& filename, bool overwrite = true);
|
||||
#endif
|
||||
virtual ~FileWriter();
|
||||
inline bool isOpen() const {return m_fileHandle != NULL;}
|
||||
|
||||
void open(bool overwrite = true);
|
||||
void close();
|
||||
inline bool isOpen() const
|
||||
{return m_fileHandle != NULL;}
|
||||
void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current);
|
||||
atUint64 position() const;
|
||||
atUint64 length() const;
|
||||
void writeUBytes(const atUint8* data, atUint64 len);
|
||||
FileWriter(const std::string& filename, bool overwrite = true)
|
||||
: m_filename(filename),
|
||||
m_fileHandle(NULL),
|
||||
m_bytePosition(0)
|
||||
{
|
||||
open(overwrite);
|
||||
}
|
||||
|
||||
#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:
|
||||
std::string m_filename;
|
||||
typename STLTRAITS::String m_filename;
|
||||
#if _WIN32
|
||||
std::wstring m_wfilename;
|
||||
typename STLTRAITS::WString m_wfilename;
|
||||
#endif
|
||||
FILE* m_fileHandle;
|
||||
atUint8 m_currentByte;
|
||||
|
|
|
@ -60,6 +60,13 @@ typedef struct stat64 stat64_t;
|
|||
|
||||
namespace Athena
|
||||
{
|
||||
struct StlTraits
|
||||
{
|
||||
template<typename T> using Vector = std::vector<T>;
|
||||
using String = std::string;
|
||||
using WString = std::wstring;
|
||||
};
|
||||
|
||||
namespace error
|
||||
{
|
||||
enum Level
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef ISTREAMREADER_HPP
|
||||
#define ISTREAMREADER_HPP
|
||||
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "IStream.hpp"
|
||||
|
||||
|
@ -10,6 +9,7 @@ namespace Athena
|
|||
{
|
||||
namespace io
|
||||
{
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class IStreamReader : public IStream
|
||||
{
|
||||
public:
|
||||
|
@ -589,9 +589,9 @@ public:
|
|||
* \return std::string The value at the current address
|
||||
* \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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -603,20 +603,21 @@ public:
|
|||
if (!chr)
|
||||
break;
|
||||
|
||||
tmp.push_back(chr);
|
||||
char mb[4];
|
||||
int c = std::wctomb(mb, chr);
|
||||
retval.append(mb, c);
|
||||
chr = readUint16();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(tmp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -628,20 +629,21 @@ public:
|
|||
if (!chr)
|
||||
break;
|
||||
|
||||
tmp.push_back(chr);
|
||||
char mb[4];
|
||||
int c = std::wctomb(mb, chr);
|
||||
retval.append(mb, c);
|
||||
chr = readUint16Little();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(tmp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -653,15 +655,16 @@ public:
|
|||
if (!chr)
|
||||
break;
|
||||
|
||||
tmp.push_back(chr);
|
||||
char mb[4];
|
||||
int c = std::wctomb(mb, chr);
|
||||
retval.append(mb, c);
|
||||
chr = readUint16Big();
|
||||
}
|
||||
|
||||
if (fixedLen >= 0 && i < fixedLen)
|
||||
seek(fixedLen - i);
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(tmp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! \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
|
||||
* \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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -692,18 +695,18 @@ public:
|
|||
return ret;
|
||||
}
|
||||
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();}
|
||||
|
||||
/*! \brief Reads a wstring and advances the position in the file
|
||||
*
|
||||
* \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
|
||||
*/
|
||||
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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -723,12 +726,12 @@ public:
|
|||
return ret;
|
||||
}
|
||||
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();}
|
||||
|
||||
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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -748,12 +751,12 @@ public:
|
|||
return ret;
|
||||
}
|
||||
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();}
|
||||
|
||||
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();
|
||||
|
||||
atInt32 i;
|
||||
|
@ -773,11 +776,11 @@ public:
|
|||
return ret;
|
||||
}
|
||||
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();}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -790,7 +793,7 @@ public:
|
|||
}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -803,7 +806,7 @@ public:
|
|||
}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -816,7 +819,7 @@ public:
|
|||
}
|
||||
|
||||
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 &&
|
||||
!std::is_same<T, atVec2f>::value &&
|
||||
!std::is_same<T, atVec3f>::value &&
|
||||
|
@ -832,7 +835,8 @@ public:
|
|||
}
|
||||
|
||||
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.reserve(count);
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Athena
|
|||
{
|
||||
namespace io
|
||||
{
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class IStreamWriter : public IStream
|
||||
{
|
||||
public:
|
||||
|
@ -436,116 +437,107 @@ public:
|
|||
* \param str The string to write to the buffer
|
||||
* \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;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp = conv.from_bytes(tmpStr);
|
||||
typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
|
||||
const char* buf = tmpStr.c_str();
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
while (*buf)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16(chr);
|
||||
wchar_t wc;
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
if (wc != 0xFEFF)
|
||||
writeUint16(wc);
|
||||
}
|
||||
writeUint16(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
wchar_t wc = 0;
|
||||
if (*buf)
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
if (wc == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
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;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp = conv.from_bytes(tmpStr);
|
||||
typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
|
||||
const char* buf = tmpStr.c_str();
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
while (*buf)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16Little(chr);
|
||||
wchar_t wc;
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
if (wc != 0xFEFF)
|
||||
writeUint16Little(wc);
|
||||
}
|
||||
writeUint16Little(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
wchar_t wc = 0;
|
||||
if (*buf)
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
if (wc == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
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;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp = conv.from_bytes(tmpStr);
|
||||
typename STLTRAITS::String tmpStr = "\xEF\xBB\xBF" + str;
|
||||
const char* buf = tmpStr.c_str();
|
||||
|
||||
if (fixedLen < 0)
|
||||
{
|
||||
for (atUint16 chr : tmp)
|
||||
while (*buf)
|
||||
{
|
||||
if (chr != 0xFEFF)
|
||||
writeUint16Big(chr);
|
||||
wchar_t wc;
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
if (wc != 0xFEFF)
|
||||
writeUint16Big(wc);
|
||||
}
|
||||
writeUint16Big(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tmp.begin();
|
||||
for (atInt32 i=0 ; i<fixedLen ; ++i)
|
||||
{
|
||||
atUint16 chr;
|
||||
if (it == tmp.end())
|
||||
chr = 0;
|
||||
else
|
||||
chr = *it++;
|
||||
wchar_t wc = 0;
|
||||
if (*buf)
|
||||
buf += std::mbtowc(&wc, buf, MB_CUR_MAX);
|
||||
|
||||
if (chr == 0xFEFF)
|
||||
if (wc == 0xFEFF)
|
||||
{
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
writeUint16Big(chr);
|
||||
writeUint16Big(wc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +548,7 @@ public:
|
|||
* \param str The string to write to the buffer
|
||||
* \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)
|
||||
{
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -591,7 +583,7 @@ public:
|
|||
* \param str The string to write to the buffer
|
||||
* \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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{for (atUint64 l=0 ; l<length ; ++l) writeUBytes(&val, 1);}
|
||||
|
@ -684,7 +676,7 @@ public:
|
|||
{fill((atUint8)val, length);}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -695,7 +687,7 @@ public:
|
|||
}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -706,7 +698,7 @@ public:
|
|||
}
|
||||
|
||||
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 ||
|
||||
std::is_same<T, atVec2f>::value ||
|
||||
std::is_same<T, atVec3f>::value ||
|
||||
|
@ -717,7 +709,7 @@ public:
|
|||
}
|
||||
|
||||
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 &&
|
||||
!std::is_same<T, atVec2f>::value &&
|
||||
!std::is_same<T, atVec3f>::value &&
|
||||
|
|
|
@ -18,10 +18,16 @@ namespace io
|
|||
* this allows for fast, flexible code as well as the ability to quickly modify data
|
||||
* \sa Stream
|
||||
*/
|
||||
class MemoryReader : public IStreamReader
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class MemoryReader : public IStreamReader<STLTRAITS>
|
||||
{
|
||||
using base = IStreamReader<STLTRAITS>;
|
||||
public:
|
||||
virtual ~MemoryReader();
|
||||
virtual ~MemoryReader()
|
||||
{
|
||||
if (m_owns)
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
/*! \brief This constructor references an existing buffer to read from.
|
||||
*
|
||||
|
@ -29,28 +35,82 @@ public:
|
|||
* \param length The length of the existing buffer
|
||||
* \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 />
|
||||
* It seeks relative to the current position by default.
|
||||
* \param position where in the buffer to seek
|
||||
* \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.
|
||||
*
|
||||
* \return Int64 The current position in the stream.
|
||||
*/
|
||||
inline atUint64 position() const
|
||||
{return m_position;}
|
||||
inline atUint64 position() const {return m_position;}
|
||||
|
||||
/*! \brief Returns whether or not the stream is at the end.
|
||||
*
|
||||
* \return bool True if at end; False otherwise.
|
||||
*/
|
||||
inline atUint64 length() const
|
||||
{return m_length;}
|
||||
inline atUint64 length() const {return m_length;}
|
||||
|
||||
|
||||
/*! \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
|
||||
* \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 />
|
||||
|
@ -73,14 +141,32 @@ public:
|
|||
* as Stream now owns the address, this is done to keep memory usage down.
|
||||
* \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
|
||||
* \param buf User-allocated buffer pointer
|
||||
* \param len Length to read
|
||||
* \param length Length to 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:
|
||||
const atUint8* m_data;
|
||||
|
@ -89,29 +175,105 @@ protected:
|
|||
bool m_owns;
|
||||
};
|
||||
|
||||
class MemoryCopyReader : public MemoryReader
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class MemoryCopyReader : public MemoryReader<STLTRAITS>
|
||||
{
|
||||
using base = MemoryReader<STLTRAITS>;
|
||||
public:
|
||||
/*! \brief This constructor copies an existing buffer to read from.
|
||||
*
|
||||
* \param data 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.
|
||||
*
|
||||
* \param filename The file to create the stream from
|
||||
*/
|
||||
MemoryCopyReader(const std::string& filename)
|
||||
: MemoryReader(NULL, 0),
|
||||
: base(NULL, 0),
|
||||
m_filepath(filename)
|
||||
{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:
|
||||
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::string m_filepath; //!< Path to the target file
|
||||
};
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace io
|
|||
* this allows for fast, flexible code as well as the ability to quickly modify data
|
||||
* \sa Stream
|
||||
*/
|
||||
class MemoryWriter : public IStreamWriter
|
||||
template<typename STLTRAITS = StlTraits>
|
||||
class MemoryWriter : public IStreamWriter<STLTRAITS>
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -28,14 +29,90 @@ public:
|
|||
* \param data 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 />
|
||||
* It seeks relative to the current position by default.
|
||||
* \param position where in the buffer to seek
|
||||
* \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.
|
||||
|
@ -63,7 +140,12 @@ public:
|
|||
* \param length The length of the new buffer.
|
||||
* \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 />
|
||||
|
@ -73,7 +155,13 @@ public:
|
|||
* as Stream now owns the address, this is done to keep memory usage down.
|
||||
* \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
|
||||
*
|
||||
|
@ -93,7 +181,52 @@ public:
|
|||
*
|
||||
* \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
|
||||
* 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 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:
|
||||
MemoryWriter() {}
|
||||
|
@ -111,8 +263,10 @@ protected:
|
|||
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:
|
||||
|
||||
/*! \brief This constructor copies an existing buffer to write to.
|
||||
|
@ -120,20 +274,100 @@ public:
|
|||
* \param data 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.
|
||||
*
|
||||
* \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 />
|
||||
* It seeks relative to the current position by default.
|
||||
* \param position where in the buffer to seek
|
||||
* \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 />
|
||||
* <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.
|
||||
* \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
|
||||
* 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 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:
|
||||
std::unique_ptr<atUint8[]> m_dataCopy;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -39,330 +39,12 @@ void HandleYAMLEmitterError(yaml_emitter_t* emitter)
|
|||
atError("YAML error: %s: %s", ErrorString(emitter->error), emitter->problem?emitter->problem:"");
|
||||
}
|
||||
|
||||
int YAMLStdStringReader(YAMLStdStringReaderState* reader,
|
||||
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 =
|
||||
const char* AT_BASE64_CHARS =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ bool FileInfo::touch() const
|
|||
#if defined(__GNUC__) && !(defined(HW_DOL) || defined(HW_RVL) || defined(GEKKO))
|
||||
stat64_t st;
|
||||
if (stat64(m_path.c_str(), &st) < 0) {
|
||||
(void)Athena::io::FileWriter(m_path);
|
||||
(void)Athena::io::FileWriter<>(m_path);
|
||||
return true;
|
||||
}
|
||||
if (utimes(m_path.c_str(), NULL) < 0) {
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -16,7 +16,7 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe
|
|||
atUint32 encodeSize = (srcLength << 8) | (0x10);
|
||||
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);
|
||||
|
||||
atUint8* ptrStart = (atUint8*)src;
|
||||
|
|
|
@ -13,7 +13,7 @@ LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimum
|
|||
|
||||
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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue