Advertisement
Guest User

Untitled

a guest
Jan 14th, 2012
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 93.96 KB | None | 0 0
  1. <pre class="brush: csharp; gutter: false;">using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace BitIntegerTest
  6. {
  7.     public class Packet
  8.     {
  9.         private List&lt;byte&gt; buffer;
  10.         private int bitIndex = 0;
  11.         private int maxBitIndex = 0;
  12.         private int previousBitIndex = -1;
  13.  
  14.         /// &lt;summary&gt;
  15.         /// Expands the buffer size appending bytes so that the write functions don't overflow.
  16.         /// Records the furthest write in the maxBitIndex
  17.         /// &lt;/summary&gt;
  18.         /// &lt;param name="bits"&gt;The number of bits to allocate and record.&lt;/param&gt;
  19.         private void ExpandBuffer(int bits)
  20.         {
  21.             if (bits &lt; 1) throw new ArgumentOutOfRangeException("bits must be greater than 0");
  22.             while ((bitIndex + bits + 7) / 8 &gt; buffer.Count) buffer.Add(new byte());
  23.             maxBitIndex = Math.Max(maxBitIndex, bitIndex + bits);
  24.         }
  25.  
  26.         /// &lt;summary&gt;
  27.         /// Constructor.
  28.         /// &lt;/summary&gt;
  29.         public Packet()
  30.         {
  31.             buffer = new List&lt;byte&gt;();
  32.         }
  33.  
  34.         /// &lt;summary&gt;
  35.         /// Fills the buffer with the requested bytes to work with.
  36.         /// &lt;/summary&gt;
  37.         /// &lt;param name="buffer"&gt;The bytes to load into the buffer&lt;/param&gt;
  38.         public Packet(byte[] buffer)
  39.         {
  40.             this.buffer = new List&lt;byte&gt;(buffer);
  41.         }
  42.  
  43.         /// &lt;summary&gt;
  44.         /// Fills the buffer with the requested bytes to work with.
  45.         /// &lt;/summary&gt;
  46.         /// &lt;param name="buffer"&gt;The bytes to load into the buffer&lt;/param&gt;
  47.         /// &lt;param name="maxBitIndex"&gt;The maximum bit index&lt;/param&gt;
  48.         public Packet(byte[] buffer, int maxBitIndex)
  49.         {
  50.             this.buffer = new List&lt;byte&gt;(buffer);
  51.             this.maxBitIndex = maxBitIndex;
  52.         }
  53.  
  54.         /// &lt;summary&gt;
  55.         /// Gets or sets the bit index.
  56.         /// &lt;/summary&gt;
  57.         public int BitIndex
  58.         {
  59.             get
  60.             {
  61.                 return bitIndex;
  62.             }
  63.             set
  64.             {
  65.                 if (value &lt; 0 || (value + 7) / 8 &gt; buffer.Count) throw new ArgumentOutOfRangeException("Unable to set the bit index outside of the buffer size.");
  66.                 bitIndex = value;
  67.             }
  68.         }
  69.  
  70.         /// &lt;summary&gt;
  71.         /// Sets the bit index to the start of the data section.
  72.         /// &lt;/summary&gt;
  73.         public void ResetBitIndex()
  74.         {
  75.             if (maxBitIndex &lt; 32) throw new InvalidOperationException("Unable to set the bit index over the max bit index.");
  76.             bitIndex = 32;
  77.         }
  78.  
  79.         /// &lt;summary&gt;
  80.         /// Gets or Sets the max bit index.
  81.         /// &lt;/summary&gt;
  82.         public int MaxBitIndex
  83.         {
  84.             set
  85.             {
  86.                 if (value &lt; 0 || (value + 7) / 8 &gt; buffer.Count) throw new ArgumentOutOfRangeException("Unable to set the max bit index outside of the buffer size.");
  87.                 maxBitIndex = value;
  88.             }
  89.         }
  90.  
  91.         public int BufferLength
  92.         {
  93.             get
  94.             {
  95.                 return buffer.Count;
  96.             }
  97.         }
  98.  
  99.         /// &lt;summary&gt;
  100.         /// Returns the buffer as an array of bytes.
  101.         /// &lt;/summary&gt;
  102.         public byte[] Buffer
  103.         {
  104.             get
  105.             {
  106.                 return buffer.ToArray();
  107.             }
  108.         }
  109.  
  110.         public int HeaderSize
  111.         {
  112.             get
  113.             {
  114.                 return 4;
  115.             }
  116.         }
  117.  
  118.         /// &lt;summary&gt;
  119.         /// Returns a string of 0s and 1s representing the bits in the buffer. Good for debugging.
  120.         /// Places a space between nibbles and two spaces between bytes.
  121.         /// &lt;/summary&gt;
  122.         /// &lt;returns&gt;&lt;/returns&gt;
  123.         public string Trace()
  124.         {
  125.             string s = string.Empty;
  126.             for (int copyBits = 0; copyBits &lt; buffer.Count * 8; ++copyBits)
  127.             {
  128.                 s += ((buffer[copyBits / 8] &gt;&gt; (7 - copyBits % 8)) &amp; 0x1) == 0 ? "0" : "1";
  129.                 if ((copyBits + 1) % 4 == 0 &amp;&amp; copyBits != 0)
  130.                 {
  131.                     s += " ";
  132.                     if ((copyBits + 1) % 8 == 0)
  133.                     {
  134.                         s += " ";
  135.                     }
  136.                 }
  137.             }
  138.             return s;
  139.         }
  140.  
  141.         /// &lt;summary&gt;
  142.         /// Rounds the bitIndex up to a byte.
  143.         /// &lt;/summary&gt;
  144.         public void RoundUpToByte()
  145.         {
  146.             bitIndex = (bitIndex + 7) / 8 * 8;
  147.         }
  148.  
  149.         /// &lt;summary&gt;
  150.         ///
  151.         /// &lt;/summary&gt;
  152.         /// &lt;returns&gt;true if 32 bits exist in the buffer&lt;/returns&gt;
  153.         public bool HasHeader()
  154.         {
  155.             return buffer.Count &gt;= 4;
  156.         }
  157.  
  158.         /// &lt;summary&gt;
  159.         /// Reads the length in bits stored in the header.
  160.         /// &lt;/summary&gt;
  161.         public void ReadHeader()
  162.         {
  163.             int oldBitIndex = bitIndex;
  164.             bitIndex = 0;
  165.             maxBitIndex = 32;
  166.             uint length;
  167.             if (ReadUInt32(out length))
  168.             {
  169.                 if (length &gt; int.MaxValue)
  170.                 {
  171.                     maxBitIndex = int.MaxValue;
  172.                 }
  173.                 else
  174.                 {
  175.                     maxBitIndex = (int)length;
  176.                 }
  177.             }
  178.             bitIndex = oldBitIndex;
  179.         }
  180.  
  181.         /// &lt;summary&gt;
  182.         /// Writes a begin packet header of 32 bits.
  183.         /// &lt;/summary&gt;
  184.         internal void BeginPacket()
  185.         {
  186.             WriteUInt32(0);
  187.         }
  188.  
  189.         /// &lt;summary&gt;
  190.         /// Writes maxBitIndex to the packet header created with BeginPacket.
  191.         /// &lt;/summary&gt;
  192.         internal void EndPacket()
  193.         {
  194.             int oldBitIndex = bitIndex;
  195.             bitIndex = 0;
  196.             WriteUInt32((uint)maxBitIndex);
  197.             bitIndex = oldBitIndex;
  198.         }
  199.  
  200.         /// &lt;summary&gt;
  201.         /// Appends a byte directly to the end of the buffer.
  202.         /// &lt;/summary&gt;
  203.         /// &lt;param name="value"&gt;&lt;/param&gt;
  204.         public void AppendByte(byte value)
  205.         {
  206.             buffer.Add(value);
  207.             bitIndex += 8;
  208.         }
  209.  
  210.         /// &lt;summary&gt;
  211.         /// Determines if the packet has read in all the data defined by the maxBitIndex.
  212.         /// &lt;/summary&gt;
  213.         /// &lt;returns&gt;&lt;/returns&gt;
  214.         public bool HasData()
  215.         {
  216.             return bitIndex &gt;= maxBitIndex;
  217.         }
  218.  
  219.         /// &lt;summary&gt;
  220.         /// Rollback as if the last read didn't occur.
  221.         /// &lt;/summary&gt;
  222.         public void RollbackRead()
  223.         {
  224.             if (previousBitIndex == -1) throw new InvalidOperationException("A read method must be called successfully first");
  225.             bitIndex = previousBitIndex;
  226.             previousBitIndex = -1;
  227.         }
  228.  
  229.         public void ClearBits(int bits)
  230.         {
  231.             if (bitIndex % 8 + bits - 1 &lt; 8)
  232.             {
  233.                 byte mask = 0xFF;
  234.                 for (int bitItr = bitIndex; bitItr &lt; bitIndex + bits; ++bitItr)
  235.                 {
  236.                     mask ^= (byte)(1 &lt;&lt; 7 - bitItr % 8);
  237.                 }
  238.                 buffer[bitIndex / 8] &amp;= mask;
  239.             }
  240.             else if (bitIndex % 8 + bits - 1 &lt; 16)
  241.             {
  242.                 int offset = 8 - bitIndex % 8;
  243.                 buffer[bitIndex / 8] &gt;&gt;= offset;
  244.                 buffer[bitIndex / 8] &lt;&lt;= offset;
  245.                 offset = bits - (8 - bitIndex % 8);
  246.                 buffer[bitIndex / 8 + 1] &lt;&lt;= offset;
  247.                 buffer[bitIndex / 8 + 1] &gt;&gt;= offset;
  248.             }
  249.             else
  250.             {
  251.                 int offset = 8 - bitIndex % 8;
  252.                 buffer[bitIndex / 8] &gt;&gt;= offset;
  253.                 buffer[bitIndex / 8] &lt;&lt;= offset;
  254.                 for (int bitItr = bitIndex + 8 - bitIndex % 8; bitItr &lt; (bitIndex + bits - 1) / 8 * 8; bitItr += 8)
  255.                 {
  256.                     buffer[bitItr / 8] = 0;
  257.                 }
  258.                 offset = bitIndex + bits - (bitIndex + bits - 1) / 8 * 8;
  259.                 buffer[(bitIndex + bits - 1) / 8] &lt;&lt;= offset;
  260.                 buffer[(bitIndex + bits - 1) / 8] &gt;&gt;= offset;
  261.             }
  262.         }
  263.  
  264.         // Write Methods
  265.  
  266.         /// &lt;summary&gt;
  267.         /// Writes an Event ID.
  268.         /// &lt;/summary&gt;
  269.         /// &lt;param name="value"&gt;The event ID normally stored in an enumeration.&lt;/param&gt;
  270.         public void WriteEventID(uint value)
  271.         {
  272.             WriteVariableWidthUInt(value, 6);
  273.         }
  274.  
  275.         /// &lt;summary&gt;
  276.         /// Writes a single bit either 0 or 1 into the buffer.
  277.         /// &lt;/summary&gt;
  278.         /// &lt;param name="value"&gt;The boolean value to write.&lt;/param&gt;
  279.         public void WriteBool(bool value)
  280.         {
  281.             ExpandBuffer(1);
  282.             if (value) buffer[bitIndex / 8] |= (byte)(1 &lt;&lt; (7 - bitIndex % 8));
  283.             ++bitIndex;
  284.         }
  285.  
  286.         /// &lt;summary&gt;
  287.         /// Writes an 8 bit unsigned byte into the buffer.
  288.         /// &lt;/summary&gt;
  289.         /// &lt;param name="value"&gt;The unsigned byte value to write.&lt;/param&gt;
  290.         public void WriteByte(byte value)
  291.         {
  292.             ExpandBuffer(8);
  293.             int offset = bitIndex % 8;
  294.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; offset);
  295.             if (offset != 0)
  296.             {
  297.                 buffer[bitIndex / 8 + 1] |= (byte)(value &lt;&lt; 8 - offset);
  298.             }
  299.             bitIndex += 8;
  300.         }
  301.  
  302.         /// &lt;summary&gt;
  303.         /// Writes an 8 bit signed byte into the buffer.
  304.         /// &lt;/summary&gt;
  305.         /// &lt;param name="value"&gt;The signed byte value to write.&lt;/param&gt;
  306.         public void WriteSByte(sbyte value)
  307.         {
  308.             WriteByte((byte)value);
  309.         }
  310.  
  311.         /// &lt;summary&gt;
  312.         /// Writes a 16 bit unsigned short into the buffer.
  313.         /// &lt;/summary&gt;
  314.         /// &lt;param name="value"&gt;The unsigned short value to write.&lt;/param&gt;
  315.         public void WriteUInt16(ushort value)
  316.         {
  317.             ExpandBuffer(16);
  318.             int offset = bitIndex % 8;
  319.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; 8 + offset);
  320.             buffer[bitIndex / 8 + 1] |= (byte)(value &gt;&gt; offset);
  321.             if (offset != 0)
  322.             {
  323.                 buffer[bitIndex / 8 + 2] |= (byte)(value &lt;&lt; 8 - offset);
  324.             }
  325.             bitIndex += 16;
  326.         }
  327.  
  328.         /// &lt;summary&gt;
  329.         /// Writes a 16 bit signed short into the buffer.
  330.         /// &lt;/summary&gt;
  331.         /// &lt;param name="value"&gt;The signed short value to write.&lt;/param&gt;
  332.         public void WriteInt16(short value)
  333.         {
  334.             WriteUInt16((ushort)value);
  335.         }
  336.  
  337.         /// &lt;summary&gt;
  338.         /// Writes a 32 bit unsigned integer into the buffer.
  339.         /// &lt;/summary&gt;
  340.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  341.         public void WriteUInt32(uint value)
  342.         {
  343.             ExpandBuffer(32);
  344.             int offset = bitIndex % 8;
  345.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; 24 + offset);
  346.             buffer[bitIndex / 8 + 1] |= (byte)(value &gt;&gt; 16 + offset);
  347.             buffer[bitIndex / 8 + 2] |= (byte)(value &gt;&gt; 8 + offset);
  348.             buffer[bitIndex / 8 + 3] |= (byte)(value &gt;&gt; offset);
  349.             if (offset != 0)
  350.             {
  351.                 buffer[bitIndex / 8 + 4] |= (byte)(value &lt;&lt; 8 - offset);
  352.             }
  353.             bitIndex += 32;
  354.         }
  355.  
  356.         /// &lt;summary&gt;
  357.         /// Writes a 32 bit signed integer into the buffer.
  358.         /// &lt;/summary&gt;
  359.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  360.         public void WriteInt32(int value)
  361.         {
  362.             WriteUInt32((uint)value);
  363.         }
  364.  
  365.         /// &lt;summary&gt;
  366.         /// Writes a 64 bit unsigned integer into the buffer.
  367.         /// &lt;/summary&gt;
  368.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  369.         public void WriteUInt64(ulong value)
  370.         {
  371.             ExpandBuffer(64);
  372.             int offset = bitIndex % 8;
  373.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; 56 + offset);
  374.             buffer[bitIndex / 8 + 1] |= (byte)(value &gt;&gt; 48 + offset);
  375.             buffer[bitIndex / 8 + 2] |= (byte)(value &gt;&gt; 32 + offset);
  376.             buffer[bitIndex / 8 + 3] |= (byte)(value &gt;&gt; 24 + offset);
  377.             buffer[bitIndex / 8 + 4] |= (byte)(value &gt;&gt; 16 + offset);
  378.             buffer[bitIndex / 8 + 5] |= (byte)(value &gt;&gt; 8 + offset);
  379.             buffer[bitIndex / 8 + 6] |= (byte)(value &gt;&gt; offset);
  380.             if (offset != 0)
  381.             {
  382.                 buffer[bitIndex / 8 + 7] |= (byte)(value &lt;&lt; 8 - offset);
  383.             }
  384.             bitIndex += 64;
  385.         }
  386.  
  387.         /// &lt;summary&gt;
  388.         /// Writes a 64 bit signed integer into the buffer.
  389.         /// &lt;/summary&gt;
  390.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  391.         public void WriteInt64(long value)
  392.         {
  393.             WriteUInt64((ulong)value);
  394.         }
  395.  
  396.         /// &lt;summary&gt;
  397.         /// Writes an n bit unsigned integer into the buffer.
  398.         /// &lt;/summary&gt;
  399.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  400.         /// &lt;param name="bits"&gt;The number of bits to use.&lt;/param&gt;
  401.         public void WriteUInt(uint value, int bits)
  402.         {
  403.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  404.             if (bits != 32 &amp;&amp; value &gt; (0x1 &lt;&lt; bits) - 1) throw new ArgumentOutOfRangeException("Value does not fit into " + bits.ToString() + " bits.");
  405.  
  406.             ExpandBuffer(bits);
  407.  
  408.             value &lt;&lt;= 32 - bits;
  409.  
  410.             int offset = bitIndex % 8;
  411.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; 24 + offset);
  412.             if (offset + bits &gt; 8)
  413.             {
  414.                 buffer[bitIndex / 8 + 1] |= (byte)(value &gt;&gt; 16 + offset);
  415.                 if (offset + bits &gt; 16)
  416.                 {
  417.                     buffer[bitIndex / 8 + 2] |= (byte)(value &gt;&gt; 8 + offset);
  418.                     if (offset + bits &gt; 24)
  419.                     {
  420.                         buffer[bitIndex / 8 + 3] |= (byte)(value &gt;&gt; offset);
  421.                         if (offset + bits &gt; 32)
  422.                         {
  423.                             buffer[bitIndex / 8 + 4] |= (byte)(value &lt;&lt; 8 - offset);
  424.                         }
  425.                     }
  426.                 }
  427.             }
  428.             bitIndex += bits;
  429.         }
  430.  
  431.         /// &lt;summary&gt;
  432.         /// Writes an n bit unsigned integer into the buffer.
  433.         /// &lt;/summary&gt;
  434.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  435.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  436.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  437.         public void WriteUInt(uint value, uint min, uint max)
  438.         {
  439.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  440.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  441.  
  442.             uint valueBase = max - min + 1;
  443.             // Log2
  444.             var bits = 32;
  445.             if (valueBase != 0)
  446.             {
  447.                 int left = 0;
  448.                 int right = 32;
  449.                 for (int i = 0; i &lt; 5; ++i)
  450.                 {
  451.                     if (valueBase &gt;&gt; (32 - (left + right) / 2) != 0)
  452.                     {
  453.                         // Left
  454.                         right = (left + right) / 2;
  455.                     }
  456.                     else
  457.                     {
  458.                         // Right
  459.                         left = (left + right) / 2;
  460.                     }
  461.                 }
  462.                 bits = 32 - left;
  463.             }
  464.             WriteUInt(value - min, bits);
  465.         }
  466.  
  467.         /// &lt;summary&gt;
  468.         /// Writes an n bit unsigned integer into the buffer.
  469.         /// &lt;/summary&gt;
  470.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  471.         /// &lt;param name="bits"&gt;The number of bits to use.&lt;/param&gt;
  472.         public void WriteUInt(ulong value, int bits)
  473.         {
  474.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  475.             if (bits != 64 &amp;&amp; value &gt; ((ulong)0x1 &lt;&lt; bits) - 1) throw new ArgumentOutOfRangeException("Value does not fit into " + bits.ToString() + " bits.");
  476.  
  477.             ExpandBuffer(bits);
  478.  
  479.             value &lt;&lt;= 64 - bits;
  480.  
  481.             int offset = bitIndex % 8;
  482.             buffer[bitIndex / 8] |= (byte)(value &gt;&gt; 56 + offset);
  483.             if (offset + bits &gt; 8)
  484.             {
  485.                 buffer[bitIndex / 8 + 1] |= (byte)(value &gt;&gt; 48 + offset);
  486.                 if (offset + bits &gt; 16)
  487.                 {
  488.                     buffer[bitIndex / 8 + 2] |= (byte)(value &gt;&gt; 40 + offset);
  489.                     if (offset + bits &gt; 24)
  490.                     {
  491.                         buffer[bitIndex / 8 + 3] |= (byte)(value &gt;&gt; 32 + offset);
  492.                         if (offset + bits &gt; 32)
  493.                         {
  494.                             buffer[bitIndex / 8 + 4] |= (byte)(value &gt;&gt; 24 + offset);
  495.                             if (offset + bits &gt; 40)
  496.                             {
  497.                                 buffer[bitIndex / 8 + 5] |= (byte)(value &gt;&gt; 16 + offset);
  498.                                 if (offset + bits &gt; 48)
  499.                                 {
  500.                                     buffer[bitIndex / 8 + 6] |= (byte)(value &gt;&gt; 8 + offset);
  501.                                     if (offset + bits &gt; 56)
  502.                                     {
  503.                                         buffer[bitIndex / 8 + 7] |= (byte)(value &gt;&gt; offset);
  504.                                         if (offset + bits &gt; 64)
  505.                                         {
  506.                                             buffer[bitIndex / 8 + 8] |= (byte)(value &lt;&lt; 8 - offset);
  507.                                         }
  508.                                     }
  509.                                 }
  510.                             }
  511.                         }
  512.                     }
  513.                 }
  514.             }
  515.             bitIndex += bits;
  516.         }
  517.  
  518.         /// &lt;summary&gt;
  519.         /// Writes an n bit unsigned integer into the buffer.
  520.         /// &lt;/summary&gt;
  521.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  522.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  523.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  524.         public void WriteUInt(ulong value, ulong min, ulong max)
  525.         {
  526.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  527.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  528.  
  529.             ulong valueBase = max - min + 1;
  530.             // Log2
  531.             var bits = 64;
  532.             if (valueBase != 0)
  533.             {
  534.                 int left = 0;
  535.                 int right = 64;
  536.                 for (int i = 0; i &lt; 6; ++i)
  537.                 {
  538.                     if (valueBase &gt;&gt; (64 - (left + right) / 2) != 0)
  539.                     {
  540.                         // Left
  541.                         right = (left + right) / 2;
  542.                     }
  543.                     else
  544.                     {
  545.                         // Right
  546.                         left = (left + right) / 2;
  547.                     }
  548.                 }
  549.                 bits = 64 - left;
  550.             }
  551.             WriteUInt(value - min, bits);
  552.         }
  553.  
  554.         /// &lt;summary&gt;
  555.         /// Writes an n bit signed integer into the buffer.
  556.         /// &lt;/summary&gt;
  557.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  558.         /// &lt;param name="bits"&gt;The number of bits to use.&lt;/param&gt;
  559.         public void WriteInt(int value, int bits)
  560.         {
  561.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  562.             if (bits != 32 &amp;&amp; (value &lt; -(0x1 &lt;&lt; (bits - 1)) || value &gt;= 0x1 &lt;&lt; (bits - 1))) throw new ArgumentOutOfRangeException("Value does not fit into " + bits.ToString() + " bits.");
  563.  
  564.             ExpandBuffer(bits);
  565.  
  566.             value &lt;&lt;= 32 - bits;
  567.             uint uvalue = (uint)value;
  568.  
  569.             int offset = bitIndex % 8;
  570.             buffer[bitIndex / 8] |= (byte)(uvalue &gt;&gt; 24 + offset);
  571.             if (offset + bits &gt; 8)
  572.             {
  573.                 buffer[bitIndex / 8 + 1] |= (byte)(uvalue &gt;&gt; 16 + offset);
  574.                 if (offset + bits &gt; 16)
  575.                 {
  576.                     buffer[bitIndex / 8 + 2] |= (byte)(uvalue &gt;&gt; 8 + offset);
  577.                     if (offset + bits &gt; 24)
  578.                     {
  579.                         buffer[bitIndex / 8 + 3] |= (byte)(uvalue &gt;&gt; offset);
  580.                         if (offset + bits &gt; 32)
  581.                         {
  582.                             buffer[bitIndex / 8 + 4] |= (byte)(uvalue &lt;&lt; 8 - offset);
  583.                         }
  584.                     }
  585.                 }
  586.             }
  587.             bitIndex += bits;
  588.         }
  589.  
  590.         /// &lt;summary&gt;
  591.         /// Writes an n bit signed integer into the buffer.
  592.         /// &lt;/summary&gt;
  593.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  594.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  595.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  596.         public void WriteInt(int value, int min, int max)
  597.         {
  598.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  599.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  600.  
  601.             uint valueBase = (uint)(max - min + 1);
  602.             // Log2
  603.             var bits = 32;
  604.             if (valueBase != 0)
  605.             {
  606.                 int left = 0;
  607.                 int right = 32;
  608.                 for (int i = 0; i &lt; 5; ++i)
  609.                 {
  610.                     if (valueBase &gt;&gt; (32 - (left + right) / 2) != 0)
  611.                     {
  612.                         // Left
  613.                         right = (left + right) / 2;
  614.                     }
  615.                     else
  616.                     {
  617.                         // Right
  618.                         left = (left + right) / 2;
  619.                     }
  620.                 }
  621.                 bits = 32 - left;
  622.             }
  623.             WriteInt(value - min, bits);
  624.         }
  625.  
  626.         /// &lt;summary&gt;
  627.         /// Writes an n bit signed integer into the buffer.
  628.         /// &lt;/summary&gt;
  629.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  630.         /// &lt;param name="bits"&gt;The number of bits to use.&lt;/param&gt;
  631.         public void WriteInt(long value, int bits)
  632.         {
  633.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  634.             if (bits != 64 &amp;&amp; (value &lt; -((long)0x1 &lt;&lt; (bits - 1)) || value &gt;= (long)0x1 &lt;&lt; (bits - 1))) throw new ArgumentOutOfRangeException("Value does not fit into " + bits.ToString() + " bits.");
  635.  
  636.             ExpandBuffer(bits);
  637.  
  638.             value &lt;&lt;= 64 - bits;
  639.             ulong uvalue = (ulong)value;
  640.  
  641.             int offset = bitIndex % 8;
  642.             buffer[bitIndex / 8] |= (byte)(uvalue &gt;&gt; 56 + offset);
  643.             if (offset + bits &gt; 8)
  644.             {
  645.                 buffer[bitIndex / 8 + 1] |= (byte)(uvalue &gt;&gt; 48 + offset);
  646.                 if (offset + bits &gt; 16)
  647.                 {
  648.                     buffer[bitIndex / 8 + 2] |= (byte)(uvalue &gt;&gt; 40 + offset);
  649.                     if (offset + bits &gt; 24)
  650.                     {
  651.                         buffer[bitIndex / 8 + 3] |= (byte)(uvalue &gt;&gt; 32 + offset);
  652.                         if (offset + bits &gt; 32)
  653.                         {
  654.                             buffer[bitIndex / 8 + 4] |= (byte)(uvalue &gt;&gt; 24 + offset);
  655.                             if (offset + bits &gt; 40)
  656.                             {
  657.                                 buffer[bitIndex / 8 + 5] |= (byte)(uvalue &gt;&gt; 16 + offset);
  658.                                 if (offset + bits &gt; 48)
  659.                                 {
  660.                                     buffer[bitIndex / 8 + 6] |= (byte)(uvalue &gt;&gt; 8 + offset);
  661.                                     if (offset + bits &gt; 56)
  662.                                     {
  663.                                         buffer[bitIndex / 8 + 7] |= (byte)(uvalue &gt;&gt; offset);
  664.                                         if (offset + bits &gt; 64)
  665.                                         {
  666.                                             buffer[bitIndex / 8 + 8] |= (byte)(uvalue &lt;&lt; 8 - offset);
  667.                                         }
  668.                                     }
  669.                                 }
  670.                             }
  671.                         }
  672.                     }
  673.                 }
  674.             }
  675.             bitIndex += bits;
  676.         }
  677.  
  678.         /// &lt;summary&gt;
  679.         /// Writes an n bit signed integer into the buffer.
  680.         /// &lt;/summary&gt;
  681.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  682.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  683.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  684.         public void WriteInt(long value, long min, long max)
  685.         {
  686.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  687.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  688.  
  689.             ulong valueBase = (ulong)(max - min + 1);
  690.             // Log2
  691.             var bits = 64;
  692.             if (valueBase != 0)
  693.             {
  694.                 int left = 0;
  695.                 int right = 64;
  696.                 for (int i = 0; i &lt; 6; ++i)
  697.                 {
  698.                     if (valueBase &gt;&gt; (64 - (left + right) / 2) != 0)
  699.                     {
  700.                         // Left
  701.                         right = (left + right) / 2;
  702.                     }
  703.                     else
  704.                     {
  705.                         // Right
  706.                         left = (left + right) / 2;
  707.                     }
  708.                 }
  709.                 bits = 64 - left;
  710.             }
  711.             WriteInt(value - min, bits);
  712.         }
  713.  
  714.         /// &lt;summary&gt;
  715.         /// Writes a 32 bit single into the buffer.
  716.         /// &lt;/summary&gt;
  717.         /// &lt;param name="value"&gt;The single value to write.&lt;/param&gt;
  718.         public void WriteSingle(float value)
  719.         {
  720.             WriteUInt32(BitConverter.ToUInt32(BitConverter.GetBytes(value), 0));
  721.         }
  722.  
  723.         /// &lt;summary&gt;
  724.         /// Writes a 64 bit double into the buffer.
  725.         /// &lt;/summary&gt;
  726.         /// &lt;param name="value"&gt;The double value to write.&lt;/param&gt;
  727.         public void WriteDouble(double value)
  728.         {
  729.             byte[] bytes = BitConverter.GetBytes(value);
  730.             WriteUInt32(BitConverter.ToUInt32(bytes, 0));
  731.             WriteUInt32(BitConverter.ToUInt32(bytes, 4));
  732.         }
  733.  
  734.         /// &lt;summary&gt;
  735.         /// Writes an integer using a variable width encoding of bits. Choose a bits value that represents the number of bits to hold the average value.
  736.         /// &lt;/summary&gt;
  737.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  738.         /// &lt;param name="bits"&gt;The number of bits to use for the sequence.&lt;/param&gt;
  739.         public void WriteVariableWidthUInt(uint value, int bits = 4)
  740.         {
  741.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  742.             int shift = bits;
  743.             // Stop when our value can fit inside
  744.             for (; shift &lt; 32 &amp;&amp; value &gt;= (0x1 &lt;&lt; shift); shift += bits)
  745.             {
  746.                 WriteBool(true); // Write a 1 for a continuation bit signifying one more interval is needed
  747.             }
  748.             if (shift &lt; 32)
  749.             {
  750.                 WriteBool(false); // Write a 0 for a continuation bit signifying the end
  751.             }
  752.             WriteUInt(value, shift &gt;= 32 ? 32 : shift);
  753.         }
  754.  
  755.         /// &lt;summary&gt;
  756.         /// Writes an integer using a variable width encoding of bits. Choose a bits value that represents the number of bits to hold the average value.
  757.         /// &lt;/summary&gt;
  758.         /// &lt;param name="value"&gt;The unsigned integer value to write.&lt;/param&gt;
  759.         /// &lt;param name="bits"&gt;The number of bits to use for the sequence.&lt;/param&gt;
  760.         public void WriteVariableWidthUInt(ulong value, int bits = 4)
  761.         {
  762.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  763.             int shift = bits;
  764.             // Stop when our value can fit inside
  765.             for (; shift &lt; 64 &amp;&amp; value &gt;= (ulong)(0x1 &lt;&lt; shift); shift += bits)
  766.             {
  767.                 WriteBool(true); // Write a 1 for a continuation bit signifying one more interval is needed
  768.             }
  769.             if (shift &lt; 64)
  770.             {
  771.                 WriteBool(false); // Write a 0 for a continuation bit signifying the end
  772.             }
  773.             WriteUInt(value, shift &gt;= 64 ? 64 : shift);
  774.         }
  775.  
  776.         /// &lt;summary&gt;
  777.         /// Writes an integer using a variable length of bits. Choose a bits value that represents the number of bits to hold the average value.
  778.         /// &lt;/summary&gt;
  779.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  780.         /// &lt;param name="bits"&gt;The number of bits to use for the sequence.&lt;/param&gt;
  781.         public void WriteVariableWidthInt(int value, int bits = 4)
  782.         {
  783.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  784.             int shift = bits;
  785.             // Stop when our value can fit inside
  786.             for (; shift &lt; 32 &amp;&amp; (value &lt; -(0x1 &lt;&lt; (shift - 1)) || value &gt;= 0x1 &lt;&lt; (shift - 1)); shift += bits)
  787.             {
  788.                 WriteBool(true); // Write a 1 for a continuation bit signifying one more interval is needed
  789.             }
  790.             if (shift &lt; 32)
  791.             {
  792.                 WriteBool(false); // Write a 0 for a continuation bit signifying the end
  793.             }
  794.             WriteInt(value, shift &gt;= 32 ? 32 : shift);
  795.         }
  796.  
  797.         /// &lt;summary&gt;
  798.         /// Writes an integer using a variable length of bits. Choose a bits value that represents the number of bits to hold the average value.
  799.         /// &lt;/summary&gt;
  800.         /// &lt;param name="value"&gt;The signed integer value to write.&lt;/param&gt;
  801.         /// &lt;param name="bits"&gt;The number of bits to use for the sequence.&lt;/param&gt;
  802.         public void WriteVariableWidthInt(long value, int bits = 4)
  803.         {
  804.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  805.             int shift = bits;
  806.             // Stop when our value can fit inside
  807.             for (; shift &lt; 64 &amp;&amp; (value &lt; -(0x1 &lt;&lt; (shift - 1)) || value &gt;= 0x1 &lt;&lt; (shift - 1)); shift += bits)
  808.             {
  809.                 WriteBool(true); // Write a 1 for a continuation bit signifying one more interval is needed
  810.             }
  811.             if (shift &lt; 64)
  812.             {
  813.                 WriteBool(false); // Write a 0 for a continuation bit signifying the end
  814.             }
  815.             WriteInt(value, shift &gt;= 64 ? 64 : shift);
  816.         }
  817.  
  818.         /// &lt;summary&gt;
  819.         /// Writes an array of unsigned integers in a given range defining a base.
  820.         /// &lt;/summary&gt;
  821.         /// &lt;param name="value"&gt;The array of unsigned integers to write.&lt;/param&gt;
  822.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  823.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  824.         public void WriteArrayUInt32(uint[] value, int min, int max)
  825.         {
  826.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  827.             ulong valueBase = (ulong)(max - min + 1);
  828.             var sum = new List&lt;ulong&gt;();
  829.             var valueBasePow = new List&lt;ulong&gt;();
  830.             valueBasePow.Add(1);
  831.             for (var i = 0; i &lt; value.Length; ++i)
  832.             {
  833.                 // sum += arrayBasePow * array[i];
  834.                 ulong multiplyCarry = 0;
  835.                 ulong addCarry = 0;
  836.                 for (var j = 0; j &lt; valueBasePow.Count || multiplyCarry != 0 || j &lt; sum.Count || addCarry != 0; ++j)
  837.                 {
  838.                     if (j &gt;= sum.Count)
  839.                     {
  840.                         sum.Add(0);
  841.                     }
  842.  
  843.                     ulong temp = 0;
  844.                     ulong product = 0;
  845.                     if (j &lt; valueBasePow.Count)
  846.                     {
  847.                         product = (ulong)(value[i] - min) * valueBasePow[j];
  848.                     }
  849.                     temp += product + multiplyCarry;
  850.                     multiplyCarry = temp &gt;&gt; 32;
  851.                     temp &amp;= 0xFFFFFFFF;
  852.  
  853.                     sum[j] += temp + addCarry;
  854.                     addCarry = sum[j] &gt;&gt; 32;
  855.                     sum[j] &amp;= 0xFFFFFFFF;
  856.                 }
  857.                 // arrayBasePow *= arrayBase;
  858.                 multiplyCarry = 0;
  859.                 for (var j = 0; j &lt; valueBasePow.Count || multiplyCarry != 0; ++j)
  860.                 {
  861.                     if (j &gt;= valueBasePow.Count)
  862.                     {
  863.                         valueBasePow.Add(0);
  864.                     }
  865.                     ulong product = 0;
  866.                     if (j &lt; valueBasePow.Count)
  867.                     {
  868.                         product = valueBase * valueBasePow[j];
  869.                     }
  870.                     valueBasePow[j] = product + multiplyCarry;
  871.                     multiplyCarry = valueBasePow[j] &gt;&gt; 32;
  872.                     valueBasePow[j] &amp;= 0xFFFFFFFF;
  873.                 }
  874.             }
  875.  
  876.             for (var i = sum.Count - 1; i &gt; 0 &amp;&amp; sum[i] == 0; --i)
  877.             {
  878.                 sum.RemoveAt(sum.Count - 1);
  879.             }
  880.  
  881.             // Log2
  882.             int numberOfBits = 0;
  883.             if (!(valueBasePow.Count == 1 &amp;&amp; valueBasePow[0] == 0))
  884.             {
  885.                 int left = 0;
  886.                 int right = 32;
  887.                 for (int i = 0; i &lt; 5; ++i)
  888.                 {
  889.                     if (valueBasePow[valueBasePow.Count - 1] &gt;&gt; (32 - (left + right) / 2) != 0)
  890.                     {
  891.                         // Left
  892.                         right = (left + right) / 2;
  893.                     }
  894.                     else
  895.                     {
  896.                         // Right
  897.                         left = (left + right) / 2;
  898.                     }
  899.                 }
  900.                 numberOfBits = (valueBasePow.Count - 1) * 32 + (32 - left);
  901.             }
  902.  
  903.             for (int copyBits = 0; copyBits &lt; numberOfBits; copyBits += 32)
  904.             {
  905.                 WriteUInt((uint)sum[copyBits / 32], numberOfBits - copyBits &gt; 32 ? 32 : numberOfBits - copyBits);
  906.             }
  907.         }
  908.  
  909.         /// &lt;summary&gt;
  910.         /// Writes an array of signed integers in a given range defining a base.
  911.         /// &lt;/summary&gt;
  912.         /// &lt;param name="value"&gt;The array of signed integers to write.&lt;/param&gt;
  913.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  914.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  915.         public void WriteArrayInt32(int[] value, int min, int max)
  916.         {
  917.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  918.             var uValue = new uint[value.Length];
  919.             for (var i = 0; i &lt; value.Length; ++i)
  920.             {
  921.                 uValue[i] = (uint)(value[i] - min);
  922.             }
  923.             WriteArrayUInt32(uValue, 0, max - min);
  924.         }
  925.  
  926.         /// &lt;summary&gt;
  927.         /// Writes an array of singles in a given range converted to a given integral base.
  928.         /// Creates a value for the ratio: value / (valueBase - 1) in relationship to value / (max - min).
  929.         /// &lt;/summary&gt;
  930.         /// &lt;param name="value"&gt;The array of singles to write.&lt;/param&gt;
  931.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  932.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  933.         /// &lt;param name="valueBase"&gt;The base to convert the singles to.&lt;/param&gt;
  934.         public void WriteArraySingle(float[] value, float min, float max, int valueBase)
  935.         {
  936.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  937.             var uValue = new uint[value.Length];
  938.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  939.             {
  940.                 for (var i = 0; i &lt; value.Length; ++i)
  941.                 {
  942.                     uValue[i] = value[i] == 0 ? 0 : (uint)Math.Round((value[i] - min) / (max - min) * (valueBase - 2)) + 1;
  943.                 }
  944.             }
  945.             else
  946.             {
  947.                 for (var i = 0; i &lt; value.Length; ++i)
  948.                 {
  949.                     uValue[i] = (uint)Math.Round((value[i] - min) / (max - min) * (valueBase - 1));
  950.                 }
  951.             }
  952.             WriteArrayUInt32(uValue, 0, valueBase - 1);
  953.         }
  954.  
  955.         /// &lt;summary&gt;
  956.         /// Writes an array of doubles in a given range converted to a given integral base.
  957.         /// Creates a value for the ratio: value / (valueBase - 1) in relationship to value / (max - min).
  958.         /// &lt;/summary&gt;
  959.         /// &lt;param name="value"&gt;The array of doubles to write.&lt;/param&gt;
  960.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  961.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  962.         /// &lt;param name="valueBase"&gt;The base to convert the doubles to.&lt;/param&gt;
  963.         public void WriteArrayDouble(double[] value, double min, double max, int valueBase)
  964.         {
  965.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  966.             var uValue = new uint[value.Length];
  967.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  968.             {
  969.                 for (var i = 0; i &lt; value.Length; ++i)
  970.                 {
  971.                     uValue[i] = value[i] == 0 ? 0 : (uint)Math.Round((value[i] - min) / (max - min) * (valueBase - 2)) + 1;
  972.                 }
  973.             }
  974.             else
  975.             {
  976.                 for (var i = 0; i &lt; value.Length; ++i)
  977.                 {
  978.                     uValue[i] = (uint)Math.Round((value[i] - min) / (max - min) * (valueBase - 1));
  979.                 }
  980.             }
  981.             WriteArrayUInt32(uValue, 0, valueBase - 1);
  982.         }
  983.  
  984.         /// &lt;summary&gt;
  985.         /// Creates a value for the ratio: value / (2 ^ bitResolution - 1) in relationship to value / (max - min).
  986.         /// This allows a floating point to have a resolution.
  987.         /// &lt;/summary&gt;
  988.         /// &lt;param name="value"&gt;The floating point value in the range.&lt;/param&gt;
  989.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  990.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  991.         /// &lt;param name="bitResolution"&gt;The number of bits to use for the ratio.&lt;/param&gt;
  992.         public void WriteCustomResolutionSingle(float value, float min, float max, int bitResolution)
  993.         {
  994.             if (bitResolution &lt; 1 || bitResolution &gt; 31) throw new ArgumentOutOfRangeException("bitResolution must be in the range (0, 32).");
  995.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  996.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  997.             uint uValue;
  998.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  999.             {
  1000.                 uValue = value == 0 ? 0 : (uint)Math.Round((value - min) / (max - min) * (float)((0x1 &lt;&lt; bitResolution) - 2)) + 1;
  1001.             }
  1002.             else
  1003.             {
  1004.                 uValue = (uint)Math.Round((value - min) / (max - min) * (float)((0x1 &lt;&lt; bitResolution) - 1));
  1005.             }
  1006.             WriteUInt(uValue, bitResolution);
  1007.         }
  1008.  
  1009.         /// &lt;summary&gt;
  1010.         /// Creates a value for the ratio: value / (2 ^ bitResolution - 1) in relationship to value / (max - min).
  1011.         /// This allows a floating point to have a resolution.
  1012.         /// &lt;/summary&gt;
  1013.         /// &lt;param name="value"&gt;The double value in the range.&lt;/param&gt;
  1014.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1015.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1016.         /// &lt;param name="bitResolution"&gt;The number of bits to use for the ratio.&lt;/param&gt;
  1017.         public void WriteCustomResolutionDouble(double value, double min, double max, int bitResolution)
  1018.         {
  1019.             if (bitResolution &lt; 1 || bitResolution &gt; 31) throw new ArgumentOutOfRangeException("bitResolution must be in the range (0, 32).");
  1020.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1021.             if (value &lt; min || value &gt; max) throw new ArgumentOutOfRangeException("The value must be on the interval [min, max]");
  1022.             uint uValue;
  1023.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  1024.             {
  1025.                 uValue = value == 0 ? 0 : (uint)Math.Round((value - min) / (max - min) * (double)((0x1 &lt;&lt; bitResolution) - 2)) + 1;
  1026.             }
  1027.             else
  1028.             {
  1029.                 uValue = (uint)Math.Round((value - min) / (max - min) * (double)((0x1 &lt;&lt; bitResolution) - 1));
  1030.             }
  1031.             WriteUInt(uValue, bitResolution);
  1032.         }
  1033.  
  1034.         /// &lt;summary&gt;
  1035.         /// Writes the length of the string using WriteVariableWidthUInt and then writes a boolean, true for unicode, false for ascii.
  1036.         /// ASCII uses a compression step using either 6 or 7 bits per character.
  1037.         /// &lt;/summary&gt;
  1038.         /// &lt;param name="value"&gt;The string value to write.&lt;/param&gt;
  1039.         /// &lt;param name="bits"&gt;The number of bits for the length written using an unsigned variable-width integer.&lt;/param&gt;
  1040.         public void WriteString(string value, int bits = 4)
  1041.         {
  1042.             if (bits &lt; 1 || bits &gt; 31) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32).");
  1043.  
  1044.             var asciiBytes = Encoding.ASCII.GetBytes(value);
  1045.             uint size = (uint)asciiBytes.Length;
  1046.             WriteVariableWidthUInt(size, bits);
  1047.             foreach (byte asciiByte in asciiBytes)
  1048.             {
  1049.                 WriteByte(asciiByte);
  1050.             }
  1051.         }
  1052.  
  1053.         /// &lt;summary&gt;
  1054.         /// Appends a binary packet to the buffer.
  1055.         /// &lt;/summary&gt;
  1056.         /// &lt;param name="value"&gt;The binary packet to write.&lt;/param&gt;
  1057.         public void WriteBinaryPacket(Packet value)
  1058.         {
  1059.             int oldBitIndex = value.bitIndex;
  1060.             value.bitIndex = 0;
  1061.             int valueMaxBitIndex = value.maxBitIndex;
  1062.             WriteVariableWidthUInt((uint)valueMaxBitIndex);
  1063.             for (int copyBits = 0; copyBits &lt; valueMaxBitIndex; copyBits += 32)
  1064.             {
  1065.                 uint uValue;
  1066.                 value.ReadUInt(out uValue, valueMaxBitIndex - copyBits &gt; 32 ? 32 : valueMaxBitIndex - copyBits);
  1067.                 WriteUInt(uValue, valueMaxBitIndex - copyBits &gt; 32 ? 32 : valueMaxBitIndex - copyBits);
  1068.             }
  1069.             bitIndex += (int)valueMaxBitIndex;
  1070.             value.bitIndex = oldBitIndex;
  1071.         }
  1072.  
  1073.         //READ METHODS
  1074.  
  1075.         /// &lt;summary&gt;
  1076.         /// Reads an Event ID.
  1077.         /// &lt;/summary&gt;
  1078.         /// &lt;param name="value"&gt;The event ID normally stored in an enumeration.&lt;/param&gt;
  1079.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1080.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1081.         public bool ReadEventID(out uint value, bool nestedRead = false)
  1082.         {
  1083.             return ReadVariableWidthUInt(out value, 6);
  1084.         }
  1085.  
  1086.         /// &lt;summary&gt;
  1087.         /// Reads one bit from the buffer.
  1088.         /// &lt;/summary&gt;
  1089.         /// &lt;param name="value"&gt;Boolean.&lt;/param&gt;
  1090.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1091.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1092.         public bool ReadBool(out bool value, bool nestedRead = false)
  1093.         {
  1094.             if (!nestedRead) previousBitIndex = bitIndex;
  1095.             value = false;
  1096.             if ((bitIndex + 1 + 7) / 8 &gt; buffer.Count)
  1097.             {
  1098.                 return false;
  1099.             }
  1100.             value = ((buffer[bitIndex / 8] &gt;&gt; (7 - bitIndex % 8)) &amp; 0x1) == 1;
  1101.             ++bitIndex;
  1102.             return true;
  1103.         }
  1104.  
  1105.         /// &lt;summary&gt;
  1106.         /// Reads an 8 bits unsigned byte from the buffer.
  1107.         /// &lt;/summary&gt;
  1108.         /// &lt;param name="value"&gt;Unsigned Byte.&lt;/param&gt;
  1109.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1110.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1111.         public bool ReadByte(out byte value, bool nestedRead = false)
  1112.         {
  1113.             if (!nestedRead) previousBitIndex = bitIndex;
  1114.             value = 0;
  1115.             if ((bitIndex + 8 + 7) / 8 &gt; buffer.Count)
  1116.             {
  1117.                 return false;
  1118.             }
  1119.             int offset = bitIndex % 8;
  1120.             value |= (byte)(buffer[bitIndex / 8] &lt;&lt; offset);
  1121.             if (offset != 0)
  1122.             {
  1123.                 value |= (byte)(buffer[bitIndex / 8 + 1] &gt;&gt; 8 - offset);
  1124.             }
  1125.             bitIndex += 8;
  1126.             return true;
  1127.         }
  1128.  
  1129.         /// &lt;summary&gt;
  1130.         /// Reads an 8 bits signed byte from the buffer.
  1131.         /// &lt;/summary&gt;
  1132.         /// &lt;param name="value"&gt;Signed Byte.&lt;/param&gt;
  1133.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1134.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1135.         public bool ReadSByte(out sbyte value, bool nestedRead = false)
  1136.         {
  1137.             if (!nestedRead) previousBitIndex = bitIndex;
  1138.             value = 0;
  1139.             if ((bitIndex + 8 + 7) / 8 &gt; buffer.Count)
  1140.             {
  1141.                 return false;
  1142.             }
  1143.             int offset = bitIndex % 8;
  1144.             value |= (sbyte)(buffer[bitIndex / 8] &lt;&lt; offset);
  1145.             if (offset != 0)
  1146.             {
  1147.                 value |= (sbyte)(buffer[bitIndex / 8 + 1] &gt;&gt; 8 - offset);
  1148.             }
  1149.             bitIndex += 8;
  1150.             return true;
  1151.         }
  1152.  
  1153.         /// &lt;summary&gt;
  1154.         /// Reads a 16 bit unsigned short from the buffer.
  1155.         /// &lt;/summary&gt;
  1156.         /// &lt;param name="value"&gt;Unsigned Short.&lt;/param&gt;
  1157.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1158.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1159.         public bool ReadUInt16(out ushort value, bool nestedRead = false)
  1160.         {
  1161.             if (!nestedRead) previousBitIndex = bitIndex;
  1162.             value = 0;
  1163.             if ((bitIndex + 16 + 7) / 8 &gt; buffer.Count)
  1164.             {
  1165.                 return false;
  1166.             }
  1167.             int offset = bitIndex % 8;
  1168.             value |= (ushort)(buffer[bitIndex / 8] &lt;&lt; 8 + offset);
  1169.             value |= (ushort)(buffer[bitIndex / 8 + 1] &lt;&lt; offset);
  1170.             if (offset != 0)
  1171.             {
  1172.                 value |= (ushort)(buffer[bitIndex / 8 + 2] &gt;&gt; 8 - offset);
  1173.             }
  1174.             bitIndex += 16;
  1175.             return true;
  1176.         }
  1177.  
  1178.         /// &lt;summary&gt;
  1179.         /// Reads a 16 bit signed short from the buffer.
  1180.         /// &lt;/summary&gt;
  1181.         /// &lt;param name="value"&gt;Signed Short.&lt;/param&gt;
  1182.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1183.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1184.         public bool ReadInt16(out short value, bool nestedRead = false)
  1185.         {
  1186.             if (!nestedRead) previousBitIndex = bitIndex;
  1187.             value = 0;
  1188.             if ((bitIndex + 16 + 7) / 8 &gt; buffer.Count)
  1189.             {
  1190.                 return false;
  1191.             }
  1192.             int offset = bitIndex % 8;
  1193.             value |= (short)(buffer[bitIndex / 8] &lt;&lt; 8 + offset);
  1194.             value |= (short)(buffer[bitIndex / 8 + 1] &lt;&lt; offset);
  1195.             if (offset != 0)
  1196.             {
  1197.                 value |= (short)(buffer[bitIndex / 8 + 2] &gt;&gt; 8 - offset);
  1198.             }
  1199.             bitIndex += 16;
  1200.             return true;
  1201.         }
  1202.  
  1203.         /// &lt;summary&gt;
  1204.         /// Reads a 32 bit unsigned integer from the buffer.
  1205.         /// &lt;/summary&gt;
  1206.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1207.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1208.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1209.         public bool ReadUInt32(out uint value, bool nestedRead = false)
  1210.         {
  1211.             if (!nestedRead) previousBitIndex = bitIndex;
  1212.             value = 0;
  1213.             if ((bitIndex + 32 + 7) / 8 &gt; buffer.Count)
  1214.             {
  1215.                 return false;
  1216.             }
  1217.             int offset = bitIndex % 8;
  1218.             value |= (uint)(buffer[bitIndex / 8] &lt;&lt; 24 + offset);
  1219.             value |= (uint)(buffer[bitIndex / 8 + 1] &lt;&lt; 16 + offset);
  1220.             value |= (uint)(buffer[bitIndex / 8 + 2] &lt;&lt; 8 + offset);
  1221.             value |= (uint)(buffer[bitIndex / 8 + 3] &lt;&lt; offset);
  1222.             if (offset != 0)
  1223.             {
  1224.                 value |= (uint)(buffer[bitIndex / 8 + 4] &gt;&gt; 8 - offset);
  1225.             }
  1226.             bitIndex += 32;
  1227.             return true;
  1228.         }
  1229.  
  1230.         /// &lt;summary&gt;
  1231.         /// Reads a 32 bit signed integer from the buffer.
  1232.         /// &lt;/summary&gt;
  1233.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1234.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1235.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1236.         public bool ReadInt32(out int value, bool nestedRead = false)
  1237.         {
  1238.             if (!nestedRead) previousBitIndex = bitIndex;
  1239.             value = 0;
  1240.             if ((bitIndex + 32 + 7) / 8 &gt; buffer.Count)
  1241.             {
  1242.                 return false;
  1243.             }
  1244.             int offset = bitIndex % 8;
  1245.             value |= (int)(buffer[bitIndex / 8] &lt;&lt; 24 + offset);
  1246.             value |= (int)(buffer[bitIndex / 8 + 1] &lt;&lt; 16 + offset);
  1247.             value |= (int)(buffer[bitIndex / 8 + 2] &lt;&lt; 8 + offset);
  1248.             value |= (int)(buffer[bitIndex / 8 + 3] &lt;&lt; offset);
  1249.             if (offset != 0)
  1250.             {
  1251.                 value |= (int)(buffer[bitIndex / 8 + 4] &gt;&gt; 8 - offset);
  1252.             }
  1253.             bitIndex += 32;
  1254.             return true;
  1255.         }
  1256.  
  1257.         /// &lt;summary&gt;
  1258.         /// Reads a 64 bit unsigned integer from the buffer.
  1259.         /// &lt;/summary&gt;
  1260.         /// &lt;param name="value"&gt;Unsigned Long.&lt;/param&gt;
  1261.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1262.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1263.         public bool ReadUInt64(out ulong value, bool nestedRead = false)
  1264.         {
  1265.             if (!nestedRead) previousBitIndex = bitIndex;
  1266.             value = 0;
  1267.             if ((bitIndex + 64 + 7) / 8 &gt; buffer.Count)
  1268.             {
  1269.                 return false;
  1270.             }
  1271.             int offset = bitIndex % 8;
  1272.             value |= (ulong)(buffer[bitIndex / 8]) &lt;&lt; 56 + offset;
  1273.             value |= (ulong)(buffer[bitIndex / 8 + 1]) &lt;&lt; 48 + offset;
  1274.             value |= (ulong)(buffer[bitIndex / 8 + 2]) &lt;&lt; 40 + offset;
  1275.             value |= (ulong)(buffer[bitIndex / 8 + 3]) &lt;&lt; 32 + offset;
  1276.             value |= (ulong)(buffer[bitIndex / 8 + 4]) &lt;&lt; 24 + offset;
  1277.             value |= (ulong)(buffer[bitIndex / 8 + 5]) &lt;&lt; 16 + offset;
  1278.             value |= (ulong)(buffer[bitIndex / 8 + 6]) &lt;&lt; 8 + offset;
  1279.             value |= (ulong)(buffer[bitIndex / 8 + 7]) &lt;&lt; offset;
  1280.             if (offset != 0)
  1281.             {
  1282.                 value |= (ulong)(buffer[bitIndex / 8 + 8]) &gt;&gt; 8 - offset;
  1283.             }
  1284.             bitIndex += 64;
  1285.             return true;
  1286.         }
  1287.  
  1288.         /// &lt;summary&gt;
  1289.         /// Reads a 64 bit signed integer from the buffer.
  1290.         /// &lt;/summary&gt;
  1291.         /// &lt;param name="value"&gt;Signed Long.&lt;/param&gt;
  1292.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1293.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1294.         public bool ReadInt64(out long value, bool nestedRead = false)
  1295.         {
  1296.             if (!nestedRead) previousBitIndex = bitIndex;
  1297.             value = 0;
  1298.             if ((bitIndex + 64 + 7) / 8 &gt; buffer.Count)
  1299.             {
  1300.                 return false;
  1301.             }
  1302.             int offset = bitIndex % 8;
  1303.             value |= (long)(buffer[bitIndex / 8]) &lt;&lt; 56 + offset;
  1304.             value |= (long)(buffer[bitIndex / 8 + 1]) &lt;&lt; 48 + offset;
  1305.             value |= (long)(buffer[bitIndex / 8 + 2]) &lt;&lt; 40 + offset;
  1306.             value |= (long)(buffer[bitIndex / 8 + 3]) &lt;&lt; 32 + offset;
  1307.             value |= (long)(buffer[bitIndex / 8 + 4]) &lt;&lt; 24 + offset;
  1308.             value |= (long)(buffer[bitIndex / 8 + 5]) &lt;&lt; 16 + offset;
  1309.             value |= (long)(buffer[bitIndex / 8 + 6]) &lt;&lt; 8 + offset;
  1310.             value |= (long)(buffer[bitIndex / 8 + 7]) &lt;&lt; offset;
  1311.             if (offset != 0)
  1312.             {
  1313.                 value |= (long)(buffer[bitIndex / 8 + 8]) &gt;&gt; 8 - offset;
  1314.             }
  1315.             bitIndex += 64;
  1316.             return true;
  1317.         }
  1318.  
  1319.         /// &lt;summary&gt;
  1320.         /// Reads an n bit unsigned integer from the buffer.
  1321.         /// &lt;/summary&gt;
  1322.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1323.         /// &lt;param name="bits"&gt;The number of bits used to write.&lt;/param&gt;
  1324.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1325.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1326.         public bool ReadUInt(out uint value, int bits, bool nestedRead = false)
  1327.         {
  1328.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  1329.  
  1330.             if (!nestedRead) previousBitIndex = bitIndex;
  1331.             value = 0;
  1332.             if ((bitIndex + bits + 7) / 8 &gt; buffer.Count)
  1333.             {
  1334.                 return false;
  1335.             }
  1336.  
  1337.             int offset = bitIndex % 8;
  1338.             value = (uint)buffer[bitIndex / 8] &lt;&lt; 24 + offset;
  1339.             if (offset + bits &gt; 8)
  1340.             {
  1341.                 value |= (uint)buffer[bitIndex / 8 + 1] &lt;&lt; 16 + offset;
  1342.                 if (offset + bits &gt; 16)
  1343.                 {
  1344.                     value |= (uint)buffer[bitIndex / 8 + 2] &lt;&lt; 8 + offset;
  1345.                     if (offset + bits &gt; 24)
  1346.                     {
  1347.                         value |= (uint)buffer[bitIndex / 8 + 3] &lt;&lt; offset;
  1348.                         if (offset + bits &gt; 32)
  1349.                         {
  1350.                             value |= (uint)buffer[bitIndex / 8 + 4] &gt;&gt; 8 - offset;
  1351.                         }
  1352.                     }
  1353.                 }
  1354.             }
  1355.  
  1356.             value &gt;&gt;= 32 - bits;
  1357.             bitIndex += bits;
  1358.             return true;
  1359.         }
  1360.  
  1361.         /// &lt;summary&gt;
  1362.         /// Reads an n bit unsigned integer from the buffer.
  1363.         /// &lt;/summary&gt;
  1364.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1365.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1366.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1367.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1368.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1369.         public bool ReadUInt(out uint value, uint min, uint max, bool nestedRead = false)
  1370.         {
  1371.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1372.  
  1373.             if (!nestedRead) previousBitIndex = bitIndex;
  1374.             uint valueBase = max - min + 1;
  1375.             // Log2
  1376.             var bits = 32;
  1377.             if (valueBase != 0)
  1378.             {
  1379.                 int left = 0;
  1380.                 int right = 32;
  1381.                 for (int i = 0; i &lt; 5; ++i)
  1382.                 {
  1383.                     if (valueBase &gt;&gt; (32 - (left + right) / 2) != 0)
  1384.                     {
  1385.                         // Left
  1386.                         right = (left + right) / 2;
  1387.                     }
  1388.                     else
  1389.                     {
  1390.                         // Right
  1391.                         left = (left + right) / 2;
  1392.                     }
  1393.                 }
  1394.                 bits = 32 - left;
  1395.             }
  1396.             if (!ReadUInt(out value, bits, true)) return false;
  1397.             value += min;
  1398.             return true;
  1399.         }
  1400.  
  1401.         /// &lt;summary&gt;
  1402.         /// Reads an n bit unsigned integer from the buffer.
  1403.         /// &lt;/summary&gt;
  1404.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1405.         /// &lt;param name="bits"&gt;The number of bits used to write.&lt;/param&gt;
  1406.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1407.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1408.         public bool ReadUInt(out ulong value, int bits, bool nestedRead = false)
  1409.         {
  1410.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  1411.  
  1412.             if (!nestedRead) previousBitIndex = bitIndex;
  1413.             value = 0;
  1414.             if ((bitIndex + bits + 7) / 8 &gt; buffer.Count)
  1415.             {
  1416.                 return false;
  1417.             }
  1418.  
  1419.             int offset = bitIndex % 8;
  1420.             value = (ulong)buffer[bitIndex / 8] &lt;&lt; 56 + offset;
  1421.             if (offset + bits &gt; 8)
  1422.             {
  1423.                 value |= (ulong)buffer[bitIndex / 8 + 1] &lt;&lt; 48 + offset;
  1424.                 if (offset + bits &gt; 16)
  1425.                 {
  1426.                     value |= (ulong)buffer[bitIndex / 8 + 2] &lt;&lt; 40 + offset;
  1427.                     if (offset + bits &gt; 24)
  1428.                     {
  1429.                         value |= (ulong)buffer[bitIndex / 8 + 3] &lt;&lt; 32 + offset;
  1430.                         if (offset + bits &gt; 32)
  1431.                         {
  1432.                             value |= (ulong)buffer[bitIndex / 8 + 4] &lt;&lt; 24 + offset;
  1433.                             if (offset + bits &gt; 40)
  1434.                             {
  1435.                                 value |= (ulong)buffer[bitIndex / 8 + 5] &lt;&lt; 16 + offset;
  1436.                                 if (offset + bits &gt; 48)
  1437.                                 {
  1438.                                     value |= (ulong)buffer[bitIndex / 8 + 6] &lt;&lt; 8 + offset;
  1439.                                     if (offset + bits &gt; 56)
  1440.                                     {
  1441.                                         value |= (ulong)buffer[bitIndex / 8 + 7] &lt;&lt; offset;
  1442.                                         if (offset + bits &gt; 64)
  1443.                                         {
  1444.                                             value |= (ulong)buffer[bitIndex / 8 + 8] &gt;&gt; 8 - offset;
  1445.                                         }
  1446.                                     }
  1447.                                 }
  1448.                             }
  1449.                         }
  1450.                     }
  1451.                 }
  1452.             }
  1453.  
  1454.             value &gt;&gt;= 64 - bits;
  1455.             bitIndex += bits;
  1456.             return true;
  1457.         }
  1458.  
  1459.         /// &lt;summary&gt;
  1460.         /// Reads an n bit unsigned integer from the buffer.
  1461.         /// &lt;/summary&gt;
  1462.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1463.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1464.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1465.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1466.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1467.         public bool ReadUInt(out ulong value, ulong min, ulong max, bool nestedRead = false)
  1468.         {
  1469.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1470.  
  1471.             if (!nestedRead) previousBitIndex = bitIndex;
  1472.             ulong valueBase = max - min + 1;
  1473.             // Log2
  1474.             var bits = 64;
  1475.             if (valueBase != 0)
  1476.             {
  1477.                 int left = 0;
  1478.                 int right = 64;
  1479.                 for (int i = 0; i &lt; 6; ++i)
  1480.                 {
  1481.                     if (valueBase &gt;&gt; (64 - (left + right) / 2) != 0)
  1482.                     {
  1483.                         // Left
  1484.                         right = (left + right) / 2;
  1485.                     }
  1486.                     else
  1487.                     {
  1488.                         // Right
  1489.                         left = (left + right) / 2;
  1490.                     }
  1491.                 }
  1492.                 bits = 64 - left;
  1493.             }
  1494.             if (!ReadUInt(out value, bits, true)) return false;
  1495.             value += min;
  1496.             return true;
  1497.         }
  1498.  
  1499.         /// &lt;summary&gt;
  1500.         /// Reads an n bit custom signed integer from the buffer.
  1501.         /// &lt;/summary&gt;
  1502.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1503.         /// &lt;param name="bits"&gt;The number of bits used to write.&lt;/param&gt;
  1504.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1505.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1506.         public bool ReadInt(out int value, int bits, bool nestedRead = false)
  1507.         {
  1508.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  1509.  
  1510.             if (!nestedRead) previousBitIndex = bitIndex;
  1511.             value = 0;
  1512.             if ((bitIndex + bits + 7) / 8 &gt; buffer.Count)
  1513.             {
  1514.                 return false;
  1515.             }
  1516.  
  1517.             int offset = bitIndex % 8;
  1518.             value = buffer[bitIndex / 8] &lt;&lt; 24 + offset;
  1519.             if (offset + bits &gt; 8)
  1520.             {
  1521.                 value |= buffer[bitIndex / 8 + 1] &lt;&lt; 16 + offset;
  1522.                 if (offset + bits &gt; 16)
  1523.                 {
  1524.                     value |= buffer[bitIndex / 8 + 2] &lt;&lt; 8 + offset;
  1525.                     if (offset + bits &gt; 24)
  1526.                     {
  1527.                         value |= buffer[bitIndex / 8 + 3] &lt;&lt; offset;
  1528.                         if (offset + bits &gt; 32)
  1529.                         {
  1530.                             value |= buffer[bitIndex / 8 + 4] &gt;&gt; 8 - offset;
  1531.                         }
  1532.                     }
  1533.                 }
  1534.             }
  1535.  
  1536.             value &gt;&gt;= 32 - bits;
  1537.             bitIndex += bits;
  1538.             return true;
  1539.         }
  1540.  
  1541.         /// &lt;summary&gt;
  1542.         /// Reads an n bit custom signed integer from the buffer.
  1543.         /// &lt;/summary&gt;
  1544.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1545.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1546.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1547.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1548.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1549.         public bool ReadInt(out int value, int min, int max, bool nestedRead = false)
  1550.         {
  1551.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1552.  
  1553.             if (!nestedRead) previousBitIndex = bitIndex;
  1554.             uint valueBase = (uint)(max - min + 1);
  1555.             // Log2
  1556.             var bits = 32;
  1557.             if (valueBase != 0)
  1558.             {
  1559.                 int left = 0;
  1560.                 int right = 32;
  1561.                 for (int i = 0; i &lt; 5; ++i)
  1562.                 {
  1563.                     if (valueBase &gt;&gt; (32 - (left + right) / 2) != 0)
  1564.                     {
  1565.                         // Left
  1566.                         right = (left + right) / 2;
  1567.                     }
  1568.                     else
  1569.                     {
  1570.                         // Right
  1571.                         left = (left + right) / 2;
  1572.                     }
  1573.                 }
  1574.                 bits = 32 - left;
  1575.             }
  1576.             if (!ReadInt(out value, bits, true)) return false;
  1577.             value += min;
  1578.             return true;
  1579.         }
  1580.  
  1581.         /// &lt;summary&gt;
  1582.         /// Reads an n bit custom signed integer from the buffer.
  1583.         /// &lt;/summary&gt;
  1584.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1585.         /// &lt;param name="bits"&gt;The number of bits used to write.&lt;/param&gt;
  1586.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1587.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1588.         public bool ReadInt(out long value, int bits, bool nestedRead = false)
  1589.         {
  1590.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  1591.  
  1592.             if (!nestedRead) previousBitIndex = bitIndex;
  1593.             value = 0;
  1594.             if ((bitIndex + bits + 7) / 8 &gt; buffer.Count)
  1595.             {
  1596.                 return false;
  1597.             }
  1598.  
  1599.             int offset = bitIndex % 8;
  1600.             value = buffer[bitIndex / 8] &lt;&lt; 56 + offset;
  1601.             if (offset + bits &gt; 8)
  1602.             {
  1603.                 value |= (long)buffer[bitIndex / 8 + 1] &lt;&lt; 48 + offset;
  1604.                 if (offset + bits &gt; 16)
  1605.                 {
  1606.                     value |= (long)buffer[bitIndex / 8 + 2] &lt;&lt; 40 + offset;
  1607.                     if (offset + bits &gt; 24)
  1608.                     {
  1609.                         value |= (long)buffer[bitIndex / 8 + 3] &lt;&lt; 32 + offset;
  1610.                         if (offset + bits &gt; 32)
  1611.                         {
  1612.                             value |= (long)buffer[bitIndex / 8 + 4] &lt;&lt; 24 + offset;
  1613.                             if (offset + bits &gt; 40)
  1614.                             {
  1615.                                 value |= (long)buffer[bitIndex / 8 + 5] &lt;&lt; 16 + offset;
  1616.                                 if (offset + bits &gt; 48)
  1617.                                 {
  1618.                                     value |= (long)buffer[bitIndex / 8 + 6] &lt;&lt; 8 + offset;
  1619.                                     if (offset + bits &gt; 56)
  1620.                                     {
  1621.                                         value |= (long)buffer[bitIndex / 8 + 7] &lt;&lt; offset;
  1622.                                         if (offset + bits &gt; 64)
  1623.                                         {
  1624.                                             value |= (long)buffer[bitIndex / 8 + 8] &gt;&gt; 8 - offset;
  1625.                                         }
  1626.                                     }
  1627.                                 }
  1628.                             }
  1629.                         }
  1630.                     }
  1631.                 }
  1632.             }
  1633.  
  1634.             value &gt;&gt;= 64 - bits;
  1635.             bitIndex += bits;
  1636.             return true;
  1637.         }
  1638.  
  1639.         /// &lt;summary&gt;
  1640.         /// Reads an n bit custom signed integer from the buffer.
  1641.         /// &lt;/summary&gt;
  1642.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1643.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1644.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1645.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1646.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1647.         public bool ReadInt(out long value, long min, long max, bool nestedRead = false)
  1648.         {
  1649.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1650.  
  1651.             if (!nestedRead) previousBitIndex = bitIndex;
  1652.             ulong valueBase = (ulong)(max - min + 1);
  1653.             // Log2
  1654.             var bits = 64;
  1655.             if (valueBase != 0)
  1656.             {
  1657.                 int left = 0;
  1658.                 int right = 64;
  1659.                 for (int i = 0; i &lt; 6; ++i)
  1660.                 {
  1661.                     if (valueBase &gt;&gt; (64 - (left + right) / 2) != 0)
  1662.                     {
  1663.                         // Left
  1664.                         right = (left + right) / 2;
  1665.                     }
  1666.                     else
  1667.                     {
  1668.                         // Right
  1669.                         left = (left + right) / 2;
  1670.                     }
  1671.                 }
  1672.                 bits = 64 - left;
  1673.             }
  1674.             if (!ReadInt(out value, bits, true)) return false;
  1675.             value += min;
  1676.             return true;
  1677.         }
  1678.  
  1679.         /// &lt;summary&gt;
  1680.         /// Reads a 32 bit single from the buffer.
  1681.         /// &lt;/summary&gt;
  1682.         /// &lt;param name="value"&gt;Single.&lt;/param&gt;
  1683.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1684.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1685.         public bool ReadSingle(out float value, bool nestedRead = false)
  1686.         {
  1687.             if (!nestedRead) previousBitIndex = bitIndex;
  1688.             value = 0;
  1689.             if ((bitIndex + 32 + 7) / 8 &gt; buffer.Count)
  1690.             {
  1691.                 return false;
  1692.             }
  1693.             uint uValue;
  1694.             if (!ReadUInt32(out uValue, true)) return false;
  1695.             value = BitConverter.ToSingle(BitConverter.GetBytes(uValue), 0);
  1696.             return true;
  1697.         }
  1698.  
  1699.         /// &lt;summary&gt;
  1700.         /// Reads a 64 bit double from the buffer.
  1701.         /// &lt;/summary&gt;
  1702.         /// &lt;param name="value"&gt;Double.&lt;/param&gt;
  1703.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1704.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1705.         public bool ReadDouble(out double value, bool nestedRead = false)
  1706.         {
  1707.             if (!nestedRead) previousBitIndex = bitIndex;
  1708.             value = 0;
  1709.             if ((bitIndex + 64 + 7) / 8 &gt; buffer.Count)
  1710.             {
  1711.                 return false;
  1712.             }
  1713.             byte[] bytes = new byte[8];
  1714.             uint uValue1;
  1715.             if (!ReadUInt32(out uValue1, true)) return false;
  1716.             byte[] first4bytes = BitConverter.GetBytes(uValue1);
  1717.             uint uValue2;
  1718.             if (!ReadUInt32(out uValue2, true)) return false;
  1719.             byte[] last4bytes = BitConverter.GetBytes(uValue2);
  1720.  
  1721.             for (uint copyBytes = 0; copyBytes &lt; 4; ++copyBytes)
  1722.             {
  1723.                 bytes[copyBytes] = first4bytes[copyBytes];
  1724.             }
  1725.             for (uint copyBytes = 4; copyBytes &lt; 8; ++copyBytes)
  1726.             {
  1727.                 bytes[copyBytes] = last4bytes[copyBytes - 4];
  1728.             }
  1729.             value = BitConverter.ToDouble(bytes, 0);
  1730.             return true;
  1731.         }
  1732.  
  1733.         /// &lt;summary&gt;
  1734.         /// Reads the variable-width unsigned integer.
  1735.         /// &lt;/summary&gt;
  1736.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1737.         /// &lt;param name="bits"&gt;The bit size of the sequence used to write.&lt;/param&gt;
  1738.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1739.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1740.         public bool ReadVariableWidthUInt(out uint value, int bits = 4, bool nestedRead = false)
  1741.         {
  1742.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  1743.  
  1744.             if (!nestedRead) previousBitIndex = bitIndex;
  1745.             value = 0;
  1746.             int valueBitCount = bits;
  1747.             bool continuationBitValue = true;
  1748.             do
  1749.             {
  1750.                 if (!ReadBool(out continuationBitValue, true)) return false;
  1751.                 if (continuationBitValue) valueBitCount += bits;
  1752.             }
  1753.             while (continuationBitValue &amp;&amp; valueBitCount &lt; 32);
  1754.             return ReadUInt(out value, valueBitCount &gt;= 32 ? 32 : valueBitCount, true);
  1755.         }
  1756.  
  1757.         /// &lt;summary&gt;
  1758.         /// Reads the variable-width unsigned integer.
  1759.         /// &lt;/summary&gt;
  1760.         /// &lt;param name="value"&gt;Unsigned Integer.&lt;/param&gt;
  1761.         /// &lt;param name="bits"&gt;The bit size of the sequence used to write.&lt;/param&gt;
  1762.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1763.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1764.         public bool ReadVariableWidthUInt(out ulong value, int bits = 4, bool nestedRead = false)
  1765.         {
  1766.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  1767.  
  1768.             if (!nestedRead) previousBitIndex = bitIndex;
  1769.             value = 0;
  1770.             int valueBitCount = bits;
  1771.             bool continuationBitValue = true;
  1772.             do
  1773.             {
  1774.                 if (!ReadBool(out continuationBitValue, true)) return false;
  1775.                 if (continuationBitValue) valueBitCount += bits;
  1776.             }
  1777.             while (continuationBitValue &amp;&amp; valueBitCount &lt; 64);
  1778.             return ReadUInt(out value, valueBitCount &gt;= 64 ? 64 : valueBitCount, true);
  1779.         }
  1780.  
  1781.         /// &lt;summary&gt;
  1782.         /// Reads the variable-width signed integer.
  1783.         /// &lt;/summary&gt;
  1784.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1785.         /// &lt;param name="bits"&gt;The bit size of the sequence used to write.&lt;/param&gt;
  1786.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1787.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1788.         public bool ReadVariableWidthInt(out int value, int bits = 4, bool nestedRead = false)
  1789.         {
  1790.             if (bits &lt; 1 || bits &gt; 32) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32].");
  1791.  
  1792.             if (!nestedRead) previousBitIndex = bitIndex;
  1793.             value = 0;
  1794.             int valueBitCount = bits;
  1795.             bool continuationBitValue = true;
  1796.             do
  1797.             {
  1798.                 if (!ReadBool(out continuationBitValue, true)) return false;
  1799.                 if (continuationBitValue) valueBitCount += bits;
  1800.             }
  1801.             while (continuationBitValue &amp;&amp; valueBitCount &lt; 32);
  1802.             return ReadInt(out value, valueBitCount &gt;= 32 ? 32 : valueBitCount, true);
  1803.         }
  1804.  
  1805.         /// &lt;summary&gt;
  1806.         /// Reads the variable-width signed integer.
  1807.         /// &lt;/summary&gt;
  1808.         /// &lt;param name="value"&gt;Signed Integer.&lt;/param&gt;
  1809.         /// &lt;param name="bits"&gt;The bit size of the sequence used to write.&lt;/param&gt;
  1810.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1811.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1812.         public bool ReadVariableWidthInt(out long value, int bits = 4, bool nestedRead = false)
  1813.         {
  1814.             if (bits &lt; 1 || bits &gt; 64) throw new ArgumentOutOfRangeException("bits must be in the range (0, 64].");
  1815.  
  1816.             if (!nestedRead) previousBitIndex = bitIndex;
  1817.             value = 0;
  1818.             int valueBitCount = bits;
  1819.             bool continuationBitValue = true;
  1820.             do
  1821.             {
  1822.                 if (!ReadBool(out continuationBitValue, true)) return false;
  1823.                 if (continuationBitValue) valueBitCount += bits;
  1824.             }
  1825.             while (continuationBitValue &amp;&amp; valueBitCount &lt; 64);
  1826.             return ReadInt(out value, valueBitCount &gt;= 64 ? 64 : valueBitCount, true);
  1827.         }
  1828.  
  1829.         /// &lt;summary&gt;
  1830.         /// Reads an array of unsigned integers in the given range defining a base.
  1831.         /// &lt;/summary&gt;
  1832.         /// &lt;param name="value"&gt;Array of Unsigned Integers.&lt;/param&gt;
  1833.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1834.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1835.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1836.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1837.         public bool ReadArrayUInt32(uint[] value, int min, int max, bool nestedRead = false)
  1838.         {
  1839.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1840.             if (!nestedRead) previousBitIndex = bitIndex;
  1841.             ulong valueBase = (ulong)(max - min + 1);
  1842.             var exponent = value.Length;
  1843.  
  1844.             var powResult = new List&lt;ulong&gt;();
  1845.             powResult.Add(1);
  1846.             var newPowResult = new List&lt;ulong&gt;();
  1847.  
  1848.             var valueBaseTemp = new List&lt;ulong&gt;();
  1849.             valueBaseTemp.Add(valueBase);
  1850.             var newValueBaseTemp = new List&lt;ulong&gt;();
  1851.  
  1852.             // Pow(value.size, arrayBase) using exponentiation by squaring
  1853.             while (exponent != 0)
  1854.             {
  1855.                 if (exponent % 2 != 0)
  1856.                 {
  1857.                     // powResult *= valueBaseTemp;
  1858.                     newPowResult.Clear();
  1859.                     for (int i = 0; i &lt; valueBaseTemp.Count; ++i)
  1860.                     {
  1861.                         ulong carry = 0;
  1862.                         for (var j = 0; j &lt; powResult.Count || carry != 0; ++j)
  1863.                         {
  1864.                             if (i + j &gt;= newPowResult.Count)
  1865.                             {
  1866.                                 newPowResult.Add(0);
  1867.                             }
  1868.                             ulong product = 0;
  1869.                             if (j &lt; powResult.Count)
  1870.                             {
  1871.                                 product = valueBaseTemp[i] * powResult[j];
  1872.                             }
  1873.                             newPowResult[j + i] += product + carry;
  1874.                             carry = newPowResult[j + i] &gt;&gt; 32;
  1875.                             newPowResult[j + i] &amp;= 0xFFFFFFFF;
  1876.                         }
  1877.                     }
  1878.                     powResult.Clear();
  1879.                     powResult.InsertRange(0, newPowResult);
  1880.                     exponent--;
  1881.                 }
  1882.                 // valueBaseTemp *= valueBaseTemp;
  1883.                 newValueBaseTemp.Clear();
  1884.                 for (int i = 0; i &lt; valueBaseTemp.Count; ++i)
  1885.                 {
  1886.                     ulong carry = 0;
  1887.                     for (var j = 0; j &lt; valueBaseTemp.Count || carry != 0; ++j)
  1888.                     {
  1889.                         if (i + j &gt;= newValueBaseTemp.Count)
  1890.                         {
  1891.                             newValueBaseTemp.Add(0);
  1892.                         }
  1893.                         ulong product = 0;
  1894.                         if (j &lt; valueBaseTemp.Count)
  1895.                         {
  1896.                             product = valueBaseTemp[i] * valueBaseTemp[j];
  1897.                         }
  1898.                         newValueBaseTemp[j + i] += product + carry;
  1899.                         carry = newValueBaseTemp[j + i] &gt;&gt; 32;
  1900.                         newValueBaseTemp[j + i] &amp;= 0xFFFFFFFF;
  1901.                     }
  1902.                 }
  1903.                 valueBaseTemp.Clear();
  1904.                 valueBaseTemp.InsertRange(0, newValueBaseTemp);
  1905.  
  1906.                 exponent /= 2;
  1907.             }
  1908.  
  1909.             for (var i = powResult.Count - 1; i &gt; 0 &amp;&amp; powResult[i] == 0; --i)
  1910.             {
  1911.                 powResult.RemoveAt(powResult.Count - 1);
  1912.             }
  1913.  
  1914.             // Log2
  1915.             int numberOfBits = 0;
  1916.             if (!(powResult.Count == 1 &amp;&amp; powResult[0] == 0))
  1917.             {
  1918.                 int left = 0;
  1919.                 int right = 32;
  1920.                 for (int i = 0; i &lt; 5; ++i)
  1921.                 {
  1922.                     if (powResult[powResult.Count - 1] &gt;&gt; (32 - (left + right) / 2) != 0)
  1923.                     {
  1924.                         // Left
  1925.                         right = (left + right) / 2;
  1926.                     }
  1927.                     else
  1928.                     {
  1929.                         // Right
  1930.                         left = (left + right) / 2;
  1931.                     }
  1932.                 }
  1933.                 numberOfBits = (powResult.Count - 1) * 32 + (32 - left);
  1934.             }
  1935.  
  1936.             var sum = new List&lt;ulong&gt;((numberOfBits + 31) / 32);
  1937.             for (int copyBits = 0; copyBits &lt; numberOfBits; copyBits += 32)
  1938.             {
  1939.                 uint uValue;
  1940.                 if (!ReadUInt(out uValue, (int)numberOfBits - copyBits &gt; 32 ? 32 : (int)numberOfBits - copyBits, true)) return false;
  1941.                 sum.Add(uValue);
  1942.             }
  1943.  
  1944.             for (var i = 0; i &lt; value.Length; ++i)
  1945.             {
  1946.                 ulong remainder = 0;
  1947.                 for (var j = sum.Count - 1; j &gt;= 0; --j)
  1948.                 {
  1949.                     sum[j] += remainder &lt;&lt; 32;
  1950.                     remainder = sum[j] % valueBase;
  1951.                     sum[j] /= valueBase;
  1952.                 }
  1953.                 value[i] = (uint)remainder + (uint)min;
  1954.             }
  1955.             return true;
  1956.         }
  1957.  
  1958.         /// &lt;summary&gt;
  1959.         /// Reads an array of signed integers in the given range defining a base.
  1960.         /// &lt;/summary&gt;
  1961.         /// &lt;param name="value"&gt;Array of Signed Integers.&lt;/param&gt;
  1962.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1963.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1964.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1965.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1966.         public bool ReadArrayInt32(int[] value, int min, int max, bool nestedRead = false)
  1967.         {
  1968.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1969.             if (!nestedRead) previousBitIndex = bitIndex;
  1970.  
  1971.             var uValue = new uint[value.Length];
  1972.             if (!ReadArrayUInt32(uValue, min, max, true)) return false;
  1973.  
  1974.             for (var i = 0; i &lt; value.Length; ++i)
  1975.             {
  1976.                 value[i] = (int)uValue[i] + min;
  1977.             }
  1978.             return true;
  1979.         }
  1980.  
  1981.         /// &lt;summary&gt;
  1982.         /// Reads an array of singles in the given range converted to the given base.
  1983.         /// &lt;/summary&gt;
  1984.         /// &lt;param name="value"&gt;Array of Singles.&lt;/param&gt;
  1985.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  1986.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  1987.         /// &lt;param name="valueBase"&gt;The base to convert the singles to.&lt;/param&gt;
  1988.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  1989.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  1990.         public bool ReadArraySingle(float[] value, float min, float max, int valueBase, bool nestedRead = false)
  1991.         {
  1992.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  1993.             if (!nestedRead) previousBitIndex = bitIndex;
  1994.             var uValue = new uint[value.Length];
  1995.             if (!ReadArrayUInt32(uValue, 0, valueBase - 1, true)) return false;
  1996.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  1997.             {
  1998.                 for (var i = 0; i &lt; value.Length; ++i)
  1999.                 {
  2000.                     value[i] = uValue[i] == 0 ? 0 : (uValue[i] - 1) / (float)(valueBase - 2) * (max - min) + min;
  2001.                 }
  2002.             }
  2003.             else
  2004.             {
  2005.                 for (var i = 0; i &lt; value.Length; ++i)
  2006.                 {
  2007.                     value[i] = uValue[i] / (float)(valueBase - 1) * (max - min) + min;
  2008.                 }
  2009.             }
  2010.             return true;
  2011.         }
  2012.  
  2013.         /// &lt;summary&gt;
  2014.         /// Reads an array of doubles in the given range converted to the given base.
  2015.         /// &lt;/summary&gt;
  2016.         /// &lt;param name="value"&gt;Array of Doubles.&lt;/param&gt;
  2017.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  2018.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  2019.         /// &lt;param name="valueBase"&gt;The base to convert the doubles to.&lt;/param&gt;
  2020.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  2021.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  2022.         public bool ReadArrayDouble(double[] value, double min, double max, int valueBase, bool nestedRead = false)
  2023.         {
  2024.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  2025.             if (!nestedRead) previousBitIndex = bitIndex;
  2026.             var uValue = new uint[value.Length];
  2027.             if (!ReadArrayUInt32(uValue, 0, valueBase - 1, true)) return false;
  2028.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  2029.             {
  2030.                 for (var i = 0; i &lt; value.Length; ++i)
  2031.                 {
  2032.                     value[i] = uValue[i] == 0 ? 0 : (uValue[i] - 1) / (double)(valueBase - 2) * (max - min) + min;
  2033.                 }
  2034.             }
  2035.             else
  2036.             {
  2037.                 for (var i = 0; i &lt; value.Length; ++i)
  2038.                 {
  2039.                     value[i] = uValue[i] / (double)(valueBase - 1) * (max - min) + min;
  2040.                 }
  2041.             }
  2042.             return true;
  2043.         }
  2044.  
  2045.         /// &lt;summary&gt;
  2046.         /// Reads a custom resolution single.
  2047.         /// &lt;/summary&gt;
  2048.         /// &lt;param name="value"&gt;Single.&lt;/param&gt;
  2049.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  2050.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  2051.         /// &lt;param name="bitResolution"&gt;The number of bits written for the ratio.&lt;/param&gt;
  2052.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  2053.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  2054.         public bool ReadCustomResolutionSingle(out float value, float min, float max, int bitResolution, bool nestedRead = false)
  2055.         {
  2056.             if (bitResolution &lt; 1 || bitResolution &gt; 31) throw new ArgumentOutOfRangeException("bitResolution must be in the range (0, 32).");
  2057.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  2058.  
  2059.             if (!nestedRead) previousBitIndex = bitIndex;
  2060.             value = 0;
  2061.             uint uValue;
  2062.             if (!ReadUInt(out uValue, bitResolution, true)) return false;
  2063.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  2064.             {
  2065.                 value = uValue == 0 ? 0 : (uValue - 1) / (float)((0x1 &lt;&lt; bitResolution) - 2) * (max - min) + min;
  2066.             }
  2067.             else
  2068.             {
  2069.                 value = uValue / (float)((0x1 &lt;&lt; bitResolution) - 1) * (max - min) + min;
  2070.             }
  2071.             return true;
  2072.         }
  2073.  
  2074.         /// &lt;summary&gt;
  2075.         /// Reads a custom resolution double.
  2076.         /// &lt;/summary&gt;
  2077.         /// &lt;param name="value"&gt;Double.&lt;/param&gt;
  2078.         /// &lt;param name="min"&gt;The minimum value in the range.&lt;/param&gt;
  2079.         /// &lt;param name="max"&gt;The maximum value in the range.&lt;/param&gt;
  2080.         /// &lt;param name="bitResolution"&gt;The number of bits written for the ratio.&lt;/param&gt;
  2081.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  2082.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  2083.         public bool ReadCustomResolutionDouble(out double value, double min, double max, int bitResolution, bool nestedRead = false)
  2084.         {
  2085.             if (bitResolution &lt; 1 || bitResolution &gt; 31) throw new ArgumentOutOfRangeException("bitResolution must be in the range (0, 32).");
  2086.             if (max &lt;= min) throw new ArgumentOutOfRangeException("max must be greater than min.");
  2087.  
  2088.             if (!nestedRead) previousBitIndex = bitIndex;
  2089.             value = 0;
  2090.             uint uValue;
  2091.             if (!ReadUInt(out uValue, bitResolution, true)) return false;
  2092.             if (min &lt; 0 &amp;&amp; max &gt; 0)
  2093.             {
  2094.                 value = uValue == 0 ? 0 : (uValue - 1) / (double)((0x1 &lt;&lt; bitResolution) - 2) * (max - min) + min;
  2095.             }
  2096.             else
  2097.             {
  2098.                 value = uValue / (double)((0x1 &lt;&lt; bitResolution) - 1) * (max - min) + min;
  2099.             }
  2100.             return true;
  2101.         }
  2102.  
  2103.         /// &lt;summary&gt;
  2104.         /// Reads a string.
  2105.         /// &lt;/summary&gt;
  2106.         /// &lt;param name="value"&gt;String.&lt;/param&gt;
  2107.         /// &lt;param name="bits"&gt;The number of bits for the length written using an unsigned variable-width integer.&lt;/param&gt;
  2108.         /// &lt;param name="limit"&gt;The maximum number of characters to read.&lt;/param&gt;
  2109.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  2110.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  2111.         public bool ReadString(out string value, int bits = 4, int limit = 255, bool nestedRead = false)
  2112.         {
  2113.             if (bits &lt; 1 || bits &gt; 31) throw new ArgumentOutOfRangeException("bits must be in the range (0, 32).");
  2114.  
  2115.             if (!nestedRead) previousBitIndex = bitIndex;
  2116.             value = string.Empty;
  2117.             uint size;
  2118.             if (!ReadVariableWidthUInt(out size, bits, true)) return false;
  2119.             for (var asciiByteItr = 0; asciiByteItr &lt; size; ++asciiByteItr)
  2120.             {
  2121.                 byte asciiByte;
  2122.                 if (!ReadByte(out asciiByte, true)) return false;
  2123.                 value += asciiByte;
  2124.                 if (value.Length &gt; limit) return false;
  2125.             }
  2126.             return true;
  2127.         }
  2128.  
  2129.         /// &lt;summary&gt;
  2130.         /// Reads a binary packet that has been written to the buffer.
  2131.         /// &lt;/summary&gt;
  2132.         /// &lt;param name="value"&gt;A binary packet.&lt;/param&gt;
  2133.         /// &lt;param name="nestedRead"&gt;If false then the previous bit index is stored so the operation can be rolled back.&lt;/param&gt;
  2134.         /// &lt;returns&gt;false on error.&lt;/returns&gt;
  2135.         public bool ReadBinaryPacket(out Packet value, bool nestedRead = false)
  2136.         {
  2137.             value = new Packet();
  2138.             if (!nestedRead) previousBitIndex = bitIndex;
  2139.             uint valueMaxBitIndex;
  2140.             if (!ReadVariableWidthUInt(out valueMaxBitIndex, nestedRead: true)) return false;
  2141.             for (int copyBits = 0; copyBits &lt; valueMaxBitIndex; copyBits += 32)
  2142.             {
  2143.                 uint uValue;
  2144.                 if (!ReadUInt(out uValue, (int)valueMaxBitIndex - copyBits &gt; 32 ? 32 : (int)valueMaxBitIndex - copyBits, true)) return false;
  2145.                 value.WriteUInt(uValue, (int)valueMaxBitIndex - copyBits &gt; 32 ? 32 : (int)valueMaxBitIndex - copyBits);
  2146.             }
  2147.             bitIndex += (int)valueMaxBitIndex;
  2148.             value.bitIndex = 0;
  2149.             return true;
  2150.         }
  2151.  
  2152.     }
  2153. }</pre>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement