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
|
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
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 &&
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
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;
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue