#ifndef ISTREAMREADER_HPP #define ISTREAMREADER_HPP #include #include #include "utf8proc.h" #include "IStream.hpp" namespace athena { namespace io { /** @brief The IStreamReader class defines a basic API for reading from streams, Implementors are provided with one pure virtual * function that must be implemented in order to interact with the stream. * * Most implementing classes will only need to implement IStreamReader::readUBytesToBuf(void*, atUint64) for basic stream intearaction */ class IStreamReader : public IStream { public: virtual ~IStreamReader() {} /** @brief Sets the Endianness of the stream * * @param endian The Endianness to set */ inline void setEndian(Endian endian) {m_endian = endian;} /** @brief Returns the current Endianness of the stream * * @return The current Stream Endianness */ inline Endian endian() const {return m_endian;} /** @brief Returns whether the stream is BigEndian * * @return bool True for BigEndian; False for LittleEndian */ inline bool isBigEndian() const {return (m_endian == Endian::BigEndian);} /** @brief Returns whether the stream is LittleEndian * * @return True for LittleEndian; False for BigEndian */ inline bool isLittleEndian()const {return (m_endian == Endian::LittleEndian);} /** @brief Sets the buffers position relative to the specified position.
* It seeks relative to the current position by default. * @param position where in the buffer to seek * @param origin The Origin to seek relative to */ virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0; /** @brief Sets the buffer's position relative to the next 64-byte aligned position.
*/ inline void seekAlign64() {seek(ROUND_UP_64(position()), SeekOrigin::Begin);} /** @brief Sets the buffers position relative to the next 32-byte aligned position.
*/ inline void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);} /** @brief Sets the buffer's position relative to the next 16-byte aligned position.
*/ inline void seekAlign16() {seek(ROUND_UP_16(position()), SeekOrigin::Begin); } /** @brief Returns whether or not the stream is at the end. * * @return True if at end; False otherwise. */ inline bool atEnd() const {return position() >= length();} /** @brief Returns the current position in the stream. * * @return The current position in the stream. */ virtual atUint64 position() const=0; /** @brief Returns the length of the file. * * @return True length of the file. */ virtual atUint64 length() const=0; /** @brief Reads a byte at the current position and advances the current position * * @return The value at the current position */ inline atInt8 readByte() {atInt8 val; readUBytesToBuf(&val, 1); return val;} template inline atInt8 readVal(typename std::enable_if::value>::type* = 0) {return readByte();} template inline atInt8 readValLittle(typename std::enable_if::value>::type* = 0) {return readByte();} template inline atInt8 readValBig(typename std::enable_if::value>::type* = 0) {return readByte();} /** @brief Reads a byte at the current position and advances the current position * * @return The value at the current position */ inline atUint8 readUByte() {return readByte();} template inline atUint8 readVal(typename std::enable_if::value>::type* = 0) {return readUByte();} template inline atUint8 readValLittle(typename std::enable_if::value>::type* = 0) {return readUByte();} template inline atUint8 readValBig(typename std::enable_if::value>::type* = 0) {return readUByte();} /** @brief Reads a byte at the current position and advances the current position. * * @return The buffer at the current position from the given length. */ inline std::unique_ptr readBytes(atUint64 length) { atInt8* buf = new atInt8[length]; readUBytesToBuf(buf, length); return std::unique_ptr(buf); } /** @brief Reads a byte at the current position and advances the current position. * * @return The buffer at the current position from the given length. */ inline std::unique_ptr readUBytes(atUint64 length) { atUint8* buf = new atUint8[length]; readUBytesToBuf(buf, length); return std::unique_ptr(buf); } /** @brief Attempts to read a fixed length of data into a pre-allocated buffer. * @param buf The buffer to read into * @param len The length of the buffer * @return How much data was actually read, useful for detecting read errors. */ inline atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);} /** @brief Attempts to read a fixed length of data into a pre-allocated buffer, this function is client defined * and must be implemented. * @param buf The buffer to read into * @param len The length of the buffer * @return How much data was actually read, useful for detecting read errors. */ virtual atUint64 readUBytesToBuf(void* buf, atUint64 len)=0; /** @brief Reads a Int16 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atInt16 readInt16() { atInt16 val; readUBytesToBuf(&val, 2); return m_endian == BigEndian ? utility::BigInt16(val) : utility::LittleInt16(val); } template inline atInt16 readVal(typename std::enable_if::value>::type* = 0) {return readInt16();} /** @brief Reads a Int16 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt16 readInt16Little() { atInt16 val; readUBytesToBuf(&val, 2); return utility::LittleInt16(val); } template inline atInt16 readValLittle(typename std::enable_if::value>::type* = 0) {return readInt16Little();} /** @brief Reads a Int16 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt16 readInt16Big() { atInt16 val; readUBytesToBuf(&val, 2); return utility::BigInt16(val); } template inline atInt16 readValBig(typename std::enable_if::value>::type* = 0) {return readInt16Big();} /** @brief Reads a Uint16 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atUint16 readUint16() {return readInt16();} template inline atUint16 readVal(typename std::enable_if::value>::type* = 0) {return readUint16();} /** @brief Reads a Uint16 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint16 readUint16Little() { atUint16 val; readUBytesToBuf(&val, 2); return utility::LittleUint16(val); } template inline atUint16 readValLittle(typename std::enable_if::value>::type* = 0) {return readUint16Little();} /** @brief Reads a Uint16 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint16 readUint16Big() { atUint16 val; readUBytesToBuf(&val, 2); return utility::BigUint16(val); } template inline atUint16 readValBig(typename std::enable_if::value>::type* = 0) {return readUint16Big();} /** @brief Reads a Int32 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atInt32 readInt32() { atInt32 val; readUBytesToBuf(&val, 4); return m_endian == BigEndian ? utility::BigInt32(val) : utility::LittleInt32(val); } template inline atInt32 readVal(typename std::enable_if::value>::type* = 0) {return readInt32();} /** @brief Reads a Int32 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt32 readInt32Little() { atInt32 val; readUBytesToBuf(&val, 4); return utility::LittleInt32(val); } template inline atInt32 readValLittle(typename std::enable_if::value>::type* = 0) {return readInt32Little();} /** @brief Reads a Int32 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt32 readInt32Big() { atInt32 val; readUBytesToBuf(&val, 4); return utility::BigInt32(val); } template inline atInt32 readValBig(typename std::enable_if::value>::type* = 0) {return readInt32Big();} /** @brief Reads a Uint32 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atUint32 readUint32() {return readInt32();} template inline atUint32 readVal(typename std::enable_if::value>::type* = 0) {return readUint32();} /** @brief Reads a Uint32 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint32 readUint32Little() { atUint32 val; readUBytesToBuf(&val, 4); return utility::LittleUint32(val); } template inline atInt32 readValLittle(typename std::enable_if::value>::type* = 0) {return readUint32Little();} /** @brief Reads a Uint32 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint32 readUint32Big() { atUint32 val; readUBytesToBuf(&val, 4); return utility::BigUint32(val); } template inline atUint32 readValBig(typename std::enable_if::value>::type* = 0) {return readUint32Big();} /** @brief Reads a Int64 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atInt64 readInt64() { atInt64 val; readUBytesToBuf(&val, 8); return m_endian == BigEndian ? utility::BigInt64(val) : utility::LittleInt64(val); } template inline atInt64 readVal(typename std::enable_if::value>::type* = 0) {return readInt64();} /** @brief Reads a Int64 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt64 readInt64Little() { atInt64 val; readUBytesToBuf(&val, 8); return utility::LittleInt64(val); } template inline atInt64 readValLittle(typename std::enable_if::value>::type* = 0) {return readInt64Little();} /** @brief Reads a Int64 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atInt64 readInt64Big() { atInt64 val; readUBytesToBuf(&val, 8); return utility::BigInt64(val); } template inline atInt64 readValBig(typename std::enable_if::value>::type* = 0) {return readInt64Big();} /** @brief Reads a Uint64 and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atUint64 readUint64() {return readInt64();} template inline atUint64 readVal(typename std::enable_if::value>::type* = 0) {return readUint64();} /** @brief Reads a Uint64 and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint64 readUint64Little() { atUint64 val; readUBytesToBuf(&val, 8); return utility::LittleUint64(val); } template inline atUint64 readValLittle(typename std::enable_if::value>::type* = 0) {return readUint64Little();} /** @brief Reads a Uint64 and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atUint64 readUint64Big() { atUint64 val; readUBytesToBuf(&val, 8); return utility::BigUint64(val); } template inline atUint64 readValBig(typename std::enable_if::value>::type* = 0) {return readUint64Big();} /** @brief Reads a float and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline float readFloat() { float val; readUBytesToBuf(&val, 4); return m_endian == BigEndian ? utility::BigFloat(val) : utility::LittleFloat(val); } template inline float readVal(typename std::enable_if::value>::type* = 0) {return readFloat();} /** @brief Reads a float and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline float readFloatLittle() { float val; readUBytesToBuf(&val, 4); return utility::LittleFloat(val); } template inline float readValLittle(typename std::enable_if::value>::type* = 0) {return readFloatLittle();} /** @brief Reads a float and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline float readFloatBig() { float val; readUBytesToBuf(&val, 4); return utility::BigFloat(val); } template inline float readValBig(typename std::enable_if::value>::type* = 0) {return readFloatBig();} /** @brief Reads a double and swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline double readDouble() { double val; readUBytesToBuf(&val, 8); return m_endian == BigEndian ? utility::BigDouble(val) : utility::LittleDouble(val); } template inline double readVal(typename std::enable_if::value>::type* = 0) {return readDouble();} /** @brief Reads a double and swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline double readDoubleLittle() { double val; readUBytesToBuf(&val, 8); return utility::LittleDouble(val); } template inline double readValLittle(typename std::enable_if::value>::type* = 0) {return readDoubleLittle();} /** @brief Reads a double and swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline double readDoubleBig() { double val; readUBytesToBuf(&val, 8); return utility::BigDouble(val); } template inline double readValBig(typename std::enable_if::value>::type* = 0) {return readDoubleBig();} /** @brief Reads a bool and advances the current position * * @return The value at the current address */ inline bool readBool() { atUint8 val; readUBytesToBuf(&val, 1); return val != 0; } template inline bool readVal(typename std::enable_if::value>::type* = 0) {return readBool();} template inline bool readValLittle(typename std::enable_if::value>::type* = 0) {return readBool();} template inline bool readValBig(typename std::enable_if::value>::type* = 0) {return readBool();} /** @brief Reads an atVec2f (8 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2f readVec2f() { atVec2f val; readUBytesToBuf(&val, 8); if (m_endian == BigEndian) { utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); } else { utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); } return val; } template inline atVec2f readVal(typename std::enable_if::value>::type* = 0) {return readVec2f();} /** @brief Reads an atVec2f (8 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2f readVec2fLittle() { atVec2f val; readUBytesToBuf(&val, 8); utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); return val; } template inline atVec2f readValLittle(typename std::enable_if::value>::type* = 0) {return readVec2fLittle();} /** @brief Reads an atVec2f (8 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2f readVec2fBig() { atVec2f val; readUBytesToBuf(&val, 8); utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); return val; } template inline atVec2f readValBig(typename std::enable_if::value>::type* = 0) {return readVec2fBig();} /** @brief Reads an atVec3f (12 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3f readVec3f() { atVec3f val; readUBytesToBuf(&val, 12); if (m_endian == BigEndian) { utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); utility::BigFloat(val.vec[2]); } else { utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); utility::LittleFloat(val.vec[2]); } return val; } template inline atVec3f readVal(typename std::enable_if::value>::type* = 0) {return readVec3f();} /** @brief Reads an atVec3f (12 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3f readVec3fLittle() { atVec3f val; readUBytesToBuf(&val, 12); utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); utility::LittleFloat(val.vec[2]); return val; } template inline atVec3f readValLittle(typename std::enable_if::value>::type* = 0) {return readVec3fLittle();} /** @brief Reads an atVec3f (12 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3f readVec3fBig() { atVec3f val; readUBytesToBuf(&val, 12); utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); utility::BigFloat(val.vec[2]); return val; } template inline atVec3f readValBig(typename std::enable_if::value>::type* = 0) {return readVec3fBig();} /** @brief Reads an atVec4f (16 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4f readVec4f() { atVec4f val; readUBytesToBuf(&val, 16); if (m_endian == BigEndian) { utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); utility::BigFloat(val.vec[2]); utility::BigFloat(val.vec[3]); } else { utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); utility::LittleFloat(val.vec[2]); utility::LittleFloat(val.vec[3]); } return val; } template inline atVec4f readVal(typename std::enable_if::value>::type* = 0) {return readVec4f();} /** @brief Reads an atVec4f (16 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4f readVec4fLittle() { atVec4f val; readUBytesToBuf(&val, 16); utility::LittleFloat(val.vec[0]); utility::LittleFloat(val.vec[1]); utility::LittleFloat(val.vec[2]); utility::LittleFloat(val.vec[3]); return val; } template inline atVec4f readValLittle(typename std::enable_if::value>::type* = 0) {return readVec4fLittle();} /** @brief Reads an atVec4f (16 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4f readVec4fBig() { atVec4f val; readUBytesToBuf(&val, 16); utility::BigFloat(val.vec[0]); utility::BigFloat(val.vec[1]); utility::BigFloat(val.vec[2]); utility::BigFloat(val.vec[3]); return val; } template inline atVec4f readValBig(typename std::enable_if::value>::type* = 0) {return readVec4fBig();} /** @brief Reads an atVec2d (16 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2d readVec2d() { atVec2d val; readUBytesToBuf(&val, 16); if (m_endian == BigEndian) { utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); } else { utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); } return val; } template inline atVec2d readVal(typename std::enable_if::value>::type* = 0) {return readVec2d();} /** @brief Reads an atVec2d (16 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2d readVec2dLittle() { atVec2d val; readUBytesToBuf(&val, 16); utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); return val; } template inline atVec2d readValLittle(typename std::enable_if::value>::type* = 0) {return readVec2dLittle();} /** @brief Reads an atVec2d (16 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec2d readVec2dBig() { atVec2d val; readUBytesToBuf(&val, 16); utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); return val; } template inline atVec2d readValBig(typename std::enable_if::value>::type* = 0) {return readVec2dBig();} /** @brief Reads an atVec3d (24 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3d readVec3d() { atVec3d val; readUBytesToBuf(&val, 24); if (m_endian == BigEndian) { utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); utility::BigDouble(val.vec[2]); } else { utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); utility::LittleDouble(val.vec[2]); } return val; } template inline atVec3d readVal(typename std::enable_if::value>::type* = 0) {return readVec3d();} /** @brief Reads an atVec3d (24 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3d readVec3dLittle() { atVec3d val; readUBytesToBuf(&val, 24); utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); utility::LittleDouble(val.vec[2]); return val; } template inline atVec3d readValLittle(typename std::enable_if::value>::type* = 0) {return readVec3dLittle();} /** @brief Reads an atVec3d (24 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec3d readVec3dBig() { atVec3d val; readUBytesToBuf(&val, 24); utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); utility::BigDouble(val.vec[2]); return val; } template inline atVec3d readValBig(typename std::enable_if::value>::type* = 0) {return readVec3dBig();} /** @brief Reads an atVec4d (32 bytes), swaps to endianness specified by setEndian depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4d readVec4d() { atVec4d val; readUBytesToBuf(&val, 32); if (m_endian == BigEndian) { utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); utility::BigDouble(val.vec[2]); utility::BigDouble(val.vec[3]); } else { utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); utility::LittleDouble(val.vec[2]); utility::LittleDouble(val.vec[3]); } return val; } template inline atVec4d readVal(typename std::enable_if::value>::type* = 0) {return readVec4d();} /** @brief Reads an atVec4d (32 bytes), swaps against little endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4d readVec4dLittle() { atVec4d val; readUBytesToBuf(&val, 32); utility::LittleDouble(val.vec[0]); utility::LittleDouble(val.vec[1]); utility::LittleDouble(val.vec[2]); utility::LittleDouble(val.vec[3]); return val; } template inline atVec4d readValLittle(typename std::enable_if::value>::type* = 0) {return readVec4dLittle();} /** @brief Reads an atVec4d (32 bytes), swaps against big endianness depending on platform * and advances the current position * * @return The value at the current address */ inline atVec4d readVec4dBig() { atVec4d val; readUBytesToBuf(&val, 32); utility::BigDouble(val.vec[0]); utility::BigDouble(val.vec[1]); utility::BigDouble(val.vec[2]); utility::BigDouble(val.vec[3]); return val; } template inline atVec4d readValBig(typename std::enable_if::value>::type* = 0) {return readVec4dBig();} /** @brief Reads a wide-char string (using endianness from setEndian), * converts to UTF8 and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read string */ inline std::string readWStringAsString(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::string(); std::string retval; atUint16 chr = readUint16(); atInt32 i; for (i=0 ;; ++i) { if (fixedLen >= 0 && i >= fixedLen - 1) break; if (!chr) break; utf8proc_uint8_t mb[4]; utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(chr), mb); if (c < 0) { atWarning("invalid UTF-8 character while encoding"); return retval; } retval.append(reinterpret_cast(mb), c); chr = readUint16(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return retval; } /** @brief Reads a wide-char string (against little-endian), * converts to UTF8 and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read string */ inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::string(); std::string retval; atUint16 chr = readUint16Little(); atInt32 i; for (i=0 ;; ++i) { if (fixedLen >= 0 && i >= fixedLen - 1) break; if (!chr) break; utf8proc_uint8_t mb[4]; utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(chr), mb); if (c < 0) { atWarning("invalid UTF-8 character while encoding"); return retval; } retval.append(reinterpret_cast(mb), c); chr = readUint16Little(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return retval; } /** @brief Reads a wide-char string (against big-endian), * converts to UTF8 and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read string */ inline std::string readWStringAsStringBig(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::string(); std::string retval; atUint16 chr = readUint16Big(); atInt32 i; for (i = 0 ;; ++i) { if (fixedLen >= 0 && i >= fixedLen - 1) break; if (!chr) break; utf8proc_uint8_t mb[4]; utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(chr), mb); if (c < 0) { atWarning("invalid UTF-8 character while encoding"); return retval; } retval.append(reinterpret_cast(mb), c); chr = readUint16Big(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return retval; } /** @brief Reads a string and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read string */ inline std::string readString(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::string(); std::string ret; atUint8 chr = readByte(); atInt32 i; for (i = 1 ; chr != 0 ; ++i) { ret += chr; if (fixedLen >= 0 && i >= fixedLen) break; chr = readByte(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return ret; } template inline std::string readVal(typename std::enable_if::value>::type* = 0) {return readString();} /** @brief Reads a wstring and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read wstring */ inline std::wstring readWString(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::wstring(); std::wstring ret; atUint16 chr = readUint16(); atInt32 i; for (i = 1 ; chr != 0 ; ++i) { ret += chr; if (fixedLen >= 0 && i >= fixedLen) break; chr = readUint16(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return ret; } template inline std::wstring readVal(typename std::enable_if::value>::type* = 0) {return readWString();} /** @brief Reads a wstring assuming little-endian characters * and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read wstring */ inline std::wstring readWStringLittle(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::wstring(); std::wstring ret; atUint16 chr = readUint16Little(); atInt32 i; for (i = 1 ; chr != 0 ; ++i) { ret += chr; if (fixedLen >= 0 && i >= fixedLen) break; chr = readUint16Little(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return ret; } template inline std::wstring readValLittle(typename std::enable_if::value>::type* = 0) {return readWStringLittle();} /** @brief Reads a wstring assuming big-endian characters * and advances the position in the file * * @param fixedLen If non-negative, this is a fixed-length string read * @return The read wstring */ inline std::wstring readWStringBig(atInt32 fixedLen = -1) { if (fixedLen == 0) return std::wstring(); std::wstring ret; atUint16 chr = readUint16Big(); atInt32 i; for (i = 1 ; chr != 0 ; ++i) { ret += chr; if (fixedLen >= 0 && i >= fixedLen) break; chr = readUint16Big(); } if (fixedLen >= 0 && i < fixedLen) seek(fixedLen - i); return ret; } template inline std::wstring readValBig(typename std::enable_if::value>::type* = 0) {return readWStringBig();} /** @brief Performs automatic std::vector enumeration reads using numeric type T * * @param vector The std::vector to clear and populate using read data * @param count The number of elements to read into vector * * Endianness is set with setEndian */ template void enumerate(std::vector& vector, size_t count, typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value>::type* = 0) { vector.clear(); vector.reserve(count); for (size_t i=0 ; i()); } /** @brief Performs automatic std::vector enumeration reads using numeric type T * * @param vector The std::vector to clear and populate using read data * @param count The number of elements to read into vector * * Endianness is little */ template void enumerateLittle(std::vector& vector, size_t count, typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value>::type* = 0) { vector.clear(); vector.reserve(count); for (size_t i=0 ; i()); } /** @brief Performs automatic std::vector enumeration reads using numeric type T * * @param vector The std::vector to clear and populate using read data * @param count The number of elements to read into vector * * Endianness is big */ template void enumerateBig(std::vector& vector, size_t count, typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value>::type* = 0) { vector.clear(); vector.reserve(count); for (size_t i=0 ; i()); } /** @brief Performs automatic std::vector enumeration reads using non-numeric type T * * @param vector The std::vector to clear and populate using read data * @param count The number of elements to read into vector */ template void enumerate(std::vector& vector, size_t count, typename std::enable_if::value && !std::is_same::value && !std::is_same::value && !std::is_same::value>::type* = 0) { vector.clear(); vector.reserve(count); for (size_t i=0 ; i void enumerate(std::vector& vector, size_t count, std::function readf) { vector.clear(); vector.reserve(count); for (size_t i=0 ; i IStreamReader& operator>>(IStreamReader& lhs, T& rhs) { rhs = lhs.readVal(); return lhs; } } } #endif // ISTREAMREADER