• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

BitStream.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #if defined(_MSC_VER) && _MSC_VER < 1299 // VC6 doesn't support template specialization
00009 #include "BitStream_NoTemplate.cpp"
00010 #else
00011 
00012 #include "BitStream.h"
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <stdlib.h>
00016 
00017 #include "SocketIncludes.h"
00018 
00019 #if defined(_XBOX) || defined(X360)
00020                             
00021 #elif defined(_WIN32)
00022 #include <winsock2.h> // htonl
00023 #include <memory.h>
00024 #include <cmath>
00025 #include <float.h>
00026 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00027                         
00028 #else
00029 #include <arpa/inet.h>
00030 #include <memory.h>
00031 #include <cmath>
00032 #include <float.h>
00033 #endif
00034 
00035 // MSWin uses _copysign, others use copysign...
00036 #ifndef _WIN32
00037 #define _copysign copysign
00038 #endif
00039 
00040 
00041 
00042 using namespace RakNet;
00043 
00044 #ifdef _MSC_VER
00045 #pragma warning( push )
00046 #endif
00047 
00048 BitStream::BitStream()
00049 {
00050         numberOfBitsUsed = 0;
00051         //numberOfBitsAllocated = 32 * 8;
00052         numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
00053         readOffset = 0;
00054         //data = ( unsigned char* ) rakMalloc_Ex( 32, __FILE__, __LINE__ );
00055         data = ( unsigned char* ) stackData;
00056 
00057 #ifdef _DEBUG   
00058         //      RakAssert( data );
00059 #endif
00060         //memset(data, 0, 32);
00061         copyData = true;
00062 }
00063 
00064 BitStream::BitStream( const unsigned int initialBytesToAllocate )
00065 {
00066         numberOfBitsUsed = 0;
00067         readOffset = 0;
00068         if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE)
00069         {
00070                 data = ( unsigned char* ) stackData;
00071                 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
00072         }
00073         else
00074         {
00075                 data = ( unsigned char* ) rakMalloc_Ex( (size_t) initialBytesToAllocate, __FILE__, __LINE__ );
00076                 numberOfBitsAllocated = initialBytesToAllocate << 3;
00077         }
00078 #ifdef _DEBUG
00079         RakAssert( data );
00080 #endif
00081         // memset(data, 0, initialBytesToAllocate);
00082         copyData = true;
00083 }
00084 
00085 BitStream::BitStream( unsigned char* _data, const unsigned int lengthInBytes, bool _copyData )
00086 {
00087         numberOfBitsUsed = lengthInBytes << 3;
00088         readOffset = 0;
00089         copyData = _copyData;
00090         numberOfBitsAllocated = lengthInBytes << 3;
00091 
00092         if ( copyData )
00093         {
00094                 if ( lengthInBytes > 0 )
00095                 {
00096                         if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE)
00097                         {
00098                                 data = ( unsigned char* ) stackData;
00099                                 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3;
00100                         }
00101                         else
00102                         {
00103                                 data = ( unsigned char* ) rakMalloc_Ex( (size_t) lengthInBytes, __FILE__, __LINE__ );
00104                         }
00105 #ifdef _DEBUG
00106                         RakAssert( data );
00107 #endif
00108                         memcpy( data, _data, (size_t) lengthInBytes );
00109                 }
00110                 else
00111                         data = 0;
00112         }
00113         else
00114                 data = ( unsigned char* ) _data;
00115 }
00116 
00117 // Use this if you pass a pointer copy to the constructor (_copyData==false) and want to overallocate to prevent reallocation
00118 void BitStream::SetNumberOfBitsAllocated( const BitSize_t lengthInBits )
00119 {
00120 #ifdef _DEBUG
00121         RakAssert( lengthInBits >= ( BitSize_t ) numberOfBitsAllocated );
00122 #endif  
00123         numberOfBitsAllocated = lengthInBits;
00124 }
00125 
00126 BitStream::~BitStream()
00127 {
00128         if ( copyData && numberOfBitsAllocated > (BITSTREAM_STACK_ALLOCATION_SIZE << 3))
00129                 rakFree_Ex( data , __FILE__, __LINE__ );  // Use realloc and free so we are more efficient than delete and new for resizing
00130 }
00131 
00132 void BitStream::Reset( void )
00133 {
00134         // Note:  Do NOT reallocate memory because BitStream is used
00135         // in places to serialize/deserialize a buffer. Reallocation
00136         // is a dangerous operation (may result in leaks).
00137 
00138         if ( numberOfBitsUsed > 0 )
00139         {
00140                 //  memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed));
00141         }
00142 
00143         // Don't free memory here for speed efficiency
00144         //free(data);  // Use realloc and free so we are more efficient than delete and new for resizing
00145         numberOfBitsUsed = 0;
00146 
00147         //numberOfBitsAllocated=8;
00148         readOffset = 0;
00149 
00150         //data=(unsigned char*)rakMalloc_Ex(1, __FILE__, __LINE__);
00151         // if (numberOfBitsAllocated>0)
00152         //  memset(data, 0, BITS_TO_BYTES(numberOfBitsAllocated));
00153 }
00154 
00155 // Write an array or casted stream
00156 void BitStream::Write( const char* inputByteArray, const unsigned int numberOfBytes )
00157 {
00158         if (numberOfBytes==0)
00159                 return;
00160 
00161         // Optimization:
00162         if ((numberOfBitsUsed & 7) == 0)
00163         {
00164                 AddBitsAndReallocate( BYTES_TO_BITS(numberOfBytes) );
00165                 memcpy(data+BITS_TO_BYTES(numberOfBitsUsed), inputByteArray, (size_t) numberOfBytes);
00166                 numberOfBitsUsed+=BYTES_TO_BITS(numberOfBytes);
00167         }
00168         else
00169         {
00170                 WriteBits( ( unsigned char* ) inputByteArray, numberOfBytes * 8, true );
00171         }
00172 
00173 }
00174 void BitStream::Write( BitStream *bitStream)
00175 {
00176         Write(bitStream, bitStream->GetNumberOfBitsUsed());
00177 }
00178 void BitStream::Write( BitStream *bitStream, BitSize_t numberOfBits )
00179 {
00180         AddBitsAndReallocate( numberOfBits );
00181         BitSize_t numberOfBitsMod8;
00182 
00183         if ((bitStream->GetReadOffset()&7)==0 && (numberOfBitsUsed&7)==0)
00184         {
00185                 int readOffsetBytes=bitStream->GetReadOffset()/8;
00186                 int numBytes=numberOfBits/8;
00187                 memcpy(data + (numberOfBitsUsed >> 3), bitStream->GetData()+readOffsetBytes, numBytes);
00188                 numberOfBits-=BYTES_TO_BITS(numBytes);
00189                 bitStream->SetReadOffset(BYTES_TO_BITS(numBytes+readOffsetBytes));
00190                 numberOfBitsUsed+=BYTES_TO_BITS(numBytes);
00191         }
00192 
00193         while (numberOfBits-->0 && bitStream->readOffset + 1 <= bitStream->numberOfBitsUsed)
00194         {
00195                 numberOfBitsMod8 = numberOfBitsUsed & 7;
00196                 if ( numberOfBitsMod8 == 0 )
00197                 {
00198                         // New byte
00199                         if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
00200                         {
00201                                 // Write 1
00202                                 data[ numberOfBitsUsed >> 3 ] = 0x80;
00203                         }
00204                         else
00205                         {
00206                                 // Write 0
00207                                 data[ numberOfBitsUsed >> 3 ] = 0;
00208                         }
00209 
00210                 }
00211                 else
00212                 {
00213                         // Existing byte
00214                         if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
00215                                 data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
00216                         // else 0, do nothing
00217                 }
00218 
00219                 bitStream->readOffset++;
00220                 numberOfBitsUsed++;
00221         }
00222 }
00223 void BitStream::Write( BitStream &bitStream, BitSize_t numberOfBits )
00224 {
00225         Write(&bitStream, numberOfBits);
00226 }
00227 void BitStream::Write( BitStream &bitStream )
00228 {
00229         Write(&bitStream);
00230 }
00231 bool BitStream::Read( BitStream *bitStream, BitSize_t numberOfBits )
00232 {
00233         if (GetNumberOfUnreadBits() < numberOfBits)
00234                 return false;
00235         bitStream->Write(this, numberOfBits);
00236         return true;
00237 }
00238 bool BitStream::Read( BitStream *bitStream )
00239 {
00240         bitStream->Write(this);
00241         return true;
00242 }
00243 bool BitStream::Read( BitStream &bitStream, BitSize_t numberOfBits )
00244 {
00245         if (GetNumberOfUnreadBits() < numberOfBits)
00246                 return false;
00247         bitStream.Write(this, numberOfBits);
00248         return true;
00249 }
00250 bool BitStream::Read( BitStream &bitStream )
00251 {
00252         bitStream.Write(this);
00253         return true;
00254 }
00255 
00256 // Read an array or casted stream
00257 bool BitStream::Read( char* outByteArray, const unsigned int numberOfBytes )
00258 {
00259         // Optimization:
00260         if ((readOffset & 7) == 0)
00261         {
00262                 if ( readOffset + ( numberOfBytes << 3 ) > numberOfBitsUsed )
00263                         return false;
00264 
00265                 // Write the data
00266                 memcpy( outByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytes );
00267 
00268                 readOffset += numberOfBytes << 3;
00269                 return true;
00270         }
00271         else
00272         {
00273                 return ReadBits( ( unsigned char* ) outByteArray, numberOfBytes * 8 );
00274         }
00275 }
00276 
00277 // Sets the read pointer back to the beginning of your data.
00278 void BitStream::ResetReadPointer( void )
00279 {
00280         readOffset = 0;
00281 }
00282 
00283 // Sets the write pointer back to the beginning of your data.
00284 void BitStream::ResetWritePointer( void )
00285 {
00286         numberOfBitsUsed = 0;
00287 }
00288 
00289 // Write a 0
00290 void BitStream::Write0( void )
00291 {
00292         AddBitsAndReallocate( 1 );
00293 
00294         // New bytes need to be zeroed
00295         if ( ( numberOfBitsUsed & 7 ) == 0 )
00296                 data[ numberOfBitsUsed >> 3 ] = 0;
00297 
00298         numberOfBitsUsed++;
00299 }
00300 
00301 // Write a 1
00302 void BitStream::Write1( void )
00303 {
00304         AddBitsAndReallocate( 1 );
00305 
00306         BitSize_t numberOfBitsMod8 = numberOfBitsUsed & 7;
00307 
00308         if ( numberOfBitsMod8 == 0 )
00309                 data[ numberOfBitsUsed >> 3 ] = 0x80;
00310         else
00311                 data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
00312 
00313         numberOfBitsUsed++;
00314 }
00315 
00316 // Returns true if the next data read is a 1, false if it is a 0
00317 bool BitStream::ReadBit( void )
00318 {
00319         bool result = ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) !=0;
00320         readOffset++;
00321         return result;
00322 }
00323 
00324 // Align the bitstream to the byte boundary and then write the specified number of bits.
00325 // This is faster than WriteBits but wastes the bits to do the alignment and requires you to call
00326 // SetReadToByteAlignment at the corresponding read position
00327 void BitStream::WriteAlignedBytes( const unsigned char* inByteArray, const unsigned int numberOfBytesToWrite )
00328 {
00329         AlignWriteToByteBoundary();
00330         Write((const char*) inByteArray, numberOfBytesToWrite);
00331 }
00332 void BitStream::EndianSwapBytes( int byteOffset, int length )
00333 {
00334         if (DoEndianSwap())
00335         {
00336                 ReverseBytesInPlace(data+byteOffset, length);
00337         }
00338 }
00340 void BitStream::WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite )
00341 {
00342         if (inByteArray==0 || inputLength==0)
00343         {
00344                 WriteCompressed((unsigned int)0);
00345                 return;
00346         }
00347         WriteCompressed(inputLength);
00348         WriteAlignedBytes((const unsigned char*) inByteArray, inputLength < maxBytesToWrite ? inputLength : maxBytesToWrite);
00349 }
00350 
00351 // Read bits, starting at the next aligned bits. Note that the modulus 8 starting offset of the
00352 // sequence must be the same as was used with WriteBits. This will be a problem with packet coalescence
00353 // unless you byte align the coalesced packets.
00354 bool BitStream::ReadAlignedBytes( unsigned char* inOutByteArray, const unsigned int numberOfBytesToRead )
00355 {
00356 #ifdef _DEBUG
00357         RakAssert( numberOfBytesToRead > 0 );
00358 #endif
00359 
00360         if ( numberOfBytesToRead <= 0 )
00361                 return false;
00362 
00363         // Byte align
00364         AlignReadToByteBoundary();
00365 
00366         if ( readOffset + ( numberOfBytesToRead << 3 ) > numberOfBitsUsed )
00367                 return false;
00368 
00369         // Write the data
00370         memcpy( inOutByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytesToRead );
00371 
00372         readOffset += numberOfBytesToRead << 3;
00373 
00374         return true;
00375 }
00376 bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead )
00377 {
00378         return ReadAlignedBytesSafe(inOutByteArray,(unsigned int&) inputLength,(unsigned int)maxBytesToRead);
00379 }
00380 bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
00381 {
00382         if (ReadCompressed(inputLength)==false)
00383                 return false;
00384         if (inputLength > maxBytesToRead)
00385                 inputLength=maxBytesToRead;
00386         if (inputLength==0)
00387                 return true;
00388         return ReadAlignedBytes((unsigned char*) inOutByteArray, inputLength);
00389 }
00390 bool BitStream::ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead )
00391 {
00392         return ReadAlignedBytesSafeAlloc(outByteArray,(unsigned int&) inputLength, maxBytesToRead);
00393 }
00394 bool BitStream::ReadAlignedBytesSafeAlloc( char ** outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
00395 {
00396         rakFree_Ex(*outByteArray, __FILE__, __LINE__ );
00397         *outByteArray=0;
00398         if (ReadCompressed(inputLength)==false)
00399                 return false;
00400         if (inputLength > maxBytesToRead)
00401                 inputLength=maxBytesToRead;
00402         if (inputLength==0)
00403                 return true;
00404         *outByteArray = (char*) rakMalloc_Ex( (size_t) inputLength, __FILE__, __LINE__ );
00405         return ReadAlignedBytes((unsigned char*) *outByteArray, inputLength);
00406 }
00407 
00408 // Write numberToWrite bits from the input source
00409 void BitStream::WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits )
00410 {
00411 //      if (numberOfBitsToWrite<=0)
00412 //              return;
00413 
00414         AddBitsAndReallocate( numberOfBitsToWrite );
00415 
00416         const BitSize_t numberOfBitsUsedMod8 = numberOfBitsUsed & 7;
00417 
00418         // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
00419         if (numberOfBitsUsedMod8==0 && (numberOfBitsToWrite&7)==0)
00420         {
00421                 memcpy( data + ( numberOfBitsUsed >> 3 ), inByteArray, numberOfBitsToWrite>>3);
00422                 numberOfBitsUsed+=numberOfBitsToWrite;
00423                 return;
00424         }
00425 
00426         unsigned char dataByte;
00427         const unsigned char* inputPtr=inByteArray;
00428 
00429         // Faster to put the while at the top surprisingly enough
00430         while ( numberOfBitsToWrite > 0 )
00431                 //do
00432         {
00433                 dataByte = *( inputPtr++ );
00434 
00435                 if ( numberOfBitsToWrite < 8 && rightAlignedBits )   // rightAlignedBits means in the case of a partial byte, the bits are aligned from the right (bit 0) rather than the left (as in the normal internal representation)
00436                         dataByte <<= 8 - numberOfBitsToWrite;  // shift left to get the bits on the left, as in our internal representation
00437 
00438                 // Writing to a new byte each time
00439                 if ( numberOfBitsUsedMod8 == 0 )
00440                         * ( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;
00441                 else
00442                 {
00443                         // Copy over the new data.
00444                         *( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half
00445 
00446                         if ( 8 - ( numberOfBitsUsedMod8 ) < 8 && 8 - ( numberOfBitsUsedMod8 ) < numberOfBitsToWrite )   // If we didn't write it all out in the first half (8 - (numberOfBitsUsed%8) is the number we wrote in the first half)
00447                         {
00448                                 *( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary)
00449                         }
00450                 }
00451 
00452                 if ( numberOfBitsToWrite >= 8 )
00453                 {
00454                         numberOfBitsUsed += 8;
00455                         numberOfBitsToWrite -= 8;
00456                 }
00457                 else
00458                 {
00459                         numberOfBitsUsed += numberOfBitsToWrite;
00460                         numberOfBitsToWrite=0;
00461                 }
00462         }
00463         // } while(numberOfBitsToWrite>0);
00464 }
00465 
00466 // Set the stream to some initial data.  For internal use
00467 void BitStream::SetData( unsigned char *inByteArray )
00468 {
00469         data=inByteArray;
00470         copyData=false;
00471 }
00472 
00473 // Assume the input source points to a native type, compress and write it
00474 void BitStream::WriteCompressed( const unsigned char* inByteArray,
00475                                                                 const unsigned int size, const bool unsignedData )
00476 {
00477         BitSize_t currentByte = ( size >> 3 ) - 1; // PCs
00478 
00479         unsigned char byteMatch;
00480 
00481         if ( unsignedData )
00482         {
00483                 byteMatch = 0;
00484         }
00485 
00486         else
00487         {
00488                 byteMatch = 0xFF;
00489         }
00490 
00491         // Write upper bytes with a single 1
00492         // From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
00493         while ( currentByte > 0 )
00494         {
00495                 if ( inByteArray[ currentByte ] == byteMatch )   // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted
00496                 {
00497                         bool b = true;
00498                         Write( b );
00499                 }
00500                 else
00501                 {
00502                         // Write the remainder of the data after writing 0
00503                         bool b = false;
00504                         Write( b );
00505 
00506                         WriteBits( inByteArray, ( currentByte + 1 ) << 3, true );
00507                         //  currentByte--;
00508 
00509 
00510                         return ;
00511                 }
00512 
00513                 currentByte--;
00514         }
00515 
00516         // If the upper half of the last byte is a 0 (positive) or 16 (negative) then write a 1 and the remaining 4 bits.  Otherwise write a 0 and the 8 bites.
00517         if ( ( unsignedData && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0x00 ) ||
00518                 ( unsignedData == false && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0xF0 ) )
00519         {
00520                 bool b = true;
00521                 Write( b );
00522                 WriteBits( inByteArray + currentByte, 4, true );
00523         }
00524 
00525         else
00526         {
00527                 bool b = false;
00528                 Write( b );
00529                 WriteBits( inByteArray + currentByte, 8, true );
00530         }
00531 }
00532 
00533 // Read numberOfBitsToRead bits to the output source
00534 // alignBitsToRight should be set to true to convert internal bitstream data to userdata
00535 // It should be false if you used WriteBits with rightAlignedBits false
00536 bool BitStream::ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight )
00537 {
00538 #ifdef _DEBUG
00539         //      RakAssert( numberOfBitsToRead > 0 );
00540 #endif
00541         if (numberOfBitsToRead<=0)
00542                 return false;
00543 
00544         if ( readOffset + numberOfBitsToRead > numberOfBitsUsed )
00545                 return false;
00546 
00547 
00548         const BitSize_t readOffsetMod8 = readOffset & 7;
00549 
00550         // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
00551         if (readOffsetMod8==0 && (numberOfBitsToRead&7)==0)
00552         {
00553                 memcpy( inOutByteArray, data + ( readOffset >> 3 ), numberOfBitsToRead>>3);
00554                 readOffset+=numberOfBitsToRead;
00555                 return true;
00556         }
00557 
00558 
00559 
00560         BitSize_t offset = 0;
00561 
00562         memset( inOutByteArray, 0, (size_t) BITS_TO_BYTES( numberOfBitsToRead ) );
00563 
00564         while ( numberOfBitsToRead > 0 )
00565         {
00566                 *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half
00567 
00568                 if ( readOffsetMod8 > 0 && numberOfBitsToRead > 8 - ( readOffsetMod8 ) )   // If we have a second half, we didn't read enough bytes in the first half
00569                         *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) + 1 ) >> ( 8 - ( readOffsetMod8 ) ); // Second half (overlaps byte boundary)
00570 
00571                 if (numberOfBitsToRead>=8)
00572                 {
00573                         numberOfBitsToRead -= 8;
00574                         readOffset += 8;
00575                         offset++;
00576                 }
00577                 else
00578                 {
00579                         int neg = (int) numberOfBitsToRead - 8;
00580 
00581                         if ( neg < 0 )   // Reading a partial byte for the last byte, shift right so the data is aligned on the right
00582                         {
00583 
00584                                 if ( alignBitsToRight )
00585                                         * ( inOutByteArray + offset ) >>= -neg;
00586 
00587                                 readOffset += 8 + neg;
00588                         }
00589                         else
00590                                 readOffset += 8;
00591 
00592                         offset++;
00593 
00594                         numberOfBitsToRead=0;
00595                 }               
00596         }
00597 
00598         return true;
00599 }
00600 
00601 // Assume the input source points to a compressed native type. Decompress and read it
00602 bool BitStream::ReadCompressed( unsigned char* inOutByteArray,
00603                                                            const unsigned int size, const bool unsignedData )
00604 {
00605         unsigned int currentByte = ( size >> 3 ) - 1;
00606 
00607 
00608         unsigned char byteMatch, halfByteMatch;
00609 
00610         if ( unsignedData )
00611         {
00612                 byteMatch = 0;
00613                 halfByteMatch = 0;
00614         }
00615 
00616         else
00617         {
00618                 byteMatch = 0xFF;
00619                 halfByteMatch = 0xF0;
00620         }
00621 
00622         // Upper bytes are specified with a single 1 if they match byteMatch
00623         // From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
00624         while ( currentByte > 0 )
00625         {
00626                 // If we read a 1 then the data is byteMatch.
00627 
00628                 bool b;
00629 
00630                 if ( Read( b ) == false )
00631                         return false;
00632 
00633                 if ( b )   // Check that bit
00634                 {
00635                         inOutByteArray[ currentByte ] = byteMatch;
00636                         currentByte--;
00637                 }
00638                 else
00639                 {
00640                         // Read the rest of the bytes
00641 
00642                         if ( ReadBits( inOutByteArray, ( currentByte + 1 ) << 3 ) == false )
00643                                 return false;
00644 
00645                         return true;
00646                 }
00647         }
00648 
00649         // All but the first bytes are byteMatch.  If the upper half of the last byte is a 0 (positive) or 16 (negative) then what we read will be a 1 and the remaining 4 bits.
00650         // Otherwise we read a 0 and the 8 bytes
00651         //RakAssert(readOffset+1 <=numberOfBitsUsed); // If this assert is hit the stream wasn't long enough to read from
00652         if ( readOffset + 1 > numberOfBitsUsed )
00653                 return false;
00654 
00655         bool b;
00656 
00657         if ( Read( b ) == false )
00658                 return false;
00659 
00660         if ( b )   // Check that bit
00661         {
00662 
00663                 if ( ReadBits( inOutByteArray + currentByte, 4 ) == false )
00664                         return false;
00665 
00666                 inOutByteArray[ currentByte ] |= halfByteMatch; // We have to set the high 4 bits since these are set to 0 by ReadBits
00667         }
00668         else
00669         {
00670                 if ( ReadBits( inOutByteArray + currentByte, 8 ) == false )
00671                         return false;
00672         }
00673 
00674         return true;
00675 }
00676 
00677 // Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
00678 void BitStream::AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite )
00679 {
00680         BitSize_t newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed;
00681 
00682         if ( numberOfBitsToWrite + numberOfBitsUsed > 0 && ( ( numberOfBitsAllocated - 1 ) >> 3 ) < ( ( newNumberOfBitsAllocated - 1 ) >> 3 ) )   // If we need to allocate 1 or more new bytes
00683         {
00684 #ifdef _DEBUG
00685                 // If this assert hits then we need to specify true for the third parameter in the constructor
00686                 // It needs to reallocate to hold all the data and can't do it unless we allocated to begin with
00687                 // Often hits if you call Write or Serialize on a read-only bitstream
00688                 RakAssert( copyData == true );
00689 #endif
00690 
00691                 // Less memory efficient but saves on news and deletes
00693                 newNumberOfBitsAllocated = ( numberOfBitsToWrite + numberOfBitsUsed ) * 2;
00694                 if (newNumberOfBitsAllocated - ( numberOfBitsToWrite + numberOfBitsUsed ) > 1048576 )
00695                         newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed + 1048576;
00696 
00697                 //              BitSize_t newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated );
00698                 // Use realloc and free so we are more efficient than delete and new for resizing
00699                 BitSize_t amountToAllocate = BITS_TO_BYTES( newNumberOfBitsAllocated );
00700                 if (data==(unsigned char*)stackData)
00701                 {
00702                         if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)
00703                         {
00704                                 data = ( unsigned char* ) rakMalloc_Ex( (size_t) amountToAllocate, __FILE__, __LINE__ );
00705 
00706                                 // need to copy the stack data over to our new memory area too
00707                                 memcpy ((void *)data, (void *)stackData, (size_t) BITS_TO_BYTES( numberOfBitsAllocated )); 
00708                         }
00709                 }
00710                 else
00711                 {
00712                         data = ( unsigned char* ) rakRealloc_Ex( data, (size_t) amountToAllocate, __FILE__, __LINE__ );
00713                 }
00714 
00715 #ifdef _DEBUG
00716                 RakAssert( data ); // Make sure realloc succeeded
00717 #endif
00718                 //  memset(data+newByteOffset, 0,  ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0
00719         }
00720 
00721         if ( newNumberOfBitsAllocated > numberOfBitsAllocated )
00722                 numberOfBitsAllocated = newNumberOfBitsAllocated;
00723 }
00724 BitSize_t BitStream::GetNumberOfBitsAllocated(void) const
00725 {
00726         return numberOfBitsAllocated;
00727 }
00728 void BitStream::PadWithZeroToByteLength( unsigned int bytes )
00729 {
00730         if (GetNumberOfBytesUsed() < bytes)
00731         {
00732                 AlignWriteToByteBoundary();
00733                 unsigned int numToWrite = bytes - GetNumberOfBytesUsed();
00734                 AddBitsAndReallocate( BYTES_TO_BITS(numToWrite) );
00735                 memset(data+BITS_TO_BYTES(numberOfBitsUsed), 0, (size_t) numToWrite);
00736                 numberOfBitsUsed+=BYTES_TO_BITS(numToWrite);
00737         }
00738 }
00739 
00740 /* 
00741 // Julius Goryavsky's version of Harley's algorithm.
00742 // 17 elementary ops plus an indexed load, if the machine
00743 // has "and not."
00744 
00745 int nlz10b(unsigned x) {
00746 
00747    static char table[64] =
00748      {32,20,19, u, u,18, u, 7,  10,17, u, u,14, u, 6, u,
00749        u, 9, u,16, u, u, 1,26,   u,13, u, u,24, 5, u, u,
00750        u,21, u, 8,11, u,15, u,   u, u, u, 2,27, 0,25, u,
00751       22, u,12, u, u, 3,28, u,  23, u, 4,29, u, u,30,31};
00752 
00753    x = x | (x >> 1);    // Propagate leftmost
00754    x = x | (x >> 2);    // 1-bit to the right.
00755    x = x | (x >> 4);
00756    x = x | (x >> 8);
00757    x = x & ~(x >> 16);
00758    x = x*0xFD7049FF;    // Activate this line or the following 3.
00759 // x = (x << 9) - x;    // Multiply by 511.
00760 // x = (x << 11) - x;   // Multiply by 2047.
00761 // x = (x << 14) - x;   // Multiply by 16383.
00762    return table[x >> 26];
00763 }
00764 */
00765 int BitStream::NumberOfLeadingZeroes( int8_t x ) {return NumberOfLeadingZeroes((uint8_t)x);}
00766 int BitStream::NumberOfLeadingZeroes( uint8_t x )
00767 {
00768         uint8_t y;
00769         int n;
00770 
00771         n = 8;
00772         y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
00773         y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
00774         y = x >> 1;  if (y != 0) return n - 2;
00775         return (int)(n - x);
00776 }
00777 int BitStream::NumberOfLeadingZeroes( int16_t x ) {return NumberOfLeadingZeroes((uint16_t)x);}
00778 int BitStream::NumberOfLeadingZeroes( uint16_t x )
00779 {
00780         uint16_t y;
00781         int n;
00782 
00783         n = 16;
00784         y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
00785         y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
00786         y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
00787         y = x >> 1;  if (y != 0) return n - 2;
00788         return (int)(n - x);
00789 }
00790 int BitStream::NumberOfLeadingZeroes( int32_t x ) {return NumberOfLeadingZeroes((uint32_t)x);}
00791 int BitStream::NumberOfLeadingZeroes( uint32_t x )
00792 {
00793         uint32_t y;
00794         int n;
00795 
00796         n = 32;
00797         y = x >>16;  if (y != 0) {n = n -16;  x = y;}
00798         y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
00799         y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
00800         y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
00801         y = x >> 1;  if (y != 0) return n - 2;
00802         return (int)(n - x);
00803 }
00804 int BitStream::NumberOfLeadingZeroes( int64_t x ) {return NumberOfLeadingZeroes((uint64_t)x);}
00805 int BitStream::NumberOfLeadingZeroes( uint64_t x )
00806 {
00807         uint64_t y;
00808         int n;
00809 
00810         n = 64;
00811         y = x >>32;  if (y != 0) {n = n -32;  x = y;}
00812         y = x >>16;  if (y != 0) {n = n -16;  x = y;}
00813         y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
00814         y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
00815         y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
00816         y = x >> 1;  if (y != 0) return n - 2;
00817         return (int)(n - x);
00818 }
00819 
00820 // Should hit if reads didn't match writes
00821 void BitStream::AssertStreamEmpty( void )
00822 {
00823         RakAssert( readOffset == numberOfBitsUsed );
00824 }
00825 void BitStream::PrintBits( char *out ) const
00826 {
00827         if ( numberOfBitsUsed <= 0 )
00828         {
00829                 strcpy(out, "No bits\n" );
00830                 return;
00831         }
00832 
00833         unsigned int strIndex=0;
00834         for ( BitSize_t counter = 0; counter < BITS_TO_BYTES( numberOfBitsUsed ); counter++ )
00835         {
00836                 BitSize_t stop;
00837 
00838                 if ( counter == ( numberOfBitsUsed - 1 ) >> 3 )
00839                         stop = 8 - ( ( ( numberOfBitsUsed - 1 ) & 7 ) + 1 );
00840                 else
00841                         stop = 0;
00842 
00843                 for ( BitSize_t counter2 = 7; counter2 >= stop; counter2-- )
00844                 {
00845                         if ( ( data[ counter ] >> counter2 ) & 1 )
00846                                 out[strIndex++]='1';
00847                         else
00848                                 out[strIndex++]='0';
00849 
00850                         if (counter2==0)
00851                                 break;
00852                 }
00853 
00854                 out[strIndex++]=' ';
00855         }
00856 
00857         out[strIndex++]='\n';
00858 
00859         out[strIndex++]=0;
00860 }
00861 void BitStream::PrintBits( void ) const
00862 {
00863         char out[2048];
00864         PrintBits(out);
00865         RAKNET_DEBUG_PRINTF(out);
00866 }
00867 void BitStream::PrintHex( char *out ) const
00868 {
00869         BitSize_t i;
00870         for ( i=0; i < GetNumberOfBytesUsed(); i++)
00871         {
00872                 sprintf(out+i*3, "%02x ", data[i]);
00873         }
00874 }
00875 void BitStream::PrintHex( void ) const
00876 {
00877         char out[2048];
00878         PrintHex(out);
00879         RAKNET_DEBUG_PRINTF(out);
00880 }
00881 
00882 // Exposes the data for you to look at, like PrintBits does.
00883 // Data will point to the stream.  Returns the length in bits of the stream.
00884 BitSize_t BitStream::CopyData( unsigned char** _data ) const
00885 {
00886 #ifdef _DEBUG
00887         RakAssert( numberOfBitsUsed > 0 );
00888 #endif
00889 
00890         *_data = (unsigned char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES( numberOfBitsUsed ), __FILE__, __LINE__ );
00891         memcpy( *_data, data, sizeof(unsigned char) * (size_t) ( BITS_TO_BYTES( numberOfBitsUsed ) ) );
00892         return numberOfBitsUsed;
00893 }
00894 
00895 // Ignore data we don't intend to read
00896 void BitStream::IgnoreBits( const BitSize_t numberOfBits )
00897 {
00898         readOffset += numberOfBits;
00899 }
00900 
00901 void BitStream::IgnoreBytes( const unsigned int numberOfBytes )
00902 {
00903         IgnoreBits(BYTES_TO_BITS(numberOfBytes));
00904 }
00905 
00906 // Move the write pointer to a position on the array.  Dangerous if you don't know what you are doing!
00907 // Doesn't work with non-aligned data!
00908 void BitStream::SetWriteOffset( const BitSize_t offset )
00909 {
00910         numberOfBitsUsed = offset;
00911 }
00912 
00913 /*
00914 BitSize_t BitStream::GetWriteOffset( void ) const
00915 {
00916 return numberOfBitsUsed;
00917 }
00918 
00919 // Returns the length in bits of the stream
00920 BitSize_t BitStream::GetNumberOfBitsUsed( void ) const
00921 {
00922 return GetWriteOffset();
00923 }
00924 
00925 // Returns the length in bytes of the stream
00926 BitSize_t BitStream::GetNumberOfBytesUsed( void ) const
00927 {
00928 return BITS_TO_BYTES( numberOfBitsUsed );
00929 }
00930 
00931 // Returns the number of bits into the stream that we have read
00932 BitSize_t BitStream::GetReadOffset( void ) const
00933 {
00934 return readOffset;
00935 }
00936 
00937 
00938 // Sets the read bit index
00939 void BitStream::SetReadOffset( const BitSize_t newReadOffset )
00940 {
00941 readOffset=newReadOffset;
00942 }
00943 
00944 // Returns the number of bits left in the stream that haven't been read
00945 BitSize_t BitStream::GetNumberOfUnreadBits( void ) const
00946 {
00947 return numberOfBitsUsed - readOffset;
00948 }
00949 // Exposes the internal data
00950 unsigned char* BitStream::GetData( void ) const
00951 {
00952 return data;
00953 }
00954 
00955 */
00956 // If we used the constructor version with copy data off, this makes sure it is set to on and the data pointed to is copied.
00957 void BitStream::AssertCopyData( void )
00958 {
00959         if ( copyData == false )
00960         {
00961                 copyData = true;
00962 
00963                 if ( numberOfBitsAllocated > 0 )
00964                 {
00965                         unsigned char * newdata = ( unsigned char* ) rakMalloc_Ex( (size_t) BITS_TO_BYTES( numberOfBitsAllocated ), __FILE__, __LINE__ );
00966 #ifdef _DEBUG
00967 
00968                         RakAssert( data );
00969 #endif
00970 
00971                         memcpy( newdata, data, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ) );
00972                         data = newdata;
00973                 }
00974 
00975                 else
00976                         data = 0;
00977         }
00978 }
00979 bool BitStream::IsNetworkOrderInternal(void)
00980 {
00981 #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00982              
00983 #else
00984         static const bool isNetworkOrder=(htonl(12345) == 12345);
00985         return isNetworkOrder;
00986 #endif
00987 }
00988 void BitStream::ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length)
00989 {
00990         for (BitSize_t i=0; i < length; i++)
00991                 inOutByteArray[i]=inByteArray[length-i-1];
00992 }
00993 void BitStream::ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length)
00994 {
00995         unsigned char temp;
00996         BitSize_t i;
00997         for (i=0; i < (length>>1); i++)
00998         {
00999                 temp = inOutData[i];
01000                 inOutData[i]=inOutData[length-i-1];
01001                 inOutData[length-i-1]=temp;
01002         }
01003 }
01004 
01005 bool BitStream::Read(char *varString)
01006 {
01007         return RakString::Deserialize(varString,this);
01008 }
01009 bool BitStream::Read(unsigned char *varString)
01010 {
01011         return RakString::Deserialize((char*) varString,this);
01012 }
01013 void BitStream::WriteAlignedVar8(const char *inByteArray)
01014 {
01015         RakAssert((numberOfBitsUsed&7)==0);
01016         AddBitsAndReallocate(1*8);
01017         data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
01018         numberOfBitsUsed+=1*8;
01019 }
01020 bool BitStream::ReadAlignedVar8(char *inOutByteArray)
01021 {
01022         RakAssert((readOffset&7)==0);
01023         if ( readOffset + 1*8 > numberOfBitsUsed )
01024                 return false;
01025 
01026         inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
01027         readOffset+=1*8;
01028         return true;
01029 }
01030 void BitStream::WriteAlignedVar16(const char *inByteArray)
01031 {
01032         RakAssert((numberOfBitsUsed&7)==0);
01033         AddBitsAndReallocate(2*8);
01034 #ifndef __BITSTREAM_NATIVE_END
01035         if (DoEndianSwap())
01036         {
01037                 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[1];
01038                 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[0];
01039         }
01040         else
01041 #endif
01042         {
01043                 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
01044                 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
01045         }
01046 
01047         numberOfBitsUsed+=2*8;
01048 }
01049 bool BitStream::ReadAlignedVar16(char *inOutByteArray)
01050 {
01051         RakAssert((readOffset&7)==0);
01052         if ( readOffset + 2*8 > numberOfBitsUsed )
01053                 return false;
01054 #ifndef __BITSTREAM_NATIVE_END
01055         if (DoEndianSwap())
01056         {
01057                 inOutByteArray[0] = data[( readOffset >> 3 ) + 1];
01058                 inOutByteArray[1] = data[( readOffset >> 3 ) + 0];
01059         }
01060         else
01061 #endif
01062         {
01063                 inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
01064                 inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
01065         }
01066 
01067         readOffset+=2*8;
01068         return true;
01069 }
01070 void BitStream::WriteAlignedVar32(const char *inByteArray)
01071 {
01072         RakAssert((numberOfBitsUsed&7)==0);
01073         AddBitsAndReallocate(4*8);
01074 #ifndef __BITSTREAM_NATIVE_END
01075         if (DoEndianSwap())
01076         {
01077                 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[3];
01078                 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[2];
01079                 data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[1];
01080                 data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[0];
01081         }
01082         else
01083 #endif
01084         {
01085                 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
01086                 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
01087                 data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[2];
01088                 data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[3];
01089         }
01090 
01091         numberOfBitsUsed+=4*8;
01092 }
01093 bool BitStream::ReadAlignedVar32(char *inOutByteArray)
01094 {
01095         RakAssert((readOffset&7)==0);
01096         if ( readOffset + 4*8 > numberOfBitsUsed )
01097                 return false;
01098 #ifndef __BITSTREAM_NATIVE_END
01099         if (DoEndianSwap())
01100         {
01101                 inOutByteArray[0] = data[( readOffset >> 3 ) + 3];
01102                 inOutByteArray[1] = data[( readOffset >> 3 ) + 2];
01103                 inOutByteArray[2] = data[( readOffset >> 3 ) + 1];
01104                 inOutByteArray[3] = data[( readOffset >> 3 ) + 0];
01105         }
01106         else
01107 #endif
01108         {
01109                 inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
01110                 inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
01111                 inOutByteArray[2] = data[( readOffset >> 3 ) + 2];
01112                 inOutByteArray[3] = data[( readOffset >> 3 ) + 3];
01113         }
01114 
01115         readOffset+=4*8;
01116         return true;
01117 }
01118 bool BitStream::ReadFloat16( float &outFloat, float floatMin, float floatMax )
01119 {
01120         unsigned short percentile;
01121         if (Read(percentile))
01122         {
01123                 RakAssert(floatMax>floatMin);
01124                 outFloat = floatMin + ((float) percentile / 65535.0f) * (floatMax-floatMin);
01125                 if (outFloat<floatMin)
01126                         outFloat=floatMin;
01127                 else if (outFloat>floatMax)
01128                         outFloat=floatMax;
01129                 return true;
01130         }
01131         return false;
01132 }
01133 bool BitStream::SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax)
01134 {
01135         if (writeToBitstream)
01136                 WriteFloat16(inOutFloat, floatMin, floatMax);
01137         else
01138                 return ReadFloat16(inOutFloat, floatMin, floatMax);
01139         return true;
01140 }
01141 void BitStream::WriteFloat16( float inOutFloat, float floatMin, float floatMax )
01142 {
01143         RakAssert(floatMax>floatMin);
01144         if (inOutFloat>floatMax+.001)
01145         {
01146                 RakAssert(inOutFloat<=floatMax+.001);
01147         }
01148         if (inOutFloat<floatMin-.001)
01149         {
01150                 RakAssert(inOutFloat>=floatMin-.001);
01151         }
01152         float percentile=65535.0f * (inOutFloat-floatMin)/(floatMax-floatMin);
01153         if (percentile<0.0)
01154                 percentile=0.0;
01155         if (percentile>65535.0f)
01156                 percentile=65535.0f;
01157         Write((unsigned short)percentile);
01158 }
01159 
01160 #ifdef _MSC_VER
01161 #pragma warning( pop )
01162 #endif
01163 
01164 #endif // #if _MSC_VER < 1299 

Generated on Thu Sep 30 2010 01:27:21 for RakNet by  doxygen 1.7.1