00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef LUGRE_FIFO_H
00025 #define LUGRE_FIFO_H
00026
00027 #include "lugre_prefix.h"
00028
00029 #include <boost/crc.hpp>
00030
00031 #ifdef WIN32
00032 #include <WinSock2.h>
00033 #else
00034 #include <arpa/inet.h>
00035 #endif
00036
00037 #include <OgreVector3.h>
00038 #include <OgreQuaternion.h>
00039 #include <string>
00040 #include <string.h>
00041 #include <stdlib.h>
00042 #include "lugre_smartptr.h"
00043
00044 #include <zlib.h>
00045
00046 #define FIFO_ASSERT(cond_true_if_correct,errormsg) if (!(cond_true_if_correct)) MyCrash(errormsg,__FILE__,__LINE__,__FUNCTION__);
00047
00048 class lua_State;
00049
00050 namespace Lugre {
00051
00053
00056
00063 class cFIFO : public cSmartPointable {
00064
00065 public:
00066 char* mpBuf;
00067 uint32 miTotalPopped;
00068 uint32 miCapacity;
00069 uint32 miLen;
00070 uint32 miStartOff;
00071
00072
00073 public:
00074 inline cFIFO (uint32 miCapacity=1024) : miTotalPopped(0), miCapacity(miCapacity), miLen(0), miStartOff(0) {
00075 assert(miCapacity > 0 && "zero sized FIFO not allowed");
00076 mpBuf = (char*)malloc(miCapacity);
00077 }
00078 virtual ~cFIFO () { free(mpBuf); mpBuf = 0; }
00079
00080
00081 inline void PushC (const char a) { PushRawEndian((const char*)&a,sizeof(char)); }
00082 inline void Push (const int a) { PushRawEndian((const char*)&a,sizeof(int)); }
00083 inline void PushU (const uint32 a) { PushRawEndian((const char*)&a,sizeof(uint32)); }
00084 inline void PushF (const float a) { PushRawEndian((const char*)&a,sizeof(float)); }
00085 inline void Push (const Ogre::Vector3& a) { PushF(a.x); PushF(a.y); PushF(a.z); }
00086 inline void Push (const Ogre::Quaternion& a) { PushF(a.x); PushF(a.y); PushF(a.z); PushF(a.w); }
00087 inline void Push (const std::string& a) { PushNetUint32(a.length()); PushRaw(a.c_str(),a.length()); }
00088 inline void Push (cFIFO& a) { PushRaw(a.HackGetRawReader(),a.size()); }
00089
00090 inline void PushFIFO (cFIFO& a) { Push(a); }
00091 inline void PushS (const std::string& a) { Push(a); }
00092
00093
00094 inline void PushPlainText(const std::string &s) { PushFilledString(s,s.size()); }
00095 inline void PushFilledString(const std::string &s, unsigned int size) {
00096
00097
00098 int x = mymin(s.length(),size);
00099
00100
00101
00102 PushRaw(s.c_str(),x);
00103 PushRawFill(0,size-x);
00104 }
00105
00106 inline void PushUint8 (const uint8 a) { PushRawEndian((const char*)&a,sizeof(uint8)); }
00107 inline void PushUint16 (const uint16 a) { PushRawEndian((const char*)&a,sizeof(uint16)); }
00108 inline void PushUint32 (const uint32 a) { PushRawEndian((const char*)&a,sizeof(uint32)); }
00109 inline void PushInt8 (const int8 a) { PushRawEndian((const char*)&a,sizeof(int8)); }
00110 inline void PushInt16 (const int16 a) { PushRawEndian((const char*)&a,sizeof(int16)); }
00111 inline void PushInt32 (const int32 a) { PushRawEndian((const char*)&a,sizeof(int32)); }
00112
00113
00114 inline void PushNetUint8 (const uint8 a) { PushRawEndian((const char*)&a,sizeof(uint8)); }
00115 inline void PushNetUint16 (const uint16 a) { uint16 b = htons(a);PushRawEndian((const char*)&b,sizeof(uint16)); }
00116 inline void PushNetUint32 (const uint32 a) { uint32 b = htonl(a);PushRawEndian((const char*)&b,sizeof(uint32)); }
00117 inline void PushPointer (const void* a) { PushRawEndian((const char*)&a,sizeof(void*)); }
00118 inline void PushNetInt8 (const int8 a) { PushRawEndian((const char*)&a,sizeof(int8)); }
00119 inline void PushNetInt16 (const int16 a) { int16 b = htons(a);PushRawEndian((const char*)&b,sizeof(int16)); }
00120 inline void PushNetInt32 (const int32 a) { int32 b = htonl(a);PushRawEndian((const char*)&b,sizeof(int32)); }
00121
00122
00123
00124
00125
00126
00127 inline bool PeekDecompressIntoFifo (const unsigned int iLenCompressed, const unsigned int iLenDecompressed, cFIFO &dst) {
00128 FIFO_ASSERT(size() >= iLenCompressed,"not enough data in buffer");
00129 uLong dstLen = iLenDecompressed;
00130 void *buffer = malloc(dstLen);
00131
00132 int r = uncompress((Bytef*)buffer,&dstLen,(Bytef*)HackGetRawReader(),iLenCompressed);
00133
00134 if(r == Z_OK)dst.PushRaw((char *)buffer,iLenDecompressed);
00135 free(buffer);
00136 return r == Z_OK;
00137 }
00138
00139
00140
00141 inline int PushCompressFromFifo(cFIFO &src) {
00142 FIFO_ASSERT(src.size() > 0,"not enough data in buffer");
00143 uLong dstLen = int(float(src.size()) * 1.1f) + 12;
00144 void *buffer = malloc(dstLen);
00145
00146 int r = compress((Bytef*)buffer,&dstLen,(Bytef*)src.HackGetRawReader(),src.size());
00147
00148 if(r == Z_OK)PushRaw((char *)buffer,dstLen);
00149 free(buffer);
00150 return r == Z_OK ? dstLen : 0;
00151 }
00152
00153
00154 inline uint32 CRC (const uint32 size) {
00155 FIFO_ASSERT(size <= this->size(),"not enough data in fifo");
00156 boost::crc_32_type result;
00157 result.process_bytes( HackGetRawReader(), size );
00158 return result.checksum();
00159 }
00160
00161
00162 inline void PopC (char& a) { PopRawEndian((char*)&a,sizeof(char)); }
00163 inline void Pop (int& a) { PopRawEndian((char*)&a,sizeof(int)); }
00164 inline void PopU (uint32& a) { PopRawEndian((char*)&a,sizeof(uint32)); }
00165 inline void PopF (float& a) { PopRawEndian((char*)&a,sizeof(float)); }
00166 inline void Pop (Ogre::Vector3& a) { float x,y,z; PopF(x); PopF(y); PopF(z); a.x = x; a.y = y; a.z = z; }
00167 inline void Pop (Ogre::Quaternion& a) { float x,y,z,w; PopF(x); PopF(y); PopF(z); PopF(w); a.x = x; a.y = y; a.z = z; a.w = w; }
00168 inline void Pop (std::string& a) {
00169 uint32 len = PopNetUint32();
00170 FIFO_ASSERT(size() >= len,"string incomplete");
00171 a.assign(HackGetRawReader(),len);
00172 PopRaw(len);
00173 }
00174
00175 inline void Pop (cFIFO& a,const uint32 len) {
00176 FIFO_ASSERT(size() >= len,"fifo incomplete");
00177 a.PushRaw(HackGetRawReader(),len);
00178 PopRaw(len);
00179 }
00180
00181 inline void PopUint32 (uint32& a) { PopRawEndian((char*)&a,sizeof(uint32)); }
00182 inline void PopUint16 (uint16& a) { PopRawEndian((char*)&a,sizeof(uint16)); }
00183 inline void PopUint8 (uint8& a) { PopRawEndian((char*)&a,sizeof(uint8)); }
00184 inline void PopInt32 (int32& a) { PopRawEndian((char*)&a,sizeof(int32)); }
00185 inline void PopInt16 (int16& a) { PopRawEndian((char*)&a,sizeof(int16)); }
00186 inline void PopInt8 (int8& a) { PopRawEndian((char*)&a,sizeof(int8)); }
00187
00188 inline void PopPointer (void*& a) { PopRawEndian((char*)&a,sizeof(void*)); }
00189 inline void PopNetUint32 (uint32& a) { PopRawEndian((char*)&a,sizeof(uint32)); a = ntohl(a); }
00190 inline void PopNetUint16 (uint16& a) { PopRawEndian((char*)&a,sizeof(uint16)); a = ntohs(a); }
00191 inline void PopNetUint8 (uint8& a) { PopRawEndian((char*)&a,sizeof(uint8)); }
00192
00193 inline void PopNetInt32 (int32& a) { PopRawEndian((char*)&a,sizeof(int32)); a = (int32)ntohl(a); }
00194 inline void PopNetInt16 (int16& a) { PopRawEndian((char*)&a,sizeof(int16)); a = (int16)ntohs(a); }
00195 inline void PopNetInt8 (int8& a) { PopRawEndian((char*)&a,sizeof(int8)); }
00196
00197 inline std::string PopFilledString(uint32 size) {
00198 FIFO_ASSERT(size <= this->size(),"not enough data in fifo");
00199 std::string s = std::string(HackGetRawReader(),size);
00200 PopRaw(size);
00201 return s;
00202 }
00203
00204
00205
00206 inline std::string PopTerminatedString(const char *terminationstring) {
00207 FIFO_ASSERT(strlen(terminationstring) > 0,"terminationstring empty");
00208 std::string s = std::string(HackGetRawReader(),size());
00209 std::string::size_type pos = s.find(terminationstring);
00210 if ( pos == std::string::npos ) {
00211
00212 return std::string();
00213 } else {
00214
00215 int len = pos + strlen(terminationstring);
00216 std::string r = s.substr(0,len);
00217 PopRaw(len);
00218 return r;
00219 }
00220 }
00221
00222
00223 inline char PopC () { char x; PopC(x); return x; }
00224 inline int PopI () { int x; Pop(x); return x; }
00225 inline uint32 PopU () { uint32 x; PopU(x); return x; }
00226 inline float PopF () { float x; PopF(x); return x; }
00227 inline Ogre::Vector3 PopV () { Ogre::Vector3 x; Pop(x); return x; }
00228 inline Ogre::Quaternion PopQ () { Ogre::Quaternion x; Pop(x); return x; }
00229 inline std::string PopS () { std::string x; Pop(x); return x; }
00230
00231 inline uint32 PopUint32 () { uint32 x; PopUint32(x); return x; }
00232 inline uint16 PopUint16 () { uint16 x; PopUint16(x); return x; }
00233 inline uint8 PopUint8 () { uint8 x; PopUint8(x); return x; }
00234 inline int32 PopInt32 () { int32 x; PopInt32(x); return x; }
00235 inline int16 PopInt16 () { int16 x; PopInt16(x); return x; }
00236 inline int8 PopInt8 () { int8 x; PopInt8(x); return x; }
00237
00238 inline void* PopPointer () { void* x; PopPointer(x); return x; }
00239 inline uint32 PopNetUint32 () { uint32 x; PopNetUint32(x); return x; }
00240 inline uint16 PopNetUint16 () { uint16 x; PopNetUint16(x); return x; }
00241 inline uint8 PopNetUint8 () { uint8 x; PopNetUint8(x); return x; }
00242
00243 inline int32 PopNetInt32 () { int32 x; PopNetInt32(x); return x; }
00244 inline int16 PopNetInt16 () { int16 x; PopNetInt16(x); return x; }
00245 inline int8 PopNetInt8 () { int8 x; PopNetInt8(x); return x; }
00246
00248 inline void Skip(unsigned int len){ PopRaw(len); }
00249
00250
00251
00252 inline void PeekB (char& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(char), offset); }
00253 inline void Peek (int& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(int), offset); }
00254 inline void PeekU (uint32& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint32), offset); }
00255
00256 inline void PeekUint8 (uint8& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint8), offset); }
00257 inline void PeekUint16 (uint16& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint16), offset); }
00258 inline void PeekUint32 (uint32& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint32), offset); }
00259 inline void PeekInt8 (int8& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(int8), offset); }
00260 inline void PeekInt16 (int16& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(int16), offset); }
00261 inline void PeekInt32 (int32& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(int32), offset); }
00262
00263 inline void PokeNetUint8 (const uint32 offset,const uint8 x) {
00264 FIFO_ASSERT(mpBuf && offset >= 0 && miLen >= 1+offset,"mpBuf=0 or illegal offset");
00265 uint32 o = offset;
00266 ((uint8*)mpBuf)[miStartOff+o] = x;
00267 }
00268 inline void PeekNetUint8 (uint8& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint8), offset); }
00269 inline void PeekNetUint16 (uint16& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint16), offset); a = ntohs(a); }
00270 inline void PeekNetUint32 (uint32& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(uint32), offset); a = ntohl(a); }
00271 inline void PeekPointer (void*& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(void*), offset); }
00272 inline void PeekFloat (float& a,const uint32 offset=-1) { PeekRawEndian((char*)&a,sizeof(float), offset); }
00273
00274
00275 inline int PeekI (const uint32 offset=-1) { int x; Peek(x,offset); return x; }
00276 inline uint32 PeekU (const uint32 offset=-1) { uint32 x; PeekU(x,offset); return x; }
00277
00278 inline uint8 PeekUint8 (const uint32 offset=-1) { uint8 x; PeekUint8(x,offset); return x; }
00279 inline uint16 PeekUint16 (const uint32 offset=-1) { uint16 x; PeekUint16(x,offset); return x; }
00280 inline uint32 PeekUint32 (const uint32 offset=-1) { uint32 x; PeekUint32(x,offset); return x; }
00281 inline int8 PeekInt8 (const uint32 offset=-1) { int8 x; PeekInt8(x,offset); return x; }
00282 inline int16 PeekInt16 (const uint32 offset=-1) { int16 x; PeekInt16(x,offset); return x; }
00283 inline int32 PeekInt32 (const uint32 offset=-1) { int32 x; PeekInt32(x,offset); return x; }
00284 inline float PeekFloat (const uint32 offset=-1) { float x; PeekFloat(x,offset); return x; }
00285
00286 inline uint8 PeekNetUint8 (const uint32 offset=-1) { uint8 x; PeekNetUint8(x,offset); return x; }
00287 inline uint16 PeekNetUint16 (const uint32 offset=-1) { uint16 x; PeekNetUint16(x,offset); return x; }
00288 inline uint32 PeekNetUint32 (const uint32 offset=-1) { uint32 x; PeekNetUint32(x,offset); return x; }
00289 inline void* PeekPointer (const uint32 offset=-1) { void* x; PeekPointer(x,offset); return x; }
00290
00291
00292 inline void HackSetU (const uint32 offset,const uint32 a) { HackSetRawEndian(offset,(const char*)&a,sizeof(uint32)); }
00293
00294
00295
00296 inline uint32 size () { return miLen; }
00297 inline uint32 GetLength () { return miLen; }
00299 inline void Clear () { miStartOff = 0; miLen = 0; }
00300
00302 inline void Reserve (const uint32 minspace) {
00303 Shrink();
00304 uint32 newlen = miLen + minspace;
00305 uint32 newcap = miCapacity;
00306 while (newlen > newcap) newcap <<= 1;
00307 if (newcap > miCapacity) {
00308 miCapacity = newcap;
00309 mpBuf = (char*)realloc(mpBuf,miCapacity);
00310 }
00311 assert(miStartOff == 0);
00312 }
00313
00314
00316 inline void Shrink () {
00317 if (miStartOff == 0) return;
00318 if (miLen > 0) memmove(mpBuf,mpBuf+miStartOff,miLen);
00319 miStartOff = 0;
00320 }
00321
00323 inline const char* HackGetRawReader () {
00324 return mpBuf+miStartOff;
00325 }
00327 inline char* HackGetRawWriter (const uint32 minspace) {
00328 Reserve(minspace);
00329 assert(miStartOff == 0);
00330 return mpBuf+miLen;
00331 }
00333 inline void HackAddLength (const uint32 len) {
00334 FIFO_ASSERT(miLen+len+miStartOff <= miCapacity,"capacity too small");
00335 miLen += len;
00336 }
00338 inline void HackSubLength (const uint32 len) {
00339 FIFO_ASSERT(miLen >= len,"too much removed");
00340 miLen -= len;
00341 }
00343 inline uint32 HackGetFreeSpace () { return miCapacity - miLen - miStartOff; }
00344
00346 inline void HackRestore (const uint32 len) {
00347 FIFO_ASSERT(miStartOff >= len,"Restoration impossible");
00348 miStartOff -= len;
00349 miLen += len;
00350 }
00351
00353 inline void PushRawEndian (const char* source,const uint32 len) {
00354 PushRaw(source,len);
00355 }
00356
00357
00358 inline void PushRawFill (const char c,const uint32 len) {
00359 if (len == 0) return;
00360 Reserve(len);
00361 assert(miStartOff == 0);
00362 memset(mpBuf+miLen,c,len);
00363 miLen += len;
00364 }
00365
00366 inline void PushRaw (const char* source,const uint32 len) {
00367 if (len == 0) return;
00368 Reserve(len);
00369 assert(miStartOff == 0);
00370 memcpy(mpBuf+miLen,source,len);
00371 miLen += len;
00372 }
00373
00375 inline void HackSetRawEndian (const uint32 offset,const char* source,const uint32 len) {
00376 HackSetRaw(offset,source,len);
00377 }
00378 inline void HackSetRaw (const uint32 offset,const char* source,const uint32 len) {
00379
00380
00381
00382 memcpy(mpBuf+miStartOff+offset,source,len);
00383
00384 }
00385
00386
00388 inline void PopRawEndian (char* dest,const uint32 len) {
00389 PopRaw(dest,len);
00390 }
00391 inline void PopRaw (char* dest,const uint32 len) {
00392 if (len == 0) return;
00393 PeekRaw(dest,len,0);
00394 miStartOff += len;
00395 miLen -= len;
00396 miTotalPopped += len;
00397 }
00398 inline int GetTotalPopped () { return miTotalPopped; }
00399
00401 inline void PeekRawEndian (char* dest,const uint32 len,const uint32 offset=0) {
00402 PeekRaw(dest,len,offset);
00403 }
00404 inline void PeekRaw (char* dest,const uint32 len,const uint32 offset=0) {
00405 if (len == 0) return;
00406 FIFO_ASSERT(mpBuf && dest && miLen >= len+offset,"mpBuf=0 or dest=0 or FIFO underrun");
00407 uint32 o = offset;
00408 memcpy(dest,mpBuf+miStartOff+o,len);
00409 }
00410
00412 inline void PopRaw (const uint32 len) {
00413 FIFO_ASSERT(miLen >= len,"FIFO underrun");
00414 miStartOff += len;
00415 miLen -= len;
00416 miTotalPopped += len;
00417 }
00418 };
00419
00420
00421
00422 void LuaRegisterFIFO (lua_State *L);
00423
00424 #if 0
00425 byte SwapTest[2] = { 1, 0 };
00426
00427 if( *(short *) SwapTest == 1 ) {
00428
00429 } else { ... }
00430
00431 float FloatSwap( float f ) {
00432 union {
00433 float f;
00434 unsigned char b[4];
00435 } dat1, dat2;
00436
00437 dat1.f = f;
00438 dat2.b[0] = dat1.b[3];
00439 dat2.b[1] = dat1.b[2];
00440 dat2.b[2] = dat1.b[1];
00441 dat2.b[3] = dat1.b[0];
00442 return dat2.f;
00443 }
00444 #endif
00445
00446 };
00447
00448 #endif