473 lines
8.0 KiB
C++
473 lines
8.0 KiB
C++
|
#include "IDataStream.h"
|
||
|
|
||
|
/**** IDataStream *************************************************************/
|
||
|
|
||
|
IDataStream::IDataStream()
|
||
|
:streamLength(0), streamOffset(0), swapBytes(false)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
IDataStream::~IDataStream()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns an 8-bit value from the stream
|
||
|
*/
|
||
|
UInt8 IDataStream::Read8(void)
|
||
|
{
|
||
|
UInt8 out;
|
||
|
|
||
|
ReadBuf(&out, sizeof(UInt8));
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 16-bit value from the stream
|
||
|
*/
|
||
|
UInt16 IDataStream::Read16(void)
|
||
|
{
|
||
|
UInt16 out;
|
||
|
|
||
|
ReadBuf(&out, sizeof(UInt16));
|
||
|
|
||
|
if(swapBytes)
|
||
|
out = Swap16(out);
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 32-bit value from the stream
|
||
|
*/
|
||
|
UInt32 IDataStream::Read32(void)
|
||
|
{
|
||
|
UInt32 out;
|
||
|
|
||
|
ReadBuf(&out, sizeof(UInt32));
|
||
|
|
||
|
if(swapBytes)
|
||
|
out = Swap32(out);
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 64-bit value from the stream
|
||
|
*/
|
||
|
UInt64 IDataStream::Read64(void)
|
||
|
{
|
||
|
UInt64 out;
|
||
|
|
||
|
ReadBuf(&out, sizeof(UInt64));
|
||
|
|
||
|
if(swapBytes)
|
||
|
out = Swap64(out);
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 32-bit floating point value from the stream
|
||
|
*/
|
||
|
float IDataStream::ReadFloat(void)
|
||
|
{
|
||
|
UInt32 out = Read32();
|
||
|
|
||
|
return *((float *)&out);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads a null-or-return-terminated string from the stream
|
||
|
*
|
||
|
* If the buffer is too small to hold the entire string, it is truncated and
|
||
|
* properly terminated.
|
||
|
*
|
||
|
* @param buf the output buffer
|
||
|
* @param bufLength the size of the output buffer
|
||
|
* @return the number of characters written to the buffer
|
||
|
*/
|
||
|
UInt32 IDataStream::ReadString(char * buf, UInt32 bufLength, char altTerminator, char altTerminator2)
|
||
|
{
|
||
|
char * traverse = buf;
|
||
|
bool breakOnReturns = false;
|
||
|
|
||
|
if((altTerminator == '\n') || (altTerminator2 == '\n'))
|
||
|
breakOnReturns = true;
|
||
|
|
||
|
ASSERT_STR(bufLength > 0, "IDataStream::ReadString: zero-sized buffer");
|
||
|
|
||
|
if(bufLength == 1)
|
||
|
{
|
||
|
buf[0] = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bufLength--;
|
||
|
|
||
|
for(UInt32 i = 0; i < bufLength; i++)
|
||
|
{
|
||
|
if(HitEOF()) break;
|
||
|
|
||
|
UInt8 data = Read8();
|
||
|
|
||
|
if(breakOnReturns)
|
||
|
{
|
||
|
if(data == 0x0D)
|
||
|
{
|
||
|
if(Peek8() == 0x0A)
|
||
|
Skip(1);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!data || (data == altTerminator) || (data == altTerminator2))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*traverse++ = data;
|
||
|
}
|
||
|
|
||
|
*traverse++ = 0;
|
||
|
|
||
|
return traverse - buf - 1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns an 8-bit value from the stream without advancing the stream's position
|
||
|
*/
|
||
|
UInt8 IDataStream::Peek8(void)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
return Read8();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 16-bit value from the stream without advancing the stream's position
|
||
|
*/
|
||
|
UInt16 IDataStream::Peek16(void)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
return Read16();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 32-bit value from the stream without advancing the stream's position
|
||
|
*/
|
||
|
UInt32 IDataStream::Peek32(void)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
return Read32();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 32-bit value from the stream without advancing the stream's position
|
||
|
*/
|
||
|
UInt64 IDataStream::Peek64(void)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
return Read64();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads and returns a 32-bit floating point value from the stream without advancing the stream's position
|
||
|
*/
|
||
|
float IDataStream::PeekFloat(void)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
return ReadFloat();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads raw data into a buffer without advancing the stream's position
|
||
|
*/
|
||
|
void IDataStream::PeekBuf(void * buf, UInt32 inLength)
|
||
|
{
|
||
|
IDataStream_PositionSaver saver(this);
|
||
|
|
||
|
ReadBuf(buf, inLength);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Skips a specified number of bytes down the stream
|
||
|
*/
|
||
|
void IDataStream::Skip(SInt64 inBytes)
|
||
|
{
|
||
|
SetOffset(GetOffset() + inBytes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes an 8-bit value to the stream.
|
||
|
*/
|
||
|
void IDataStream::Write8(UInt8 inData)
|
||
|
{
|
||
|
WriteBuf(&inData, sizeof(UInt8));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a 16-bit value to the stream.
|
||
|
*/
|
||
|
void IDataStream::Write16(UInt16 inData)
|
||
|
{
|
||
|
if(swapBytes)
|
||
|
inData = Swap16(inData);
|
||
|
|
||
|
WriteBuf(&inData, sizeof(UInt16));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a 32-bit value to the stream.
|
||
|
*/
|
||
|
void IDataStream::Write32(UInt32 inData)
|
||
|
{
|
||
|
if(swapBytes)
|
||
|
inData = Swap32(inData);
|
||
|
|
||
|
WriteBuf(&inData, sizeof(UInt32));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a 64-bit value to the stream.
|
||
|
*/
|
||
|
void IDataStream::Write64(UInt64 inData)
|
||
|
{
|
||
|
if(swapBytes)
|
||
|
inData = Swap64(inData);
|
||
|
|
||
|
WriteBuf(&inData, sizeof(UInt64));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a 32-bit floating point value to the stream.
|
||
|
*/
|
||
|
void IDataStream::WriteFloat(float inData)
|
||
|
{
|
||
|
if(swapBytes)
|
||
|
{
|
||
|
UInt32 temp = *((UInt32 *)&inData);
|
||
|
|
||
|
temp = Swap32(temp);
|
||
|
|
||
|
WriteBuf(&temp, sizeof(UInt32));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteBuf(&inData, sizeof(float));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a null-terminated string to the stream.
|
||
|
*/
|
||
|
void IDataStream::WriteString(const char * buf)
|
||
|
{
|
||
|
WriteBuf(buf, std::strlen(buf) + 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the length of the stream
|
||
|
*/
|
||
|
SInt64 IDataStream::GetLength(void)
|
||
|
{
|
||
|
return streamLength;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the number of bytes remaining in the stream
|
||
|
*/
|
||
|
SInt64 IDataStream::GetRemain(void)
|
||
|
{
|
||
|
return streamLength - streamOffset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the current offset into the stream
|
||
|
*/
|
||
|
SInt64 IDataStream::GetOffset(void)
|
||
|
{
|
||
|
return streamOffset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether we have reached the end of the stream or not
|
||
|
*/
|
||
|
bool IDataStream::HitEOF(void)
|
||
|
{
|
||
|
return streamOffset >= streamLength;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Moves the current offset into the stream
|
||
|
*/
|
||
|
void IDataStream::SetOffset(SInt64 inOffset)
|
||
|
{
|
||
|
streamOffset = inOffset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enables or disables byte swapping for basic data transfers
|
||
|
*/
|
||
|
void IDataStream::SwapBytes(bool inSwapBytes)
|
||
|
{
|
||
|
swapBytes = inSwapBytes;
|
||
|
}
|
||
|
|
||
|
IDataStream * IDataStream::GetRootParent(void)
|
||
|
{
|
||
|
IDataStream * parent = GetParent();
|
||
|
|
||
|
if(parent)
|
||
|
return parent->GetRootParent();
|
||
|
else
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
void IDataStream::CopyStreams(IDataStream * out, IDataStream * in, UInt64 bufferSize, UInt8 * buf)
|
||
|
{
|
||
|
in->Rewind();
|
||
|
|
||
|
bool ourBuffer = false;
|
||
|
|
||
|
if(!buf)
|
||
|
{
|
||
|
buf = new UInt8[bufferSize];
|
||
|
ourBuffer = true;
|
||
|
}
|
||
|
|
||
|
UInt64 remain = in->GetLength();
|
||
|
|
||
|
while(remain > 0)
|
||
|
{
|
||
|
UInt64 transferSize = remain;
|
||
|
|
||
|
if(transferSize > bufferSize)
|
||
|
transferSize = bufferSize;
|
||
|
|
||
|
in->ReadBuf(buf, transferSize);
|
||
|
out->WriteBuf(buf, transferSize);
|
||
|
|
||
|
remain -= transferSize;
|
||
|
}
|
||
|
|
||
|
if(ourBuffer)
|
||
|
delete [] buf;
|
||
|
}
|
||
|
|
||
|
void IDataStream::CopySubStreams(IDataStream * out, IDataStream * in, UInt64 remain, UInt64 bufferSize, UInt8 * buf)
|
||
|
{
|
||
|
bool ourBuffer = false;
|
||
|
|
||
|
if(!buf)
|
||
|
{
|
||
|
buf = new UInt8[bufferSize];
|
||
|
ourBuffer = true;
|
||
|
}
|
||
|
|
||
|
while(remain > 0)
|
||
|
{
|
||
|
UInt64 transferSize = remain;
|
||
|
|
||
|
if(transferSize > bufferSize)
|
||
|
transferSize = bufferSize;
|
||
|
|
||
|
in->ReadBuf(buf, transferSize);
|
||
|
out->WriteBuf(buf, transferSize);
|
||
|
|
||
|
remain -= transferSize;
|
||
|
}
|
||
|
|
||
|
if(ourBuffer)
|
||
|
delete [] buf;
|
||
|
}
|
||
|
|
||
|
/**** IDataStream_PositionSaver ***********************************************/
|
||
|
|
||
|
/**
|
||
|
* The constructor; save the stream's position
|
||
|
*/
|
||
|
IDataStream_PositionSaver::IDataStream_PositionSaver(IDataStream * tgt)
|
||
|
{
|
||
|
stream = tgt;
|
||
|
offset = tgt->GetOffset();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The destructor; restore the stream's saved position
|
||
|
*/
|
||
|
IDataStream_PositionSaver::~IDataStream_PositionSaver()
|
||
|
{
|
||
|
stream->SetOffset(offset);
|
||
|
}
|
||
|
|
||
|
/**** IDataSubStream **********************************************************/
|
||
|
|
||
|
IDataSubStream::IDataSubStream()
|
||
|
:stream(NULL), subBase(0)
|
||
|
{
|
||
|
//
|
||
|
}
|
||
|
|
||
|
IDataSubStream::IDataSubStream(IDataStream * inStream, SInt64 inOffset, SInt64 inLength)
|
||
|
{
|
||
|
stream = inStream;
|
||
|
subBase = inOffset;
|
||
|
streamLength = inLength;
|
||
|
|
||
|
stream->SetOffset(inOffset);
|
||
|
}
|
||
|
|
||
|
IDataSubStream::~IDataSubStream()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
void IDataSubStream::Attach(IDataStream * inStream, SInt64 inOffset, SInt64 inLength)
|
||
|
{
|
||
|
stream = inStream;
|
||
|
subBase = inOffset;
|
||
|
streamLength = inLength;
|
||
|
|
||
|
stream->SetOffset(inOffset);
|
||
|
}
|
||
|
|
||
|
void IDataSubStream::ReadBuf(void * buf, UInt32 inLength)
|
||
|
{
|
||
|
ASSERT_STR(inLength <= GetRemain(), "IDataSubStream::ReadBuf: hit eof");
|
||
|
|
||
|
if(stream->GetOffset() != subBase + streamOffset)
|
||
|
stream->SetOffset(subBase + streamOffset);
|
||
|
|
||
|
stream->ReadBuf(buf, inLength);
|
||
|
|
||
|
streamOffset += inLength;
|
||
|
}
|
||
|
|
||
|
void IDataSubStream::WriteBuf(const void * buf, UInt32 inLength)
|
||
|
{
|
||
|
if(stream->GetOffset() != subBase + streamOffset)
|
||
|
stream->SetOffset(subBase + streamOffset);
|
||
|
|
||
|
stream->WriteBuf(buf, inLength);
|
||
|
|
||
|
streamOffset += inLength;
|
||
|
|
||
|
if(streamLength < streamOffset)
|
||
|
streamLength = streamOffset;
|
||
|
}
|
||
|
|
||
|
void IDataSubStream::SetOffset(SInt64 inOffset)
|
||
|
{
|
||
|
stream->SetOffset(subBase + inOffset);
|
||
|
streamOffset = inOffset;
|
||
|
}
|