lugre_fifo.h

Go to the documentation of this file.
00001 /*
00002 http://www.opensource.org/licenses/mit-license.php  (MIT-License)
00003 
00004 Copyright (c) 2007 Lugre-Team
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a copy
00007 of this software and associated documentation files (the "Software"), to deal
00008 in the Software without restriction, including without limitation the rights
00009 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, subject to the following conditions:
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00019 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00020 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00021 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00022 THE SOFTWARE.
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> // Ogre::Vector3, Ogre::Quaternion, Ogre::Real
00039 #include <string> // std::string
00040 #include <string.h> // memcpy,memmove
00041 #include <stdlib.h> // malloc,realloc
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 //private: // disabled for debugging (HexDump lua binding), HexDump is obsolete now, reconsider ?
00065 public:
00066     char*   mpBuf;
00067     uint32  miTotalPopped; 
00068     uint32  miCapacity;
00069     uint32  miLen;
00070     uint32  miStartOff;
00071     //uint32    miNextPeekOff;  //< for pop like peek usablility
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     // push cluster
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) { /*PushU(a.size());*/   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     // pushes a string (max size) into the fifo, filled with zeros.
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 //#ifdef WIN32
00098         int x = mymin(s.length(),size);
00099 //#else
00100 //      int x = std::min(s.length(),size);
00101 //#endif
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     // respecting network byte order
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     // decompress a buffer using zlib, dont touch the source fifo
00123     // iLenCompressed = size of the data to pop from fifo and decode
00124     // iLenDecompressed = length of the decompressed data
00125     // dst = targetfifo to store decompressed data
00126     // returns true on success and false on error
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         //int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
00132         int r = uncompress((Bytef*)buffer,&dstLen,(Bytef*)HackGetRawReader(),iLenCompressed);
00133         // if ok push new uncompressed data into dst fifo
00134         if(r == Z_OK)dst.PushRaw((char *)buffer,iLenDecompressed);
00135         free(buffer);
00136         return r == Z_OK;
00137     }
00138     
00139     // compresses the given fifo into this, src remains untouched
00140     // returns the compressed size or 0 in error
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         // if ok push new uncompressed data into dst fifo
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     // pop cluster with byref arguments
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     // pops a string including terminationsymbol that stops at the first occurance of term.string
00205     // if there is no termination string you get an empty string and the fifo is untouched
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             // not found
00212             return std::string();
00213         } else {
00214             // found
00215             int len = pos + strlen(terminationstring);
00216             std::string r = s.substr(0,len);
00217             PopRaw(len);
00218             return r;
00219         }
00220     }
00221 
00222     // pop cluster with return values
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     // peek cluster with byref arguments
00251      // TODO : endian
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     // peek cluster with return values
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     // changing values within the fifo
00292     inline  void    HackSetU    (const uint32 offset,const uint32 a) { HackSetRawEndian(offset,(const char*)&a,sizeof(uint32)); }
00293     
00294     // the methods below here are rather private, but used for some optimizations
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; // double capacity until it is large enough
00307         if (newcap > miCapacity) {
00308             miCapacity = newcap;
00309             mpBuf = (char*)realloc(mpBuf,miCapacity);
00310         }
00311         assert(miStartOff == 0); // because of Shrink
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); // because of Reserve
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); // TODO : endian conversion if neccessary
00355     }
00356     
00357     // pushes c len times
00358     inline  void    PushRawFill (const char c,const uint32 len) {
00359         if (len == 0) return;
00360         Reserve(len);
00361         assert(miStartOff == 0); // because of Reserve
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); // because of Reserve
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); // TODO : endian conversion if neccessary
00377     }
00378     inline  void    HackSetRaw  (const uint32 offset,const char* source,const uint32 len) {
00379         // printf("HackSetRaw(offset=%d,source=%#08x,len=%d) : miLen=%d, miStartOff=%d\n",offset,source,len,miLen,miStartOff);
00380         // for (int i=0;i<miLen/4;++i) printf("HackSetRaw bevore Debug[%d] : %d\n",i,PeekU(sizeof(uint32)*i));
00381         // printf("write %d to offset %d\n",*(uint32*)source,offset);
00382         memcpy(mpBuf+miStartOff+offset,source,len);
00383         // for (int i=0;i<miLen/4;++i) printf("HackSetRaw after Debug[%d] : %d\n",i,PeekU(sizeof(uint32)*i));
00384     }
00385     
00386     
00388     inline  void    PopRawEndian    (char* dest,const uint32 len) {
00389         PopRaw(dest,len); // TODO : endian conversion if neccessary
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); // TODO : endian conversion if neccessary
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         //little endian
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

Generated on Wed Feb 8 06:00:12 2012 for cpp by  doxygen 1.5.6