SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BitStream.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2019, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
18
19 #include "slikenet/BitStream.h"
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 #include "slikenet/SocketIncludes.h"
25 #include "slikenet/defines.h"
26
27
28
29 #if defined(_WIN32)
30 #include "slikenet/WindowsIncludes.h"
31 #include <memory.h>
32 #include <cmath>
33 #include <float.h>
34
35
36
37
38 #else
39 #include <arpa/inet.h>
40 #include <memory.h>
41 #if defined(ANDROID)
42 #include <math.h>
43 #else
44 #include <cmath>
45 #endif
46 #include <float.h>
47 #endif
48 #include "slikenet/linux_adapter.h"
49 #include "slikenet/osx_adapter.h"
50
51 // MSWin uses _copysign, others use copysign...
52 #ifndef _WIN32
53 #define _copysign copysign
54 #endif
55
56 using namespace SLNet;
57
58 STATIC_FACTORY_DEFINITIONS(BitStream,BitStream)
59
60 BitStream::BitStream()
61 {
62 numberOfBitsUsed = 0;
63 //numberOfBitsAllocated = 32 * 8;
64 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
65 readOffset = 0;
66 //data = ( unsigned char* ) rakMalloc_Ex( 32, _FILE_AND_LINE_ );
67 data = ( unsigned char* ) stackData;
68
69 #ifdef _DEBUG
70 // RakAssert( data );
71 #endif
72 //memset(data, 0, 32);
73 copyData = true;
74 }
75
76 BitStream::BitStream( const unsigned int initialBytesToAllocate )
77 {
78 numberOfBitsUsed = 0;
79 readOffset = 0;
80 if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE)
81 {
82 data = ( unsigned char* ) stackData;
83 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
84 }
85 else
86 {
87 data = ( unsigned char* ) rakMalloc_Ex( (size_t) initialBytesToAllocate, _FILE_AND_LINE_ );
88 numberOfBitsAllocated = initialBytesToAllocate << 3;
89 }
90 #ifdef _DEBUG
91 RakAssert( data );
92 #endif
93 // memset(data, 0, initialBytesToAllocate);
94 copyData = true;
95 }
96
97 BitStream::BitStream( unsigned char* _data, const unsigned int lengthInBytes, bool _copyData )
98 {
99 numberOfBitsUsed = lengthInBytes << 3;
100 readOffset = 0;
101 copyData = _copyData;
102 numberOfBitsAllocated = lengthInBytes << 3;
103
104 if ( copyData )
105 {
106 if ( lengthInBytes > 0 )
107 {
108 if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE)
109 {
110 data = ( unsigned char* ) stackData;
111 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3;
112 }
113 else
114 {
115 data = ( unsigned char* ) rakMalloc_Ex( (size_t) lengthInBytes, _FILE_AND_LINE_ );
116 }
117 #ifdef _DEBUG
118 RakAssert( data );
119 #endif
120 memcpy( data, _data, (size_t) lengthInBytes );
121 }
122 else
123 data = 0;
124 }
125 else
126 data = ( unsigned char* ) _data;
127 }
128
129 // Use this if you pass a pointer copy to the constructor (_copyData==false) and want to overallocate to prevent reallocation
130 void BitStream::SetNumberOfBitsAllocated( const BitSize_t lengthInBits )
131 {
132 #ifdef _DEBUG
133 RakAssert( lengthInBits >= ( BitSize_t ) numberOfBitsAllocated );
134 #endif
135 numberOfBitsAllocated = lengthInBits;
136 }
137
138 BitStream::~BitStream()
139 {
140 if ( copyData && numberOfBitsAllocated > (BITSTREAM_STACK_ALLOCATION_SIZE << 3))
141 rakFree_Ex( data , _FILE_AND_LINE_ ); // Use realloc and free so we are more efficient than delete and new for resizing
142 }
143
144 void BitStream::Reset( void )
145 {
146 // Note: Do NOT reallocate memory because BitStream is used
147 // in places to serialize/deserialize a buffer. Reallocation
148 // is a dangerous operation (may result in leaks).
149
150 if ( numberOfBitsUsed > 0 )
151 {
152 // memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed));
153 }
154
155 // Don't free memory here for speed efficiency
156 //free(data); // Use realloc and free so we are more efficient than delete and new for resizing
157 numberOfBitsUsed = 0;
158
159 //numberOfBitsAllocated=8;
160 readOffset = 0;
161
162 //data=(unsigned char*)rakMalloc_Ex(1, _FILE_AND_LINE_);
163 // if (numberOfBitsAllocated>0)
164 // memset(data, 0, BITS_TO_BYTES(numberOfBitsAllocated));
165 }
166
167 // Write an array or casted stream
168 void BitStream::Write( const char* inputByteArray, const unsigned int numberOfBytes )
169 {
170 if (numberOfBytes==0)
171 return;
172
173 // Optimization:
174 if ((numberOfBitsUsed & 7) == 0)
175 {
176 AddBitsAndReallocate( BYTES_TO_BITS(numberOfBytes) );
177 memcpy(data+BITS_TO_BYTES(numberOfBitsUsed), inputByteArray, (size_t) numberOfBytes);
178 numberOfBitsUsed+=BYTES_TO_BITS(numberOfBytes);
179 }
180 else
181 {
182 WriteBits( ( unsigned char* ) inputByteArray, numberOfBytes * 8, true );
183 }
184
185 }
186 void BitStream::Write( BitStream *bitStream)
187 {
188 Write(bitStream, bitStream->GetNumberOfBitsUsed()-bitStream->GetReadOffset());
189 }
190 void BitStream::Write( BitStream *bitStream, BitSize_t numberOfBits )
191 {
192 if (numberOfBits > bitStream->GetNumberOfUnreadBits())
193 return;
194
195 AddBitsAndReallocate( numberOfBits );
196 BitSize_t numberOfBitsMod8;
197
198 if ((bitStream->GetReadOffset()&7)==0 && (numberOfBitsUsed&7)==0)
199 {
200 int readOffsetBytes=bitStream->GetReadOffset()/8;
201 int numBytes=numberOfBits/8;
202 memcpy(data + (numberOfBitsUsed >> 3), bitStream->GetData()+readOffsetBytes, numBytes);
203 numberOfBits-=BYTES_TO_BITS(numBytes);
204 bitStream->SetReadOffset(BYTES_TO_BITS(numBytes+readOffsetBytes));
205 numberOfBitsUsed+=BYTES_TO_BITS(numBytes);
206 }
207
208 while (numberOfBits-->0)
209 {
210 numberOfBitsMod8 = numberOfBitsUsed & 7;
211 if ( numberOfBitsMod8 == 0 )
212 {
213 // New byte
214 if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
215 {
216 // Write 1
217 data[ numberOfBitsUsed >> 3 ] = 0x80;
218 }
219 else
220 {
221 // Write 0
222 data[ numberOfBitsUsed >> 3 ] = 0;
223 }
224
225 }
226 else
227 {
228 // Existing byte
229 if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
230 data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
231 // else 0, do nothing
232 }
233
234 bitStream->readOffset++;
235 numberOfBitsUsed++;
236 }
237 }
238 void BitStream::Write( BitStream &bitStream, BitSize_t numberOfBits )
239 {
240 Write(&bitStream, numberOfBits);
241 }
242 void BitStream::Write( BitStream &bitStream )
243 {
244 Write(&bitStream);
245 }
246 bool BitStream::Read( BitStream *bitStream, BitSize_t numberOfBits )
247 {
248 if (GetNumberOfUnreadBits() < numberOfBits)
249 return false;
250 bitStream->Write(this, numberOfBits);
251 return true;
252 }
253 bool BitStream::Read( BitStream *bitStream )
254 {
255 bitStream->Write(this);
256 return true;
257 }
258 bool BitStream::Read( BitStream &bitStream, BitSize_t numberOfBits )
259 {
260 if (GetNumberOfUnreadBits() < numberOfBits)
261 return false;
262 bitStream.Write(this, numberOfBits);
263 return true;
264 }
265 bool BitStream::Read( BitStream &bitStream )
266 {
267 bitStream.Write(this);
268 return true;
269 }
270
271 // Read an array or casted stream
272 bool BitStream::Read( char* outByteArray, const unsigned int numberOfBytes )
273 {
274 // Optimization:
275 if ((readOffset & 7) == 0)
276 {
277 if (GetNumberOfUnreadBits() < (numberOfBytes << 3))
278 return false;
279
280 // Write the data
281 memcpy( outByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytes );
282
283 readOffset += numberOfBytes << 3;
284 return true;
285 }
286 else
287 {
288 return ReadBits( ( unsigned char* ) outByteArray, numberOfBytes * 8 );
289 }
290 }
291
292 // Sets the read pointer back to the beginning of your data.
293 void BitStream::ResetReadPointer( void )
294 {
295 readOffset = 0;
296 }
297
298 // Sets the write pointer back to the beginning of your data.
299 void BitStream::ResetWritePointer( void )
300 {
301 numberOfBitsUsed = 0;
302 }
303
304 // Write a 0
305 void BitStream::Write0( void )
306 {
307 AddBitsAndReallocate( 1 );
308
309 // New bytes need to be zeroed
310 if ( ( numberOfBitsUsed & 7 ) == 0 )
311 data[ numberOfBitsUsed >> 3 ] = 0;
312
313 numberOfBitsUsed++;
314 }
315
316 // Write a 1
317 void BitStream::Write1( void )
318 {
319 AddBitsAndReallocate( 1 );
320
321 BitSize_t numberOfBitsMod8 = numberOfBitsUsed & 7;
322
323 if ( numberOfBitsMod8 == 0 )
324 data[ numberOfBitsUsed >> 3 ] = 0x80;
325 else
326 data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
327
328 numberOfBitsUsed++;
329 }
330
331 // Returns true if the next data read is a 1, false if it is a 0
332 bool BitStream::ReadBit( void )
333 {
334 if (GetNumberOfUnreadBits() == 0) {
335 return false;
336 }
337
338 bool result = ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) !=0;
339 readOffset++;
340 return result;
341 }
342
343 // Align the bitstream to the byte boundary and then write the specified number of bits.
344 // This is faster than WriteBits but wastes the bits to do the alignment and requires you to call
345 // SetReadToByteAlignment at the corresponding read position
346 void BitStream::WriteAlignedBytes( const unsigned char* inByteArray, const unsigned int numberOfBytesToWrite )
347 {
348 AlignWriteToByteBoundary();
349 Write((const char*) inByteArray, numberOfBytesToWrite);
350 }
351 void BitStream::EndianSwapBytes( int byteOffset, int length )
352 {
353 if (DoEndianSwap())
354 {
355 ReverseBytesInPlace(data+byteOffset, length);
356 }
357 }
359 void BitStream::WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite )
360 {
361 if (inByteArray==0 || inputLength==0)
362 {
363 WriteCompressed((unsigned int)0);
364 return;
365 }
366 WriteCompressed(inputLength);
367 WriteAlignedBytes((const unsigned char*) inByteArray, inputLength < maxBytesToWrite ? inputLength : maxBytesToWrite);
368 }
369
370 // Read bits, starting at the next aligned bits. Note that the modulus 8 starting offset of the
371 // sequence must be the same as was used with WriteBits. This will be a problem with packet coalescence
372 // unless you byte align the coalesced packets.
373 bool BitStream::ReadAlignedBytes( unsigned char* inOutByteArray, const unsigned int numberOfBytesToRead )
374 {
375 #ifdef _DEBUG
376 RakAssert( numberOfBytesToRead > 0 );
377 #endif
378
379 if ( numberOfBytesToRead <= 0 )
380 return false;
381
382 // Byte align
383 AlignReadToByteBoundary();
384
385 if (GetNumberOfUnreadBits() < (numberOfBytesToRead << 3))
386 return false;
387
388 // Write the data
389 memcpy( inOutByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytesToRead );
390
391 readOffset += numberOfBytesToRead << 3;
392
393 return true;
394 }
395 bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead )
396 {
397 return ReadAlignedBytesSafe(inOutByteArray,(unsigned int&) inputLength,(unsigned int)maxBytesToRead);
398 }
399 bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
400 {
401 if (ReadCompressed(inputLength)==false)
402 return false;
403 if (inputLength > maxBytesToRead)
404 inputLength=maxBytesToRead;
405 if (inputLength==0)
406 return true;
407 return ReadAlignedBytes((unsigned char*) inOutByteArray, inputLength);
408 }
409 bool BitStream::ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead )
410 {
411 return ReadAlignedBytesSafeAlloc(outByteArray,(unsigned int&) inputLength, maxBytesToRead);
412 }
413 bool BitStream::ReadAlignedBytesSafeAlloc( char ** outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
414 {
415 rakFree_Ex(*outByteArray, _FILE_AND_LINE_ );
416 *outByteArray=0;
417 if (ReadCompressed(inputLength)==false)
418 return false;
419 if (inputLength > maxBytesToRead)
420 inputLength=maxBytesToRead;
421 if (inputLength==0)
422 return true;
423 *outByteArray = (char*) rakMalloc_Ex( (size_t) inputLength, _FILE_AND_LINE_ );
424 return ReadAlignedBytes((unsigned char*) *outByteArray, inputLength);
425 }
426
427 // Write numberToWrite bits from the input source
428 void BitStream::WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits )
429 {
430 // if (numberOfBitsToWrite<=0)
431 // return;
432
433 AddBitsAndReallocate( numberOfBitsToWrite );
434
435 const BitSize_t numberOfBitsUsedMod8 = numberOfBitsUsed & 7;
436
437 // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
438 if (numberOfBitsUsedMod8==0 && (numberOfBitsToWrite&7)==0)
439 {
440 memcpy( data + ( numberOfBitsUsed >> 3 ), inByteArray, numberOfBitsToWrite>>3);
441 numberOfBitsUsed+=numberOfBitsToWrite;
442 return;
443 }
444
445 unsigned char dataByte;
446 const unsigned char* inputPtr=inByteArray;
447
448 // Faster to put the while at the top surprisingly enough
449 while ( numberOfBitsToWrite > 0 )
450 //do
451 {
452 dataByte = *( inputPtr++ );
453
454 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)
455 dataByte <<= 8 - numberOfBitsToWrite; // shift left to get the bits on the left, as in our internal representation
456
457 // Writing to a new byte each time
458 if ( numberOfBitsUsedMod8 == 0 )
459 * ( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;
460 else
461 {
462 // Copy over the new data.
463 *( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half
464
465 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)
466 {
467 *( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary)
468 }
469 }
470
471 if ( numberOfBitsToWrite >= 8 )
472 {
473 numberOfBitsUsed += 8;
474 numberOfBitsToWrite -= 8;
475 }
476 else
477 {
478 numberOfBitsUsed += numberOfBitsToWrite;
479 numberOfBitsToWrite=0;
480 }
481 }
482 // } while(numberOfBitsToWrite>0);
483 }
484
485 // Set the stream to some initial data. For internal use
486 void BitStream::SetData( unsigned char *inByteArray )
487 {
488 data=inByteArray;
489 copyData=false;
490 }
491
492 // Assume the input source points to a native type, compress and write it
493 void BitStream::WriteCompressed( const unsigned char* inByteArray,
494 const unsigned int size, const bool unsignedData )
495 {
496 BitSize_t currentByte = ( size >> 3 ) - 1; // PCs
497
498 unsigned char byteMatch;
499
500 if ( unsignedData )
501 {
502 byteMatch = 0;
503 }
504
505 else
506 {
507 byteMatch = 0xFF;
508 }
509
510 // Write upper bytes with a single 1
511 // 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
512 while ( currentByte > 0 )
513 {
514 if ( inByteArray[ currentByte ] == byteMatch ) // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted
515 {
516 bool b = true;
517 Write( b );
518 }
519 else
520 {
521 // Write the remainder of the data after writing 0
522 bool b = false;
523 Write( b );
524
525 WriteBits( inByteArray, ( currentByte + 1 ) << 3, true );
526 // currentByte--;
527
528
529 return ;
530 }
531
532 currentByte--;
533 }
534
535 // 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.
536 if ( ( unsignedData && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0x00 ) ||
537 ( unsignedData == false && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0xF0 ) )
538 {
539 bool b = true;
540 Write( b );
541 WriteBits( inByteArray + currentByte, 4, true );
542 }
543
544 else
545 {
546 bool b = false;
547 Write( b );
548 WriteBits( inByteArray + currentByte, 8, true );
549 }
550 }
551
552 // Read numberOfBitsToRead bits to the output source
553 // alignBitsToRight should be set to true to convert internal bitstream data to userdata
554 // It should be false if you used WriteBits with rightAlignedBits false
555 bool BitStream::ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight )
556 {
557 #ifdef _DEBUG
558 // RakAssert( numberOfBitsToRead > 0 );
559 #endif
560 if (numberOfBitsToRead<=0)
561 return false;
562
563 if (GetNumberOfUnreadBits() < numberOfBitsToRead)
564 return false;
565
566
567 const BitSize_t readOffsetMod8 = readOffset & 7;
568
569 // If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
570 if (readOffsetMod8==0 && (numberOfBitsToRead&7)==0)
571 {
572 memcpy( inOutByteArray, data + ( readOffset >> 3 ), numberOfBitsToRead>>3);
573 readOffset+=numberOfBitsToRead;
574 return true;
575 }
576
577
578
579 BitSize_t offset = 0;
580
581 memset( inOutByteArray, 0, (size_t) BITS_TO_BYTES( numberOfBitsToRead ) );
582
583 while ( numberOfBitsToRead > 0 )
584 {
585 *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half
586
587 if ( readOffsetMod8 > 0 && numberOfBitsToRead > 8 - ( readOffsetMod8 ) ) // If we have a second half, we didn't read enough bytes in the first half
588 *( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) + 1 ) >> ( 8 - ( readOffsetMod8 ) ); // Second half (overlaps byte boundary)
589
590 if (numberOfBitsToRead>=8)
591 {
592 numberOfBitsToRead -= 8;
593 readOffset += 8;
594 offset++;
595 }
596 else
597 {
598 int neg = (int) numberOfBitsToRead - 8;
599
600 if ( neg < 0 ) // Reading a partial byte for the last byte, shift right so the data is aligned on the right
601 {
602
603 if ( alignBitsToRight )
604 * ( inOutByteArray + offset ) >>= -neg;
605
606 readOffset += 8 + neg;
607 }
608 else
609 readOffset += 8;
610
611 offset++;
612
613 numberOfBitsToRead=0;
614 }
615 }
616
617 return true;
618 }
619
620 // Assume the input source points to a compressed native type. Decompress and read it
621 bool BitStream::ReadCompressed( unsigned char* inOutByteArray,
622 const unsigned int size, const bool unsignedData )
623 {
624 unsigned int currentByte = ( size >> 3 ) - 1;
625
626
627 unsigned char byteMatch, halfByteMatch;
628
629 if ( unsignedData )
630 {
631 byteMatch = 0;
632 halfByteMatch = 0;
633 }
634
635 else
636 {
637 byteMatch = 0xFF;
638 halfByteMatch = 0xF0;
639 }
640
641 // Upper bytes are specified with a single 1 if they match byteMatch
642 // 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
643 while ( currentByte > 0 )
644 {
645 // If we read a 1 then the data is byteMatch.
646
647 bool b;
648
649 if ( Read( b ) == false )
650 return false;
651
652 if ( b ) // Check that bit
653 {
654 inOutByteArray[ currentByte ] = byteMatch;
655 currentByte--;
656 }
657 else
658 {
659 // Read the rest of the bytes
660
661 if ( ReadBits( inOutByteArray, ( currentByte + 1 ) << 3 ) == false )
662 return false;
663
664 return true;
665 }
666 }
667
668 // 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.
669 // Otherwise we read a 0 and the 8 bytes
670 //RakAssert(readOffset+1 <=numberOfBitsUsed); // If this assert is hit the stream wasn't long enough to read from
671 if ( readOffset + 1 > numberOfBitsUsed )
672 return false;
673
674 bool b=false;
675
676 if ( Read( b ) == false )
677 return false;
678
679 if ( b ) // Check that bit
680 {
681
682 if ( ReadBits( inOutByteArray + currentByte, 4 ) == false )
683 return false;
684
685 inOutByteArray[ currentByte ] |= halfByteMatch; // We have to set the high 4 bits since these are set to 0 by ReadBits
686 }
687 else
688 {
689 if ( ReadBits( inOutByteArray + currentByte, 8 ) == false )
690 return false;
691 }
692
693 return true;
694 }
695
696 // Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
697 void BitStream::AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite )
698 {
699 BitSize_t newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed;
700
701 if ( numberOfBitsToWrite + numberOfBitsUsed > 0 && ( ( numberOfBitsAllocated - 1 ) >> 3 ) < ( ( newNumberOfBitsAllocated - 1 ) >> 3 ) ) // If we need to allocate 1 or more new bytes
702 {
703 #ifdef _DEBUG
704 // If this assert hits then we need to specify true for the third parameter in the constructor
705 // It needs to reallocate to hold all the data and can't do it unless we allocated to begin with
706 // Often hits if you call Write or Serialize on a read-only bitstream
707 RakAssert( copyData == true );
708 #endif
709
710 // Less memory efficient but saves on news and deletes
712 newNumberOfBitsAllocated = ( numberOfBitsToWrite + numberOfBitsUsed ) * 2;
713 if (newNumberOfBitsAllocated - ( numberOfBitsToWrite + numberOfBitsUsed ) > 1048576 )
714 newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed + 1048576;
715
716 // BitSize_t newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated );
717 // Use realloc and free so we are more efficient than delete and new for resizing
718 BitSize_t amountToAllocate = BITS_TO_BYTES( newNumberOfBitsAllocated );
719 if (data==(unsigned char*)stackData)
720 {
721 if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)
722 {
723 data = ( unsigned char* ) rakMalloc_Ex( (size_t) amountToAllocate, _FILE_AND_LINE_ );
724 RakAssert(data);
725
726 // need to copy the stack data over to our new memory area too
727 memcpy ((void *)data, (void *)stackData, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ));
728 }
729 }
730 else
731 {
732 data = ( unsigned char* ) rakRealloc_Ex( data, (size_t) amountToAllocate, _FILE_AND_LINE_ );
733 }
734
735 #ifdef _DEBUG
736 RakAssert( data ); // Make sure realloc succeeded
737 #endif
738 // memset(data+newByteOffset, 0, ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0
739 }
740
741 if ( newNumberOfBitsAllocated > numberOfBitsAllocated )
742 numberOfBitsAllocated = newNumberOfBitsAllocated;
743 }
744 BitSize_t BitStream::GetNumberOfBitsAllocated(void) const
745 {
746 return numberOfBitsAllocated;
747 }
748 void BitStream::PadWithZeroToByteLength( unsigned int bytes )
749 {
750 if (GetNumberOfBytesUsed() < bytes)
751 {
752 AlignWriteToByteBoundary();
753 unsigned int numToWrite = bytes - GetNumberOfBytesUsed();
754 AddBitsAndReallocate( BYTES_TO_BITS(numToWrite) );
755 memset(data+BITS_TO_BYTES(numberOfBitsUsed), 0, (size_t) numToWrite);
756 numberOfBitsUsed+=BYTES_TO_BITS(numToWrite);
757 }
758 }
759
760 /*
761 // Julius Goryavsky's version of Harley's algorithm.
762 // 17 elementary ops plus an indexed load, if the machine
763 // has "and not."
764
765 int nlz10b(unsigned x) {
766
767 static char table[64] =
768 {32,20,19, u, u,18, u, 7, 10,17, u, u,14, u, 6, u,
769 u, 9, u,16, u, u, 1,26, u,13, u, u,24, 5, u, u,
770 u,21, u, 8,11, u,15, u, u, u, u, 2,27, 0,25, u,
771 22, u,12, u, u, 3,28, u, 23, u, 4,29, u, u,30,31};
772
773 x = x | (x >> 1); // Propagate leftmost
774 x = x | (x >> 2); // 1-bit to the right.
775 x = x | (x >> 4);
776 x = x | (x >> 8);
777 x = x & ~(x >> 16);
778 x = x*0xFD7049FF; // Activate this line or the following 3.
779 // x = (x << 9) - x; // Multiply by 511.
780 // x = (x << 11) - x; // Multiply by 2047.
781 // x = (x << 14) - x; // Multiply by 16383.
782 return table[x >> 26];
783 }
784 */
785 int BitStream::NumberOfLeadingZeroes( int8_t x ) {return NumberOfLeadingZeroes((uint8_t)x);}
786 int BitStream::NumberOfLeadingZeroes( uint8_t x )
787 {
788 uint8_t y;
789 int n;
790
791 n = 8;
792 y = x >> 4; if (y != 0) {n = n - 4; x = y;}
793 y = x >> 2; if (y != 0) {n = n - 2; x = y;}
794 y = x >> 1; if (y != 0) return n - 2;
795 return (int)(n - x);
796 }
797 int BitStream::NumberOfLeadingZeroes( int16_t x ) {return NumberOfLeadingZeroes((uint16_t)x);}
798 int BitStream::NumberOfLeadingZeroes( uint16_t x )
799 {
800 uint16_t y;
801 int n;
802
803 n = 16;
804 y = x >> 8; if (y != 0) {n = n - 8; x = y;}
805 y = x >> 4; if (y != 0) {n = n - 4; x = y;}
806 y = x >> 2; if (y != 0) {n = n - 2; x = y;}
807 y = x >> 1; if (y != 0) return n - 2;
808 return (int)(n - x);
809 }
810 int BitStream::NumberOfLeadingZeroes( int32_t x ) {return NumberOfLeadingZeroes((uint32_t)x);}
811 int BitStream::NumberOfLeadingZeroes( uint32_t x )
812 {
813 uint32_t y;
814 int n;
815
816 n = 32;
817 y = x >>16; if (y != 0) {n = n -16; x = y;}
818 y = x >> 8; if (y != 0) {n = n - 8; x = y;}
819 y = x >> 4; if (y != 0) {n = n - 4; x = y;}
820 y = x >> 2; if (y != 0) {n = n - 2; x = y;}
821 y = x >> 1; if (y != 0) return n - 2;
822 return (int)(n - x);
823 }
824 int BitStream::NumberOfLeadingZeroes( int64_t x ) {return NumberOfLeadingZeroes((uint64_t)x);}
825 int BitStream::NumberOfLeadingZeroes( uint64_t x )
826 {
827 uint64_t y;
828 int n;
829
830 n = 64;
831 y = x >>32; if (y != 0) {n = n -32; x = y;}
832 y = x >>16; if (y != 0) {n = n -16; x = y;}
833 y = x >> 8; if (y != 0) {n = n - 8; x = y;}
834 y = x >> 4; if (y != 0) {n = n - 4; x = y;}
835 y = x >> 2; if (y != 0) {n = n - 2; x = y;}
836 y = x >> 1; if (y != 0) return n - 2;
837 return (int)(n - x);
838 }
839
840 // Should hit if reads didn't match writes
841 void BitStream::AssertStreamEmpty( void )
842 {
843 RakAssert( readOffset == numberOfBitsUsed );
844 }
845
846 void BitStream::PrintBits( char *out ) const
847 {
848 if (numberOfBitsUsed <= 0)
849 {
850 #pragma warning(push)
851 #pragma warning(disable:4996)
852 strcpy(out, "No bits\n");
853 #pragma warning(pop)
854 return;
855 }
856
857 unsigned int strIndex = 0;
858 for (BitSize_t counter = 0; counter < BITS_TO_BYTES(numberOfBitsUsed) && strIndex < 2000; counter++)
859 {
860 BitSize_t stop;
861
862 if (counter == (numberOfBitsUsed - 1) >> 3)
863 stop = 8 - (((numberOfBitsUsed - 1) & 7) + 1);
864 else
865 stop = 0;
866
867 for (BitSize_t counter2 = 7; counter2 >= stop; counter2--)
868 {
869 if ((data[counter] >> counter2) & 1)
870 out[strIndex++] = '1';
871 else
872 out[strIndex++] = '0';
873
874 if (counter2 == 0)
875 break;
876 }
877
878 out[strIndex++] = ' ';
879 }
880
881 out[strIndex++] = '\n';
882
883 out[strIndex++] = 0;
884 }
885
886 void BitStream::PrintBits( char *out, size_t outLength ) const
887 {
888 if ( numberOfBitsUsed <= 0 )
889 {
890 strcpy_s(out, outLength, "No bits\n" );
891 return;
892 }
893
894 unsigned int strIndex=0;
895 for ( BitSize_t counter = 0; counter < BITS_TO_BYTES( numberOfBitsUsed ) && strIndex < 2000 ; counter++ )
896 {
897 BitSize_t stop;
898
899 if ( counter == ( numberOfBitsUsed - 1 ) >> 3 )
900 stop = 8 - ( ( ( numberOfBitsUsed - 1 ) & 7 ) + 1 );
901 else
902 stop = 0;
903
904 for ( BitSize_t counter2 = 7; counter2 >= stop; counter2-- )
905 {
906 if ( ( data[ counter ] >> counter2 ) & 1 )
907 out[strIndex++]='1';
908 else
909 out[strIndex++]='0';
910
911 if (counter2==0)
912 break;
913 }
914
915 out[strIndex++]=' ';
916 }
917
918 out[strIndex++]='\n';
919
920 out[strIndex++]=0;
921 }
922 void BitStream::PrintBits( void ) const
923 {
924 char out[2048];
925 PrintBits(out, 2048);
926 RAKNET_DEBUG_PRINTF("%s", out);
927 }
928
929 void BitStream::PrintHex( char *out, size_t outLength ) const
930 {
931 BitSize_t i;
932 for ( i=0; i < GetNumberOfBytesUsed(); i++)
933 {
934 sprintf_s(out+i*3, outLength-i*3, "%02x ", data[i]);
935 }
936 }
937
938 void BitStream::PrintHex( char *out ) const
939 {
940 BitSize_t i;
941 for (i = 0; i < GetNumberOfBytesUsed(); i++)
942 {
943 #pragma warning(push)
944 #pragma warning(disable:4996)
945 sprintf(out + i * 3, "%02x ", data[i]);
946 #pragma warning(pop)
947 }
948 }
949
950 void BitStream::PrintHex( void ) const
951 {
952 char out[2048];
953 PrintHex(out, 2048);
954 RAKNET_DEBUG_PRINTF("%s", out);
955 }
956
957 // Exposes the data for you to look at, like PrintBits does.
958 // Data will point to the stream. Returns the length in bits of the stream.
959 BitSize_t BitStream::CopyData( unsigned char** _data ) const
960 {
961 #ifdef _DEBUG
962 RakAssert( numberOfBitsUsed > 0 );
963 #endif
964
965 *_data = (unsigned char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES( numberOfBitsUsed ), _FILE_AND_LINE_ );
966 memcpy( *_data, data, sizeof(unsigned char) * (size_t) ( BITS_TO_BYTES( numberOfBitsUsed ) ) );
967 return numberOfBitsUsed;
968 }
969
970 // Ignore data we don't intend to read
971 void BitStream::IgnoreBits( const BitSize_t numberOfBits )
972 {
973 readOffset += numberOfBits;
974 }
975
976 void BitStream::IgnoreBytes( const unsigned int numberOfBytes )
977 {
978 IgnoreBits(BYTES_TO_BITS(numberOfBytes));
979 }
980
981 // Move the write pointer to a position on the array. Dangerous if you don't know what you are doing!
982 // Doesn't work with non-aligned data!
983 void BitStream::SetWriteOffset( const BitSize_t offset )
984 {
985 numberOfBitsUsed = offset;
986 }
987
988 /*
989 BitSize_t BitStream::GetWriteOffset( void ) const
990 {
991 return numberOfBitsUsed;
992 }
993
994 // Returns the length in bits of the stream
995 BitSize_t BitStream::GetNumberOfBitsUsed( void ) const
996 {
997 return GetWriteOffset();
998 }
999
1000 // Returns the length in bytes of the stream
1001 BitSize_t BitStream::GetNumberOfBytesUsed( void ) const
1002 {
1003 return BITS_TO_BYTES( numberOfBitsUsed );
1004 }
1005
1006 // Returns the number of bits into the stream that we have read
1007 BitSize_t BitStream::GetReadOffset( void ) const
1008 {
1009 return readOffset;
1010 }
1011
1012
1013 // Sets the read bit index
1014 void BitStream::SetReadOffset( const BitSize_t newReadOffset )
1015 {
1016 readOffset=newReadOffset;
1017 }
1018
1019 // Returns the number of bits left in the stream that haven't been read
1020 BitSize_t BitStream::GetNumberOfUnreadBits( void ) const
1021 {
1022 return numberOfBitsUsed - readOffset;
1023 }
1024 // Exposes the internal data
1025 unsigned char* BitStream::GetData( void ) const
1026 {
1027 return data;
1028 }
1029
1030 */
1031 // 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.
1032 void BitStream::AssertCopyData( void )
1033 {
1034 if ( copyData == false )
1035 {
1036 copyData = true;
1037
1038 if ( numberOfBitsAllocated > 0 )
1039 {
1040 unsigned char * newdata = ( unsigned char* ) rakMalloc_Ex( (size_t) BITS_TO_BYTES( numberOfBitsAllocated ), _FILE_AND_LINE_ );
1041 #ifdef _DEBUG
1042
1043 RakAssert( data );
1044 #endif
1045
1046 memcpy( newdata, data, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ) );
1047 data = newdata;
1048 }
1049
1050 else
1051 data = 0;
1052 }
1053 }
1054 bool BitStream::IsNetworkOrderInternal(void)
1055 {
1056
1057
1058
1059
1060
1061 static unsigned long htonlValue = htonl(12345);
1062 return htonlValue == 12345;
1063
1064 }
1065 void BitStream::ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length)
1066 {
1067 for (BitSize_t i=0; i < length; i++)
1068 inOutByteArray[i]=inByteArray[length-i-1];
1069 }
1070 void BitStream::ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length)
1071 {
1072 unsigned char temp;
1073 BitSize_t i;
1074 for (i=0; i < (length>>1); i++)
1075 {
1076 temp = inOutData[i];
1077 inOutData[i]=inOutData[length-i-1];
1078 inOutData[length-i-1]=temp;
1079 }
1080 }
1081
1082 bool BitStream::Read(char *varString)
1083 {
1084 return RakString::Deserialize(varString,this);
1085 }
1086 bool BitStream::Read(unsigned char *varString)
1087 {
1088 return RakString::Deserialize((char*) varString,this);
1089 }
1090 void BitStream::WriteAlignedVar8(const char *inByteArray)
1091 {
1092 RakAssert((numberOfBitsUsed&7)==0);
1093 AddBitsAndReallocate(1*8);
1094 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
1095 numberOfBitsUsed+=1*8;
1096 }
1097 bool BitStream::ReadAlignedVar8(char *inOutByteArray)
1098 {
1099 RakAssert((readOffset&7)==0);
1100 if (GetNumberOfUnreadBits() < 1 * 8)
1101 return false;
1102
1103 inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
1104 readOffset+=1*8;
1105 return true;
1106 }
1107 void BitStream::WriteAlignedVar16(const char *inByteArray)
1108 {
1109 RakAssert((numberOfBitsUsed&7)==0);
1110 AddBitsAndReallocate(2*8);
1111 #ifndef __BITSTREAM_NATIVE_END
1112 if (DoEndianSwap())
1113 {
1114 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[1];
1115 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[0];
1116 }
1117 else
1118 #endif
1119 {
1120 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
1121 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
1122 }
1123
1124 numberOfBitsUsed+=2*8;
1125 }
1126 bool BitStream::ReadAlignedVar16(char *inOutByteArray)
1127 {
1128 RakAssert((readOffset&7)==0);
1129 if (GetNumberOfUnreadBits() < 2 * 8)
1130 return false;
1131 #ifndef __BITSTREAM_NATIVE_END
1132 if (DoEndianSwap())
1133 {
1134 inOutByteArray[0] = data[( readOffset >> 3 ) + 1];
1135 inOutByteArray[1] = data[( readOffset >> 3 ) + 0];
1136 }
1137 else
1138 #endif
1139 {
1140 inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
1141 inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
1142 }
1143
1144 readOffset+=2*8;
1145 return true;
1146 }
1147 void BitStream::WriteAlignedVar32(const char *inByteArray)
1148 {
1149 RakAssert((numberOfBitsUsed&7)==0);
1150 AddBitsAndReallocate(4*8);
1151 #ifndef __BITSTREAM_NATIVE_END
1152 if (DoEndianSwap())
1153 {
1154 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[3];
1155 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[2];
1156 data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[1];
1157 data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[0];
1158 }
1159 else
1160 #endif
1161 {
1162 data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
1163 data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
1164 data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[2];
1165 data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[3];
1166 }
1167
1168 numberOfBitsUsed+=4*8;
1169 }
1170 bool BitStream::ReadAlignedVar32(char *inOutByteArray)
1171 {
1172 RakAssert((readOffset&7)==0);
1173 if (GetNumberOfUnreadBits() < 4*8)
1174 return false;
1175 #ifndef __BITSTREAM_NATIVE_END
1176 if (DoEndianSwap())
1177 {
1178 inOutByteArray[0] = data[( readOffset >> 3 ) + 3];
1179 inOutByteArray[1] = data[( readOffset >> 3 ) + 2];
1180 inOutByteArray[2] = data[( readOffset >> 3 ) + 1];
1181 inOutByteArray[3] = data[( readOffset >> 3 ) + 0];
1182 }
1183 else
1184 #endif
1185 {
1186 inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
1187 inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
1188 inOutByteArray[2] = data[( readOffset >> 3 ) + 2];
1189 inOutByteArray[3] = data[( readOffset >> 3 ) + 3];
1190 }
1191
1192 readOffset+=4*8;
1193 return true;
1194 }
1195 bool BitStream::ReadFloat16( float &outFloat, float floatMin, float floatMax )
1196 {
1197 unsigned short percentile;
1198 if (Read(percentile))
1199 {
1200 RakAssert(floatMax>floatMin);
1201 outFloat = floatMin + ((float) percentile / 65535.0f) * (floatMax-floatMin);
1202 if (outFloat<floatMin)
1203 outFloat=floatMin;
1204 else if (outFloat>floatMax)
1205 outFloat=floatMax;
1206 return true;
1207 }
1208 return false;
1209 }
1210 bool BitStream::SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax)
1211 {
1212 if (writeToBitstream)
1213 WriteFloat16(inOutFloat, floatMin, floatMax);
1214 else
1215 return ReadFloat16(inOutFloat, floatMin, floatMax);
1216 return true;
1217 }
1218 void BitStream::WriteFloat16( float inOutFloat, float floatMin, float floatMax )
1219 {
1220 RakAssert(floatMax>floatMin);
1221 if (inOutFloat>floatMax+.001)
1222 {
1223 RakAssert(inOutFloat<=floatMax+.001);
1224 }
1225 if (inOutFloat<floatMin-.001)
1226 {
1227 RakAssert(inOutFloat>=floatMin-.001);
1228 }
1229 float percentile=65535.0f * (inOutFloat-floatMin)/(floatMax-floatMin);
1230 if (percentile<0.0)
1231 percentile=0.0;
1232 if (percentile>65535.0f)
1233 percentile=65535.0f;
1234 Write((unsigned short)percentile);
1235 }