예제 #1
0
 /// <summary>
 /// Compress
 /// </summary>
 /// <param name="dataXf">can be null</param>
 /// <param name="input">input array to compress</param>
 /// <param name="compressedData"></param>
 internal void Compress(DataXform dataXf, int[] input, List<byte> compressedData)
 {
     //
     // use the writer to write to the list<byte>
     //
     BitStreamWriter writer = new BitStreamWriter(compressedData);
     if (null != dataXf)
     {
         dataXf.ResetState();
         int xfData = 0;
         int xfExtra = 0;
         for (uint i = 0; i < input.Length; i++)
         {
             dataXf.Transform(input[i], ref xfData, ref xfExtra);
             Encode(xfData, xfExtra, writer);
         }
     }
     else
     {
         for (uint i = 0; i < input.Length; i++)
         {
             Encode(input[i], 0, writer);
         }
     }
 }
예제 #2
0
 public static void WriteUInt64(this BitStreamWriter writer, UInt64 value)
 {
     BitConverterX.UInt64ToUInt32(value, out UInt32 left, out UInt32 right);
     writer.WriteUInt32(left);
     writer.WriteUInt32(right);
 }
예제 #3
0
 public static void WriteUInt16(this BitStreamWriter writer, UInt16 value)
 {
     writer.WriteBits(value, 16);
 }
예제 #4
0
 public static void WriteChar(this BitStreamWriter writer, Char value)
 {
     writer.WriteBits(value, 16);
 }
예제 #5
0
 internal override void WriteToStreamWriter(BitStreamWriter bsw)
 {
     throw new NotImplementedException();
 }
예제 #6
0
 internal override void WriteToStreamWriter(BitStreamWriter bsw)
 {
     bsw.WriteByte((byte)Channel);
     MsgInfo?.WriteToStreamWriter(bsw);
 }
예제 #7
0
 public void Serialize(BitStreamWriter aWriter)
 {
     aWriter.WriteBit(0);
     left.Serialize(aWriter);
     right.Serialize(aWriter);
 }
예제 #8
0
        void WriteDynamicArraySize(BitStreamWriter writer, int count, ArrayDsdlType arrayDsdlType)
        {
            var bitLen = BitSerializer.IntBitLength(arrayDsdlType.MaxSize + 1);

            BitSerializer.Write(writer, count, bitLen);
        }
 public static void Serialize(Single value, BitStreamWriter writer) => writer.WriteFloat32(value);
 public static void Serialize(Byte value, BitStreamWriter writer) => writer.WriteByte(value);
예제 #11
0
 public static void Serialize(object obj, BitStreamWriter writer) => impl.Serialize(obj, writer);
예제 #12
0
        /// <summary>
        /// Creates a 32x32 fingerprint for the specified bitmap.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <returns>Returns a fingerprint with 6 bits per pixel (32 px = 6144 bit = 768 byte = 1024 base32 chars).</returns>
        public static FingerPrint Create(IBitmap32 bitmap)
        {
            using var thumb = bitmap.Resize(32, 32, ResizeMode.TouchFromInside);
            var data = thumb.Data;

            using var ms = new MemoryStream();
            // calculate fingerprint and distance matrix
            var writer         = new BitStreamWriter(ms);
            var distanceMatrix = new float[16];
            {
                int  x = 0, y = 0;
                ARGB last = 0;
                foreach (ARGB pixel in data.Data)
                {
                    if (++x > 15)
                    {
                        x = 0;
                        ++y;
                    }

                    var r = pixel.Red >> 6;
                    var g = pixel.Green >> 6;
                    var b = pixel.Blue >> 6;
                    writer.WriteBits(r, 2);
                    writer.WriteBits(g, 2);
                    writer.WriteBits(b, 2);

                    unchecked
                    {
                        var i        = ((y << 1) & 0xC) + (x >> 2);
                        var distance = Math.Abs(pixel.GetDistance(last));
                        distanceMatrix[i] += distance;
                        last = pixel;
                    }
                }
            }

            // normalize matrix
            var maxDistance = distanceMatrix.Max();

            for (var i = 0; i < distanceMatrix.Length; i++)
            {
                distanceMatrix[i] /= maxDistance;
            }

            // calculate blocks
            var blocks = new uint[4];
            var index  = new int[] { 0, 2, 8, 10 };

            for (var i = 0; i < 4; i++)
            {
                var idx        = index[i];
                var blockValue = (uint)(255 * distanceMatrix[idx]) << 24;
                blockValue |= (uint)(255 * distanceMatrix[idx + 1]) << 16;
                blockValue |= (uint)(255 * distanceMatrix[idx + 4]) << 8;
                blockValue |= (uint)(255 * distanceMatrix[idx + 5]);
                blocks[i]   = blockValue;
            }

            /*
             * uint b1 = (uint)(uint.MaxValue * (distanceMatrix[0] + distanceMatrix[1]  + distanceMatrix[4] + distanceMatrix[5]) /4);
             * uint b2 = (uint)(uint.MaxValue * (distanceMatrix[3] + distanceMatrix[2]  + distanceMatrix[7] + distanceMatrix[6]) / 4);
             * uint b3 = (uint)(uint.MaxValue * (distanceMatrix[12] + distanceMatrix[13]  + distanceMatrix[8]  + distanceMatrix[9]) / 4);
             * uint b4 = (uint)(uint.MaxValue * (distanceMatrix[15] + distanceMatrix[14]  + distanceMatrix[11] + distanceMatrix[10]) / 4);
             */
            return(new FingerPrint(32, blocks, ms.ToArray()));
        }
예제 #13
0
        void WriteUnionFieldIndex(BitStreamWriter writer, int index, CompositeDsdlTypeBase t)
        {
            var bitLen = BitSerializer.IntBitLength(t.Fields.Count);

            BitSerializer.Write(writer, index, bitLen);
        }
예제 #14
0
        void SerializeObjectCore(
            BitStreamWriter writer,
            Func <string, ResolvedProperty?> propertyResolver,
            ContainerContract containerContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization)
        {
            var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(containerContract, derivedDsdlType);

            //WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

            VoidDsdlType voidDsdlType      = null;
            int          voidDsdlTypeIndex = -1;
            var          isUnion           = dsdlScheme.IsUnion;
            var          unionMemberFound  = false;

            for (int i = 0; i < dsdlScheme.Fields.Count; i++)
            {
                var dsdlMember   = dsdlScheme.Fields[i];
                var isLastMember = i == dsdlScheme.Fields.Count - 1;

                if ((voidDsdlType = (dsdlMember.Type as VoidDsdlType)) != null)
                {
                    voidDsdlTypeIndex = i;
                    if (!isUnion)
                    {
                        WriteAlignment(writer, voidDsdlType);
                    }
                    continue;
                }

                var resolvedProp = propertyResolver(dsdlMember.Name);

                if (isUnion)
                {
                    if (resolvedProp == null)
                    {
                        continue;
                    }
                    if (unionMemberFound)
                    {
                        throw new InvalidOperationException($"Cannot find single union value for type '{containerContract.UnderlyingType.FullName}'.");
                    }
                    unionMemberFound = true;
                    WriteUnionFieldIndex(writer, i, dsdlScheme);
                    var rp = resolvedProp.Value;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type);
                }
                else
                {
                    if (resolvedProp == null)
                    {
                        throw new InvalidOperationException($"Cannot resove member '{containerContract.UnderlyingType.FullName}.{dsdlMember.Name}'.");
                    }
                    var rp  = resolvedProp.Value;
                    var tao = tailArrayOptimization &&
                              isLastMember &&
                              dsdlMember.Type is ArrayDsdlType adt;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type, tao);
                }
            }

            if (isUnion && !unionMemberFound)
            {
                if (voidDsdlType != null)
                {
                    WriteUnionFieldIndex(writer, voidDsdlTypeIndex, dsdlScheme);
                    WriteAlignment(writer, voidDsdlType);
                }
                else
                {
                    throw new InvalidOperationException($"Cannot find union value for '{containerContract.UnderlyingType.FullName}' type.");
                }
            }
        }
 public static void Serialize(Boolean value, BitStreamWriter writer) => writer.WriteBool(value);
