Ejemplo n.º 1
0
        /// <summary>
        /// Compresses int[] packet data, returns it as a byte[]
        /// </summary>
        /// <param name="input">assumed to be point data (x,x,x,x,x,x,x)</param>
        /// <param name="compression">magic byte specifying the compression to use</param>
        /// <returns></returns>
        internal byte[] CompressPacketData(int[] input, byte compression)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            List <byte> compressedData = new List <byte>();

            //leave room at the beginning of
            //compressedData for the compression header byte
            //which we will add at the end
            compressedData.Add((byte)0);

            if (DefaultCompression == (DefaultCompression & compression))
            {
                compression = GetBestDefHuff(input);
            }
            if (IndexedHuffman == (DefaultCompression & compression))
            {
                DataXform dtxf      = this.HuffModule.FindDtXf(compression);
                HuffCodec huffCodec = this.HuffModule.FindCodec(compression);
                huffCodec.Compress(dtxf, input, compressedData);
                if (((compressedData.Count - 1 /*for the algo byte we just made room for*/) >> 2) > input.Length)
                {
                    //recompress with no compression (gorilla)
                    compression = NoCompression;
                    //reset
                    compressedData.Clear();
                    compressedData.Add((byte)0);
                }
            }
            if (NoCompression == (DefaultCompression & compression))
            {
                bool testDelDel = ((compression & 0x20) != 0);
                compression =
                    this.GorillaCodec.FindPacketAlgoByte(input, testDelDel);

                DeltaDelta dtxf = null;
                if ((compression & 0x20) != 0)
                {
                    dtxf = this.DeltaDelta;
                }

                int inputIndex = 0;
                if (null != dtxf)
                {
                    //multibyteencode the first two values
                    int xfData  = 0;
                    int xfExtra = 0;

                    dtxf.ResetState();
                    dtxf.Transform(input[0], ref xfData, ref xfExtra);
                    this.MultiByteCodec.SignEncode(xfData, compressedData);

                    dtxf.Transform(input[1], ref xfData, ref xfExtra);
                    this.MultiByteCodec.SignEncode(xfData, compressedData);

                    //advance to the third member, we've already read the first two
                    inputIndex = 2;
                }

                //Gorllia time
                int bitCount = (compression & 0x1F);
                this.GorillaCodec.Compress(bitCount,            //the max count of bits required for each int
                                           input,               //the input array to compress
                                           inputIndex,          //the index to start compressing at
                                           dtxf,                //data transform to use when compressing, can be null
                                           compressedData);     //a ref to the compressed data that will be written to
            }

            // compression / algo data always goes in index 0
            compressedData[0] = compression;
            return(compressedData.ToArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// DecompressPacketData - given a compressed byte[], uncompress it to the outputBuffer
        /// </summary>
        /// <param name="input">compressed byte from the ISF stream</param>
        /// <param name="outputBuffer">prealloc'd buffer to write to</param>
        /// <returns></returns>
        internal uint DecompressPacketData(byte[] input, int[] outputBuffer)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (input.Length < 2)
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Input buffer passed was shorter than expected"));
            }
            if (outputBuffer == null)
            {
                throw new ArgumentNullException("outputBuffer");
            }
            if (outputBuffer.Length == 0)
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("output buffer length was zero"));
            }

            byte compression    = input[0];
            uint totalBytesRead = 1; //we just read one
            int  inputIndex     = 1;

            switch (compression & 0xC0)
            {
            case 0x80:    //IndexedHuffman
            {
                DataXform dtxf      = this.HuffModule.FindDtXf(compression);
                HuffCodec huffCodec = this.HuffModule.FindCodec(compression);
                totalBytesRead += huffCodec.Uncompress(dtxf, input, inputIndex, outputBuffer);
                return(totalBytesRead);
            }

            case 0x00:     //NoCompression
            {
                int        outputBufferIndex = 0;
                DeltaDelta dtxf = null;
                if ((compression & 0x20) != 0)
                {
                    dtxf = this.DeltaDelta;
                }

                int bitCount = 0;
                if ((compression & 0x1F) == 0)
                {
                    bitCount = Native.BitsPerInt;        //32
                }
                else
                {
                    bitCount = (compression & 0x1F);
                }

                if (null != dtxf)
                {
                    //must have at least two more bytes besides the
                    //initial algo byte
                    if (input.Length < 3)
                    {
                        throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Input buffer was too short (must be at least 3 bytes)"));
                    }

                    //multibyteencode the first two values
                    int xfData  = 0;
                    int xfExtra = 0;

                    dtxf.ResetState();

                    uint bytesRead =
                        this.MultiByteCodec.SignDecode(input, inputIndex, ref xfData);
                    //advance our index
                    inputIndex     += (int)bytesRead;
                    totalBytesRead += bytesRead;
                    int result = dtxf.InverseTransform(xfData, xfExtra);
                    Debug.Assert(outputBufferIndex < outputBuffer.Length);
                    outputBuffer[outputBufferIndex++] = result;

                    bytesRead =
                        this.MultiByteCodec.SignDecode(input, inputIndex, ref xfData);
                    //advance our index
                    inputIndex     += (int)bytesRead;
                    totalBytesRead += bytesRead;
                    result          = dtxf.InverseTransform(xfData, xfExtra);
                    Debug.Assert(outputBufferIndex < outputBuffer.Length);
                    outputBuffer[outputBufferIndex++] = result;
                }

                totalBytesRead +=
                    this.GorillaCodec.Uncompress(bitCount,              //the max count of bits required for each int
                                                 input,                 //the input array to uncompress
                                                 inputIndex,            //the index to start uncompressing at
                                                 dtxf,                  //data transform to use when compressing, can be null
                                                 outputBuffer,          //a ref to the output buffer to write to
                                                 outputBufferIndex);    //the index of the output buffer to write to

                return(totalBytesRead);
            }

            default:
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid decompression algo byte"));
            }
            }
        }