Read bits from a string.
        public void TestAvailableBitsAndEOF()
        {
            byte[] data = { unchecked((byte)-120), unchecked((byte)6) };
            BitStringReader reader = new BitStringReader(Base64.ByteEncoding.GetString(data));

            Assert.AreEqual(16, reader.AvailableBits());
            Assert.AreEqual(false, reader.Eof);

            reader.Read(3);
            Assert.AreEqual(13, reader.AvailableBits());
            Assert.AreEqual(false, reader.Eof);

            reader.Read(3);
            Assert.AreEqual(10, reader.AvailableBits());
            Assert.AreEqual(false, reader.Eof);

            reader.Read(3);
            Assert.AreEqual(7, reader.AvailableBits());
            Assert.AreEqual(false, reader.Eof);

            reader.Read(7);
            Assert.AreEqual(0, reader.AvailableBits());
            Assert.AreEqual(true, reader.Eof);

            Assert.AreEqual((uint)0, reader.Read(3));
            Assert.AreEqual(true, reader.Eof);
            Assert.AreEqual(0, reader.AvailableBits());
        }
        public int[] Decompress(string data, ref int algorithm)
        {
            // TODO: this is not exactly what the C++ version does
            if (algorithm <= 0)
            {
                algorithm = (int)data[0];
            }

            int length = ((byte)(data[1]) << 16) | ((byte)(data[2]) << 8) | ((byte)(data[3]));

            BitStringReader reader = new BitStringReader(data);
            reader.Read(8);
            reader.Read(8);
            reader.Read(8);
            reader.Read(8);

            m_result = new List<int>(length);

            for (int i = 0; i < length; i++)
            {
                m_result.Add(-1);
            }

            reader.Reset();
            ReadNormalBits(reader);
            reader.Reset();
            ReadExceptionBits(reader);
            UnpackBits();

            // TODO: no list needed?
            return m_result.ToArray();
        }
        public void TestTwoBytesSplit()
        {
            byte[] data = { unchecked((byte)-120), unchecked((byte)6) };
            BitStringReader reader = new BitStringReader(Base64.ByteEncoding.GetString(data));

            Assert.AreEqual((uint)0, reader.Read(3));
            Assert.AreEqual((uint)1, reader.Read(3));
            Assert.AreEqual((uint)2, reader.Read(3));
            Assert.AreEqual((uint)3, reader.Read(3));
        }
        public void TestOneByte()
        {
            byte[] data = { unchecked((byte)-28) };
            BitStringReader reader = new BitStringReader(Base64.ByteEncoding.GetString(data));

            Assert.AreEqual((uint)0, reader.Read(2));
            Assert.AreEqual((uint)1, reader.Read(2));
            Assert.AreEqual((uint)2, reader.Read(2));
            Assert.AreEqual((uint)3, reader.Read(2));
        }
        public int[] Decompress(string data, ref int algorithm)
        {
            if (data.Length < 4)
            {
                // Invalid fingerprint (shorter than 4 bytes)
                return new int[0];
            }

            // TODO: this is not exactly what the C++ version does
            if (algorithm <= 0)
            {
                algorithm = (int)data[0];
            }

            int length = ((byte)(data[1]) << 16) | ((byte)(data[2]) << 8) | ((byte)(data[3]));

            BitStringReader reader = new BitStringReader(data);
            reader.Read(8);
            reader.Read(8);
            reader.Read(8);
            reader.Read(8);

            if (reader.AvailableBits() < length * kNormalBits)
            {
                // Invalid fingerprint (too short)
                return new int[0];
            }

            m_result = new List<int>(length);

            for (int i = 0; i < length; i++)
            {
                m_result.Add(-1);
            }

            reader.Reset();
            if (!ReadNormalBits(reader))
            {
                return new int[0];
            }

            reader.Reset();
            if (!ReadExceptionBits(reader))
            {
                return new int[0];
            }

            UnpackBits();

            // TODO: no list needed?
            return m_result.ToArray();
        }
 void ReadNormalBits(BitStringReader reader)
 {
     int i = 0;
     while (i < m_result.Count)
     {
         int bit = (int)reader.Read(kNormalBits);
         if (bit == 0)
         {
             i++;
         }
         m_bits.Add((byte)bit);
     }
 }
 void ReadExceptionBits(BitStringReader reader)
 {
     for (int i = 0; i < m_bits.Count; i++)
     {
         if (m_bits[i] == kMaxNormalValue)
         {
             m_bits[i] += (byte)reader.Read(kExceptionBits);
         }
     }
 }
        bool ReadExceptionBits(BitStringReader reader)
        {
            for (int i = 0; i < m_bits.Count; i++)
            {
                if (m_bits[i] == kMaxNormalValue)
                {
                    if (reader.Eof)
                    {
                        // Invalid fingerprint (reached EOF while reading exception bits)
                        return false;
                    }

                    m_bits[i] += (byte)reader.Read(kExceptionBits);
                }
            }

            return true;
        }