zoukankan      html  css  js  c++  java
  • 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 
  • 相关阅读:
    假如我那时再努力点
    C语言经典算法100例-030-判断一个数是否为回文数
    C语言经典算法100例-029-求一个整数的位数且逆序打印
    C语言经典算法100例-028-五个人问岁数
    Abap-Smartforms中如何去掉开头的中文文本
    C语言经典算法100例-027-用递归逆序输出字符
    逐梦之路充满艰辛
    C语言经典算法100例-026-递归求阶乘
    C语言经典算法100例-025-求1+2!+3!+...+20!的和
    集合类Set、Map
  • 原文地址:https://www.cnblogs.com/ishowfun/p/4026834.html
Copyright © 2011-2022 走看看