Ejemplo n.º 1
0
        public static Base Read(Stream stream)
        {
            var b = (byte)stream.ReadByte();
            bool f = (b & 0x80) == 0x80;
            if (!f) throw new UnknownValueFlagException();

            var valueType = stream.ReadUtf8String(b & 0x7f);
            var tmp = new byte[4];
            stream.FillInBuffer(tmp, 2);
            int valueLength = BitConverter.ToUInt16(tmp, 0);

            if (valueLength == 0xffff)
                valueLength = stream.ReadInt32() - 4; //todo: shouldn't it be 6???
            else
            {
                stream.FillInBuffer(tmp, 2, tmp.Length - 2);
                valueLength = BitConverter.ToInt32(tmp, 0);
            }

            tmp = new byte[valueLength];
            stream.FillInBuffer(tmp);

            switch (valueType)
            {
                case "Uint8":
                    return new Uint8(tmp);
                case "Uint16":
                    return new Uint16(tmp);
                case "Uint":
                    return new Uint(tmp);
                case "Uint64":
                    return new Uint64(tmp);
                case "Int8":
                    return new Int8(tmp);
                case "Int16":
                    return new Int16(tmp);
                case "Int":
                    return new Int(tmp);
                case "Int64":
                    return new Int64(tmp);
                case "String":
                    return new String(tmp);
                case "CGUID":
                    return new CGuid(tmp);
                case "Bool":
                    return new Bool(tmp);
                case "SQuestLogPhaseStatus":
                    return new SQuestLogPhaseStatus(tmp);
                default:
                    return new UnknownValueType(tmp){valueTypeName = valueType};
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Decompresses the data using LibLZF algorithm
        /// </summary>
        /// <param name="input">Reference to the data to decompress</param>
        /// <param name="inputLength">Lenght of the data to decompress</param>
        /// <param name="output">Reference to a buffer which will contain the decompressed data</param>
        /// <param name="outputLength">The size of the decompressed archive in the output buffer</param>
        /// <returns>Returns decompressed size</returns>
        public static int Decompress(this Stream input, Stream output, long inputLength, long outputLength)
        {
            uint readBytes = 0;
            uint writtenBytes = 0;

            do
            {
                var ctrl = (uint)input.ReadByte();
                readBytes++;

                if (ctrl < (1 << 5)) /* literal run */
                {
                    ctrl++;

                    if (writtenBytes + ctrl > outputLength)
                        throw new InvalidOperationException("LZF decompression error E2BIG.");

                    var tmp = new byte[ctrl];
                    input.FillInBuffer(tmp);
                    readBytes += ctrl;
                    output.Write(tmp, 0, tmp.Length);
                    writtenBytes += ctrl;
                }
                else /* back reference */
                {
                    uint len = ctrl >> 5;

                    int reference = (int)(writtenBytes - ((ctrl & 0x1f) << 8) - 1);

                    if (len == 7)
                    {
                        len += (uint)input.ReadByte();
                        readBytes++;
                    }

                    reference -= input.ReadByte();
                    readBytes++;

                    if (writtenBytes + len + 2 > outputLength)
                        throw new InvalidOperationException("LZF decompression error E2BIG.");

                    if (reference < 0)
                        throw new InvalidOperationException("LZF decompression error EINVAL.");

                    var currentPosition = output.Position;
                    output.Seek(reference, SeekOrigin.Begin);
                    var patternLength = len + 2;

                    /*
                     * fun part is when pattern length is longer than we have
                     * so, if we have  'abcdef' in output and have to write a pattern of length 7, starting from d,
                     * we have to have 'abcdefdefdefd' in the end.
                     */
                    var tmp = new byte[Math.Min(currentPosition - reference, patternLength)];
                    var read = output.FillInBuffer(tmp);
                    if (read != tmp.Length)
                        throw new InvalidOperationException(string.Format("Expected {0} bytes to be read, but was {1}", tmp.Length, read));
                    output.Seek(currentPosition, SeekOrigin.Begin);

                    //making copies until we write a pattern of given length
                    do
                    {
                        var blockSize = (int)Math.Min(tmp.Length, patternLength);
                        output.Write(tmp, 0, blockSize);
                        patternLength -= (uint)blockSize;
                    } while (patternLength > 0);
                    writtenBytes += len + 2;
                }
            }
            while (readBytes < inputLength);

            return (int)writtenBytes;
        }