Beispiel #1
0
        /// <summary>
        /// Writes a signed integer using 1 to 32 bits
        /// </summary>
        public BitWriter Write(Int32 source, int numberOfBits)
        {
            BitBufferException.Assert((numberOfBits > 0 && numberOfBits <= 32), "Write(int, numberOfBits) can only write between 1 and 32 bits");
            EnsureBufferSize(_lengthBits + numberOfBits);

            if (numberOfBits != 32)
            {
                // make first bit sign
                int signBit = 1 << (numberOfBits - 1);
                if (source < 0)
                {
                    source = (-source - 1) | signBit;
                }
                else
                {
                    source &= (~signBit);
                }
            }

            BitReaderWriter.WriteUInt32((uint)source, numberOfBits, _data, _lengthBits);

            _lengthBits += numberOfBits;

            return(this);
        }
        /// <summary>
        /// Reads the specified number of bits into an Int32 without advancing the read pointer
        /// </summary>
        public Int32 PeekInt32(int numberOfBits)
        {
            BitBufferException.Assert((numberOfBits > 0 && numberOfBits <= 32), "ReadInt() can only read between 1 and 32 bits");
            ReadOverflowException.Assert(_lengthBits - _readPosition >= numberOfBits);

            uint retval = BitReaderWriter.ReadUInt32(_data, numberOfBits, _readPosition);

            if (numberOfBits == 32)
            {
                return((int)retval);
            }

            int signBit = 1 << (numberOfBits - 1);

            if ((retval & signBit) == 0)
            {
                return((int)retval);                // positive
            }
            // negative
            unchecked
            {
                uint mask = ((uint)-1) >> (33 - numberOfBits);
                uint tmp  = (retval & mask) + 1;
                return(-((int)tmp));
            }
        }
        //public static ulong ReadUInt64(byte[] fromBuffer, int numberOfBits, int readBitOffset)

        /// <summary>
        /// Writes an unsigned 16 bit integer
        /// </summary>
        public static void WriteUInt16(ushort source, int numberOfBits, byte[] destination, int destinationBitOffset)
        {
            if (numberOfBits == 0)
            {
                return;
            }

            BitBufferException.Assert((numberOfBits >= 0 && numberOfBits <= 16), "numberOfBits must be between 0 and 16");
#if BIGENDIAN
            // reorder bytes
            uint intSource = source;
            intSource = ((intSource & 0x0000ff00) >> 8) | ((intSource & 0x000000ff) << 8);
            source    = (ushort)intSource;
#endif
            if (numberOfBits <= 8)
            {
                BitReaderWriter.WriteByte((byte)source, numberOfBits, destination, destinationBitOffset);
                return;
            }

            BitReaderWriter.WriteByte((byte)source, 8, destination, destinationBitOffset);

            numberOfBits -= 8;
            if (numberOfBits > 0)
            {
                BitReaderWriter.WriteByte((byte)(source >> 8), numberOfBits, destination, destinationBitOffset + 8);
            }
        }
        /// <summary>
        /// Read 1-8 bits from a buffer into a byte
        /// </summary>
        public static byte ReadByte(byte[] fromBuffer, int numberOfBits, int readBitOffset)
        {
            BitBufferException.Assert(((numberOfBits > 0) && (numberOfBits < 9)), "Read() can only read between 1 and 8 bits");

            int bytePtr          = readBitOffset >> 3;
            int startReadAtIndex = readBitOffset - (bytePtr * 8);             // (readBitOffset % 8);

            if (startReadAtIndex == 0 && numberOfBits == 8)
            {
                return(fromBuffer[bytePtr]);
            }

            // mask away unused bits lower than (right of) relevant bits in first byte
            byte returnValue = (byte)(fromBuffer[bytePtr] >> startReadAtIndex);

            int numberOfBitsInSecondByte = numberOfBits - (8 - startReadAtIndex);

            if (numberOfBitsInSecondByte < 1)
            {
                // we don't need to read from the second byte, but we DO need
                // to mask away unused bits higher than (left of) relevant bits
                return((byte)(returnValue & (255 >> (8 - numberOfBits))));
            }

            byte second = fromBuffer[bytePtr + 1];

            // mask away unused bits higher than (left of) relevant bits in second byte
            second &= (byte)(255 >> (8 - numberOfBitsInSecondByte));

            return((byte)(returnValue | (byte)(second << (numberOfBits - numberOfBitsInSecondByte))));
        }
        /// <summary>
        /// Reads the specified number of bytes without advancing the read pointer
        /// </summary>
        public void PeekBytes(byte[] into, int offset, int numberOfBytes)
        {
            ReadOverflowException.Assert(_lengthBits - _readPosition >= (numberOfBytes * 8));
            BitBufferException.Assert(offset + numberOfBytes <= into.Length);

            BitReaderWriter.ReadBytes(_data, numberOfBytes, _readPosition, into, offset);
            return;
        }
