首页 > 代码库 > C#版BitStream 1.0

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 static readonly int B16_1 = 0;   6 private static readonly int B16_0 = 1;   7    8 private static readonly int B32_3 = 0;   9 private static readonly int B32_2 = 1;  10 private static readonly int B32_1 = 2;  11 private static readonly int B32_0 = 3;  12   13 private static readonly int B64_7 = 0;  14 private static readonly int B64_6 = 1;  15 private static readonly int B64_5 = 2;  16 private static readonly int B64_4 = 3;  17 private static readonly int B64_3 = 4;  18 private static readonly int B64_2 = 5;  19 private static readonly int B64_1 = 6;  20 private static readonly int B64_0 = 7;  21   22 #else  23 // Default to producing Little-End network streams.  24         private static readonly int B16_1 = 1;  25         private static readonly int B16_0 = 0;  26   27         private static readonly int B32_3 = 3;  28         private static readonly int B32_2 = 2;  29         private static readonly int B32_1 = 1;  30         private static readonly int B32_0 = 0;  31   32         private static readonly int B64_7 = 7;  33         private static readonly int B64_6 = 6;  34         private static readonly int B64_5 = 5;  35         private static readonly int B64_4 = 4;  36         private static readonly int B64_3 = 3;  37         private static readonly int B64_2 = 2;  38         private static readonly int B64_1 = 1;  39         private static readonly int B64_0 = 0;  40 #endif  41         public static readonly 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 = http://www.mamicode.com/( unsigned char* ) malloc( 32 );  72             data =http://www.mamicode.com/ stackData;  73             copyData = http://www.mamicode.com/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 =http://www.mamicode.com/ stackData;  88                 numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE*8;  89             }  90             else  91             {  92                 data = http://www.mamicode.com/new Byte[initialBytesToAllocate];  93                 numberOfBitsAllocated = initialBytesToAllocate << 3;  94             }  95             copyData = http://www.mamicode.com/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 =http://www.mamicode.com/ _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 =http://www.mamicode.com/ stackData; 124                         numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3; 125                     } 126                     else 127                     { 128                         data = http://www.mamicode.com/new Byte[lengthInBytes]; 129                     } 130                     _data.CopyTo(data, 0); 131                 } 132                 else 133                     data = http://www.mamicode.com/null; 134             } 135             else 136             { 137                 data =http://www.mamicode.com/ _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 =http://www.mamicode.com/ _data; 149             copyData = http://www.mamicode.com/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 =http://www.mamicode.com/ _data; 179             copyData = http://www.mamicode.com/false; 180         } 181  182         public void ClearBuffer() 183         { 184             numberOfBitsUsed = 0; 185             readOffset = 0; 186             numberOfBitsAllocated = 0; 187             data = http://www.mamicode.com/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 stream1005          */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 offset1020                  */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 read1034          */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 read1044          */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 to1053          * the stream. Returns the length in bits of the stream. Partial1054          * 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 = http://www.mamicode.com/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 use1067          * Partial bytes are left aligned1068          * @param input The data1069          * @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 aligned1094          * data means in the case of a partial byte, the bits are aligned1095          * from the right (bit 0) rather than the left (as in the normal1096          * internal representation) You would set this to true when1097          * writing user data, and false when copying bitstream data, such1098          * as writing one bitstream to another1099          * @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 enough1114             while (numberOfBitsToWrite > 0)1115                 //do1116             {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 representation1123 1124                 // Writing to a new byte each time1125                 if (numberOfBitsUsedMod8 == 0)1126                     data[numberOfBitsUsed >> 3] = dataByte; //*( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;1127                 else1128                 {1129                     // Copy over the new data.1130                     data[numberOfBitsUsed >> 3] |= (Byte) (dataByte >> (numberOfBitsUsedMod8));1131                     //*( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half1132 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                 else1144                     numberOfBitsUsed += numberOfBitsToWrite;1145 1146                 numberOfBitsToWrite -= 8;1147 1148                 offset++;1149             }1150         }1151 1152         /**1153          * Align the bitstream to the byte boundary and then write the1154          * specified number of bits.  This is faster than WriteBits but1155          * wastes the bits to do the alignment and requires you to call1156          * ReadAlignedBits at the corresponding read position.1157          * @param input The data1158          * @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 everything1165             AddBitsAndReallocate(numberOfBytesToWrite << 3);1166 1167             // Write the data1168             //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 the1175          * modulus 8 starting offset of the sequence must be the same as1176          * was used with WriteBits. This will be a problem with packet1177          * coalescence unless you byte align the coalesced packets.1178          * @param output The byte array larger than @em numberOfBytesToRead1179          * @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 align1191             AlignReadToByteBoundary();1192             if (readOffset + (numberOfBytesToRead << 3) > numberOfBitsUsed)1193             {1194                 output = null;1195                 return false;1196             }1197 1198             // Write the data1199             //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 can1208          * be used to ‘waste‘ bits to byte align for efficiency reasons It1209          * can also be used to force coalesced bitstreams to start on byte1210          * boundaries so so WriteAlignedBits and ReadAlignedBits both1211          * 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 can1222          * be used to ‘waste‘ bits to byte align for efficiency reasons It1223          * can also be used to force coalesced bitstreams to start on byte1224          * boundaries so so WriteAlignedBits and ReadAlignedBits both1225          * 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 source1236          * alignBitsToRight should be set to true to convert internal1237          * bitstream data to userdata It should be false if you used1238          * WriteBits with rightAlignedBits false1239          * @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             // do1259             // Faster to put the while at the top surprisingly enough1260             while (numberOfBitsToRead > 0)1261             {1262                 //*( output + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half1263                 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 half1266                     //*(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 right1274                 {1275                     if (alignBitsToRight)1276                         output[offset] >>= -numberOfBitsToRead;1277                     //*(output + offset) >>= -numberOfBitsToRead;1278 1279                     readOffset += 8 + numberOfBitsToRead;1280                 }1281                 else1282                     readOffset += 8;1283 1284                 offset++;1285             }1286             return true;1287         }1288 1289         /**1290          * --- Low level functions --- 1291          * These are for when you want to deal1292          * 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 zeroed1301 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 deal1311          * 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             else1324                 data[numberOfBitsUsed >> 3] |= (Byte) (0x80 >> (numberOfBitsMod8));1325             //data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 11326 1327             numberOfBitsUsed++;1328         }1329 1330         /**1331          * --- Low level functions --- 1332          * These are for when you want to deal1333          * 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 01335          */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, this1344          * makes sure it is set to on and the data pointed to is copied.1345          */1346 1347         public void AssertCopyData()1348         {1349             if (copyData =http://www.mamicode.com/= false)1350             {1351                 copyData = http://www.mamicode.com/true;1352 1353                 if (numberOfBitsAllocated > 0)1354                 {1355                     var newdata = http://www.mamicode.com/new Byte[BITS_TO_BYTES(numberOfBitsAllocated)];1356                     data.CopyTo(newdata, 0);1357                     data =http://www.mamicode.com/ newdata;1358                 }1359                 else1360                     data = http://www.mamicode.com/null;1361             }1362         }1363 1364         /**1365          * Use this if you pass a pointer copy to the constructor1366          * (_copyData=http://www.mamicode.com/=false) and want to overallocate to prevent>1367          * reallocation1368          */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; // PCs1383 1384             Byte byteMatch;1385 1386             if (unsignedData)1387             {1388                 byteMatch = 0;1389             }1390 1391             else1392             {1393                 byteMatch = 0xFF;1394             }1395 1396             // Write upper bytes with a single 11397             // 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 bytes1398             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 shifted1402                 {1403                     bool b = true;1404                     WriteBool(b);1405                 }1406                 else1407                 {1408                     // Write the remainder of the data after writing 01409                     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 =http://www.mamicode.com/= 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             else1434             {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             else1462             {1463                 byteMatch = 0xFF;1464                 halfByteMatch = 0xF0;1465             }1466 1467             // Upper bytes are specified with a single 1 if they match byteMatch1468             // 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 bytes1469             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 bit1476                 {1477                     output[currentByte] = byteMatch;1478                     currentByte--;1479                 }1480                 else1481                 {1482                     // Read the rest of the bytes1483 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 writing1495          * 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 bytes1508             {1509                 // Less memory efficient but saves on news and deletes1510                 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 resizing1513                 int amountToAllocate = BITS_TO_BYTES(newNumberOfBitsAllocated);1514                 if (data =http://www.mamicode.com/= stackData)1515                 {1516                     if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)1517                     {1518                         data = http://www.mamicode.com/new byte[amountToAllocate];1519 1520                         // need to copy the stack data over to our new memory area too1521                         stackData.CopyTo(data, 0);1522                     }1523                 }1524                 else1525                 {1526                     data = http://www.mamicode.com/data.Concat(new Byte[amountToAllocate - data.Length]).ToArray();1527                     //data = http://www.mamicode.com/( unsigned char* ) realloc( data, amountToAllocate );1528                 }1529                 //  memset(data+newByteOffset, 0,  ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 01530             }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         private1545             int numberOfBitsAllocated;1546 1547         /**1548          * Current readOffset 1549          */1550 1551         private1552             int readOffset;1553 1554         /**1555          * array of byte storing the data.  Points to stackData or if is bigger than that then is allocated1556          */1557 1558         private1559             Byte[] data;1560 1561         /**1562          * true if the internal buffer is copy of the data passed to the1563          * constructor1564          */1565 1566         private1567             bool copyData;1568 1569         private Byte[] stackData = http://www.mamicode.com/new Byte[BITSTREAM_STACK_ALLOCATION_SIZE];1570     }

 

C#版BitStream 1.0