ovr_sdk
diff LibOVR/Src/Net/OVR_BitStream.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Net/OVR_BitStream.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,1151 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_BitStream.cpp 1.7 +Content : A generic serialization toolkit for packing data to a binary stream. 1.8 +Created : June 10, 2014 1.9 +Authors : Kevin Jenkins 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +************************************************************************************/ 1.29 + 1.30 +#include "OVR_BitStream.h" 1.31 + 1.32 +#ifdef OVR_OS_WIN32 1.33 +#include <WinSock2.h> 1.34 +#else 1.35 +#include <arpa/inet.h> 1.36 +#endif 1.37 + 1.38 +namespace OVR { namespace Net { 1.39 + 1.40 + 1.41 +//----------------------------------------------------------------------------- 1.42 +// BitStream 1.43 + 1.44 +BitStream::BitStream() 1.45 +{ 1.46 + numberOfBitsUsed = 0; 1.47 + //numberOfBitsAllocated = 32 * 8; 1.48 + numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8; 1.49 + readOffset = 0; 1.50 + //data = ( unsigned char* ) OVR_ALLOC( 32); 1.51 + data = ( unsigned char* ) stackData; 1.52 + 1.53 +#ifdef _DEBUG 1.54 + // OVR_ASSERT( data ); 1.55 +#endif 1.56 + //memset(data, 0, 32); 1.57 + copyData = true; 1.58 +} 1.59 + 1.60 +BitStream::BitStream( const unsigned int initialBytesToAllocate ) 1.61 +{ 1.62 + numberOfBitsUsed = 0; 1.63 + readOffset = 0; 1.64 + if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE) 1.65 + { 1.66 + data = ( unsigned char* ) stackData; 1.67 + numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8; 1.68 + } 1.69 + else 1.70 + { 1.71 + data = ( unsigned char* ) OVR_ALLOC( (size_t) initialBytesToAllocate); 1.72 + numberOfBitsAllocated = initialBytesToAllocate << 3; 1.73 + } 1.74 +#ifdef _DEBUG 1.75 + OVR_ASSERT( data ); 1.76 +#endif 1.77 + // memset(data, 0, initialBytesToAllocate); 1.78 + copyData = true; 1.79 +} 1.80 + 1.81 +BitStream::BitStream( char* _data, const unsigned int lengthInBytes, bool _copyData ) 1.82 +{ 1.83 + numberOfBitsUsed = lengthInBytes << 3; 1.84 + readOffset = 0; 1.85 + copyData = _copyData; 1.86 + numberOfBitsAllocated = lengthInBytes << 3; 1.87 + 1.88 + if ( copyData ) 1.89 + { 1.90 + if ( lengthInBytes > 0 ) 1.91 + { 1.92 + if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE) 1.93 + { 1.94 + data = ( unsigned char* ) stackData; 1.95 + numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3; 1.96 + } 1.97 + else 1.98 + { 1.99 + data = ( unsigned char* ) OVR_ALLOC( (size_t) lengthInBytes); 1.100 + } 1.101 +#ifdef _DEBUG 1.102 + OVR_ASSERT( data ); 1.103 +#endif 1.104 + memcpy( data, _data, (size_t) lengthInBytes ); 1.105 + } 1.106 + else 1.107 + data = 0; 1.108 + } 1.109 + else 1.110 + data = ( unsigned char* ) _data; 1.111 +} 1.112 + 1.113 +// Use this if you pass a pointer copy to the constructor (_copyData==false) and want to overallocate to prevent reallocation 1.114 +void BitStream::SetNumberOfBitsAllocated( const BitSize_t lengthInBits ) 1.115 +{ 1.116 +#ifdef _DEBUG 1.117 + OVR_ASSERT( lengthInBits >= ( BitSize_t ) numberOfBitsAllocated ); 1.118 +#endif 1.119 + numberOfBitsAllocated = lengthInBits; 1.120 +} 1.121 + 1.122 +BitStream::~BitStream() 1.123 +{ 1.124 + if ( copyData && numberOfBitsAllocated > (BITSTREAM_STACK_ALLOCATION_SIZE << 3)) 1.125 + OVR_FREE( data ); // Use realloc and free so we are more efficient than delete and new for resizing 1.126 +} 1.127 + 1.128 +void BitStream::Reset( void ) 1.129 +{ 1.130 + // Note: Do NOT reallocate memory because BitStream is used 1.131 + // in places to serialize/deserialize a buffer. Reallocation 1.132 + // is a dangerous operation (may result in leaks). 1.133 + 1.134 + if ( numberOfBitsUsed > 0 ) 1.135 + { 1.136 + // memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed)); 1.137 + } 1.138 + 1.139 + // Don't free memory here for speed efficiency 1.140 + //free(data); // Use realloc and free so we are more efficient than delete and new for resizing 1.141 + numberOfBitsUsed = 0; 1.142 + 1.143 + //numberOfBitsAllocated=8; 1.144 + readOffset = 0; 1.145 + 1.146 + //data=(unsigned char*)OVR_ALLOC(1, _FILE_AND_LINE_); 1.147 + // if (numberOfBitsAllocated>0) 1.148 + // memset(data, 0, BITS_TO_BYTES(numberOfBitsAllocated)); 1.149 +} 1.150 + 1.151 +// Write an array or casted stream 1.152 +void BitStream::Write( const char* inputByteArray, const unsigned int numberOfBytes ) 1.153 +{ 1.154 + if (numberOfBytes==0) 1.155 + return; 1.156 + 1.157 + // Optimization: 1.158 + if ((numberOfBitsUsed & 7) == 0) 1.159 + { 1.160 + AddBitsAndReallocate( BYTES_TO_BITS(numberOfBytes) ); 1.161 + memcpy(data+BITS_TO_BYTES(numberOfBitsUsed), inputByteArray, (size_t) numberOfBytes); 1.162 + numberOfBitsUsed+=BYTES_TO_BITS(numberOfBytes); 1.163 + } 1.164 + else 1.165 + { 1.166 + WriteBits( ( unsigned char* ) inputByteArray, numberOfBytes * 8, true ); 1.167 + } 1.168 + 1.169 +} 1.170 +void BitStream::Write( BitStream *bitStream) 1.171 +{ 1.172 + Write(bitStream, bitStream->GetNumberOfBitsUsed()-bitStream->GetReadOffset()); 1.173 +} 1.174 +void BitStream::Write( BitStream *bitStream, BitSize_t numberOfBits ) 1.175 +{ 1.176 + AddBitsAndReallocate( numberOfBits ); 1.177 + BitSize_t numberOfBitsMod8; 1.178 + 1.179 + if ((bitStream->GetReadOffset()&7)==0 && (numberOfBitsUsed&7)==0) 1.180 + { 1.181 + int readOffsetBytes=bitStream->GetReadOffset()/8; 1.182 + int numBytes=numberOfBits/8; 1.183 + memcpy(data + (numberOfBitsUsed >> 3), bitStream->GetData()+readOffsetBytes, numBytes); 1.184 + numberOfBits-=BYTES_TO_BITS(numBytes); 1.185 + bitStream->SetReadOffset(BYTES_TO_BITS(numBytes+readOffsetBytes)); 1.186 + numberOfBitsUsed+=BYTES_TO_BITS(numBytes); 1.187 + } 1.188 + 1.189 + while (numberOfBits-->0 && bitStream->readOffset + 1 <= bitStream->numberOfBitsUsed) 1.190 + { 1.191 + numberOfBitsMod8 = numberOfBitsUsed & 7; 1.192 + if ( numberOfBitsMod8 == 0 ) 1.193 + { 1.194 + // New byte 1.195 + if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) ) 1.196 + { 1.197 + // Write 1 1.198 + data[ numberOfBitsUsed >> 3 ] = 0x80; 1.199 + } 1.200 + else 1.201 + { 1.202 + // Write 0 1.203 + data[ numberOfBitsUsed >> 3 ] = 0; 1.204 + } 1.205 + 1.206 + } 1.207 + else 1.208 + { 1.209 + // Existing byte 1.210 + if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) ) 1.211 + data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1 1.212 + // else 0, do nothing 1.213 + } 1.214 + 1.215 + bitStream->readOffset++; 1.216 + numberOfBitsUsed++; 1.217 + } 1.218 +} 1.219 +void BitStream::Write( BitStream &bitStream, BitSize_t numberOfBits ) 1.220 +{ 1.221 + Write(&bitStream, numberOfBits); 1.222 +} 1.223 +void BitStream::Write( BitStream &bitStream ) 1.224 +{ 1.225 + Write(&bitStream); 1.226 +} 1.227 +bool BitStream::Read( BitStream *bitStream, BitSize_t numberOfBits ) 1.228 +{ 1.229 + if (GetNumberOfUnreadBits() < numberOfBits) 1.230 + return false; 1.231 + bitStream->Write(this, numberOfBits); 1.232 + return true; 1.233 +} 1.234 +bool BitStream::Read( BitStream *bitStream ) 1.235 +{ 1.236 + bitStream->Write(this); 1.237 + return true; 1.238 +} 1.239 +bool BitStream::Read( BitStream &bitStream, BitSize_t numberOfBits ) 1.240 +{ 1.241 + if (GetNumberOfUnreadBits() < numberOfBits) 1.242 + return false; 1.243 + bitStream.Write(this, numberOfBits); 1.244 + return true; 1.245 +} 1.246 +bool BitStream::Read( BitStream &bitStream ) 1.247 +{ 1.248 + bitStream.Write(this); 1.249 + return true; 1.250 +} 1.251 + 1.252 +// Read an array or casted stream 1.253 +bool BitStream::Read( char* outByteArray, const unsigned int numberOfBytes ) 1.254 +{ 1.255 + // Optimization: 1.256 + if ((readOffset & 7) == 0) 1.257 + { 1.258 + if ( readOffset + ( numberOfBytes << 3 ) > numberOfBitsUsed ) 1.259 + return false; 1.260 + 1.261 + // Write the data 1.262 + memcpy( outByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytes ); 1.263 + 1.264 + readOffset += numberOfBytes << 3; 1.265 + return true; 1.266 + } 1.267 + else 1.268 + { 1.269 + return ReadBits( ( unsigned char* ) outByteArray, numberOfBytes * 8 ); 1.270 + } 1.271 +} 1.272 + 1.273 +// Sets the read pointer back to the beginning of your data. 1.274 +void BitStream::ResetReadPointer( void ) 1.275 +{ 1.276 + readOffset = 0; 1.277 +} 1.278 + 1.279 +// Sets the write pointer back to the beginning of your data. 1.280 +void BitStream::ResetWritePointer( void ) 1.281 +{ 1.282 + numberOfBitsUsed = 0; 1.283 +} 1.284 + 1.285 +// Write a 0 1.286 +void BitStream::Write0( void ) 1.287 +{ 1.288 + AddBitsAndReallocate( 1 ); 1.289 + 1.290 + // New bytes need to be zeroed 1.291 + if ( ( numberOfBitsUsed & 7 ) == 0 ) 1.292 + data[ numberOfBitsUsed >> 3 ] = 0; 1.293 + 1.294 + numberOfBitsUsed++; 1.295 +} 1.296 + 1.297 +// Write a 1 1.298 +void BitStream::Write1( void ) 1.299 +{ 1.300 + AddBitsAndReallocate( 1 ); 1.301 + 1.302 + BitSize_t numberOfBitsMod8 = numberOfBitsUsed & 7; 1.303 + 1.304 + if ( numberOfBitsMod8 == 0 ) 1.305 + data[ numberOfBitsUsed >> 3 ] = 0x80; 1.306 + else 1.307 + data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1 1.308 + 1.309 + numberOfBitsUsed++; 1.310 +} 1.311 + 1.312 +// Returns true if the next data read is a 1, false if it is a 0 1.313 +bool BitStream::ReadBit( void ) 1.314 +{ 1.315 + bool result = ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) !=0; 1.316 + readOffset++; 1.317 + return result; 1.318 +} 1.319 + 1.320 +// Align the bitstream to the byte boundary and then write the specified number of bits. 1.321 +// This is faster than WriteBits but wastes the bits to do the alignment and requires you to call 1.322 +// SetReadToByteAlignment at the corresponding read position 1.323 +void BitStream::WriteAlignedBytes( const unsigned char* inByteArray, const unsigned int numberOfBytesToWrite ) 1.324 +{ 1.325 + AlignWriteToByteBoundary(); 1.326 + Write((const char*) inByteArray, numberOfBytesToWrite); 1.327 +} 1.328 +void BitStream::EndianSwapBytes( int byteOffset, int length ) 1.329 +{ 1.330 + if (DoEndianSwap()) 1.331 + { 1.332 + ReverseBytesInPlace(data+byteOffset, length); 1.333 + } 1.334 +} 1.335 +/// Aligns the bitstream, writes inputLength, and writes input. Won't write beyond maxBytesToWrite 1.336 +void BitStream::WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite ) 1.337 +{ 1.338 + if (inByteArray==0 || inputLength==0) 1.339 + { 1.340 + WriteCompressed((unsigned int)0); 1.341 + return; 1.342 + } 1.343 + WriteCompressed(inputLength); 1.344 + WriteAlignedBytes((const unsigned char*) inByteArray, inputLength < maxBytesToWrite ? inputLength : maxBytesToWrite); 1.345 +} 1.346 + 1.347 +// Read bits, starting at the next aligned bits. Note that the modulus 8 starting offset of the 1.348 +// sequence must be the same as was used with WriteBits. This will be a problem with packet coalescence 1.349 +// unless you byte align the coalesced packets. 1.350 +bool BitStream::ReadAlignedBytes( unsigned char* inOutByteArray, const unsigned int numberOfBytesToRead ) 1.351 +{ 1.352 +#ifdef _DEBUG 1.353 + OVR_ASSERT( numberOfBytesToRead > 0 ); 1.354 +#endif 1.355 + 1.356 + if ( numberOfBytesToRead <= 0 ) 1.357 + return false; 1.358 + 1.359 + // Byte align 1.360 + AlignReadToByteBoundary(); 1.361 + 1.362 + if ( readOffset + ( numberOfBytesToRead << 3 ) > numberOfBitsUsed ) 1.363 + return false; 1.364 + 1.365 + // Write the data 1.366 + memcpy( inOutByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytesToRead ); 1.367 + 1.368 + readOffset += numberOfBytesToRead << 3; 1.369 + 1.370 + return true; 1.371 +} 1.372 +bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead ) 1.373 +{ 1.374 + return ReadAlignedBytesSafe(inOutByteArray,(unsigned int&) inputLength,(unsigned int)maxBytesToRead); 1.375 +} 1.376 +bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead ) 1.377 +{ 1.378 + if (ReadCompressed(inputLength)==false) 1.379 + return false; 1.380 + if (inputLength > maxBytesToRead) 1.381 + inputLength=maxBytesToRead; 1.382 + if (inputLength==0) 1.383 + return true; 1.384 + return ReadAlignedBytes((unsigned char*) inOutByteArray, inputLength); 1.385 +} 1.386 +bool BitStream::ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead ) 1.387 +{ 1.388 + return ReadAlignedBytesSafeAlloc(outByteArray,(unsigned int&) inputLength, maxBytesToRead); 1.389 +} 1.390 +bool BitStream::ReadAlignedBytesSafeAlloc( char ** outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead ) 1.391 +{ 1.392 + OVR_FREE(*outByteArray); 1.393 + *outByteArray=0; 1.394 + if (ReadCompressed(inputLength)==false) 1.395 + return false; 1.396 + if (inputLength > maxBytesToRead) 1.397 + inputLength=maxBytesToRead; 1.398 + if (inputLength==0) 1.399 + return true; 1.400 + *outByteArray = (char*) OVR_ALLOC( (size_t) inputLength); 1.401 + return ReadAlignedBytes((unsigned char*) *outByteArray, inputLength); 1.402 +} 1.403 + 1.404 +// Write numberToWrite bits from the input source 1.405 +void BitStream::WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits ) 1.406 +{ 1.407 +// if (numberOfBitsToWrite<=0) 1.408 +// return; 1.409 + 1.410 + AddBitsAndReallocate( numberOfBitsToWrite ); 1.411 + 1.412 + const BitSize_t numberOfBitsUsedMod8 = numberOfBitsUsed & 7; 1.413 + 1.414 + // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed 1.415 + if (numberOfBitsUsedMod8==0 && (numberOfBitsToWrite&7)==0) 1.416 + { 1.417 + memcpy( data + ( numberOfBitsUsed >> 3 ), inByteArray, numberOfBitsToWrite>>3); 1.418 + numberOfBitsUsed+=numberOfBitsToWrite; 1.419 + return; 1.420 + } 1.421 + 1.422 + unsigned char dataByte; 1.423 + const unsigned char* inputPtr=inByteArray; 1.424 + 1.425 + // Faster to put the while at the top surprisingly enough 1.426 + while ( numberOfBitsToWrite > 0 ) 1.427 + //do 1.428 + { 1.429 + dataByte = *( inputPtr++ ); 1.430 + 1.431 + 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) 1.432 + dataByte <<= 8 - numberOfBitsToWrite; // shift left to get the bits on the left, as in our internal representation 1.433 + 1.434 + // Writing to a new byte each time 1.435 + if ( numberOfBitsUsedMod8 == 0 ) 1.436 + * ( data + ( numberOfBitsUsed >> 3 ) ) = dataByte; 1.437 + else 1.438 + { 1.439 + // Copy over the new data. 1.440 + *( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half 1.441 + 1.442 + 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) 1.443 + { 1.444 + *( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary) 1.445 + } 1.446 + } 1.447 + 1.448 + if ( numberOfBitsToWrite >= 8 ) 1.449 + { 1.450 + numberOfBitsUsed += 8; 1.451 + numberOfBitsToWrite -= 8; 1.452 + } 1.453 + else 1.454 + { 1.455 + numberOfBitsUsed += numberOfBitsToWrite; 1.456 + numberOfBitsToWrite=0; 1.457 + } 1.458 + } 1.459 + // } while(numberOfBitsToWrite>0); 1.460 +} 1.461 + 1.462 +// Set the stream to some initial data. For internal use 1.463 +void BitStream::SetData( unsigned char *inByteArray ) 1.464 +{ 1.465 + data=inByteArray; 1.466 + copyData=false; 1.467 +} 1.468 + 1.469 +// Assume the input source points to a native type, compress and write it 1.470 +void BitStream::WriteCompressed( const unsigned char* inByteArray, 1.471 + const unsigned int size, const bool unsignedData ) 1.472 +{ 1.473 + BitSize_t currentByte = ( size >> 3 ) - 1; // PCs 1.474 + 1.475 + unsigned char byteMatch; 1.476 + 1.477 + if ( unsignedData ) 1.478 + { 1.479 + byteMatch = 0; 1.480 + } 1.481 + 1.482 + else 1.483 + { 1.484 + byteMatch = 0xFF; 1.485 + } 1.486 + 1.487 + // Write upper bytes with a single 1 1.488 + // 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 1.489 + while ( currentByte > 0 ) 1.490 + { 1.491 + if ( inByteArray[ currentByte ] == byteMatch ) // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted 1.492 + { 1.493 + bool b = true; 1.494 + Write( b ); 1.495 + } 1.496 + else 1.497 + { 1.498 + // Write the remainder of the data after writing 0 1.499 + bool b = false; 1.500 + Write( b ); 1.501 + 1.502 + WriteBits( inByteArray, ( currentByte + 1 ) << 3, true ); 1.503 + // currentByte--; 1.504 + 1.505 + 1.506 + return ; 1.507 + } 1.508 + 1.509 + currentByte--; 1.510 + } 1.511 + 1.512 + // 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. 1.513 + if ( ( unsignedData && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0x00 ) || 1.514 + ( unsignedData == false && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0xF0 ) ) 1.515 + { 1.516 + bool b = true; 1.517 + Write( b ); 1.518 + WriteBits( inByteArray + currentByte, 4, true ); 1.519 + } 1.520 + 1.521 + else 1.522 + { 1.523 + bool b = false; 1.524 + Write( b ); 1.525 + WriteBits( inByteArray + currentByte, 8, true ); 1.526 + } 1.527 +} 1.528 + 1.529 +// Read numberOfBitsToRead bits to the output source 1.530 +// alignBitsToRight should be set to true to convert internal bitstream data to userdata 1.531 +// It should be false if you used WriteBits with rightAlignedBits false 1.532 +bool BitStream::ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight ) 1.533 +{ 1.534 +#ifdef _DEBUG 1.535 + // OVR_ASSERT( numberOfBitsToRead > 0 ); 1.536 +#endif 1.537 + if (numberOfBitsToRead<=0) 1.538 + return false; 1.539 + 1.540 + if ( readOffset + numberOfBitsToRead > numberOfBitsUsed ) 1.541 + return false; 1.542 + 1.543 + 1.544 + const BitSize_t readOffsetMod8 = readOffset & 7; 1.545 + 1.546 + // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed 1.547 + if (readOffsetMod8==0 && (numberOfBitsToRead&7)==0) 1.548 + { 1.549 + memcpy( inOutByteArray, data + ( readOffset >> 3 ), numberOfBitsToRead>>3); 1.550 + readOffset+=numberOfBitsToRead; 1.551 + return true; 1.552 + } 1.553 + 1.554 + 1.555 + 1.556 + BitSize_t offset = 0; 1.557 + 1.558 + memset( inOutByteArray, 0, (size_t) BITS_TO_BYTES( numberOfBitsToRead ) ); 1.559 + 1.560 + while ( numberOfBitsToRead > 0 ) 1.561 + { 1.562 + *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half 1.563 + 1.564 + if ( readOffsetMod8 > 0 && numberOfBitsToRead > 8 - ( readOffsetMod8 ) ) // If we have a second half, we didn't read enough bytes in the first half 1.565 + *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) + 1 ) >> ( 8 - ( readOffsetMod8 ) ); // Second half (overlaps byte boundary) 1.566 + 1.567 + if (numberOfBitsToRead>=8) 1.568 + { 1.569 + numberOfBitsToRead -= 8; 1.570 + readOffset += 8; 1.571 + offset++; 1.572 + } 1.573 + else 1.574 + { 1.575 + int neg = (int) numberOfBitsToRead - 8; 1.576 + 1.577 + if ( neg < 0 ) // Reading a partial byte for the last byte, shift right so the data is aligned on the right 1.578 + { 1.579 + 1.580 + if ( alignBitsToRight ) 1.581 + * ( inOutByteArray + offset ) >>= -neg; 1.582 + 1.583 + readOffset += 8 + neg; 1.584 + } 1.585 + else 1.586 + readOffset += 8; 1.587 + 1.588 + offset++; 1.589 + 1.590 + numberOfBitsToRead=0; 1.591 + } 1.592 + } 1.593 + 1.594 + return true; 1.595 +} 1.596 + 1.597 +// Assume the input source points to a compressed native type. Decompress and read it 1.598 +bool BitStream::ReadCompressed( unsigned char* inOutByteArray, 1.599 + const unsigned int size, const bool unsignedData ) 1.600 +{ 1.601 + unsigned int currentByte = ( size >> 3 ) - 1; 1.602 + 1.603 + 1.604 + unsigned char byteMatch, halfByteMatch; 1.605 + 1.606 + if ( unsignedData ) 1.607 + { 1.608 + byteMatch = 0; 1.609 + halfByteMatch = 0; 1.610 + } 1.611 + 1.612 + else 1.613 + { 1.614 + byteMatch = 0xFF; 1.615 + halfByteMatch = 0xF0; 1.616 + } 1.617 + 1.618 + // Upper bytes are specified with a single 1 if they match byteMatch 1.619 + // 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 1.620 + while ( currentByte > 0 ) 1.621 + { 1.622 + // If we read a 1 then the data is byteMatch. 1.623 + 1.624 + bool b; 1.625 + 1.626 + if ( Read( b ) == false ) 1.627 + return false; 1.628 + 1.629 + if ( b ) // Check that bit 1.630 + { 1.631 + inOutByteArray[ currentByte ] = byteMatch; 1.632 + currentByte--; 1.633 + } 1.634 + else 1.635 + { 1.636 + // Read the rest of the bytes 1.637 + 1.638 + if ( ReadBits( inOutByteArray, ( currentByte + 1 ) << 3 ) == false ) 1.639 + return false; 1.640 + 1.641 + return true; 1.642 + } 1.643 + } 1.644 + 1.645 + // 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. 1.646 + // Otherwise we read a 0 and the 8 bytes 1.647 + //OVR_ASSERT(readOffset+1 <=numberOfBitsUsed); // If this assert is hit the stream wasn't long enough to read from 1.648 + if ( readOffset + 1 > numberOfBitsUsed ) 1.649 + return false; 1.650 + 1.651 + bool b=false; 1.652 + 1.653 + if ( Read( b ) == false ) 1.654 + return false; 1.655 + 1.656 + if ( b ) // Check that bit 1.657 + { 1.658 + 1.659 + if ( ReadBits( inOutByteArray + currentByte, 4 ) == false ) 1.660 + return false; 1.661 + 1.662 + inOutByteArray[ currentByte ] |= halfByteMatch; // We have to set the high 4 bits since these are set to 0 by ReadBits 1.663 + } 1.664 + else 1.665 + { 1.666 + if ( ReadBits( inOutByteArray + currentByte, 8 ) == false ) 1.667 + return false; 1.668 + } 1.669 + 1.670 + return true; 1.671 +} 1.672 + 1.673 +// Reallocates (if necessary) in preparation of writing numberOfBitsToWrite 1.674 +void BitStream::AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite ) 1.675 +{ 1.676 + BitSize_t newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed; 1.677 + 1.678 + if ( numberOfBitsToWrite + numberOfBitsUsed > 0 && ( ( numberOfBitsAllocated - 1 ) >> 3 ) < ( ( newNumberOfBitsAllocated - 1 ) >> 3 ) ) // If we need to allocate 1 or more new bytes 1.679 + { 1.680 +#ifdef _DEBUG 1.681 + // If this assert hits then we need to specify true for the third parameter in the constructor 1.682 + // It needs to reallocate to hold all the data and can't do it unless we allocated to begin with 1.683 + // Often hits if you call Write or Serialize on a read-only bitstream 1.684 + OVR_ASSERT( copyData == true ); 1.685 +#endif 1.686 + 1.687 + // Less memory efficient but saves on news and deletes 1.688 + /// Cap to 1 meg buffer to save on huge allocations 1.689 + newNumberOfBitsAllocated = ( numberOfBitsToWrite + numberOfBitsUsed ) * 2; 1.690 + if (newNumberOfBitsAllocated - ( numberOfBitsToWrite + numberOfBitsUsed ) > 1048576 ) 1.691 + newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed + 1048576; 1.692 + 1.693 + // BitSize_t newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated ); 1.694 + // Use realloc and free so we are more efficient than delete and new for resizing 1.695 + BitSize_t amountToAllocate = BITS_TO_BYTES( newNumberOfBitsAllocated ); 1.696 + if (data==(unsigned char*)stackData) 1.697 + { 1.698 + if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE) 1.699 + { 1.700 + data = ( unsigned char* ) OVR_ALLOC( (size_t) amountToAllocate); 1.701 + OVR_ASSERT(data); 1.702 + if (data) 1.703 + { 1.704 + // need to copy the stack data over to our new memory area too 1.705 + memcpy ((void *)data, (void *)stackData, (size_t) BITS_TO_BYTES( numberOfBitsAllocated )); 1.706 + } 1.707 + } 1.708 + } 1.709 + else 1.710 + { 1.711 + data = ( unsigned char* ) OVR_REALLOC( data, (size_t) amountToAllocate); 1.712 + } 1.713 + 1.714 +#ifdef _DEBUG 1.715 + OVR_ASSERT( data ); // Make sure realloc succeeded 1.716 +#endif 1.717 + // memset(data+newByteOffset, 0, ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0 1.718 + } 1.719 + 1.720 + if ( newNumberOfBitsAllocated > numberOfBitsAllocated ) 1.721 + numberOfBitsAllocated = newNumberOfBitsAllocated; 1.722 +} 1.723 +BitSize_t BitStream::GetNumberOfBitsAllocated(void) const 1.724 +{ 1.725 + return numberOfBitsAllocated; 1.726 +} 1.727 +void BitStream::PadWithZeroToByteLength( unsigned int bytes ) 1.728 +{ 1.729 + if (GetNumberOfBytesUsed() < bytes) 1.730 + { 1.731 + AlignWriteToByteBoundary(); 1.732 + unsigned int numToWrite = bytes - GetNumberOfBytesUsed(); 1.733 + AddBitsAndReallocate( BYTES_TO_BITS(numToWrite) ); 1.734 + memset(data+BITS_TO_BYTES(numberOfBitsUsed), 0, (size_t) numToWrite); 1.735 + numberOfBitsUsed+=BYTES_TO_BITS(numToWrite); 1.736 + } 1.737 +} 1.738 + 1.739 +/* 1.740 +// Julius Goryavsky's version of Harley's algorithm. 1.741 +// 17 elementary ops plus an indexed load, if the machine 1.742 +// has "and not." 1.743 + 1.744 +int nlz10b(unsigned x) { 1.745 + 1.746 + static char table[64] = 1.747 + {32,20,19, u, u,18, u, 7, 10,17, u, u,14, u, 6, u, 1.748 + u, 9, u,16, u, u, 1,26, u,13, u, u,24, 5, u, u, 1.749 + u,21, u, 8,11, u,15, u, u, u, u, 2,27, 0,25, u, 1.750 + 22, u,12, u, u, 3,28, u, 23, u, 4,29, u, u,30,31}; 1.751 + 1.752 + x = x | (x >> 1); // Propagate leftmost 1.753 + x = x | (x >> 2); // 1-bit to the right. 1.754 + x = x | (x >> 4); 1.755 + x = x | (x >> 8); 1.756 + x = x & ~(x >> 16); 1.757 + x = x*0xFD7049FF; // Activate this line or the following 3. 1.758 +// x = (x << 9) - x; // Multiply by 511. 1.759 +// x = (x << 11) - x; // Multiply by 2047. 1.760 +// x = (x << 14) - x; // Multiply by 16383. 1.761 + return table[x >> 26]; 1.762 +} 1.763 +*/ 1.764 +int BitStream::NumberOfLeadingZeroes( int8_t x ) {return NumberOfLeadingZeroes((uint8_t)x);} 1.765 +int BitStream::NumberOfLeadingZeroes( uint8_t x ) 1.766 +{ 1.767 + uint8_t y; 1.768 + int n; 1.769 + 1.770 + n = 8; 1.771 + y = x >> 4; if (y != 0) {n = n - 4; x = y;} 1.772 + y = x >> 2; if (y != 0) {n = n - 2; x = y;} 1.773 + y = x >> 1; if (y != 0) return n - 2; 1.774 + return (int)(n - x); 1.775 +} 1.776 +int BitStream::NumberOfLeadingZeroes( int16_t x ) {return NumberOfLeadingZeroes((uint16_t)x);} 1.777 +int BitStream::NumberOfLeadingZeroes( uint16_t x ) 1.778 +{ 1.779 + uint16_t y; 1.780 + int n; 1.781 + 1.782 + n = 16; 1.783 + y = x >> 8; if (y != 0) {n = n - 8; x = y;} 1.784 + y = x >> 4; if (y != 0) {n = n - 4; x = y;} 1.785 + y = x >> 2; if (y != 0) {n = n - 2; x = y;} 1.786 + y = x >> 1; if (y != 0) return n - 2; 1.787 + return (int)(n - x); 1.788 +} 1.789 +int BitStream::NumberOfLeadingZeroes( int32_t x ) {return NumberOfLeadingZeroes((uint32_t)x);} 1.790 +int BitStream::NumberOfLeadingZeroes( uint32_t x ) 1.791 +{ 1.792 + uint32_t y; 1.793 + int n; 1.794 + 1.795 + n = 32; 1.796 + y = x >>16; if (y != 0) {n = n -16; x = y;} 1.797 + y = x >> 8; if (y != 0) {n = n - 8; x = y;} 1.798 + y = x >> 4; if (y != 0) {n = n - 4; x = y;} 1.799 + y = x >> 2; if (y != 0) {n = n - 2; x = y;} 1.800 + y = x >> 1; if (y != 0) return n - 2; 1.801 + return (int)(n - x); 1.802 +} 1.803 +int BitStream::NumberOfLeadingZeroes( int64_t x ) {return NumberOfLeadingZeroes((uint64_t)x);} 1.804 +int BitStream::NumberOfLeadingZeroes( uint64_t x ) 1.805 +{ 1.806 + uint64_t y; 1.807 + int n; 1.808 + 1.809 + n = 64; 1.810 + y = x >>32; if (y != 0) {n = n -32; x = y;} 1.811 + y = x >>16; if (y != 0) {n = n -16; x = y;} 1.812 + y = x >> 8; if (y != 0) {n = n - 8; x = y;} 1.813 + y = x >> 4; if (y != 0) {n = n - 4; x = y;} 1.814 + y = x >> 2; if (y != 0) {n = n - 2; x = y;} 1.815 + y = x >> 1; if (y != 0) return n - 2; 1.816 + return (int)(n - x); 1.817 +} 1.818 + 1.819 +// Should hit if reads didn't match writes 1.820 +void BitStream::AssertStreamEmpty( void ) 1.821 +{ 1.822 + OVR_ASSERT( readOffset == numberOfBitsUsed ); 1.823 +} 1.824 +void BitStream::PrintBits( char *out ) const 1.825 +{ 1.826 + if ( numberOfBitsUsed <= 0 ) 1.827 + { 1.828 + OVR_strcpy(out, 128, "No bits\n" ); 1.829 + return; 1.830 + } 1.831 + 1.832 + unsigned int strIndex=0; 1.833 + for ( BitSize_t counter = 0; counter < BITS_TO_BYTES( numberOfBitsUsed ) && strIndex < 2000 ; counter++ ) 1.834 + { 1.835 + BitSize_t stop; 1.836 + 1.837 + if ( counter == ( numberOfBitsUsed - 1 ) >> 3 ) 1.838 + stop = 8 - ( ( ( numberOfBitsUsed - 1 ) & 7 ) + 1 ); 1.839 + else 1.840 + stop = 0; 1.841 + 1.842 + for ( BitSize_t counter2 = 7; counter2 >= stop; counter2-- ) 1.843 + { 1.844 + if ( ( data[ counter ] >> counter2 ) & 1 ) 1.845 + out[strIndex++]='1'; 1.846 + else 1.847 + out[strIndex++]='0'; 1.848 + 1.849 + if (counter2==0) 1.850 + break; 1.851 + } 1.852 + 1.853 + out[strIndex++]=' '; 1.854 + } 1.855 + 1.856 + out[strIndex++]='\n'; 1.857 + 1.858 + out[strIndex++]=0; 1.859 +} 1.860 +void BitStream::PrintBits( void ) const 1.861 +{ 1.862 + char out[2048]; 1.863 + PrintBits(out); 1.864 + printf("%s", out); 1.865 +} 1.866 +void BitStream::PrintHex( char *out ) const 1.867 +{ 1.868 + BitSize_t i; 1.869 + for ( i=0; i < GetNumberOfBytesUsed(); i++) 1.870 + { 1.871 + OVR_sprintf(out+i*3, 128, "%02x ", data[i]); 1.872 + } 1.873 +} 1.874 +void BitStream::PrintHex( void ) const 1.875 +{ 1.876 + char out[2048]; 1.877 + PrintHex(out); 1.878 + printf("%s", out); 1.879 +} 1.880 + 1.881 +// Exposes the data for you to look at, like PrintBits does. 1.882 +// Data will point to the stream. Returns the length in bits of the stream. 1.883 +BitSize_t BitStream::CopyData( unsigned char** _data ) const 1.884 +{ 1.885 +#ifdef _DEBUG 1.886 + OVR_ASSERT( numberOfBitsUsed > 0 ); 1.887 +#endif 1.888 + 1.889 + *_data = (unsigned char*) OVR_ALLOC( (size_t) BITS_TO_BYTES( numberOfBitsUsed )); 1.890 + memcpy( *_data, data, sizeof(unsigned char) * (size_t) ( BITS_TO_BYTES( numberOfBitsUsed ) ) ); 1.891 + return numberOfBitsUsed; 1.892 +} 1.893 + 1.894 +// Ignore data we don't intend to read 1.895 +void BitStream::IgnoreBits( const BitSize_t numberOfBits ) 1.896 +{ 1.897 + readOffset += numberOfBits; 1.898 +} 1.899 + 1.900 +void BitStream::IgnoreBytes( const unsigned int numberOfBytes ) 1.901 +{ 1.902 + IgnoreBits(BYTES_TO_BITS(numberOfBytes)); 1.903 +} 1.904 + 1.905 +// Move the write pointer to a position on the array. Dangerous if you don't know what you are doing! 1.906 +// Doesn't work with non-aligned data! 1.907 +void BitStream::SetWriteOffset( const BitSize_t offset ) 1.908 +{ 1.909 + numberOfBitsUsed = offset; 1.910 +} 1.911 + 1.912 +/* 1.913 +BitSize_t BitStream::GetWriteOffset( void ) const 1.914 +{ 1.915 +return numberOfBitsUsed; 1.916 +} 1.917 + 1.918 +// Returns the length in bits of the stream 1.919 +BitSize_t BitStream::GetNumberOfBitsUsed( void ) const 1.920 +{ 1.921 +return GetWriteOffset(); 1.922 +} 1.923 + 1.924 +// Returns the length in bytes of the stream 1.925 +BitSize_t BitStream::GetNumberOfBytesUsed( void ) const 1.926 +{ 1.927 +return BITS_TO_BYTES( numberOfBitsUsed ); 1.928 +} 1.929 + 1.930 +// Returns the number of bits into the stream that we have read 1.931 +BitSize_t BitStream::GetReadOffset( void ) const 1.932 +{ 1.933 +return readOffset; 1.934 +} 1.935 + 1.936 + 1.937 +// Sets the read bit index 1.938 +void BitStream::SetReadOffset( const BitSize_t newReadOffset ) 1.939 +{ 1.940 +readOffset=newReadOffset; 1.941 +} 1.942 + 1.943 +// Returns the number of bits left in the stream that haven't been read 1.944 +BitSize_t BitStream::GetNumberOfUnreadBits( void ) const 1.945 +{ 1.946 +return numberOfBitsUsed - readOffset; 1.947 +} 1.948 +// Exposes the internal data 1.949 +unsigned char* BitStream::GetData( void ) const 1.950 +{ 1.951 +return data; 1.952 +} 1.953 + 1.954 +*/ 1.955 +// 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. 1.956 +void BitStream::AssertCopyData( void ) 1.957 +{ 1.958 + if ( copyData == false ) 1.959 + { 1.960 + copyData = true; 1.961 + 1.962 + if ( numberOfBitsAllocated > 0 ) 1.963 + { 1.964 + unsigned char * newdata = ( unsigned char* ) OVR_ALLOC( (size_t) BITS_TO_BYTES( numberOfBitsAllocated )); 1.965 +#ifdef _DEBUG 1.966 + 1.967 + OVR_ASSERT( data ); 1.968 +#endif 1.969 + 1.970 + memcpy( newdata, data, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ) ); 1.971 + data = newdata; 1.972 + } 1.973 + 1.974 + else 1.975 + data = 0; 1.976 + } 1.977 +} 1.978 +bool BitStream::IsNetworkOrderInternal(void) 1.979 +{ 1.980 +#if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) 1.981 + return true; 1.982 +#elif defined(SN_TARGET_PSP2) 1.983 + return false; 1.984 +#else 1.985 + static unsigned long htonlValue = htonl(12345); 1.986 + return htonlValue == 12345; 1.987 +#endif 1.988 +} 1.989 +void BitStream::ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length) 1.990 +{ 1.991 + for (BitSize_t i=0; i < length; i++) 1.992 + inOutByteArray[i]=inByteArray[length-i-1]; 1.993 +} 1.994 +void BitStream::ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length) 1.995 +{ 1.996 + unsigned char temp; 1.997 + BitSize_t i; 1.998 + for (i=0; i < (length>>1); i++) 1.999 + { 1.1000 + temp = inOutData[i]; 1.1001 + inOutData[i]=inOutData[length-i-1]; 1.1002 + inOutData[length-i-1]=temp; 1.1003 + } 1.1004 +} 1.1005 + 1.1006 +void BitStream::WriteAlignedVar8(const char *inByteArray) 1.1007 +{ 1.1008 + OVR_ASSERT((numberOfBitsUsed&7)==0); 1.1009 + AddBitsAndReallocate(1*8); 1.1010 + data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0]; 1.1011 + numberOfBitsUsed+=1*8; 1.1012 +} 1.1013 +bool BitStream::ReadAlignedVar8(char *inOutByteArray) 1.1014 +{ 1.1015 + OVR_ASSERT((readOffset&7)==0); 1.1016 + if ( readOffset + 1*8 > numberOfBitsUsed ) 1.1017 + return false; 1.1018 + 1.1019 + inOutByteArray[0] = data[( readOffset >> 3 ) + 0]; 1.1020 + readOffset+=1*8; 1.1021 + return true; 1.1022 +} 1.1023 +void BitStream::WriteAlignedVar16(const char *inByteArray) 1.1024 +{ 1.1025 + OVR_ASSERT((numberOfBitsUsed&7)==0); 1.1026 + AddBitsAndReallocate(2*8); 1.1027 +#ifndef __BITSTREAM_NATIVE_END 1.1028 + if (DoEndianSwap()) 1.1029 + { 1.1030 + data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[1]; 1.1031 + data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[0]; 1.1032 + } 1.1033 + else 1.1034 +#endif 1.1035 + { 1.1036 + data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0]; 1.1037 + data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1]; 1.1038 + } 1.1039 + 1.1040 + numberOfBitsUsed+=2*8; 1.1041 +} 1.1042 +bool BitStream::ReadAlignedVar16(char *inOutByteArray) 1.1043 +{ 1.1044 + OVR_ASSERT((readOffset&7)==0); 1.1045 + if ( readOffset + 2*8 > numberOfBitsUsed ) 1.1046 + return false; 1.1047 +#ifndef __BITSTREAM_NATIVE_END 1.1048 + if (DoEndianSwap()) 1.1049 + { 1.1050 + inOutByteArray[0] = data[( readOffset >> 3 ) + 1]; 1.1051 + inOutByteArray[1] = data[( readOffset >> 3 ) + 0]; 1.1052 + } 1.1053 + else 1.1054 +#endif 1.1055 + { 1.1056 + inOutByteArray[0] = data[( readOffset >> 3 ) + 0]; 1.1057 + inOutByteArray[1] = data[( readOffset >> 3 ) + 1]; 1.1058 + } 1.1059 + 1.1060 + readOffset+=2*8; 1.1061 + return true; 1.1062 +} 1.1063 +void BitStream::WriteAlignedVar32(const char *inByteArray) 1.1064 +{ 1.1065 + OVR_ASSERT((numberOfBitsUsed&7)==0); 1.1066 + AddBitsAndReallocate(4*8); 1.1067 +#ifndef __BITSTREAM_NATIVE_END 1.1068 + if (DoEndianSwap()) 1.1069 + { 1.1070 + data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[3]; 1.1071 + data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[2]; 1.1072 + data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[1]; 1.1073 + data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[0]; 1.1074 + } 1.1075 + else 1.1076 +#endif 1.1077 + { 1.1078 + data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0]; 1.1079 + data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1]; 1.1080 + data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[2]; 1.1081 + data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[3]; 1.1082 + } 1.1083 + 1.1084 + numberOfBitsUsed+=4*8; 1.1085 +} 1.1086 +bool BitStream::ReadAlignedVar32(char *inOutByteArray) 1.1087 +{ 1.1088 + OVR_ASSERT((readOffset&7)==0); 1.1089 + if ( readOffset + 4*8 > numberOfBitsUsed ) 1.1090 + return false; 1.1091 +#ifndef __BITSTREAM_NATIVE_END 1.1092 + if (DoEndianSwap()) 1.1093 + { 1.1094 + inOutByteArray[0] = data[( readOffset >> 3 ) + 3]; 1.1095 + inOutByteArray[1] = data[( readOffset >> 3 ) + 2]; 1.1096 + inOutByteArray[2] = data[( readOffset >> 3 ) + 1]; 1.1097 + inOutByteArray[3] = data[( readOffset >> 3 ) + 0]; 1.1098 + } 1.1099 + else 1.1100 +#endif 1.1101 + { 1.1102 + inOutByteArray[0] = data[( readOffset >> 3 ) + 0]; 1.1103 + inOutByteArray[1] = data[( readOffset >> 3 ) + 1]; 1.1104 + inOutByteArray[2] = data[( readOffset >> 3 ) + 2]; 1.1105 + inOutByteArray[3] = data[( readOffset >> 3 ) + 3]; 1.1106 + } 1.1107 + 1.1108 + readOffset+=4*8; 1.1109 + return true; 1.1110 +} 1.1111 +bool BitStream::ReadFloat16( float &outFloat, float floatMin, float floatMax ) 1.1112 +{ 1.1113 + uint16_t percentile; 1.1114 + if (Read(percentile)) 1.1115 + { 1.1116 + OVR_ASSERT(floatMax>floatMin); 1.1117 + outFloat = floatMin + ((float) percentile / 65535.0f) * (floatMax-floatMin); 1.1118 + if (outFloat<floatMin) 1.1119 + outFloat=floatMin; 1.1120 + else if (outFloat>floatMax) 1.1121 + outFloat=floatMax; 1.1122 + return true; 1.1123 + } 1.1124 + return false; 1.1125 +} 1.1126 +bool BitStream::SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax) 1.1127 +{ 1.1128 + if (writeToBitstream) 1.1129 + WriteFloat16(inOutFloat, floatMin, floatMax); 1.1130 + else 1.1131 + return ReadFloat16(inOutFloat, floatMin, floatMax); 1.1132 + return true; 1.1133 +} 1.1134 +void BitStream::WriteFloat16( float inOutFloat, float floatMin, float floatMax ) 1.1135 +{ 1.1136 + OVR_ASSERT(floatMax>floatMin); 1.1137 + if (inOutFloat>floatMax+.001) 1.1138 + { 1.1139 + OVR_ASSERT(inOutFloat<=floatMax+.001); 1.1140 + } 1.1141 + if (inOutFloat<floatMin-.001) 1.1142 + { 1.1143 + OVR_ASSERT(inOutFloat>=floatMin-.001); 1.1144 + } 1.1145 + float percentile=65535.0f * (inOutFloat-floatMin)/(floatMax-floatMin); 1.1146 + if (percentile<0.0) 1.1147 + percentile=0.0; 1.1148 + if (percentile>65535.0f) 1.1149 + percentile=65535.0f; 1.1150 + Write((uint16_t)percentile); 1.1151 +} 1.1152 + 1.1153 + 1.1154 +}} // OVR::Net