예제 #16
0
        /// <summary>
        /// Compress - compresses the byte[] being read by the BitStreamReader into compressed data
        /// </summary>
        /// <param name="bitCount">the number of bits to use for each element</param>
        /// <param name="reader">a reader over the byte[] to compress</param>
        /// <param name="encodingType">int, short or byte?</param>
        /// <param name="unitsToEncode">number of logical units to encoded</param>
        /// <param name="compressedData">output write buffer</param>
        internal void Compress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToEncode, List<byte> compressedData)
        {
            if (null == reader || null == compressedData)
            {
                throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("reader or compressedData was null in compress"));
            }
            if (bitCount < 0)
            {
                throw new ArgumentOutOfRangeException("bitCount");
            }
            if (unitsToEncode < 0)
            {
                throw new ArgumentOutOfRangeException("unitsToEncode");
            }

            if (bitCount == 0)
            {
                //adjust if the bitcount is 0
                //(this makes bitCount 32)
                switch (encodingType)
                {
                    case GorillaEncodingType.Int:
                        {
                            bitCount = Native.BitsPerInt;
                            break;
                        }
                    case GorillaEncodingType.Short:
                        {
                            bitCount = Native.BitsPerShort;
                            break;
                        }
                    case GorillaEncodingType.Byte:
                        {
                            bitCount = Native.BitsPerByte;
                            break;
                        }
                    default:
                        {
                            throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to compress"));
                        }
                }
            }

            //have the writer adapt to the List<byte> passed in and write to it
            BitStreamWriter writer = new BitStreamWriter(compressedData);
            while (!reader.EndOfStream && unitsToEncode > 0)
            {
                int data = GetDataFromReader(reader, encodingType);
                writer.Write((uint)data, bitCount);
                unitsToEncode--;
            }
        }
 public static void Serialize(ref Char value, BitStreamWriter writer) => writer.WriteChar(value);
예제 #18
0
        /// <summary>
        /// Decodes a single pixel row.
        /// </summary>
        public byte[] DecodeRow(byte[] data)
        {
            Reset(CCITT4DecoderState.White);
            var reader = new BitStreamReaderReverse(new MemoryStream(data));
            var writer = new BitStreamWriter(new MemoryStream());

            while (reader.Position < reader.Length)
            {
                // read a bit
                currentValue = (currentValue << 1) | reader.ReadBit();
                currentBitLength++;
                if (currentBitLength > 13)
                {
                    throw new FormatException();
                }

                // did we get a EndOfLine code ?
                if ((currentBitLength == EOL[1]) && (currentValue == EOL[0]))
                {
                    Reset(0);
                    continue;
                }
                if (state == 0)
                {
                    // white makeup search
                    for (var i = 0; i < WhiteMakeUpCodes.GetLength(0); i++)
                    {
                        if ((WhiteMakeUpCodes[i, 1] == currentBitLength) &&
                            (WhiteMakeUpCodes[i, 0] == currentValue))
                        {
                            writer.WriteBits(WhiteMakeUpCodes[i, 2], true);
                            Reset(CCITT4DecoderState.WhiteTerminationRequired);
                            break;
                        }
                    }
                    if (state != 0)
                    {
                        continue;
                    }
                }
                if ((int)state <= 1)
                {
                    // white termination search
                    for (var i = 0; i < WhiteTerminatingCodes.GetLength(0); i++)
                    {
                        if ((WhiteTerminatingCodes[i, 1] == currentBitLength) &&
                            (WhiteTerminatingCodes[i, 0] == currentValue))
                        {
                            writer.WriteBits(i, true);
                            Reset(CCITT4DecoderState.Black);
                            break;
                        }
                    }
                    if ((int)state != 1)
                    {
                        continue;
                    }
                }
                if ((int)state == 2)
                {
                    // black makeup search
                    for (var i = 0; i < BlackMakeUpCodes.GetLength(0); i++)
                    {
                        if ((BlackMakeUpCodes[i, 1] == currentBitLength) &&
                            (BlackMakeUpCodes[i, 0] == currentValue))
                        {
                            writer.WriteBits(BlackMakeUpCodes[i, 2], false);
                            Reset(CCITT4DecoderState.BlackTerminationRequired);
                            break;
                        }
                    }
                    if ((int)state != 2)
                    {
                        continue;
                    }
                }
                if ((int)state >= 2)
                {
                    // black termination search
                    for (var i = 0; i < BlackTerminatingCodes.GetLength(0); i++)
                    {
                        if ((BlackTerminatingCodes[i, 1] == currentBitLength) &&
                            (BlackTerminatingCodes[i, 0] == currentValue))
                        {
                            writer.WriteBits(i, false);
                            Reset(CCITT4DecoderState.White);
                            break;
                        }
                    }
                    if ((int)state != 3)
                    {
                        continue;
                    }
                }
            }
            return(((MemoryStream)writer.BaseStream).ToArray());
        }
 public static void Serialize(ref Vector3Int value, BitStreamWriter writer) => writer.WriteVector3Int(value);
