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

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

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