예제 #1
0
        public static byte[] Decode(byte[] src, int srcOff, int srcLen)
        {
            var len = VarInt.UvarInt(src, srcOff);

            byte[] ret = new byte[len.Value];

            Decode(src, srcOff, srcLen, ret, 0, ret.Length);
            return(ret);
        }
예제 #2
0
        public static int Decode(byte[] source, int sourceOffset, int sourceLength, byte[] destination, int destinationOffset, int destinationLength)
        {
            // Get the uncompressed size
            var len = VarInt.UvarInt(source, sourceOffset);

            // Destination array doesn't have enough room for the decoded data.
            if (destinationLength < (int)len.Value)
            {
                throw new IndexOutOfRangeException("snappy: destination array too short");
            }

            // Adjust the lengths
            sourceLength      += sourceOffset;
            destinationLength += destinationOffset;

            // Current offsets
            int s      = sourceOffset + len.VarIntLength;
            int d      = destinationOffset;
            int offset = 0;
            int length = 0;

            while (s < sourceLength)
            {
                byte tag = (byte)(source[s] & 0x03);
                if (tag == SnappyTag.Literal)
                {
                    uint x = (uint)(source[s] >> 2);
                    if (x < 60)
                    {
                        s += 1;
                    }
                    else if (x == 60)
                    {
                        s += 2;
                        if (s > sourceLength)
                        {
                            throw new IndexOutOfRangeException("snappy: corrupt input");
                        }
                        x = (uint)source[s - 1];
                    }
                    else if (x == 61)
                    {
                        s += 3;
                        if (s > sourceLength)
                        {
                            throw new IndexOutOfRangeException("snappy: corrupt input");
                        }
                        x = (uint)source[s - 2] | (uint)source[s - 1] << 8;
                    }
                    else if (x == 62)
                    {
                        s += 4;
                        if (s > sourceLength)
                        {
                            throw new IndexOutOfRangeException("snappy: corrupt input");
                        }
                        x = (uint)source[s - 3] | (uint)source[s - 2] << 8 | (uint)source[s - 1] << 16;
                    }
                    else if (x == 63)
                    {
                        s += 5;
                        if (s > sourceLength)
                        {
                            throw new IndexOutOfRangeException("snappy: corrupt input");
                        }
                        x = (uint)source[s - 4] | (uint)source[s - 3] << 8 | (uint)source[s - 2] << 16 | (uint)source[s - 1] << 24;
                    }
                    length = (int)(x + 1);
                    if (length <= 0)
                    {
                        throw new IndexOutOfRangeException("snappy: unsupported literal length");
                    }
                    if (length > destinationLength - d || length > sourceOffset + sourceLength - s)
                    {
                        throw new IndexOutOfRangeException("snappy: corrupt input");
                    }
                    Array.Copy(source, s, destination, d, length);
                    d += length;
                    s += length;
                    continue;
                }
                else if (tag == SnappyTag.Copy1)
                {
                    s += 2;
                    if (s > sourceOffset + sourceLength)
                    {
                        throw new IndexOutOfRangeException("snappy: corrupt input");
                    }
                    length = 4 + (((int)source[s - 2] >> 2) & 0x7);
                    offset = ((int)source[s - 2] & 0xe0) << 3 | (int)source[s - 1];
                }
                else if (tag == SnappyTag.Copy2)
                {
                    s += 3;
                    if (s > sourceOffset + sourceLength)
                    {
                        throw new IndexOutOfRangeException("snappy: corrupt input");
                    }
                    length = 1 + ((int)source[s - 3] >> 2);
                    offset = (int)source[s - 2] | (int)source[s - 1] << 8;
                }
                else if (tag == SnappyTag.Copy4)
                {
                    throw new NotSupportedException("snappy: unsupported COPY_4 tag");
                }

                int end = d + length;
                if (offset > d || end > destinationLength)
                {
                    throw new IndexOutOfRangeException("snappy: corrupt input");
                }

                for (; d < end; d++)
                {
                    destination[d] = destination[d - offset];
                }
            }

            return(d);
        }