예제 #20
0
 public void Serialize(BitStreamWriter aWriter)
 {
     aWriter.WriteBit(1);
     aWriter.WriteBits(data, 8);
 }
 public static void Serialize(ref DateTime value, BitStreamWriter writer)
 {
     Log.Assert(value.Kind == DateTimeKind.Utc, "DateTime must be UTC");
     writer.WriteInt64(value.Ticks);
 }
예제 #22
0
 public static void Write(BitStreamWriter destination, double value, int bitLength) =>
 Write(destination, b => LittleEndianBitConverter.FillBytes(value, b), bitLength);
 public static void Serialize(ref UInt64 value, BitStreamWriter writer) => writer.WriteUInt64(value);
 public static void Serialize(ref Entity value, BitStreamWriter writer)
 {
     writer.WriteInt32(value.Index);
     writer.WriteInt32(value.Version);
 }
 public static void Serialize(UInt32 value, BitStreamWriter writer) => writer.WriteUInt32(value);
예제 #26
0
 public static void WriteInt32(this BitStreamWriter writer, Int32 value)
 {
     writer.WriteBits(BitConverterX.Int32ToUInt32(value), 32);
 }
 public static void Serialize(Int16 value, BitStreamWriter writer) => writer.WriteInt16(value);
예제 #28
0
 public static void WriteUInt32(this BitStreamWriter writer, UInt32 value)
 {
     writer.WriteBits(value, 32);
 }
예제 #29
0
 internal override void WriteToStreamWriter(BitStreamWriter bsw)
 {
 }
