text: #include "IFIFO.h"
  
  IFIFO::IFIFO(UInt32 length)
  {
  	fifoBuf = new UInt8[length];
  	fifoBufSize = length;
  	fifoBase = 0;
  	fifoDataLength = 0;
  }
  
  IFIFO::~IFIFO()
  {
  	delete fifoBuf;
  }
  
  bool IFIFO::Push(UInt8 * buf, UInt32 length)
  {
  	// would that overflow the buffer?
  	if(length > GetBufferRemain())
  		return false;
  
  	UInt32	writeOffset = GetWriteOffset();
  
  	// will this cross the end of the buffer?
  	if(writeOffset + length > fifoBufSize)
  	{
  		UInt32	segmentLength = fifoBufSize - writeOffset;
  
  		std::memcpy(&fifoBuf[writeOffset], buf, segmentLength);
  		std::memcpy(fifoBuf, &buf[segmentLength], length - segmentLength);
  	}
  	else
  	{
  		std::memcpy(&fifoBuf[writeOffset], buf, length);
  	}
  
  	// update pointers
  	fifoDataLength += length;
  
  	return true;
  }
  
  bool IFIFO::Pop(UInt8 * buf, UInt32 length)
  {
  	bool	result = Peek(buf, length);
  
  	// update pointers if we were successful
  	if(result)
  	{
  		fifoDataLength -= length;
  		fifoBase = ToRawOffset(fifoBase + length);
  	}
  
  	return result;
  }
  
  bool IFIFO::Peek(UInt8 * buf, UInt32 length)
  {
  	// would that underflow the buffer?
  	if(length > fifoDataLength)
  		return false;
  
  	// will this cross the end of the buffer?
  	if(fifoBase + length > fifoBufSize)
  	{
  		UInt32	segmentLength = fifoBufSize - fifoBase;
  
  		std::memcpy(buf, &fifoBuf[fifoBase], segmentLength);
  		std::memcpy(&buf[segmentLength], fifoBuf, length - segmentLength);
  	}
  	else
  	{
  		std::memcpy(buf, &fifoBuf[fifoBase], length);
  	}
  
  	return true;
  }
  
  void IFIFO::Clear(void)
  {
  	fifoDataLength = 0;
  
  	// this isn't needed, but staying away from the buffer end is always good
  	fifoBase = 0;
  }
  