| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 | #include "StdInc.h"#include "CBinaryReader.h"#include <SDL_endian.h>#include "CInputStream.h"#include "../CGeneralTextHandler.h"#if SDL_BYTEORDER == SDL_BIG_ENDIANtemplate <typename CData>CData readLE(CData data){	auto dataPtr = (char*)&data;	std::reverse(dataPtr, dataPtr + sizeof(data));	return data;}#elsetemplate <typename CData>CData readLE(CData data){	return data;}#endifCBinaryReader::CBinaryReader() : stream(nullptr){}CBinaryReader::CBinaryReader(CInputStream * stream) : stream(stream){}CInputStream * CBinaryReader::getStream(){	return stream;}void CBinaryReader::setStream(CInputStream * stream){	this->stream = stream;}si64 CBinaryReader::read(ui8 * data, si64 size){	si64 bytesRead = stream->read(data, size);	if(bytesRead != size)	{		throw std::runtime_error(getEndOfStreamExceptionMsg(size));	}	return bytesRead;}template <typename CData>CData CBinaryReader::readInteger(){	CData val;	stream->read(reinterpret_cast<unsigned char *>(&val), sizeof(val));	return readLE(val);}//FIXME: any way to do this without macro?#define INSTANTIATE(datatype, methodname) \datatype CBinaryReader::methodname() \{ return readInteger<datatype>(); }// While it is certanly possible to leave only template method// but typing template parameter every time can be annoying// and templates parameters can't be resolved by return typeINSTANTIATE(ui8, readUInt8)INSTANTIATE(si8, readInt8)INSTANTIATE(ui16, readUInt16)INSTANTIATE(si16, readInt16)INSTANTIATE(ui32, readUInt32)INSTANTIATE(si32, readInt32)INSTANTIATE(ui64, readUInt64)INSTANTIATE(si64, readInt64)#undef INSTANTIATEstd::string CBinaryReader::readString(){	unsigned int len = readUInt32();	assert(len <= 500000); //not too long	if (len > 0)	{		std::string ret;		ret.resize(len);		read(reinterpret_cast<ui8*>(&ret[0]), len);		//FIXME: any need to move this into separate "read localized string" method?		if (Unicode::isValidASCII(ret))			return ret;		return Unicode::toUnicode(ret);	}	return "";}void CBinaryReader::skip(int count){	stream->skip(count);}std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const{	std::stringstream ss;	ss << "The end of the stream was reached unexpectedly. The stream has a length of " << stream->getSize() << " and the current reading position is "				<< stream->tell() << ". The client wanted to read " << bytesToRead << " bytes.";	return ss.str();}
 |