예제 #30
0
        /// <summary>
        /// Encode
        /// </summary>
        /// <param name="data"></param>
        /// <param name="extra"></param>
        /// <param name="writer"></param>
        /// <returns>number of bits encoded, 0 for failure</returns>
        internal byte Encode(int data, int extra, BitStreamWriter writer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (data == 0)
            {
                writer.Write((byte)0, 1); //more efficent
                return (byte)1;
            }
            
            // First, encode extra if non-ZERO
            uint bitSize = _huffBits.GetSize();
            if (0 != extra)
            {
                // Prefix lenght is 1 more than table size
                byte extraPrefixLength = (byte)(bitSize + 1);
                int extraPrefix = ((1 << extraPrefixLength) - 2);

                writer.Write((uint)extraPrefix, (int)extraPrefixLength);

                // Encode the extra data first
                byte extraCodeLength = Encode(extra, 0, writer);
                // Encode the actual data next
                byte dataCodeLength = Encode(data, 0, writer);
                // Return the total code lenght
                return (byte)((int)extraPrefixLength + (int)extraCodeLength + (int)dataCodeLength);
            }
            // Find the absolute value of the data
            // IMPORTANT : It is extremely important that nData is uint, and NOT int
            // If it is int, the LONG_MIN will be encoded erroneaouly
            uint nData = (uint)MathHelper.AbsNoThrow(data);
            // Find the prefix lenght
            byte nPrefLen = 1;
            for (; (nPrefLen < bitSize) && (nData >= _mins[nPrefLen]); ++nPrefLen) ;
            // Get the data length
            uint nDataLen = _huffBits.GetBitsAtIndex((uint)nPrefLen - 1);

            // Find the prefix
            int nPrefix = ((1 << nPrefLen) - 2);
            // Append the prefix to the bit stream
            writer.Write((uint)nPrefix, (int)nPrefLen);
            // Find the data offset by lower bound
            // and append sign bit at LSB
            Debug.Assert(nDataLen > 0 && nDataLen - 1 <= Int32.MaxValue);
            int dataLenMinusOne = (int)(nDataLen - 1); //can't left shift by a uint, we need to thunk to an int
            nData = ((((nData - _mins[nPrefLen - 1]) & (uint)((1 << dataLenMinusOne) - 1)) << 1) | (uint)((data < 0) ? 1 : 0));
            // Append data into the bit streamdataLenMinusOne
            Debug.Assert(nDataLen <= Int32.MaxValue);
            writer.Write(nData, (int)nDataLen);

            return (byte)((uint)nPrefLen + nDataLen);
        }
        /// <summary>
        /// Encode
        /// </summary>
        /// <param name="data"></param>
        /// <param name="extra"></param>
        /// <param name="writer"></param>
        /// <returns>number of bits encoded, 0 for failure</returns>
        internal byte Encode(int data, int extra, BitStreamWriter writer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (data == 0)
            {
                writer.Write((byte)0, 1); //more efficent
                return((byte)1);
            }

            // First, encode extra if non-ZERO
            uint bitSize = _huffBits.GetSize();

            if (0 != extra)
            {
                // Prefix lenght is 1 more than table size
                byte extraPrefixLength = (byte)(bitSize + 1);
                int  extraPrefix       = ((1 << extraPrefixLength) - 2);

                writer.Write((uint)extraPrefix, (int)extraPrefixLength);

                // Encode the extra data first
                byte extraCodeLength = Encode(extra, 0, writer);
                // Encode the actual data next
                byte dataCodeLength = Encode(data, 0, writer);
                // Return the total code lenght
                return((byte)((int)extraPrefixLength + (int)extraCodeLength + (int)dataCodeLength));
            }
            // Find the absolute value of the data
            // IMPORTANT : It is extremely important that nData is uint, and NOT int
            // If it is int, the LONG_MIN will be encoded erroneaouly
            uint nData = (uint)MathHelper.AbsNoThrow(data);
            // Find the prefix lenght
            byte nPrefLen = 1;

            for (; (nPrefLen < bitSize) && (nData >= _mins[nPrefLen]); ++nPrefLen)
            {
                ;
            }
            // Get the data length
            uint nDataLen = _huffBits.GetBitsAtIndex((uint)nPrefLen - 1);

            // Find the prefix
            int nPrefix = ((1 << nPrefLen) - 2);

            // Append the prefix to the bit stream
            writer.Write((uint)nPrefix, (int)nPrefLen);
            // Find the data offset by lower bound
            // and append sign bit at LSB
            Debug.Assert(nDataLen > 0 && nDataLen - 1 <= Int32.MaxValue);
            int dataLenMinusOne = (int)(nDataLen - 1); //can't left shift by a uint, we need to thunk to an int

            nData = ((((nData - _mins[nPrefLen - 1]) & (uint)((1 << dataLenMinusOne) - 1)) << 1) | (uint)((data < 0) ? 1 : 0));
            // Append data into the bit streamdataLenMinusOne
            Debug.Assert(nDataLen <= Int32.MaxValue);
            writer.Write(nData, (int)nDataLen);

            return((byte)((uint)nPrefLen + nDataLen));
        }
