|
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|
|
|
|
|
Copyright (c) 2006-2020, assimp team
|
|
Copyright (c) 2006-2020, assimp team
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
All rights reserved.
|
|
All rights reserved.
|
|
|
|
|
|
Redistribution and use of this software in source and binary forms,
|
|
Redistribution and use of this software in source and binary forms,
|
|
@@ -49,13 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#define AI_STREAMREADER_H_INCLUDED
|
|
#define AI_STREAMREADER_H_INCLUDED
|
|
|
|
|
|
#ifdef __GNUC__
|
|
#ifdef __GNUC__
|
|
-# pragma GCC system_header
|
|
|
|
|
|
+#pragma GCC system_header
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-#include <assimp/IOStream.hpp>
|
|
|
|
-#include <assimp/Defines.h>
|
|
|
|
#include <assimp/ByteSwapper.h>
|
|
#include <assimp/ByteSwapper.h>
|
|
|
|
+#include <assimp/Defines.h>
|
|
#include <assimp/Exceptional.h>
|
|
#include <assimp/Exceptional.h>
|
|
|
|
+#include <assimp/IOStream.hpp>
|
|
|
|
|
|
#include <memory>
|
|
#include <memory>
|
|
|
|
|
|
@@ -74,10 +72,8 @@ namespace Assimp {
|
|
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
|
|
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
|
|
class StreamReader {
|
|
class StreamReader {
|
|
public:
|
|
public:
|
|
- // FIXME: use these data types throughout the whole library,
|
|
|
|
- // then change them to 64 bit values :-)
|
|
|
|
- using diff = int;
|
|
|
|
- using pos = unsigned int;
|
|
|
|
|
|
+ using diff = size_t;
|
|
|
|
+ using pos = size_t;
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Construction from a given stream with a well-defined endianness.
|
|
/** Construction from a given stream with a well-defined endianness.
|
|
@@ -91,40 +87,45 @@ public:
|
|
* stream is in little endian byte order. Otherwise the
|
|
* stream is in little endian byte order. Otherwise the
|
|
* endianness information is contained in the @c SwapEndianess
|
|
* endianness information is contained in the @c SwapEndianess
|
|
* template parameter and this parameter is meaningless. */
|
|
* template parameter and this parameter is meaningless. */
|
|
- StreamReader(std::shared_ptr<IOStream> stream, bool le = false)
|
|
|
|
- : stream(stream)
|
|
|
|
- , le(le)
|
|
|
|
- {
|
|
|
|
|
|
+ StreamReader(std::shared_ptr<IOStream> stream, bool le = false) :
|
|
|
|
+ mStream(stream),
|
|
|
|
+ mBuffer(nullptr),
|
|
|
|
+ mCurrent(nullptr),
|
|
|
|
+ mEnd(nullptr),
|
|
|
|
+ mLimit(nullptr),
|
|
|
|
+ mLe(le) {
|
|
ai_assert(stream);
|
|
ai_assert(stream);
|
|
InternBegin();
|
|
InternBegin();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- StreamReader(IOStream* stream, bool le = false)
|
|
|
|
- : stream(std::shared_ptr<IOStream>(stream))
|
|
|
|
- , le(le)
|
|
|
|
- {
|
|
|
|
- ai_assert(stream);
|
|
|
|
|
|
+ StreamReader(IOStream *stream, bool le = false) :
|
|
|
|
+ mStream(std::shared_ptr<IOStream>(stream)),
|
|
|
|
+ mBuffer(nullptr),
|
|
|
|
+ mCurrent(nullptr),
|
|
|
|
+ mEnd(nullptr),
|
|
|
|
+ mLimit(nullptr),
|
|
|
|
+ mLe(le) {
|
|
|
|
+ ai_assert(nullptr != stream);
|
|
InternBegin();
|
|
InternBegin();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
~StreamReader() {
|
|
~StreamReader() {
|
|
- delete[] buffer;
|
|
|
|
|
|
+ delete[] mBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
// deprecated, use overloaded operator>> instead
|
|
// deprecated, use overloaded operator>> instead
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Read a float from the stream */
|
|
|
|
- float GetF4()
|
|
|
|
- {
|
|
|
|
|
|
+ /// Read a float from the stream.
|
|
|
|
+ float GetF4() {
|
|
return Get<float>();
|
|
return Get<float>();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Read a double from the stream */
|
|
|
|
- double GetF8() {
|
|
|
|
|
|
+ /// Read a double from the stream.
|
|
|
|
+ double GetF8() {
|
|
return Get<double>();
|
|
return Get<double>();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -136,7 +137,7 @@ public:
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Read a signed 8 bit integer from the stream */
|
|
/** Read a signed 8 bit integer from the stream */
|
|
- int8_t GetI1() {
|
|
|
|
|
|
+ int8_t GetI1() {
|
|
return Get<int8_t>();
|
|
return Get<int8_t>();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -154,55 +155,55 @@ public:
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Read a unsigned 16 bit integer from the stream */
|
|
/** Read a unsigned 16 bit integer from the stream */
|
|
- uint16_t GetU2() {
|
|
|
|
|
|
+ uint16_t GetU2() {
|
|
return Get<uint16_t>();
|
|
return Get<uint16_t>();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Read a unsigned 8 bit integer from the stream */
|
|
|
|
|
|
+ /// Read a unsigned 8 bit integer from the stream
|
|
uint8_t GetU1() {
|
|
uint8_t GetU1() {
|
|
return Get<uint8_t>();
|
|
return Get<uint8_t>();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Read an unsigned 32 bit integer from the stream */
|
|
|
|
- uint32_t GetU4() {
|
|
|
|
|
|
+ /// Read an unsigned 32 bit integer from the stream
|
|
|
|
+ uint32_t GetU4() {
|
|
return Get<uint32_t>();
|
|
return Get<uint32_t>();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Read a unsigned 64 bit integer from the stream */
|
|
|
|
- uint64_t GetU8() {
|
|
|
|
|
|
+ /// Read a unsigned 64 bit integer from the stream
|
|
|
|
+ uint64_t GetU8() {
|
|
return Get<uint64_t>();
|
|
return Get<uint64_t>();
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
- /** Get the remaining stream size (to the end of the stream) */
|
|
|
|
- unsigned int GetRemainingSize() const {
|
|
|
|
- return (unsigned int)(end - current);
|
|
|
|
|
|
+ /// Get the remaining stream size (to the end of the stream)
|
|
|
|
+ size_t GetRemainingSize() const {
|
|
|
|
+ return (unsigned int)(mEnd - mCurrent);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Get the remaining stream size (to the current read limit). The
|
|
/** Get the remaining stream size (to the current read limit). The
|
|
* return value is the remaining size of the stream if no custom
|
|
* return value is the remaining size of the stream if no custom
|
|
* read limit has been set. */
|
|
* read limit has been set. */
|
|
- unsigned int GetRemainingSizeToLimit() const {
|
|
|
|
- return (unsigned int)(limit - current);
|
|
|
|
|
|
+ size_t GetRemainingSizeToLimit() const {
|
|
|
|
+ return (unsigned int)(mLimit - mCurrent);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Increase the file pointer (relative seeking) */
|
|
/** Increase the file pointer (relative seeking) */
|
|
- void IncPtr(intptr_t plus) {
|
|
|
|
- current += plus;
|
|
|
|
- if (current > limit) {
|
|
|
|
|
|
+ void IncPtr(intptr_t plus) {
|
|
|
|
+ mCurrent += plus;
|
|
|
|
+ if (mCurrent > mLimit) {
|
|
throw DeadlyImportError("End of file or read limit was reached");
|
|
throw DeadlyImportError("End of file or read limit was reached");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Get the current file pointer */
|
|
/** Get the current file pointer */
|
|
- int8_t* GetPtr() const {
|
|
|
|
- return current;
|
|
|
|
|
|
+ int8_t *GetPtr() const {
|
|
|
|
+ return mCurrent;
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
@@ -211,9 +212,9 @@ public:
|
|
* large chunks of data at once.
|
|
* large chunks of data at once.
|
|
* @param p The new pointer, which is validated against the size
|
|
* @param p The new pointer, which is validated against the size
|
|
* limit and buffer boundaries. */
|
|
* limit and buffer boundaries. */
|
|
- void SetPtr(int8_t* p) {
|
|
|
|
- current = p;
|
|
|
|
- if (current > limit || current < buffer) {
|
|
|
|
|
|
+ void SetPtr(int8_t *p) {
|
|
|
|
+ mCurrent = p;
|
|
|
|
+ if (mCurrent > mLimit || mCurrent < mBuffer) {
|
|
throw DeadlyImportError("End of file or read limit was reached");
|
|
throw DeadlyImportError("End of file or read limit was reached");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -222,21 +223,20 @@ public:
|
|
/** Copy n bytes to an external buffer
|
|
/** Copy n bytes to an external buffer
|
|
* @param out Destination for copying
|
|
* @param out Destination for copying
|
|
* @param bytes Number of bytes to copy */
|
|
* @param bytes Number of bytes to copy */
|
|
- void CopyAndAdvance(void* out, size_t bytes) {
|
|
|
|
- int8_t* ur = GetPtr();
|
|
|
|
- SetPtr(ur+bytes); // fire exception if eof
|
|
|
|
|
|
+ void CopyAndAdvance(void *out, size_t bytes) {
|
|
|
|
+ int8_t *ur = GetPtr();
|
|
|
|
+ SetPtr(ur + bytes); // fire exception if eof
|
|
|
|
|
|
- ::memcpy(out,ur,bytes);
|
|
|
|
|
|
+ ::memcpy(out, ur, bytes);
|
|
}
|
|
}
|
|
|
|
|
|
- // ---------------------------------------------------------------------
|
|
|
|
- /** Get the current offset from the beginning of the file */
|
|
|
|
- int GetCurrentPos() const {
|
|
|
|
- return (unsigned int)(current - buffer);
|
|
|
|
|
|
+ /// @brief Get the current offset from the beginning of the file
|
|
|
|
+ int GetCurrentPos() const {
|
|
|
|
+ return (unsigned int)(mCurrent - mBuffer);
|
|
}
|
|
}
|
|
|
|
|
|
void SetCurrentPos(size_t pos) {
|
|
void SetCurrentPos(size_t pos) {
|
|
- SetPtr(buffer + pos);
|
|
|
|
|
|
+ SetPtr(mBuffer + pos);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
@@ -246,15 +246,15 @@ public:
|
|
* the beginning of the file. Specifying UINT_MAX
|
|
* the beginning of the file. Specifying UINT_MAX
|
|
* resets the limit to the original end of the stream.
|
|
* resets the limit to the original end of the stream.
|
|
* Returns the previously set limit. */
|
|
* Returns the previously set limit. */
|
|
- unsigned int SetReadLimit(unsigned int _limit) {
|
|
|
|
|
|
+ unsigned int SetReadLimit(unsigned int _limit) {
|
|
unsigned int prev = GetReadLimit();
|
|
unsigned int prev = GetReadLimit();
|
|
if (UINT_MAX == _limit) {
|
|
if (UINT_MAX == _limit) {
|
|
- limit = end;
|
|
|
|
|
|
+ mLimit = mEnd;
|
|
return prev;
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
|
|
- limit = buffer + _limit;
|
|
|
|
- if (limit > end) {
|
|
|
|
|
|
+ mLimit = mBuffer + _limit;
|
|
|
|
+ if (mLimit > mEnd) {
|
|
throw DeadlyImportError("StreamReader: Invalid read limit");
|
|
throw DeadlyImportError("StreamReader: Invalid read limit");
|
|
}
|
|
}
|
|
return prev;
|
|
return prev;
|
|
@@ -263,21 +263,21 @@ public:
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Get the current read limit in bytes. Reading over this limit
|
|
/** Get the current read limit in bytes. Reading over this limit
|
|
* accidentally raises an exception. */
|
|
* accidentally raises an exception. */
|
|
- unsigned int GetReadLimit() const {
|
|
|
|
- return (unsigned int)(limit - buffer);
|
|
|
|
|
|
+ unsigned int GetReadLimit() const {
|
|
|
|
+ return (unsigned int)(mLimit - mBuffer);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** Skip to the read limit in bytes. Reading over this limit
|
|
/** Skip to the read limit in bytes. Reading over this limit
|
|
* accidentally raises an exception. */
|
|
* accidentally raises an exception. */
|
|
- void SkipToReadLimit() {
|
|
|
|
- current = limit;
|
|
|
|
|
|
+ void SkipToReadLimit() {
|
|
|
|
+ mCurrent = mLimit;
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
/** overload operator>> and allow chaining of >> ops. */
|
|
/** overload operator>> and allow chaining of >> ops. */
|
|
template <typename T>
|
|
template <typename T>
|
|
- StreamReader& operator >> (T& f) {
|
|
|
|
|
|
+ StreamReader &operator>>(T &f) {
|
|
f = Get<T>();
|
|
f = Get<T>();
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
@@ -286,14 +286,14 @@ public:
|
|
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
|
|
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
|
|
template <typename T>
|
|
template <typename T>
|
|
T Get() {
|
|
T Get() {
|
|
- if ( current + sizeof(T) > limit) {
|
|
|
|
|
|
+ if (mCurrent + sizeof(T) > mLimit) {
|
|
throw DeadlyImportError("End of file or stream limit was reached");
|
|
throw DeadlyImportError("End of file or stream limit was reached");
|
|
}
|
|
}
|
|
|
|
|
|
T f;
|
|
T f;
|
|
- ::memcpy (&f, current, sizeof(T));
|
|
|
|
- Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
|
|
|
|
- current += sizeof(T);
|
|
|
|
|
|
+ ::memcpy(&f, mCurrent, sizeof(T));
|
|
|
|
+ Intern::Getter<SwapEndianess, T, RuntimeSwitch>()(&f, mLe);
|
|
|
|
+ mCurrent += sizeof(T);
|
|
|
|
|
|
return f;
|
|
return f;
|
|
}
|
|
}
|
|
@@ -301,46 +301,44 @@ public:
|
|
private:
|
|
private:
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
void InternBegin() {
|
|
void InternBegin() {
|
|
- if (!stream) {
|
|
|
|
- // in case someone wonders: StreamReader is frequently invoked with
|
|
|
|
- // no prior validation whether the input stream is valid. Since
|
|
|
|
- // no one bothers changing the error message, this message here
|
|
|
|
- // is passed down to the caller and 'unable to open file'
|
|
|
|
- // simply describes best what happened.
|
|
|
|
|
|
+ if (nullptr == mStream) {
|
|
throw DeadlyImportError("StreamReader: Unable to open file");
|
|
throw DeadlyImportError("StreamReader: Unable to open file");
|
|
}
|
|
}
|
|
|
|
|
|
- const size_t s = stream->FileSize() - stream->Tell();
|
|
|
|
- if (!s) {
|
|
|
|
|
|
+ const size_t filesize = mStream->FileSize() - mStream->Tell();
|
|
|
|
+ if (0 == filesize) {
|
|
throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
|
|
throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
|
|
}
|
|
}
|
|
|
|
|
|
- current = buffer = new int8_t[s];
|
|
|
|
- const size_t read = stream->Read(current,1,s);
|
|
|
|
|
|
+ mCurrent = mBuffer = new int8_t[filesize];
|
|
|
|
+ const size_t read = mStream->Read(mCurrent, 1, filesize);
|
|
// (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
|
|
// (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
|
|
- ai_assert(read <= s);
|
|
|
|
- end = limit = &buffer[read-1] + 1;
|
|
|
|
|
|
+ ai_assert(read <= filesize);
|
|
|
|
+ mEnd = mLimit = &mBuffer[read - 1] + 1;
|
|
}
|
|
}
|
|
|
|
|
|
private:
|
|
private:
|
|
- std::shared_ptr<IOStream> stream;
|
|
|
|
- int8_t *buffer, *current, *end, *limit;
|
|
|
|
- bool le;
|
|
|
|
|
|
+ std::shared_ptr<IOStream> mStream;
|
|
|
|
+ int8_t *mBuffer;
|
|
|
|
+ int8_t *mCurrent;
|
|
|
|
+ int8_t *mEnd;
|
|
|
|
+ int8_t *mLimit;
|
|
|
|
+ bool mLe;
|
|
};
|
|
};
|
|
|
|
|
|
// --------------------------------------------------------------------------------------------
|
|
// --------------------------------------------------------------------------------------------
|
|
// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
|
|
// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
|
|
#ifdef AI_BUILD_BIG_ENDIAN
|
|
#ifdef AI_BUILD_BIG_ENDIAN
|
|
- typedef StreamReader<true> StreamReaderLE;
|
|
|
|
- typedef StreamReader<false> StreamReaderBE;
|
|
|
|
|
|
+typedef StreamReader<true> StreamReaderLE;
|
|
|
|
+typedef StreamReader<false> StreamReaderBE;
|
|
#else
|
|
#else
|
|
- typedef StreamReader<true> StreamReaderBE;
|
|
|
|
- typedef StreamReader<false> StreamReaderLE;
|
|
|
|
|
|
+typedef StreamReader<true> StreamReaderBE;
|
|
|
|
+typedef StreamReader<false> StreamReaderLE;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
// `dynamic` StreamReader. The byte order of the input data is specified in the
|
|
// `dynamic` StreamReader. The byte order of the input data is specified in the
|
|
// c'tor. This involves runtime branching and might be a little bit slower.
|
|
// c'tor. This involves runtime branching and might be a little bit slower.
|
|
-typedef StreamReader<true,true> StreamReaderAny;
|
|
|
|
|
|
+typedef StreamReader<true, true> StreamReaderAny;
|
|
|
|
|
|
} // end namespace Assimp
|
|
} // end namespace Assimp
|
|
|
|
|