Adding overloads for unsigned integer types to ByteSwap and StreamReader.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@540 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2010-02-06 13:15:35 +00:00
parent 1fd3cfd311
commit 7dcbff5d5c
2 changed files with 171 additions and 121 deletions

View File

@ -118,40 +118,48 @@ public:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap a float. Not a joke. /** ByteSwap a float. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(float* fOut) static inline void Swap(float* fOut) {
{
Swap4(fOut); Swap4(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap a double. Not a joke. /** ByteSwap a double. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(double* fOut) static inline void Swap(double* fOut) {
{
Swap8(fOut); Swap8(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int16t. Not a joke. /** ByteSwap an int16t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int16_t* fOut) static inline void Swap(int16_t* fOut) {
{ Swap2(fOut);
}
static inline void Swap(uint16_t* fOut) {
Swap2(fOut); Swap2(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int32t. Not a joke. /** ByteSwap an int32t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int32_t* fOut) static inline void Swap(int32_t* fOut){
{ Swap4(fOut);
}
static inline void Swap(uint32_t* fOut){
Swap4(fOut); Swap4(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int64t. Not a joke. /** ByteSwap an int64t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int64_t* fOut) static inline void Swap(int64_t* fOut) {
{ Swap8(fOut);
}
static inline void Swap(uint64_t* fOut) {
Swap8(fOut); Swap8(fOut);
} }
}; };

View File

@ -40,29 +40,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** @file Defines the StreamReader class which reads data from /** @file Defines the StreamReader class which reads data from
* a binary stream with a well-defined endianess. * a binary stream with a well-defined endianess. */
*/
#ifndef AI_STREAMREADER_H_INCLUDED #ifndef AI_STREAMREADER_H_INCLUDED
#define AI_STREAMREADER_H_INCLUDED #define AI_STREAMREADER_H_INCLUDED
#include "ByteSwap.h" #include "ByteSwap.h"
namespace Assimp {
namespace Assimp // --------------------------------------------------------------------------------------------
{ /** Wrapper class around IOStream to allow for consistent reading of binary data in both
* little and big endian format. Don't attempt to instance the template directly. Use
/** Wrapper class around IOStream to allow for consistent reading * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a
* of binary data in both little and big endian format. * BE stream. The class expects that the endianess of any input data is known at
* Don't use this type directly. Use StreamReaderLE to read * compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements
* from a little-endian stream and StreamReaderBE to read from a * runtime endianess conversions for text files).
* BE stream. This class expects that the endianess of the data *
* is known at compile-time. * XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/
*/ // --------------------------------------------------------------------------------------------
template <bool SwapEndianess = false> template <bool SwapEndianess = false>
class StreamReader class StreamReader
{ {
public: public:
// ---------------------------------------------------------------------
/** Construction from a given stream with a well-defined endianess /** Construction from a given stream with a well-defined endianess
* *
* The stream will be deleted afterwards. * The stream will be deleted afterwards.
@ -70,13 +72,15 @@ public:
*/ */
StreamReader(IOStream* _stream) StreamReader(IOStream* _stream)
{ {
if (!_stream) if (!_stream) {
throw new ImportErrorException("StreamReader: Unable to open file"); throw new ImportErrorException("StreamReader: Unable to open file");
}
stream = _stream; stream = _stream;
size_t s = stream->FileSize(); const size_t s = stream->FileSize();
if (!s) if (!s) {
throw new ImportErrorException("StreamReader: File is empty"); throw new ImportErrorException("StreamReader: File is empty");
}
current = buffer = new int8_t[s]; current = buffer = new int8_t[s];
stream->Read(current,s,1); stream->Read(current,s,1);
@ -89,170 +93,206 @@ public:
delete stream; delete stream;
} }
public:
/** Read a float from the stream // deprecated, use overloaded operator>> instead
*/
// ---------------------------------------------------------------------
/** Read a float from the stream */
float GetF4() float GetF4()
{ {
return Get<float>(); return Get<float>();
} }
/** Read a double from the stream // ---------------------------------------------------------------------
*/ /** Read a double from the stream */
double GetF8() double GetF8() {
{
return Get<double>(); return Get<double>();
} }
/** Read a short from the stream // ---------------------------------------------------------------------
*/ /** Read a signed 16 bit integer from the stream */
int16_t GetI2() int16_t GetI2() {
{
return Get<int16_t>(); return Get<int16_t>();
} }
/** Read a char from the stream // ---------------------------------------------------------------------
*/ /** Read a signed 8 bit integer from the stream */
int8_t GetI1() int8_t GetI1() {
{ return Get<int8_t>();
if (current >= end)
throw new ImportErrorException("End of file was reached");
return *current++;
} }
/** Read an int from the stream // ---------------------------------------------------------------------
*/ /** Read an signed 32 bit integer from the stream */
int32_t GetI4() int32_t GetI4() {
{
return Get<int32_t>(); return Get<int32_t>();
} }
/** Read a long from the stream // ---------------------------------------------------------------------
*/ /** Read a signed 64 bit integer from the stream */
int64_t GetI8() int64_t GetI8() {
{
return Get<int64_t>(); return Get<int64_t>();
} }
/** Get the remaining stream size (to the end of the srream) // ---------------------------------------------------------------------
*/ /** Read a unsigned 16 bit integer from the stream */
unsigned int GetRemainingSize() uint16_t GetU2() {
{ return Get<uint16_t>();
}
// ---------------------------------------------------------------------
/** Read a unsigned 8 bit integer from the stream */
uint8_t GetU1() {
return Get<uint8_t>();
}
// ---------------------------------------------------------------------
/** Read an unsigned 32 bit integer from the stream */
uint32_t GetU4() {
return Get<uint32_t>();
}
// ---------------------------------------------------------------------
/** Read a unsigned 64 bit integer from the stream */
uint64_t GetU8() {
return Get<uint64_t>();
}
public:
// ---------------------------------------------------------------------
/** Get the remaining stream size (to the end of the srream) */
unsigned int GetRemainingSize() const {
return (unsigned int)(end - current); return (unsigned int)(end - current);
} }
/** Get the remaining stream size (to the current read limit) // ---------------------------------------------------------------------
*/ /** Get the remaining stream size (to the current read limit). The
unsigned int GetRemainingSizeToLimit() * return value is the remaining size of the stream if no custom
{ * read limit has been set. */
unsigned int GetRemainingSizeToLimit() const {
return (unsigned int)(limit - current); return (unsigned int)(limit - current);
} }
/** Increase the file pointer // ---------------------------------------------------------------------
*/ /** Increase the file pointer (relative seeking) */
void IncPtr(unsigned int plus) void IncPtr(unsigned int plus) {
{
current += plus; current += plus;
if (current > end) if (current > end) {
{
throw new ImportErrorException("End of file was reached"); throw new ImportErrorException("End of file was reached");
} }
} }
/** Get the current file pointer // ---------------------------------------------------------------------
*/ /** Get the current file pointer */
int8_t* GetPtr() const int8_t* GetPtr() const {
{
return current; return current;
} }
/** Set current file pointer
*/ // ---------------------------------------------------------------------
void SetPtr(int8_t* p) /** Set current file pointer (Get it from #GetPtr). This is if you
{ * prefer to do pointer arithmetics on your own or want to copy
* large chunks of data at once.
* @param p The new pointer, which is validated against the size
* limit and buffer boundaries. */
void SetPtr(int8_t* p) {
current = p; current = p;
if (current > end || current < buffer) if (current > end || current < buffer) {
{
throw new ImportErrorException("End of file was reached"); throw new ImportErrorException("End of file was reached");
} }
} }
/** Get the current offset from the beginning of the file // ---------------------------------------------------------------------
*/ /** Copy n bytes to an external buffer
int GetCurrentPos() const * @param out Destination for copying
{ * @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
memcpy(out,ur,bytes);
}
// ---------------------------------------------------------------------
/** Get the current offset from the beginning of the file */
int GetCurrentPos() const {
return (unsigned int)(current - buffer); return (unsigned int)(current - buffer);
} }
// ---------------------------------------------------------------------
/** Setup a temporary read limit /** Setup a temporary read limit
* *
* @param limit Maximum number of bytes to be read from * @param limit Maximum number of bytes to be read from
* the beginning of the file. Passing 0xffffffff * the beginning of the file. Passing 0xffffffff
* resets the limit. * resets the limit to the original end of the stream. */
*/ void SetReadLimit(unsigned int _limit) {
void SetReadLimit(unsigned int _limit)
{ if (0xffffffff == _limit) {
if (0xffffffff == _limit)
{
limit = end; limit = end;
return; return;
} }
limit = buffer + _limit; limit = buffer + _limit;
if (limit > end) if (limit > end) {
throw new ImportErrorException("StreamReader: Invalid read limit"); throw new ImportErrorException("StreamReader: Invalid read limit");
} }
}
/** Get the current read limit // ---------------------------------------------------------------------
*/ /** Get the current read limit in bytes. Reading over this limit
int GetReadLimit() const * accidentially raises an exception. */
{ int GetReadLimit() const {
return (unsigned int)(limit - buffer); return (unsigned int)(limit - buffer);
} }
/** Skip to the read limit // ---------------------------------------------------------------------
*/ /** Skip to the read limit in bytes. Reading over this limit
void SkipToReadLimit() * accidentially raises an exception. */
{ void SkipToReadLimit() {
current = limit; current = limit;
} }
// overload operator>> for those who prefer this way ... // ---------------------------------------------------------------------
void operator >> (float& f) /** overload operator>> and allow chaining of >> ops. */
{f = GetF4();} template <typename T>
StreamReader& operator >> (T& f) {
void operator >> (double& f) f = Get<T>();
{f = GetF8();} return *this;
}
void operator >> (int16_t& f)
{f = GetI2();}
void operator >> (int32_t& f)
{f = GetI4();}
void operator >> (int64_t& f)
{f = GetI8();}
void operator >> (int8_t& f)
{f = GetI1();}
private: private:
/** Generic read method. ByteSwap::Swap(T*) must exist. template <typename T, bool doit>
*/ struct ByteSwapper {
void operator() (T* inout) {
ByteSwap::Swap(inout);
}
};
template <typename T> template <typename T>
T Get() struct ByteSwapper<T,false> {
{ void operator() (T*) {
if (current + sizeof(T) > limit) }
};
// ---------------------------------------------------------------------
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
template <typename T>
T Get() {
if (current + sizeof(T) > limit) {
throw new ImportErrorException("End of file or stream limit was reached"); throw new ImportErrorException("End of file or stream limit was reached");
}
T f = *((const T*)current); T f = *((const T*)current);
if (SwapEndianess) ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> swapper;
{ swapper(&f);
ByteSwap::Swap(&f);
}
current += sizeof(T); current += sizeof(T);
return f; return f;
} }
@ -261,6 +301,8 @@ private:
int8_t *buffer, *current, *end, *limit; int8_t *buffer, *current, *end, *limit;
}; };
// --------------------------------------------------------------------------------------------
#ifdef AI_BUILD_BIG_ENDIAN #ifdef AI_BUILD_BIG_ENDIAN
typedef StreamReader<true> StreamReaderLE; typedef StreamReader<true> StreamReaderLE;
typedef StreamReader<false> StreamReaderBE; typedef StreamReader<false> StreamReaderBE;