예제 #32
0
        /// <summary>
        /// Compress - compress the input[] into compressedData
        /// </summary>
        /// <param name="bitCount">The count of bits needed for all elements</param>
        /// <param name="input">input buffer</param>
        /// <param name="startInputIndex">offset into the input buffer</param>
        /// <param name="dtxf">data transform.  can be null</param>
        /// <param name="compressedData">The list of bytes to write the compressed input to</param>
        internal void Compress(int bitCount, int[] input, int startInputIndex, DeltaDelta dtxf, List<byte> compressedData)
        {
            if (null == input || null == compressedData)
            {
                throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("input or compressed data was null in Compress"));
            }
            if (bitCount < 0)
            {
                throw new ArgumentOutOfRangeException("bitCount");
            }

            if (bitCount == 0)
            {
                //adjust if the bitcount is 0
                //(this makes bitCount 32)
                bitCount = (int)(Native.SizeOfInt << 3);
            }

            //have the writer adapt to the List<byte> passed in and write to it
            BitStreamWriter writer = new BitStreamWriter(compressedData);
            if (null != dtxf)
            {
                int xfData = 0;
                int xfExtra = 0;
                for (int i = startInputIndex; i < input.Length; i++)
                {
                    dtxf.Transform(input[i], ref xfData, ref xfExtra);
                    if (xfExtra != 0)
                    {
                        throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage("Transform returned unexpected results"));
                    }
                    writer.Write((uint)xfData, bitCount);
                }
            }
            else
            {
                for (int i = startInputIndex; i < input.Length; i++)
                {
                    writer.Write((uint)input[i], bitCount);
                }
            }
        }
        /// <summary>
        /// Uncompress - uncompress the byte[] in the reader to a byte[] to return
        /// </summary>
        /// <param name="bitCount">number of bits each element is compressed to</param>
        /// <param name="reader">a reader over the compressed byte[]</param>
        /// <param name="encodingType">int, short or byte?</param>
        /// <param name="unitsToDecode">number of logical units to decode</param>
        /// <returns>Uncompressed byte[]</returns>
        internal byte[] Uncompress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToDecode)
        {
            if (null == reader)
            {
                throw new ArgumentNullException("reader");
            }
            if (bitCount < 0)
            {
                throw new ArgumentOutOfRangeException("bitCount");
            }
            if (unitsToDecode < 0)
            {
                throw new ArgumentOutOfRangeException("unitsToDecode");
            }

            int bitsToWrite = 0;

            // Test whether the items are signed. For unsigned number, we don't need mask
            // If we are trying to compress signed long values with bit count = 5
            // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th
            // bit is 1, the number is negative numbe, othrwise it's positive. Testing
            // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask
            // otherwise we leave the number as it is.
            uint bitMask = 0;

            //adjust if the bitcount is 0
            //(this makes bitCount 32)
            switch (encodingType)
            {
            case GorillaEncodingType.Int:
            {
                if (bitCount == 0)
                {
                    bitCount = Native.BitsPerInt;
                }
                bitsToWrite = Native.BitsPerInt;
                //we decode int's as unsigned, so we need to create a mask
                bitMask = (unchecked ((uint)~0) << (bitCount - 1));
                break;
            }

            case GorillaEncodingType.Short:
            {
                if (bitCount == 0)
                {
                    bitCount = Native.BitsPerShort;
                }
                bitsToWrite = Native.BitsPerShort;
                //shorts are decoded as unsigned values, no mask required
                bitMask = 0;
                break;
            }

            case GorillaEncodingType.Byte:
            {
                if (bitCount == 0)
                {
                    bitCount = Native.BitsPerByte;
                }
                bitsToWrite = Native.BitsPerByte;
                //bytes are decoded as unsigned values, no mask required
                bitMask = 0;
                break;
            }

            default:
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to Uncompress"));
            }
            }
            List <byte>     output  = new List <byte>((bitsToWrite / 8) * unitsToDecode);
            BitStreamWriter writer  = new BitStreamWriter(output);
            uint            bitData = 0;

            while (!reader.EndOfStream && unitsToDecode > 0)
            {
                //we're going to cast to an uint anyway, just read as one
                bitData = reader.ReadUInt32(bitCount);
                // Construct the item
                bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData;
                writer.WriteReverse(bitData, bitsToWrite);
                unitsToDecode--;
            }

            return(output.ToArray());
        }
