C#版BitStream 1.0

根据C++版的改编,刚刚改完,估计使用会有问题,对于uint8处理的不好

关于使用:

1 BitStream bs = new BitStream( );
2             bs.WriteInt32( 123 );
3 
4             int a = bs.ReadInt32( );

非常简单

BitStream.cs

   1 public class BitStream
   2     {
   3 #if __BITSTREAM_BIG_END
   4 // Set up the read/write routines to produce Big-End network streams.
   5 private const int B16_1 = 0;
   6 private const int B16_0 = 1;
   7 
   8 private const int B32_3 = 0;
   9 private const int B32_2 = 1;
  10 private const int B32_1 = 2;
  11 private const int B32_0 = 3;
  12 
  13 private const int B64_7 = 0;
  14 private const int B64_6 = 1;
  15 private const int B64_5 = 2;
  16 private const int B64_4 = 3;
  17 private const int B64_3 = 4;
  18 private const int B64_2 = 5;
  19 private const int B64_1 = 6;
  20 private const int B64_0 = 7;
  21 
  22 #else
  23 // Default to producing Little-End network streams.
  24         private const int B16_1 = 1;
  25         private const int B16_0 = 0;
  26 
  27         private const int B32_3 = 3;
  28         private const int B32_2 = 2;
  29         private const int B32_1 = 1;
  30         private const int B32_0 = 0;
  31 
  32         private const int B64_7 = 7;
  33         private const int B64_6 = 6;
  34         private const int B64_5 = 5;
  35         private const int B64_4 = 4;
  36         private const int B64_3 = 3;
  37         private const int B64_2 = 2;
  38         private const int B64_1 = 1;
  39         private const int B64_0 = 0;
  40 #endif
  41         public const int BITSTREAM_STACK_ALLOCATION_SIZE = 2048;
  42 
  43         /// Default Constructor
  44         public static int BITS_TO_BYTES(int x)
  45         {
  46             return (((x) + 7) >> 3);
  47         }
  48 
  49         public static int BYTES_TO_BITS(int x)
  50         {
  51             return (x << 3);
  52         }
  53 
  54         /**
  55      * @brief Packets encoding and decoding facilities 
  56      * 
  57      * Helper class to encode and decode packets. 
  58      * 
  59      */
  60 
  61         /**
  62          * Default Constructor 
  63          */
  64 
  65         public BitStream()
  66         {
  67             numberOfBitsUsed = 0;
  68             //numberOfBitsAllocated = 32 * 8;
  69             numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE*8;
  70             readOffset = 0;
  71             //data = ( unsigned char* ) malloc( 32 );
  72             data = stackData;
  73             copyData = true;
  74         }
  75 
  76         /**
  77          * Preallocate some memory for the construction of the packet 
  78          * @param initialBytesToAllocate the amount of byte to pre-allocate. 
  79          */
  80 
  81         public BitStream(int initialBytesToAllocate)
  82         {
  83             numberOfBitsUsed = 0;
  84             readOffset = 0;
  85             if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE)
  86             {
  87                 data = stackData;
  88                 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE*8;
  89             }
  90             else
  91             {
  92                 data = new Byte[initialBytesToAllocate];
  93                 numberOfBitsAllocated = initialBytesToAllocate << 3;
  94             }
  95             copyData = true;
  96         }
  97 
  98         /**
  99          * Initialize the BitStream object using data from the network. 
 100          * Set _copyData to true if you want to make an internal copy of
 101          * the data you are passing. You can then Write and do all other
 102          * operations Set it to false if you want to just use a pointer to
 103          * the data you are passing, in order to save memory and speed.
 104          * You should only then do read operations.
 105          * @param _data An array of bytes.
 106          * @param lengthInBytes Size of the @em _data.
 107          * @param _copyData Does a copy of the input data.  
 108          */
 109 
 110         public BitStream(Byte[] _data, int lengthInBytes, bool _copyData)
 111         {
 112             numberOfBitsUsed = lengthInBytes << 3;
 113             readOffset = 0;
 114             copyData = _copyData;
 115             numberOfBitsAllocated = lengthInBytes << 3;
 116 
 117             if (copyData)
 118             {
 119                 if (lengthInBytes > 0)
 120                 {
 121                     if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE)
 122                     {
 123                         data = stackData;
 124                         numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3;
 125                     }
 126                     else
 127                     {
 128                         data = new Byte[lengthInBytes];
 129                     }
 130                     _data.CopyTo(data, 0);
 131                 }
 132                 else
 133                     data = null;
 134             }
 135             else
 136             {
 137                 data = _data;
 138                 numberOfBitsUsed = 0;
 139             }
 140         }
 141 
 142         //
 143         public BitStream(Byte[] _data, int lengthInBytes, int datasize)
 144         {
 145             numberOfBitsUsed = datasize << 3;
 146             readOffset = 0;
 147             numberOfBitsAllocated = lengthInBytes << 3;
 148             data = _data;
 149             copyData = false;
 150         }
 151 
 152         /**
 153          * Destructor 
 154          */
 155         //~BitStream(){}
 156         /**
 157          * Reset the bitstream for reuse
 158          */
 159 
 160         private void Reset()
 161         {
 162             if (numberOfBitsUsed > 0)
 163             {
 164                 //  memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed));
 165             }
 166             // Don't free memory here for speed efficiency
 167             //free(data);  // Use realloc and free so we are more efficient than delete and new for resizing
 168             numberOfBitsUsed = 0;
 169             //numberOfBitsAllocated=8;
 170             readOffset = 0;
 171         }
 172 
 173         public void SetBuffer(Byte[] _data, int lengthInBytes, int datasize)
 174         {
 175             numberOfBitsUsed = datasize << 3;
 176             readOffset = 0;
 177             numberOfBitsAllocated = lengthInBytes << 3;
 178             data = _data;
 179             copyData = false;
 180         }
 181 
 182         public void ClearBuffer()
 183         {
 184             numberOfBitsUsed = 0;
 185             readOffset = 0;
 186             numberOfBitsAllocated = 0;
 187             data = null;
 188         }
 189 
 190         /**
 191          * Write the native types to the end of the buffer
 192          * without any compression mecanism. 
 193          * @param input The data 
 194          */
 195 
 196         public void WriteBool(bool input)
 197         {
 198             if (input)
 199                 WriteInt8(1);
 200             else
 201                 WriteInt8(0);
 202         }
 203 
 204         /**
 205          * Write the native types to the end of the buffer
 206          * without any compression mecanism. 
 207          * @param input The data 
 208          */
 209 
 210         public void WriteUInt8(Byte input)
 211         {
 212             WriteBits(BitConverter.GetBytes(input), sizeof (Byte)*8, true);
 213         }
 214 
 215         //
 216 
 217         /**
 218          * Write the native types to the end of the buffer
 219          * without any compression mecanism. 
 220          * @param input The data 
 221          */
 222 
 223         public void WriteInt8(SByte input)
 224         {
 225             WriteBits(BitConverter.GetBytes(input), sizeof (SByte)*8, true);
 226         }
 227 
 228         /**
 229          * Write the native types to the end of the buffer
 230          * without any compression mecanism. 
 231          * @param input The data 
 232          */
 233 
 234         public void WriteUInt16(UInt16 input)
 235         {
 236             var uint16w = new Byte[2];
 237             uint16w[B16_1] = (Byte) ((Byte) (input >> 8) & (0xff));
 238             uint16w[B16_0] = (Byte) (input & (0xff));
 239 
 240             WriteBits(uint16w, sizeof (UInt16)*8, true);
 241         }
 242 
 243         /**
 244          * Write the native types to the end of the buffer
 245          * without any compression mecanism. 
 246          * @param input The data 
 247          */
 248 
 249         public void WriteInt16(Int16 input)
 250         {
 251             var int16w = new Byte[2];
 252             int16w[B16_1] = (Byte) ((Byte) (input >> 8) & (0xff));
 253             int16w[B16_0] = (Byte) (input & (0xff));
 254 
 255             WriteBits(int16w, sizeof (Int16)*8, true);
 256         }
 257 
 258         /**
 259          * Write the native types to the end of the buffer
 260          * without any compression mecanism. 
 261          * @param input The data 
 262          */
 263 
 264         public void WriteUInt32(UInt32 input)
 265         {
 266             var uint32w = new Byte[4];
 267             uint32w[B32_3] = (Byte) ((Byte) (input >> 24) & (0x000000ff));
 268             uint32w[B32_2] = (Byte) ((Byte) (input >> 16) & (0x000000ff));
 269             uint32w[B32_1] = (Byte) ((Byte) (input >> 8) & (0x000000ff));
 270             uint32w[B32_0] = (Byte) ((input) & (0x000000ff));
 271 
 272             WriteBits(uint32w, sizeof (UInt32)*8, true);
 273         }
 274 
 275         /**
 276          * Write the native types to the end of the buffer
 277          * without any compression mecanism. 
 278          * @param input The data 
 279          */
 280 
 281         public void WriteInt32(int input)
 282         {
 283             var int32w = new Byte[4];
 284             int32w[B32_3] = (Byte) ((Byte) (input >> 24) & (0x000000ff));
 285             int32w[B32_2] = (Byte) ((Byte) (input >> 16) & (0x000000ff));
 286             int32w[B32_1] = (Byte) ((Byte) (input >> 8) & (0x000000ff));
 287             int32w[B32_0] = (Byte) ((input) & (0x000000ff));
 288 
 289             WriteBits(int32w, sizeof (int)*8, true);
 290         }
 291 
 292 //#if HAS_INT64
 293         /**
 294          * Write the native types to the end of the buffer
 295          * without any compression mecanism. 
 296          * @param input The data 
 297          */
 298 
 299         public void WriteUInt64(UInt64 input)
 300         {
 301             var uint64w = new Byte[8];
 302             uint64w[B64_7] = (Byte) ((input >> 56) & 0xff);
 303             uint64w[B64_6] = (Byte) ((input >> 48) & 0xff);
 304             uint64w[B64_5] = (Byte) ((input >> 40) & 0xff);
 305             uint64w[B64_4] = (Byte) ((input >> 32) & 0xff);
 306             uint64w[B64_3] = (Byte) ((input >> 24) & 0xff);
 307             uint64w[B64_2] = (Byte) ((input >> 16) & 0xff);
 308             uint64w[B64_1] = (Byte) ((input >> 8) & 0xff);
 309             uint64w[B64_0] = (Byte) (input & 0xff);
 310 
 311             WriteBits(uint64w, sizeof (UInt64)*8, true);
 312         }
 313 
 314         /**
 315          * Write the native types to the end of the buffer
 316          * without any compression mecanism. 
 317          * @param input The data 
 318          */
 319 
 320         public void WriteInt64(Int64 input)
 321         {
 322             var int64w = new Byte[8];
 323             int64w[B64_7] = (Byte) ((input >> 56) & 0xff);
 324             int64w[B64_6] = (Byte) ((input >> 48) & 0xff);
 325             int64w[B64_5] = (Byte) ((input >> 40) & 0xff);
 326             int64w[B64_4] = (Byte) ((input >> 32) & 0xff);
 327             int64w[B64_3] = (Byte) ((input >> 24) & 0xff);
 328             int64w[B64_2] = (Byte) ((input >> 16) & 0xff);
 329             int64w[B64_1] = (Byte) ((input >> 8) & 0xff);
 330             int64w[B64_0] = (Byte) (input & 0xff);
 331 
 332             WriteBits(int64w, sizeof (Int64)*8, true);
 333         }
 334 
 335 //#endif
 336 
 337         /**
 338          * Write the native types to the end of the buffer
 339          * without any compression mecanism. 
 340          * @param input The data 
 341          */
 342 
 343         public void WriteFloat(float input)
 344         {
 345             WriteBits(BitConverter.GetBytes(input), sizeof (float)*8, true);
 346         }
 347 
 348         /**
 349          * Write the native types to the end of the buffer
 350          * without any compression mechanism. 
 351          * @param input The data 
 352          */
 353 
 354         public void WriteDouble(double input)
 355         {
 356             WriteBits(BitConverter.GetBytes(input), sizeof (double)*8, true);
 357         }
 358 
 359         /**
 360          * Write an array or casted stream. It is supposed to
 361          * be raw data. It is also not possible to deal with endian problem 
 362          * @param input a byte buffer 
 363          * @param numberOfBytes the size of the byte buffer 
 364          */
 365 
 366         public void WriteBytes(Byte[] input, int numberOfBytes)
 367         {
 368             WriteBits(input, numberOfBytes*8, true);
 369         }
 370 
 371         /**
 372                  * write multi bytes string
 373                  * @param input
 374                  */
 375 
 376         public void WriteStr(string input)
 377         {
 378             var len = (short) input.Length;
 379             WriteUInt16((ushort) len);
 380             if (len > 0)
 381             {
 382                 WriteBytes(Encoding.Default.GetBytes(input), len);
 383             }
 384         }
 385 
 386         /// **
 387         //         * write standard string
 388         //         * @param input
 389         //         */
 390         //    public void WriteStr(
 391         //     const std::
 392         //     string 
 393         //&
 394         //     input 
 395         //){}
 396         /**
 397         * Copy from another bitstream
 398         * @bitStream the bitstream to copy from
 399         */
 400         public void WriteBS(BitStream bitStream)
 401         {
 402             WriteBits(bitStream.GetData(), bitStream.GetWriteOffset(), false);
 403         }
 404 
 405         /**
 406          * Write the native types with simple compression.
 407          * Best used with  negatives and positives close to 0
 408          * @param input The data.
 409          */
 410 
 411         public void WriteCompUInt8(Byte input)
 412         {
 413             WriteCompressed(BitConverter.GetBytes(input), sizeof (Byte)*8, true);
 414         }
 415 
 416         /**
 417          * Write the native types with simple compression.
 418          * Best used with  negatives and positives close to 0
 419          * @param input The data.
 420          */
 421 
 422         public void WriteCompInt8(SByte input)
 423         {
 424             WriteCompressed(BitConverter.GetBytes(input), sizeof (SByte)*8, false);
 425         }
 426 
 427         /**
 428          * Write the native types with simple compression.
 429          * Best used with  negatives and positives close to 0
 430          * @param input The data.
 431          */
 432 
 433         public void WriteCompUInt16(UInt16 input)
 434         {
 435             var uint16wc = new Byte[2];
 436             uint16wc[B16_1] = (byte) ((Byte) (input >> 8) & (0xff));
 437             uint16wc[B16_0] = (byte) (input & (0xff));
 438 
 439             WriteCompressed(uint16wc, sizeof (UInt16)*8, true);
 440         }
 441 
 442         /**
 443          * Write the native types with simple compression.
 444          * Best used with  negatives and positives close to 0
 445          * @param input The data.
 446          */
 447 
 448         public void WriteCompInt16(Int16 input)
 449         {
 450             var int16wc = new Byte[2];
 451             int16wc[B16_1] = (Byte) ((input >> 8) & (0xff));
 452             int16wc[B16_0] = (Byte) (input & (0xff));
 453 
 454             WriteCompressed(int16wc, sizeof (Int16)*8, false);
 455         }
 456 
 457         /**
 458          * Write the native types with simple compression.
 459          * Best used with  negatives and positives close to 0
 460          * @param input The data.
 461          */
 462 
 463         public void WriteCompUInt32(UInt32 input)
 464         {
 465             var uint32wc = new Byte[4];
 466             uint32wc[B32_3] = (Byte) ((input >> 24) & (0x000000ff));
 467             uint32wc[B32_2] = (Byte) ((input >> 16) & (0x000000ff));
 468             uint32wc[B32_1] = (Byte) ((input >> 8) & (0x000000ff));
 469             uint32wc[B32_0] = (Byte) ((input) & (0x000000ff));
 470 
 471             WriteCompressed(uint32wc, sizeof (UInt32)*8, true);
 472         }
 473 
 474         /**
 475          * Write the native types with simple compression.
 476          * Best used with  negatives and positives close to 0
 477          * @param input The data.
 478          */
 479 
 480         public void WriteCompInt32(int input)
 481         {
 482             var int32wc = new Byte[4];
 483             int32wc[B32_3] = (Byte) ((input >> 24) & (0x000000ff));
 484             int32wc[B32_2] = (Byte) ((input >> 16) & (0x000000ff));
 485             int32wc[B32_1] = (Byte) ((input >> 8) & (0x000000ff));
 486             int32wc[B32_0] = (Byte) ((input) & (0x000000ff));
 487 
 488             WriteCompressed(int32wc, sizeof (int)*8, false);
 489         }
 490 
 491 //#ifdef HAS_INT64
 492         /**
 493          * Write the native types with simple compression.
 494          * Best used with  negatives and positives close to 0
 495          * @param input The data.
 496          */
 497 
 498         public void WriteCompUInt64(UInt64 input)
 499         {
 500             var uint64wc = new Byte[8];
 501             uint64wc[B64_7] = (Byte) ((input >> 56) & 0xff);
 502             uint64wc[B64_6] = (Byte) ((input >> 48) & 0xff);
 503             uint64wc[B64_5] = (Byte) ((input >> 40) & 0xff);
 504             uint64wc[B64_4] = (Byte) ((input >> 32) & 0xff);
 505             uint64wc[B64_3] = (Byte) ((input >> 24) & 0xff);
 506             uint64wc[B64_2] = (Byte) ((input >> 16) & 0xff);
 507             uint64wc[B64_1] = (Byte) ((input >> 8) & 0xff);
 508             uint64wc[B64_0] = (Byte) (input & 0xff);
 509 
 510             WriteCompressed(uint64wc, sizeof (UInt64)*8, true);
 511         }
 512 
 513         /**
 514          * Write the native types with simple compression.
 515          * Best used with  negatives and positives close to 0
 516          * @param input The data.
 517          */
 518 
 519         public void WriteCompInt64(Int64 input)
 520         {
 521             var int64wc = new Byte[8];
 522             int64wc[B64_7] = (Byte) ((input >> 56) & 0xff);
 523             int64wc[B64_6] = (Byte) ((input >> 48) & 0xff);
 524             int64wc[B64_5] = (Byte) ((input >> 40) & 0xff);
 525             int64wc[B64_4] = (Byte) ((input >> 32) & 0xff);
 526             int64wc[B64_3] = (Byte) ((input >> 24) & 0xff);
 527             int64wc[B64_2] = (Byte) ((input >> 16) & 0xff);
 528             int64wc[B64_1] = (Byte) ((input >> 8) & 0xff);
 529             int64wc[B64_0] = (Byte) (input & 0xff);
 530 
 531             WriteCompressed(int64wc, sizeof (Int64)*8, false);
 532         }
 533 
 534 //#endif
 535         /**
 536          * Write the native types with simple compression.
 537          * Best used with  negatives and positives close to 0
 538          * @param input The data.
 539          */
 540 
 541         public void WriteCompFloat(float input)
 542         {
 543             WriteFloat(input);
 544         }
 545 
 546         /**
 547          * Write the native types with simple compression.
 548          * Best used with  negatives and positives close to 0
 549          * @param input The data.
 550          */
 551 
 552         public void WriteCompDouble(double input)
 553         {
 554             WriteDouble(input);
 555         }
 556 
 557         /**
 558          * Read the native types from the front of the buffer
 559          * @param output The readed value. 
 560          * @return true on success false otherwise. The result of a reading 
 561          * can only be wrong in the case we reach the end of the BitStream 
 562          * with some missing bits. 
 563          */
 564 
 565         public bool ReadBool()
 566         {
 567             if (readOffset + 1 > numberOfBitsUsed)
 568                 return false;
 569 
 570             //if (ReadBit()) // Check that bit
 571             if ((data[readOffset >> 3] & (0x80 >> (readOffset++%8))) != 0) // Is it faster to just write it out here?
 572                 return true;
 573 
 574             return false;
 575         }
 576 
 577         /**
 578          * Read the native types from the front of the buffer
 579          * @param output The readed value. 
 580          * @return true on success false otherwise. The result of a reading 
 581          * can only be wrong in the case we reach the end of the BitStream 
 582          * with some missing bits. 
 583          */
 584 
 585         public SByte ReadUInt8()
 586         {
 587             var x = new Byte[sizeof (SByte)];
 588             if (ReadBits(ref x, sizeof (SByte)*8))
 589             {
 590                 return (SByte) BitConverter.ToChar(x, 0);
 591             }
 592             return 0;
 593         }
 594 
 595         /**
 596          * Read the native types from the front of the buffer
 597          * @param output The readed value. 
 598          * @return true on success false otherwise. The result of a reading 
 599          * can only be wrong in the case we reach the end of the BitStream 
 600          * with some missing bits. 
 601          */
 602 
 603         public Byte ReadInt8()
 604         {
 605             var x = new Byte[sizeof (Byte)];
 606             if (ReadBits(ref x, sizeof (Byte)*8))
 607             {
 608                 return (Byte) BitConverter.ToChar(x, 0);
 609                 ;
 610             }
 611             return 0;
 612         }
 613 
 614         /**
 615          * Read the native types from the front of the buffer
 616          * @param output The readed value. 
 617          * @return true on success false otherwise. The result of a reading 
 618          * can only be wrong in the case we reach the end of the BitStream 
 619          * with some missing bits. 
 620          */
 621 
 622         public UInt16 ReadUInt16()
 623         {
 624             var uint16r = new Byte[2];
 625             if (ReadBits(ref uint16r, sizeof (UInt16)*8) != true)
 626                 return 0;
 627             return (ushort) ((uint16r[B16_1] << 8) | uint16r[B16_0]);
 628         }
 629 
 630         /**
 631          * Read the native types from the front of the buffer
 632          * @param output The readed value. 
 633          * @return true on success false otherwise. The result of a reading 
 634          * can only be wrong in the case we reach the end of the BitStream 
 635          * with some missing bits. 
 636          */
 637 
 638         public short ReadInt16()
 639         {
 640             var int16r = new Byte[2];
 641             if (ReadBits(ref int16r, sizeof (short)*8) != true)
 642                 return 0;
 643 
 644             return (short) ((int16r[B16_1] << 8) | int16r[B16_0]);
 645         }
 646 
 647         /**
 648          * Read the native types from the front of the buffer
 649          * @param output The readed value. 
 650          * @return true on success false otherwise. The result of a reading 
 651          * can only be wrong in the case we reach the end of the BitStream 
 652          * with some missing bits. 
 653          */
 654 
 655         public UInt32 ReadUInt32()
 656         {
 657             var uint32r = new Byte[4];
 658             if (ReadBits(ref uint32r, sizeof (UInt32)*8) != true)
 659                 return 0;
 660             return (((UInt32) uint32r[B32_3]) << 24) |
 661                    (((UInt32) uint32r[B32_2]) << 16) |
 662                    (((UInt32) uint32r[B32_1]) << 8) |
 663                    uint32r[B32_0];
 664         }
 665 
 666         /**
 667          * Read the native types from the front of the buffer
 668          * @param output The readed value. 
 669          * @return true on success false otherwise. The result of a reading 
 670          * can only be wrong in the case we reach the end of the BitStream 
 671          * with some missing bits. 
 672          */
 673 
 674         public int ReadInt32()
 675         {
 676             var int32r = new Byte[4];
 677             if (ReadBits(ref int32r, sizeof (int)*8) != true)
 678                 return 0;
 679             return (int32r[B32_3] << 24) |
 680                    (int32r[B32_2] << 16) |
 681                    (int32r[B32_1] << 8) |
 682                    int32r[B32_0];
 683         }
 684 
 685 
 686 //#ifdef HAS_INT64
 687         /**
 688          * Read the native types from the front of the buffer
 689          * @param output The readed value. 
 690          * @return true on success false otherwise. The result of a reading 
 691          * can only be wrong in the case we reach the end of the BitStream 
 692          * with some missing bits. 
 693          */
 694 
 695         public UInt64 ReadUInt64()
 696         {
 697             var uint64r = new Byte[8];
 698             if (ReadBits(ref uint64r, sizeof (UInt64)*8) != true)
 699                 return 0;
 700             return (((UInt64) uint64r[B64_7]) << 56) | (((UInt64) uint64r[B64_6]) << 48) |
 701                    (((UInt64) uint64r[B64_5]) << 40) | (((UInt64) uint64r[B64_4]) << 32) |
 702                    (((UInt64) uint64r[B64_3]) << 24) | (((UInt64) uint64r[B64_2]) << 16) |
 703                    (((UInt64) uint64r[B64_1]) << 8) | uint64r[B64_0];
 704         }
 705 
 706         /**
 707          * Read the native types from the front of the buffer
 708          * @param output The readed value. 
 709          * @return true on success false otherwise. The result of a reading 
 710          * can only be wrong in the case we reach the end of the BitStream 
 711          * with some missing bits. 
 712          */
 713 
 714         public Int64 ReadInt64()
 715         {
 716             var int64r = new Byte[8];
 717             if (ReadBits(ref int64r, sizeof (Int64)*8) != true)
 718                 return 0;
 719             return (Int64) ((((UInt64) int64r[B64_7]) << 56) | (((UInt64) int64r[B64_6]) << 48) |
 720                             (((UInt64) int64r[B64_5]) << 40) | (((UInt64) int64r[B64_4]) << 32) |
 721                             (((UInt64) int64r[B64_3]) << 24) | (((UInt64) int64r[B64_2]) << 16) |
 722                             (((UInt64) int64r[B64_1]) << 8) | int64r[B64_0]);
 723         }
 724 
 725 //#endif
 726         /**
 727          * Read the native types from the front of the buffer
 728          * @param output The readed value. 
 729          * @return true on success false otherwise. The result of a reading 
 730          * can only be wrong in the case we reach the end of the BitStream 
 731          * with some missing bits. 
 732          */
 733 
 734         public float ReadFloat()
 735         {
 736             uint val = ReadUInt32();
 737             return BitConverter.ToSingle(BitConverter.GetBytes(val), 0);
 738         }
 739 
 740         /**
 741          * Read the native types from the front of the buffer
 742          * @param output The readed value. 
 743          * @return true on success false otherwise. The result of a reading 
 744          * can only be wrong in the case we reach the end of the BitStream 
 745          * with some missing bits. 
 746          */
 747 
 748         public double ReadDouble()
 749         {
 750             UInt64 val = ReadUInt64();
 751             return BitConverter.ToDouble(BitConverter.GetBytes(val), 0);
 752         }
 753 
 754         /**
 755          * Read an array or casted stream of byte. The array
 756          * is raw data. There is no automatic conversion on
 757          * big endian arch
 758          * @param output The result byte array. It should be larger than @em numberOfBytes. 
 759          * @param numberOfBytes The number of byte to read
 760          * @return true on success false if there is some missing bytes. 
 761          */
 762 
 763         public bool ReadBytes(ref Byte[] output, int numberOfBytes)
 764         {
 765             return ReadBits(ref output, numberOfBytes*8);
 766         }
 767 
 768         /**
 769                  * Read standard string
 770                  * @return
 771                  */
 772 
 773         public string ReadStr()
 774         {
 775             string strs;
 776             ushort len = ReadUInt16();
 777             if (len > 0)
 778             {
 779                 var str = new Byte[len + 1];
 780                 if (ReadBytes(ref str, len))
 781                 {
 782                     str[len] = 10;
 783                     strs = Encoding.Default.GetString(str);
 784                     return strs;
 785                 }
 786             }
 787             return string.Empty;
 788         }
 789 
 790         /**
 791          * Read the types you wrote with WriteCompressed
 792          * @param output The read value
 793          * @return true on success, false on not enough data to read
 794          */
 795 
 796         public SByte ReadCompUInt8()
 797         {
 798             var uint8rc = new Byte[sizeof (Byte)];
 799 
 800             if (ReadCompressed(ref uint8rc, sizeof (Byte)*8, true))
 801             {
 802                 return (SByte) uint8rc[0];
 803             }
 804             return 0;
 805         }
 806 
 807         /**
 808          * Read the types you wrote with WriteCompressed
 809          * @param output The read value
 810          * @return true on success, false on not enough data to read
 811          */
 812 
 813         public Byte ReadCompInt8()
 814         {
 815             var uint8rc = new Byte[sizeof (Byte)];
 816 
 817             if (ReadCompressed(ref uint8rc, sizeof (Byte)*8, true))
 818             {
 819                 return uint8rc[0];
 820             }
 821             return 0;
 822         }
 823 
 824         /**
 825          * Read the types you wrote with WriteCompressed
 826          * @param output The read value
 827          * @return true on success, false on not enough data to read
 828          */
 829 
 830         public UInt16 ReadCompUInt16()
 831         {
 832             var uint16rc = new Byte[2];
 833             if (ReadCompressed(ref uint16rc, sizeof (UInt16)*8, true) != true)
 834                 return 0;
 835             return (ushort) ((uint16rc[B16_1] << 8) |
 836                              uint16rc[B16_0]);
 837         }
 838 
 839         /**
 840          * Read the types you wrote with WriteCompressed
 841          * @param output The read value
 842          * @return true on success, false on not enough data to read
 843          */
 844 
 845         public short ReadCompInt16()
 846         {
 847             var int16rc = new byte[2];
 848             if (ReadCompressed(ref int16rc, sizeof (short)*8, false) != true) return 0;
 849             return (short) ((int16rc[B16_1] << 8) | int16rc[B16_0]);
 850         }
 851 
 852         /**
 853          * Read the types you wrote with WriteCompressed
 854          * @param output The read value
 855          * @return true on success, false on not enough data to read
 856          */
 857 
 858         public UInt32 ReadCompUInt32()
 859         {
 860             var uint32rc = new Byte[4];
 861             if (ReadCompressed(ref uint32rc, sizeof (UInt32)*8, true) != true)
 862                 return 0;
 863             return (((UInt32) uint32rc[B32_3]) << 24) |
 864                    (((UInt32) uint32rc[B32_2]) << 16) |
 865                    (((UInt32) uint32rc[B32_1]) << 8) |
 866                    uint32rc[B32_0];
 867         }
 868 
 869         /**
 870          * Read the types you wrote with WriteCompressed
 871          * @param output The read value
 872          * @return true on success, false on not enough data to read
 873          */
 874 
 875         public int ReadCompInt32()
 876         {
 877             var int32rc = new Byte[4];
 878             if (ReadCompressed(ref int32rc, sizeof (int)*8, false) != true)
 879                 return 0;
 880             return (int) ((((UInt32) int32rc[B32_3]) << 24) |
 881                           (((UInt32) int32rc[B32_2]) << 16) |
 882                           (((UInt32) int32rc[B32_1]) << 8) |
 883                           int32rc[B32_0]);
 884         }
 885 
 886 //#ifdef HAS_INT64
 887         /**
 888          * Read the types you wrote with WriteCompressed
 889          * @param output The read value
 890          * @return true on success, false on not enough data to read
 891          */
 892 
 893         public UInt64 ReadCompUInt64()
 894         {
 895             var uint64rc = new Byte[8];
 896             if (ReadCompressed(ref uint64rc, sizeof (UInt64)*8, true) != true)
 897                 return 0;
 898             return (((UInt64) uint64rc[B64_7]) << 56) | (((UInt64) uint64rc[B64_6]) << 48) |
 899                    (((UInt64) uint64rc[B64_5]) << 40) | (((UInt64) uint64rc[B64_4]) << 32) |
 900                    (((UInt64) uint64rc[B64_3]) << 24) | (((UInt64) uint64rc[B64_2]) << 16) |
 901                    (((UInt64) uint64rc[B64_1]) << 8) | uint64rc[B64_0];
 902         }
 903 
 904         /**
 905          * Read the types you wrote with WriteCompressed
 906          * @param output The read value
 907          * @return true on success, false on not enough data to read
 908          */
 909 
 910         public Int64 ReadCompInt64()
 911         {
 912             var int64rc = new Byte[8];
 913             if (ReadCompressed(ref int64rc, sizeof (Int64)*8, false) != true)
 914                 return 0;
 915             return (Int64) ((((UInt64) int64rc[B64_7]) << 56) | (((UInt64) int64rc[B64_6]) << 48) |
 916                             (((UInt64) int64rc[B64_5]) << 40) | (((UInt64) int64rc[B64_4]) << 32) |
 917                             (((UInt64) int64rc[B64_3]) << 24) | (((UInt64) int64rc[B64_2]) << 16) |
 918                             (((UInt64) int64rc[B64_1]) << 8) | int64rc[B64_0]);
 919         }
 920 
 921 //#endif
 922         /**
 923          * Read the types you wrote with WriteCompressed
 924          * @param output The read value
 925          * @return true on success, false on not enough data to read
 926          */
 927 
 928         public float ReadCompFloat()
 929         {
 930             return ReadFloat();
 931         }
 932 
 933         /**
 934          * Read the types you wrote with WriteCompressed
 935          * @param output The read value
 936          * @return true on success, false on not enough data to read
 937          */
 938 
 939         public double ReadCompDouble()
 940         {
 941             return ReadDouble();
 942         }
 943 
 944         /**
 945         * Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12 bytes.  Will further compress y or z axis aligned vectors.
 946         * Accurate to 1/32767.5.
 947         * @param x x
 948         * @param y y
 949         * @param z z
 950         */
 951 
 952 
 953         /**
 954          * This is good to call when you are done with the stream to make
 955          * sure you didn't leave any data left over void
 956          */
 957 
 958         public void AssertStreamEmpty()
 959         {
 960             if (readOffset == numberOfBitsUsed)
 961                 throw new Exception();
 962         }
 963 
 964         // * print to the standard output the state of the stream bit by bit 
 965         // */
 966 
 967         //public void PrintBits()
 968         //{
 969 
 970         //}
 971         /// **
 972         /// **
 973         // * Ignore data we don't intend to read
 974         // * @param numberOfBits The number of bits to ignore
 975         // */
 976         public void IgnoreBits(int numberOfBits)
 977         {
 978             readOffset += numberOfBits;
 979         }
 980 
 981         /**
 982          * Move the write pointer to a position on the array.  
 983          * @param offset the offset from the start of the array. 
 984          * @attention 
 985          * Dangerous if you don't know what you are doing!
 986          *
 987          */
 988 
 989         public void SetWriteOffset(int offset)
 990         {
 991             numberOfBitsUsed = offset;
 992         }
 993 
 994         /**
 995          * Returns the length in bits of the stream
 996          */
 997 
 998         public int GetWriteOffset()
 999         {
1000             return numberOfBitsUsed;
1001         }
1002 
1003         /**
1004          * Returns the length in bytes of the stream
1005          */
1006 
1007         public int GetNumberOfBytesUsed()
1008         {
1009             return BITS_TO_BYTES(numberOfBitsUsed);
1010         }
1011 
1012         public int GetNumberOfBytesRead()
1013         {
1014             return BITS_TO_BYTES(readOffset);
1015         }
1016 
1017         /**
1018                  * Move the read pointer to a position on the array.
1019                  * @param offset
1020                  */
1021 
1022         public void SetReadOffset(int offset)
1023         {
1024             readOffset = offset;
1025         }
1026 
1027         public void SetByteReadOffSet(int offset)
1028         {
1029             readOffset = BYTES_TO_BITS(offset);
1030         }
1031 
1032         /**
1033          * Returns the number of bits into the stream that we have read
1034          */
1035 
1036         public int GetReadOffset()
1037         {
1038             return readOffset;
1039         }
1040 
1041 
1042         /**
1043          * Returns the number of bits left in the stream that haven't been read
1044          */
1045 
1046         public int GetNumberOfUnreadBits()
1047         {
1048             return numberOfBitsUsed - readOffset;
1049         }
1050 
1051         /**
1052          * Makes a copy of the internal data for you Data will point to
1053          * the stream. Returns the length in bits of the stream. Partial
1054          * bytes are left aligned 
1055          * @param _data the resulting byte copy of the internal state. 
1056          */
1057 
1058         public int CopyData(Byte[] _data)
1059         {
1060             _data = new Byte[BITS_TO_BYTES(numberOfBitsUsed)];
1061             data.CopyTo(_data, 0);
1062             return numberOfBitsUsed;
1063         }
1064 
1065         /**
1066          * Set the stream to some initial data.  For internal use
1067          * Partial bytes are left aligned
1068          * @param input The data
1069          * @param numberOfBits the number of bits set in the data buffer 
1070          */
1071 
1072         public void SetData(Byte[] input, int numberOfBits)
1073         {
1074             if (numberOfBits <= 0)
1075                 return;
1076             AddBitsAndReallocate(numberOfBits);
1077             input.CopyTo(data, 0);
1078             numberOfBitsUsed = numberOfBits;
1079         }
1080 
1081         /**
1082          * Exposes the internal data.
1083          * Partial bytes are left aligned.
1084          * @return A pointer to the internal state 
1085          */
1086 
1087         public Byte[] GetData()
1088         {
1089             return data;
1090         }
1091 
1092         /**
1093          * Write numberToWrite bits from the input source Right aligned
1094          * data means in the case of a partial byte, the bits are aligned
1095          * from the right (bit 0) rather than the left (as in the normal
1096          * internal representation) You would set this to true when
1097          * writing user data, and false when copying bitstream data, such
1098          * as writing one bitstream to another
1099          * @param input The data 
1100          * @param numberOfBitsToWrite The number of bits to write 
1101          * @param rightAlignedBits if true data will be right aligned 
1102          */
1103 
1104         public void WriteBits(Byte[] input, int numberOfBitsToWrite, bool rightAlignedBits = true)
1105         {
1106             AddBitsAndReallocate(numberOfBitsToWrite);
1107             int offset = 0;
1108             Byte dataByte;
1109             int numberOfBitsUsedMod8;
1110 
1111             numberOfBitsUsedMod8 = numberOfBitsUsed%8;
1112 
1113             // Faster to put the while at the top surprisingly enough
1114             while (numberOfBitsToWrite > 0)
1115                 //do
1116             {
1117                 dataByte = input[offset]; //*( input + offset );
1118 
1119                 if (numberOfBitsToWrite < 8 && rightAlignedBits)
1120                     // 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)
1121                     dataByte <<= 8 - numberOfBitsToWrite;
1122                 // shift left to get the bits on the left, as in our internal representation
1123 
1124                 // Writing to a new byte each time
1125                 if (numberOfBitsUsedMod8 == 0)
1126                     data[numberOfBitsUsed >> 3] = dataByte; //*( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;
1127                 else
1128                 {
1129                     // Copy over the new data.
1130                     data[numberOfBitsUsed >> 3] |= (Byte) (dataByte >> (numberOfBitsUsedMod8));
1131                     //*( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half
1132 
1133                     if (8 - (numberOfBitsUsedMod8) < 8 && 8 - (numberOfBitsUsedMod8) < numberOfBitsToWrite)
1134                         // If we didn't write it all out in the first half (8 - (numberOfBitsUsed%8) is the number we wrote in the first half)
1135                     {
1136                         //*( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary)
1137                         data[(numberOfBitsUsed >> 3) + 1] = (Byte) (dataByte << (8 - (numberOfBitsUsedMod8)));
1138                     }
1139                 }
1140 
1141                 if (numberOfBitsToWrite >= 8)
1142                     numberOfBitsUsed += 8;
1143                 else
1144                     numberOfBitsUsed += numberOfBitsToWrite;
1145 
1146                 numberOfBitsToWrite -= 8;
1147 
1148                 offset++;
1149             }
1150         }
1151 
1152         /**
1153          * Align the bitstream to the byte boundary and then write the
1154          * specified number of bits.  This is faster than WriteBits but
1155          * wastes the bits to do the alignment and requires you to call
1156          * ReadAlignedBits at the corresponding read position.
1157          * @param input The data
1158          * @param numberOfBytesToWrite The size of data. 
1159          */
1160 
1161         public void WriteAlignedBytes(Byte[] input, int numberOfBytesToWrite)
1162         {
1163             AlignWriteToByteBoundary();
1164             // Allocate enough memory to hold everything
1165             AddBitsAndReallocate(numberOfBytesToWrite << 3);
1166 
1167             // Write the data
1168             //memcpy( data + ( numberOfBitsUsed >> 3 ), input, numberOfBytesToWrite );
1169             input.CopyTo(data, (numberOfBitsUsed >> 3));
1170             numberOfBitsUsed += numberOfBytesToWrite << 3;
1171         }
1172 
1173         /**
1174          * Read bits, starting at the next aligned bits. Note that the
1175          * modulus 8 starting offset of the sequence must be the same as
1176          * was used with WriteBits. This will be a problem with packet
1177          * coalescence unless you byte align the coalesced packets.
1178          * @param output The byte array larger than @em numberOfBytesToRead
1179          * @param numberOfBytesToRead The number of byte to read from the internal state 
1180          * @return true if there is enough byte. 
1181          */
1182 
1183         public bool ReadAlignedBytes(out Byte[] output, int numberOfBytesToRead)
1184         {
1185             if (numberOfBytesToRead <= 0)
1186             {
1187                 output = null;
1188                 return false;
1189             }
1190             // Byte align
1191             AlignReadToByteBoundary();
1192             if (readOffset + (numberOfBytesToRead << 3) > numberOfBitsUsed)
1193             {
1194                 output = null;
1195                 return false;
1196             }
1197 
1198             // Write the data
1199             //memcpy( output, data + ( readOffset >> 3 ), numberOfBytesToRead );
1200             output = new byte[] {};
1201             Array.Copy(data, readOffset >> 3, output, 0, numberOfBytesToRead);
1202             readOffset += numberOfBytesToRead << 3;
1203             return true;
1204         }
1205 
1206         /**
1207          * Align the next write and/or read to a byte boundary.  This can
1208          * be used to 'waste' bits to byte align for efficiency reasons It
1209          * can also be used to force coalesced bitstreams to start on byte
1210          * boundaries so so WriteAlignedBits and ReadAlignedBits both
1211          * calculate the same offset when aligning.
1212          */
1213 
1214         public void AlignWriteToByteBoundary()
1215         {
1216             if (numberOfBitsUsed > 0)
1217                 numberOfBitsUsed += 8 - ((numberOfBitsUsed - 1)%8 + 1);
1218         }
1219 
1220         /**
1221          * Align the next write and/or read to a byte boundary.  This can
1222          * be used to 'waste' bits to byte align for efficiency reasons It
1223          * can also be used to force coalesced bitstreams to start on byte
1224          * boundaries so so WriteAlignedBits and ReadAlignedBits both
1225          * calculate the same offset when aligning.
1226          */
1227 
1228         public void AlignReadToByteBoundary()
1229         {
1230             if (readOffset > 0)
1231                 readOffset += 8 - ((readOffset - 1)%8 + 1);
1232         }
1233 
1234         /**
1235          * Read numberOfBitsToRead bits to the output source
1236          * alignBitsToRight should be set to true to convert internal
1237          * bitstream data to userdata It should be false if you used
1238          * WriteBits with rightAlignedBits false
1239          * @param output The resulting bits array 
1240          * @param numberOfBitsToRead The number of bits to read 
1241          * @param alignsBitsToRight if true bits will be right aligned. 
1242          * @return true if there is enough bits to read 
1243          */
1244 
1245         public bool ReadBits(ref Byte[] output, int numberOfBitsToRead, bool alignBitsToRight = true)
1246         {
1247             if (readOffset + numberOfBitsToRead > numberOfBitsUsed)
1248             {
1249                 output = null;
1250                 return false;
1251             }
1252 
1253             int readOffsetMod8;
1254             int offset = 0;
1255             //memset( output, 0, BITS_TO_BYTES( numberOfBitsToRead ) );
1256             readOffsetMod8 = readOffset%8;
1257 
1258             // do
1259             // Faster to put the while at the top surprisingly enough
1260             while (numberOfBitsToRead > 0)
1261             {
1262                 //*( output + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half
1263                 output[offset] |= (Byte) (data[readOffset >> 3] << (readOffsetMod8));
1264                 if (readOffsetMod8 > 0 && numberOfBitsToRead > 8 - (readOffsetMod8))
1265                     // If we have a second half, we didn't read enough bytes in the first half
1266                     //*(output + offset) |= *(data + (readOffset >> 3) + 1) >> (8 - (readOffsetMod8));
1267                     output[offset] |= (Byte) (data[(readOffset >> 3) + 1] >> (8 - (readOffsetMod8)));
1268                 // Second half (overlaps byte boundary)
1269 
1270                 numberOfBitsToRead -= 8;
1271 
1272                 if (numberOfBitsToRead < 0)
1273                     // Reading a partial byte for the last byte, shift right so the data is aligned on the right
1274                 {
1275                     if (alignBitsToRight)
1276                         output[offset] >>= -numberOfBitsToRead;
1277                     //*(output + offset) >>= -numberOfBitsToRead;
1278 
1279                     readOffset += 8 + numberOfBitsToRead;
1280                 }
1281                 else
1282                     readOffset += 8;
1283 
1284                 offset++;
1285             }
1286             return true;
1287         }
1288 
1289         /**
1290          * --- Low level functions --- 
1291          * These are for when you want to deal
1292          * with bits and don't care about type checking 
1293          * Write a 0  
1294          */
1295 
1296         public void Write0()
1297         {
1298             AddBitsAndReallocate(1);
1299 
1300             // New bytes need to be zeroed
1301 
1302             if ((numberOfBitsUsed%8) == 0)
1303                 data[numberOfBitsUsed >> 3] = 0;
1304 
1305             numberOfBitsUsed++;
1306         }
1307 
1308         /**
1309          * --- Low level functions --- 
1310          * These are for when you want to deal
1311          * with bits and don't care about type checking 
1312          * Write a 1 
1313          */
1314 
1315         public void Write1()
1316         {
1317             AddBitsAndReallocate(1);
1318 
1319             int numberOfBitsMod8 = numberOfBitsUsed%8;
1320 
1321             if (numberOfBitsMod8 == 0)
1322                 data[numberOfBitsUsed >> 3] = 0x80;
1323             else
1324                 data[numberOfBitsUsed >> 3] |= (Byte) (0x80 >> (numberOfBitsMod8));
1325             //data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
1326 
1327             numberOfBitsUsed++;
1328         }
1329 
1330         /**
1331          * --- Low level functions --- 
1332          * These are for when you want to deal
1333          * with bits and don't care about type checking 
1334          * Reads 1 bit and returns true if that bit is 1 and false if it is 0
1335          */
1336 
1337         public bool ReadBit()
1338         {
1339             return (data[readOffset >> 3] & (0x80 >> (readOffset++%8))) == 1;
1340         }
1341 
1342         /**
1343          * If we used the constructor version with copy data off, this
1344          * makes sure it is set to on and the data pointed to is copied.
1345          */
1346 
1347         public void AssertCopyData()
1348         {
1349             if (copyData == false)
1350             {
1351                 copyData = true;
1352 
1353                 if (numberOfBitsAllocated > 0)
1354                 {
1355                     var newdata = new Byte[BITS_TO_BYTES(numberOfBitsAllocated)];
1356                     data.CopyTo(newdata, 0);
1357                     data = newdata;
1358                 }
1359                 else
1360                     data = null;
1361             }
1362         }
1363 
1364         /**
1365          * Use this if you pass a pointer copy to the constructor
1366          * (_copyData==false) and want to overallocate to prevent
1367          * reallocation
1368          */
1369 
1370         public void SetNumberOfBitsAllocated(int lengthInBits)
1371         {
1372             numberOfBitsAllocated = lengthInBits;
1373         }
1374 
1375 
1376         /**
1377          * Assume the input source points to a native type, compress and write it.
1378          */
1379 
1380         public void WriteCompressed(Byte[] input, int size, bool unsignedData)
1381         {
1382             int currentByte = (size >> 3) - 1; // PCs
1383 
1384             Byte byteMatch;
1385 
1386             if (unsignedData)
1387             {
1388                 byteMatch = 0;
1389             }
1390 
1391             else
1392             {
1393                 byteMatch = 0xFF;
1394             }
1395 
1396             // Write upper bytes with a single 1
1397             // 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
1398             while (currentByte > 0)
1399             {
1400                 if (input[currentByte] == byteMatch)
1401                     // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted
1402                 {
1403                     bool b = true;
1404                     WriteBool(b);
1405                 }
1406                 else
1407                 {
1408                     // Write the remainder of the data after writing 0
1409                     bool b = false;
1410                     WriteBool(b);
1411 
1412                     WriteBits(input, (currentByte + 1) << 3, true);
1413                     //  currentByte--;
1414 
1415 
1416                     return;
1417                 }
1418 
1419                 currentByte--;
1420             }
1421 
1422             // 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.
1423             if ((unsignedData && (((input[currentByte])) & 0xF0) == 0x00) ||
1424                 (unsignedData == false && (((input[currentByte])) & 0xF0) == 0xF0))
1425             {
1426                 bool b = true;
1427                 WriteBool(b);
1428                 var bs = new byte[4];
1429                 Array.Copy(input, currentByte, bs, 0, 4);
1430                 WriteBits(bs, 4, true);
1431             }
1432 
1433             else
1434             {
1435                 bool b = false;
1436                 WriteBool(b);
1437                 var bs = new byte[9];
1438                 Array.Copy(input, currentByte, bs, 0, 9);
1439                 WriteBits(bs, 8, true);
1440             }
1441         }
1442 
1443         /**
1444          * Assume the input source points to a compressed native type.
1445          * Decompress and read it.
1446          */
1447 
1448         public bool ReadCompressed(ref Byte[] output, int size, bool unsignedData)
1449         {
1450             int currentByte = (size >> 3) - 1;
1451 
1452 
1453             Byte byteMatch, halfByteMatch;
1454 
1455             if (unsignedData)
1456             {
1457                 byteMatch = 0;
1458                 halfByteMatch = 0;
1459             }
1460 
1461             else
1462             {
1463                 byteMatch = 0xFF;
1464                 halfByteMatch = 0xF0;
1465             }
1466 
1467             // Upper bytes are specified with a single 1 if they match byteMatch
1468             // 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
1469             while (currentByte > 0)
1470             {
1471                 // If we read a 1 then the data is byteMatch.
1472 
1473                 bool b = ReadBool();
1474 
1475                 if (b) // Check that bit
1476                 {
1477                     output[currentByte] = byteMatch;
1478                     currentByte--;
1479                 }
1480                 else
1481                 {
1482                     // Read the rest of the bytes
1483 
1484                     if (ReadBits(ref output, (currentByte + 1) << 3) == false)
1485                         return false;
1486 
1487                     return true;
1488                 }
1489             }
1490             return false;
1491         }
1492 
1493         /**
1494          * Reallocates (if necessary) in preparation of writing
1495          * numberOfBitsToWrite 
1496          */
1497 
1498         public void AddBitsAndReallocate(int numberOfBitsToWrite)
1499         {
1500             if (numberOfBitsToWrite <= 0)
1501                 return;
1502 
1503             int newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed;
1504 
1505             if (numberOfBitsToWrite + numberOfBitsUsed > 0 &&
1506                 ((numberOfBitsAllocated - 1) >> 3) < ((newNumberOfBitsAllocated - 1) >> 3))
1507                 // If we need to allocate 1 or more new bytes
1508             {
1509                 // Less memory efficient but saves on news and deletes
1510                 newNumberOfBitsAllocated = (numberOfBitsToWrite + numberOfBitsUsed)*2;
1511 //        int newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated );
1512                 // Use realloc and free so we are more efficient than delete and new for resizing
1513                 int amountToAllocate = BITS_TO_BYTES(newNumberOfBitsAllocated);
1514                 if (data == stackData)
1515                 {
1516                     if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)
1517                     {
1518                         data = new byte[amountToAllocate];
1519 
1520                         // need to copy the stack data over to our new memory area too
1521                         stackData.CopyTo(data, 0);
1522                     }
1523                 }
1524                 else
1525                 {
1526                     data = data.Concat(new Byte[amountToAllocate - data.Length]).ToArray();
1527                     //data = ( unsigned char* ) realloc( data, amountToAllocate );
1528                 }
1529                 //  memset(data+newByteOffset, 0,  ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0
1530             }
1531 
1532             if (newNumberOfBitsAllocated > numberOfBitsAllocated)
1533                 numberOfBitsAllocated = newNumberOfBitsAllocated;
1534         }
1535 
1536         /**
1537          * Number of bits currently used 
1538          */
1539         private int numberOfBitsUsed;
1540         /**
1541          * Number of bits currently allocated 
1542          */
1543 
1544         private
1545             int numberOfBitsAllocated;
1546 
1547         /**
1548          * Current readOffset 
1549          */
1550 
1551         private
1552             int readOffset;
1553 
1554         /**
1555          * array of byte storing the data.  Points to stackData or if is bigger than that then is allocated
1556          */
1557 
1558         private
1559             Byte[] data;
1560 
1561         /**
1562          * true if the internal buffer is copy of the data passed to the
1563          * constructor
1564          */
1565 
1566         private
1567             bool copyData;
1568 
1569         private Byte[] stackData = new Byte[BITSTREAM_STACK_ALLOCATION_SIZE];
1570     }

 

const 
posted @ 2014-10-15 17:15  ishowfun  阅读(666)  评论(0编辑  收藏  举报