Beispiel #6
0
        /// <summary>
        /// Reads 1 to 8 bits into a byte
        /// </summary>
        public byte ReadByte(int numberOfBits)
        {
            BitBufferException.Assert(numberOfBits > 0 && numberOfBits <= 8, "ReadByte(bits) can only read between 1 and 8 bits");
            byte retval = BitReaderWriter.ReadByte(_data, numberOfBits, _readPosition);

            _readPosition += numberOfBits;
            return(retval);
        }
Beispiel #7
0
        /// <summary>
        /// Writes a 32 bit signed integer
        /// </summary>
        public BitWriter Write(UInt32 source, int numberOfBits)
        {
            BitBufferException.Assert((numberOfBits > 0 && numberOfBits <= 32), "Write(uint, numberOfBits) can only write between 1 and 32 bits");
            EnsureBufferSize(_lengthBits + numberOfBits);
            BitReaderWriter.WriteUInt32(source, numberOfBits, _data, _lengthBits);
            _lengthBits += numberOfBits;

            return(this);
        }
        /// <summary>
        /// Reads the specified number of bits into a UInt32 without advancing the read pointer
        /// </summary>
        public UInt32 PeekUInt32(int numberOfBits)
        {
            BitBufferException.Assert((numberOfBits > 0 && numberOfBits <= 32), "ReadUInt() can only read between 1 and 32 bits");
            //NetException.Assert(m_bitLength - m_readBitPtr >= numberOfBits, "tried to read past buffer size");

            UInt32 retval = BitReaderWriter.ReadUInt32(_data, numberOfBits, _readPosition);

            return(retval);
        }
Beispiel #9
0
        /// <summary>
        /// Compress (lossy) a float in the range 0..1 using numberOfBits bits
        /// </summary>
        public BitWriter WriteUnitSingle(float value, int numberOfBits)
        {
            BitBufferException.Assert(((value >= 0.0) && (value <= 1.0)), " WriteUnitSingle() must be passed a float in the range 0 to 1; val is " + value);

            int  maxValue = (1 << numberOfBits) - 1;
            uint writeVal = (uint)(value * (float)maxValue);

            Write(writeVal, numberOfBits);

            return(this);
        }
Beispiel #10
0
        /// <summary>
        /// Compress (lossy) a float in the range -1..1 using numberOfBits bits
        /// </summary>
        public BitWriter WriteSignedSingle(float value, int numberOfBits)
        {
            BitBufferException.Assert(((value >= -1.0) && (value <= 1.0)), " WriteSignedSingle() must be passed a float in the range -1 to 1; val is " + value);

            float unit     = (value + 1.0f) * 0.5f;
            int   maxVal   = (1 << numberOfBits) - 1;
            uint  writeVal = (uint)(unit * (float)maxVal);

            Write(writeVal, numberOfBits);

            return(this);
        }
Beispiel #11
0
        /// <summary>
        /// Compress a float within a specified range using a certain number of bits
        /// </summary>
        public BitWriter WriteRangedSingle(float value, float min, float max, int numberOfBits)
        {
            BitBufferException.Assert(((value >= min) && (value <= max)), " WriteRangedSingle() must be passed a float in the range MIN to MAX; val is " + value);

            float range  = max - min;
            float unit   = ((value - min) / range);
            int   maxVal = (1 << numberOfBits) - 1;

            Write((UInt32)((float)maxVal * unit), numberOfBits);

            return(this);
        }
        /// <summary>
        /// Write 0-8 bits of data to buffer
        /// </summary>
        public static void WriteByte(byte source, int numberOfBits, byte[] destination, int destBitOffset)
        {
            if (numberOfBits == 0)
            {
                return;
            }

            BitBufferException.Assert(((numberOfBits >= 0) && (numberOfBits <= 8)), "Must write between 0 and 8 bits!");

            // Mask out all the bits we dont want
            source = (byte)(source & (0xFF >> (8 - numberOfBits)));

            int p        = destBitOffset >> 3;
            int bitsUsed = destBitOffset & 0x7;             // mod 8
            int bitsFree = 8 - bitsUsed;
            int bitsLeft = bitsFree - numberOfBits;

            // Fast path, everything fits in the first byte
            if (bitsLeft >= 0)
            {
                int mask = (0xFF >> bitsFree) | (0xFF << (8 - bitsLeft));

                destination[p] = (byte)(
                    // Mask out lower and upper bits
                    (destination[p] & mask) |

                    // Insert new bits
                    (source << bitsUsed)
                    );

                return;
            }

            destination[p] = (byte)(
                // Mask out upper bits
                (destination[p] & (0xFF >> bitsFree)) |

                // Write the lower bits to the upper bits in the first byte
                (source << bitsUsed)
                );

            p += 1;

            destination[p] = (byte)(
                // Mask out lower bits
                (destination[p] & (0xFF << (numberOfBits - bitsFree))) |

                // Write the upper bits to the lower bits of the second byte
                (source >> bitsFree)
                );
        }