예제 #34
0
        /// <summary>
        /// Uncompress - uncompress the byte[] in the reader to a byte[] to return
        /// </summary>
        /// <param name="bitCount">number of bits each element is compressed to</param>
        /// <param name="reader">a reader over the compressed byte[]</param>
        /// <param name="encodingType">int, short or byte?</param>
        /// <param name="unitsToDecode">number of logical units to decode</param>
        /// <returns>Uncompressed byte[]</returns>
        internal byte[] Uncompress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToDecode)
        {
            if (null == reader)
            {
                throw new ArgumentNullException("reader");
            }
            if (bitCount < 0)
            {
                throw new ArgumentOutOfRangeException("bitCount");
            }
            if (unitsToDecode < 0)
            {
                throw new ArgumentOutOfRangeException("unitsToDecode");
            }

            int bitsToWrite = 0;

            // Test whether the items are signed. For unsigned number, we don't need mask
            // If we are trying to compress signed long values with bit count = 5
            // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th
            // bit is 1, the number is negative numbe, othrwise it's positive. Testing
            // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask
            // otherwise we leave the number as it is.
            uint bitMask = 0;
            //adjust if the bitcount is 0
            //(this makes bitCount 32)
            switch (encodingType)
            {
                case GorillaEncodingType.Int:
                    {
                        if (bitCount == 0)
                        {
                            bitCount = Native.BitsPerInt;
                        }
                        bitsToWrite = Native.BitsPerInt;
                        //we decode int's as unsigned, so we need to create a mask
                        bitMask = (unchecked((uint)~0) << (bitCount - 1));
                        break;
                    }
                case GorillaEncodingType.Short:
                    {
                        if (bitCount == 0)
                        {
                            bitCount = Native.BitsPerShort;
                        }
                        bitsToWrite = Native.BitsPerShort;
                        //shorts are decoded as unsigned values, no mask required
                        bitMask = 0;
                        break;
                    }
                case GorillaEncodingType.Byte:
                    {
                        if (bitCount == 0)
                        {
                            bitCount = Native.BitsPerByte;
                        }
                        bitsToWrite = Native.BitsPerByte;
                        //bytes are decoded as unsigned values, no mask required
                        bitMask = 0;
                        break;
                    }
                default:
                    {
                        throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to Uncompress"));
                    }
            }
            List<byte> output = new List<byte>((bitsToWrite / 8) * unitsToDecode);
            BitStreamWriter writer = new BitStreamWriter(output);
            uint bitData = 0;

            while (!reader.EndOfStream && unitsToDecode > 0)
            {
                //we're going to cast to an uint anyway, just read as one
                bitData = reader.ReadUInt32(bitCount);
                // Construct the item
                bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData;
                writer.WriteReverse(bitData, bitsToWrite);
                unitsToDecode--;
            }

            return output.ToArray();
        }
예제 #35
0
        void SerializeList(
            BitStreamWriter writer,
            IEnumerable values,
            IContract contract,
            IContract finalItemContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization)
        {
            if (!(derivedDsdlType is ArrayDsdlType arrayDsdlType))
            {
                throw new InvalidOperationException($"Array DSDL type expected for type '{contract.UnderlyingType.FullName}'.");
            }

            object underlyingList = values is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : values;

            _serializeStack.Push(underlyingList);

            var arrayCount = values.Count();

            switch (arrayDsdlType.Mode)
            {
            case ArrayDsdlTypeMode.Dynamic:
            {
                if (arrayCount > arrayDsdlType.MaxSize)
                {
                    throw new SerializationException($"'{contract.UnderlyingType.FullName}' is too big. MaxSize is {arrayDsdlType.MaxSize}.");
                }
                if (!tailArrayOptimization || arrayDsdlType.ElementType.MinBitlen < 8)
                {
                    WriteDynamicArraySize(writer, arrayCount, arrayDsdlType);
                }
                else
                {
                    tailArrayOptimization = false;
                }
                break;
            }

            case ArrayDsdlTypeMode.Static:
            {
                if (arrayCount != arrayDsdlType.MaxSize)
                {
                    throw new SerializationException($"'{contract.UnderlyingType.FullName}' expected size is {arrayDsdlType.MaxSize}.");
                }
                break;
            }
            }

            // Note: an exception from the IEnumerable won't be caught.
            int i = 0;

            foreach (object value in values)
            {
                i++;

                var valueContract = finalItemContract ??
                                    (value == null ? null : _serializer.ContractResolver.ResolveContract(value.GetType()));

                if (!CheckForCircularReference(value, null, valueContract))
                {
                    continue;
                }

                if (!CheckDsdlTypeCompatibility(arrayDsdlType.ElementType, valueContract))
                {
                    throw new InvalidOperationException(
                              $"DSDL type mismatch for enumerated item '{contract.UnderlyingType.FullName}.{valueContract.UnderlyingType}'.");
                }

                var tao = i == arrayCount ? tailArrayOptimization : false;
                SerializeValue(writer, value, valueContract, arrayDsdlType.ElementType, tao);
            }

            //writer.WriteEndArray();

            _serializeStack.Pop();
        }