# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

bit_mem_stream.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdmisc.h"
00027 
00028 #include "nel/misc/bit_mem_stream.h"
00029 
00030 using namespace std;
00031 
00032 
00033 namespace NLMISC {
00034 
00035 
00036 /*
00037  * Constructor
00038  */
00039 CBitMemStream::CBitMemStream( bool inputStream, uint32 defaultcapacity ) :
00040         CMemStream( inputStream, false, defaultcapacity ),
00041         _FreeBits( 8 )
00042 {
00043         _BufPos--;
00044 }
00045 
00046 
00047 /*
00048  * Copy constructor
00049  */
00050 CBitMemStream::CBitMemStream( const CBitMemStream& other ) :
00051         CMemStream( other ),
00052         _FreeBits( other._FreeBits )
00053 {
00054 }
00055 
00056 
00057 /*
00058  * Serialize a buffer
00059  */
00060 void CBitMemStream::serialBuffer( uint8 *buf, uint len )
00061 {
00062         uint i;
00063         uint32 v;
00064         if ( isReading() )
00065         {
00066                 for ( i=0; i!=len; ++i )
00067                 {
00068                         serial( v, 8 );
00069                         buf[i] = (uint8)v;
00070                 }
00071         }
00072         else
00073         {
00074                 for ( i=0; i!=len; ++i )
00075                 {
00076                         v = (uint32)buf[i];
00077                         serial( v, 8 );
00078                 }
00079         }
00080 }
00081 
00082 
00083 /*
00084  * Serialize one bit
00085  */
00086 void CBitMemStream::serialBit( bool& bit )
00087 {
00088         uint32 ubit=0;
00089         if ( isReading() )
00090         {
00091                 serial( ubit, 1 );
00092                 bit = ( ubit!=0 );
00093         }
00094         else
00095         {
00096                 ubit = bit;
00097                 serial( ubit, 1 );
00098         }
00099 }
00100 
00101 
00102 //sint32 CBitMemStream::getPosInBit ()
00103 
00104 
00105 #define displayByteBits(a,b,c)
00106 /*void displayByteBits( uint8 b, uint nbits, sint beginpos )
00107 {
00108         string s1, s2;
00109         sint i;
00110         for ( i=nbits-1; i!=-1; --i )
00111         {
00112                 s1 += ( (b >> i) & 1 ) ? "1" : "0";
00113         }
00114         nlinfo( "%s", s1.c_str() );
00115         for ( i=nbits; i>beginpos+1; --i )
00116         {
00117                 s2 += " ";
00118         }
00119         s2 += "^";
00120         nlinfo( "%s beginpos=%u", s2.c_str(), beginpos );
00121 }*/
00122 
00123 
00124 #define displayDwordBits(a,b,c)
00125 /*void displayDwordBits( uint32 b, uint nbits, sint beginpos )
00126 {
00127         string s1, s2;
00128         sint i;
00129         for ( i=nbits-1; i!=-1; --i )
00130         {
00131                 s1 += ( (b >> i) & 1 ) ? "1" : "0";
00132         }
00133         nlinfo( "%s", s1.c_str() );
00134         for ( i=nbits; i>beginpos+1; --i )
00135         {
00136                 s2 += " ";
00137         }
00138         s2 += "^";
00139         nlinfo( "%s beginpos=%u", s2.c_str(), beginpos );
00140 }*/
00141 
00142 
00143 /*
00144  * Serialize only the nbits lower bits of value
00145  */
00146 void    CBitMemStream::serial( uint32& value, uint nbits, bool resetvalue )
00147 {
00148         //nlassert( (nbits <= 32) && (nbits != 0) );
00149         if (nbits>32 || nbits==0)
00150                 throw EMemStream (string("trying to serial ")+toString(nbits)+string(" %d bits"));
00151 
00152         if ( isReading() )
00153         {
00154                 // Check that we don't read more than there is to read
00155                 if (getPosInBit() + nbits > lengthR() * 8)
00156                 {
00157                         throw EStreamOverflow();
00158                 }
00159 
00160                 if ( resetvalue )
00161                 {
00162                         value = 0;
00163                 }
00164 
00165                 // Clear high-order bits after _FreeBits
00166                 uint8 v = *_BufPos & ((1 << _FreeBits) - 1);
00167 
00168                 if ( nbits > _FreeBits )
00169                 {
00170                         //nldebug( "Reading byte %u from %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
00171                         value |= (v << (nbits-_FreeBits));
00172                         ++_BufPos;
00173                         uint readbits = _FreeBits;
00174                         displayByteBits( *_BufPos, 8, readbits-1 );
00175                         _FreeBits = 8;
00176                         serial( value, nbits - readbits, false ); // read without resetting value
00177                 }
00178                 else
00179                 {
00180                         //nlinfo( "Reading last byte %u from %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
00181                         //displayByteBits( *_BufPos, 8, _FreeBits-1 );
00182                         value |= (v >> (_FreeBits-nbits));
00183                         displayByteBits( *_BufPos, 8, _FreeBits-1 );
00184                         if ( _FreeBits == nbits )
00185                         {
00186                                 _FreeBits = 8;
00187                                 ++_BufPos;
00188                         }
00189                         else
00190                         {
00191                                 _FreeBits -= nbits;
00192                         }
00193                 }
00194         }
00195         else
00196         {
00197                 // Resize if necessary
00198                 if ( _FreeBits == 8 ) // _FreeBits is from 7 downto 1, then 8
00199                 {
00200                         if (_BufPos == _Buffer.getPtr()+_Buffer.size() - 1)
00201                         {
00202                                 // need to resize
00203                                 _Buffer.resize(_Buffer.size()*2+1);
00204                                 _BufPos = _Buffer.getPtr() + ((_Buffer.size()-1)/2);
00205                         }
00206                         else
00207                         {
00208                                 _BufPos++;
00209                         }
00210 //                      _Buffer.push_back(0);
00211 //                      _BufPos = _Buffer.end() - 1;
00212                         *_BufPos = 0;
00213                 }
00214 
00215                 // Clear high-order bits after nbits
00216                 //displayDwordBits( value, 32, nbits-1 );
00217 
00218                 //uint32 mask = (-1 >> (32-nbits)); // does not work
00219                 uint32 v;
00220                 if ( nbits != 32 ) // arg of shl/sal/shr/sal ranges from 0 to 31
00221                 {
00222                         uint32 mask = (1 << nbits) - 1;
00223                         v = value & mask;
00224                 }
00225                 else
00226                 {
00227                         v = value;
00228                 }
00229 
00230                 // Set
00231                 if ( nbits > _FreeBits )
00232                 {
00233                         // Longer than the room in the current byte
00234                         //nldebug( "Writing byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
00235                         displayDwordBits( value, 32, nbits-1 );
00236                         *_BufPos |= (v >> (nbits - _FreeBits));
00237                         uint filledbits = _FreeBits;
00238                         displayByteBits( *_BufPos, 8, filledbits-1 );
00239                         _FreeBits = 8;
00240                         serial( v, nbits - filledbits );
00241                 }
00242                 else
00243                 {
00244                         // Shorter or equal
00245                         //nldebug( "Writing last byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
00246                         displayByteBits( *_BufPos, 8, 7 );
00247                         *_BufPos |= (v << (_FreeBits-nbits));
00248                         displayByteBits( *_BufPos, 8, _FreeBits-1 );
00249                         _FreeBits = ((_FreeBits-1 - nbits) % 8) + 1; // ((uint)-1) % 8 equals 7
00250                 }
00251 
00252         }
00253 
00254 }
00255 
00256 
00257 /*
00258  * Serial float
00259  */
00260 void    CBitMemStream::serial(float &b)
00261 {
00262         uint32 uf=0;
00263         if ( isReading() )
00264         {
00265                 serial( uf );
00266                 b = *(float*)&uf;
00267         }
00268         else
00269         {
00270                 uf = *(uint32*)&b;
00271                 serial( uf );
00272         }
00273 }
00274 
00275 
00276 /*
00277  * Serial string
00278  */
00279 void    CBitMemStream::serial(std::string &b) 
00280 {
00281         uint32 len=0;
00282 
00283         // Serialize length
00284         if ( isReading() )
00285         {
00286                 serial( len );
00287                 if (len > length()-getPos())
00288                 {
00289                         nlwarning("string maximum length reached, perhaps invalid string size (%d)", len);
00290                         throw NLMISC::EInvalidDataStream();
00291                 }
00292                 b.resize( len );
00293         }
00294         else
00295         {
00296                 len = b.size();
00297                 serial( len );
00298         }
00299 
00300         // Serialize buffer
00301         if ( len != 0 )
00302         {
00303                 serialBuffer( (uint8*)(&*b.begin()), len );
00304         }
00305 }
00306 
00307 /*
00308  * Serial string
00309  */
00310 void    CBitMemStream::serial(CBitMemStream &b)
00311 {
00312         uint32 len=0;
00313 
00314         // Serialize length
00315         if ( isReading() )
00316         {
00317                 // fill b with data from this
00318                 serial (len);
00319                 if (len > length()-getPos())
00320                 {
00321                         nlwarning("bitmemstream maximum length reached, perhaps invalid bitmemstream size (%d)", len);
00322                         throw NLMISC::EInvalidDataStream();
00323                 }
00324 
00325                 serialBuffer (b.bufferToFill (len), len);
00326                 b.resetBufPos ();
00327         }
00328         else
00329         {
00330                 // fill this with data from b
00331                 len = b.length();
00332 
00333                 serial( len );
00334                 serialBuffer( (uint8*) b.buffer (), len );
00335         }
00336 
00337 }
00338 
00339 /*
00340  * Specialisation of serialCont() for vector<bool>
00341  */
00342 void CBitMemStream::serialCont(std::vector<bool> &cont)
00343 {
00344         sint32  len=0;
00345         if(isReading())
00346         {
00347                 serial(len);
00348                 if (len/8 > (sint32)(length()-getPos()))
00349                 {
00350                         nlwarning("stl container maximum length reached, perhaps invalid container size (%d)", len);
00351                         throw NLMISC::EInvalidDataStream();
00352                 }
00353                 // special version for vector: adjut good size.
00354                 contReset(cont);
00355                 cont.reserve(len);
00356 
00357                 for(sint i=0;i<len;i++)
00358                 {
00359                         bool    v;
00360                         serialBit(v);
00361                         cont.insert(cont.end(), v);
00362                 }
00363         }
00364         else
00365         {
00366                 len= cont.size();
00367                 serial(len);
00368 
00369                 std::vector<bool>::iterator it= cont.begin();
00370                 for(sint i=0;i<len;i++, it++)
00371                 {
00372                         bool b = *it;
00373                         serialBit( b );
00374                 }
00375         }
00376 }
00377 
00378 
00379 
00380 } // NLMISC