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); }
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); }