Beispiel #13
0
        /// <summary>
        /// Writes an integer with the least amount of bits need for the specified range
        /// Returns number of bits written
        /// </summary>
        public BitWriter WriteRangedInteger(long min, long max, long value, out int bitsWritten)
        {
            BitBufferException.Assert(value >= min && value <= max, "Value not within min/max range!");

            ulong range   = (ulong)(max - min);
            int   numBits = BitUtility.BitsToHoldUInt64(range);

            ulong rvalue = (ulong)(value - min);

            Write(rvalue, numBits);

            bitsWritten = numBits;

            return(this);
        }
        public static uint ReadUInt32(byte[] fromBuffer, int numberOfBits, int readBitOffset)
        {
            BitBufferException.Assert(((numberOfBits > 0) && (numberOfBits <= 32)), "ReadUInt32() can only read between 1 and 32 bits");
#endif
            uint returnValue;
            if (numberOfBits <= 8)
            {
                returnValue = ReadByte(fromBuffer, numberOfBits, readBitOffset);
                return(returnValue);
            }
            returnValue    = ReadByte(fromBuffer, 8, readBitOffset);
            numberOfBits  -= 8;
            readBitOffset += 8;

            if (numberOfBits <= 8)
            {
                returnValue |= (uint)(ReadByte(fromBuffer, numberOfBits, readBitOffset) << 8);
                return(returnValue);
            }
            returnValue   |= (uint)(ReadByte(fromBuffer, 8, readBitOffset) << 8);
            numberOfBits  -= 8;
            readBitOffset += 8;

            if (numberOfBits <= 8)
            {
                uint r = ReadByte(fromBuffer, numberOfBits, readBitOffset);
                r          <<= 16;
                returnValue |= r;
                return(returnValue);
            }
            returnValue   |= (uint)(ReadByte(fromBuffer, 8, readBitOffset) << 16);
            numberOfBits  -= 8;
            readBitOffset += 8;

            returnValue |= (uint)(ReadByte(fromBuffer, numberOfBits, readBitOffset) << 24);

#if BIGENDIAN
            // reorder bytes
            return
                (((returnValue & 0xff000000) >> 24) |
                 ((returnValue & 0x00ff0000) >> 8) |
                 ((returnValue & 0x0000ff00) << 8) |
                 ((returnValue & 0x000000ff) << 24));
#else
            return(returnValue);
#endif
        }
        /// <summary>
        /// Reads a UInt32 written using WriteUnsignedVarInt(); will increment offset!
        /// </summary>
        public static uint ReadVariableUInt32(byte[] buffer, ref int offset)
        {
            int num1 = 0;
            int num2 = 0;

            while (true)
            {
                BitBufferException.Assert(num2 != 0x23, "Bad 7-bit encoded integer");

                byte num3 = buffer[offset++];
                num1 |= (num3 & 0x7f) << (num2 & 0x1f);
                num2 += 7;
                if ((num3 & 0x80) == 0)
                {
                    return((uint)num1);
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Reads the specified number of bits into an UInt64 without advancing the read pointer
        /// </summary>
        public UInt64 PeekUInt64(int numberOfBits)
        {
            BitBufferException.Assert((numberOfBits > 0 && numberOfBits <= 64), "ReadUInt() can only read between 1 and 64 bits");
            ReadOverflowException.Assert(_lengthBits - _readPosition >= numberOfBits);

            ulong retval;

            if (numberOfBits <= 32)
            {
                retval = (ulong)BitReaderWriter.ReadUInt32(_data, numberOfBits, _readPosition);
            }
            else
            {
                retval  = BitReaderWriter.ReadUInt32(_data, 32, _readPosition);
                retval |= (UInt64)BitReaderWriter.ReadUInt32(_data, numberOfBits - 32, _readPosition + 32) << 32;
            }
            return(retval);
        }
Beispiel #17
0
        /// <summary>
        /// Reads the specified number of bits into a preallocated array
        /// </summary>
        /// <param name="into">The destination array</param>
        /// <param name="offset">The offset where to start writing in the destination array</param>
        /// <param name="numberOfBits">The number of bits to read</param>
        public BitReader ReadBits(byte[] into, int offset, int numberOfBits)
        {
            ReadOverflowException.Assert(_lengthBits - _readPosition >= numberOfBits);
            BitBufferException.Assert(offset + BitUtility.BytesToHoldBits(numberOfBits) <= into.Length);

            int numberOfWholeBytes = numberOfBits / 8;
            int extraBits          = numberOfBits - (numberOfWholeBytes * 8);

            BitReaderWriter.ReadBytes(_data, numberOfWholeBytes, _readPosition, into, offset);
            _readPosition += (8 * numberOfWholeBytes);

            if (extraBits > 0)
            {
                into[offset + numberOfWholeBytes] = ReadByte(extraBits);
            }

            return(this);
        }
Beispiel #18
0
 /// <summary>
 /// Reads the specified number of bits into an Int64 without advancing the read pointer
 /// </summary>
 public Int64 PeekInt64(int numberOfBits)
 {
     BitBufferException.Assert(((numberOfBits > 0) && (numberOfBits < 65)), "ReadInt64(bits) can only read between 1 and 64 bits");
     return((long)PeekUInt64(numberOfBits));
 }