Exemple #1
0
        public static string ReadNullTerminatedUtf16String(this IReadOnlyBinaryDataAccessor accessor, long offset)
        {
            var         encoding = Encoding.Unicode;
            var         output   = new StringBuilder();
            var         index    = offset;
            Span <char> chars    = stackalloc char[1];

            do
            {
                var length = encoding.GetChars(accessor.ReadSpan(index, 2), chars);
                if (length > 0)
                {
                    output.Append(chars);
                }
                index += 2;
            } while (chars[0] != '\0');
            output.Length -= 1; // Trim the null char
            return(output.ToString());
        }
        public static IBinaryDataAccessor Decompress(IReadOnlyBinaryDataAccessor data)
        {
            var Magic  = data.ReadInt32(0);
            var Length = data.ReadInt32(4);

            IBinaryDataAccessor dest = new BinaryFile(new byte[Length]);

            var dataIndex = 8;
            var destIndex = 0;

            while (true)
            {
                byte cur = data.ReadByte(dataIndex++);

                if (cur < 0x80)
                {
                    var next = data.ReadByte(dataIndex++);

                    // EOF marker
                    if (cur == 0x7F && next == 0xFF)
                    {
                        return(dest);
                    }

                    var offset = 0x400 - ((cur & 3) * 0x100 + next);
                    var bytes  = dest.ReadSpan(destIndex - offset, (cur >> 2) + 2);
                    dest.Write(destIndex, bytes);
                    destIndex += bytes.Length;
                    continue;
                }

                var op  = (Opcode)((cur >> 5) - 4);
                var arg = cur & 0x1F;

                switch (op)
                {
                case Opcode.Copy:
                {
                    var bytes = data.ReadSpan(dataIndex, arg + 1);
                    dataIndex += bytes.Length;
                    dest.Write(destIndex, bytes);
                    destIndex += bytes.Length;
                    break;
                }

                case Opcode.SplitCopy:
                {
                    var sep   = data.ReadByte(dataIndex++);
                    var bytes = data.ReadSpan(dataIndex, arg + 2);
                    dataIndex += bytes.Length;
                    foreach (byte x in bytes)
                    {
                        dest.Write(destIndex++, sep);
                        dest.Write(destIndex++, x);
                    }
                    break;
                }

                case Opcode.Fill:
                {
                    var fill = data.ReadByte(dataIndex++);
                    for (int i = 0; i < arg + 2; i++)
                    {
                        dest.Write(destIndex++, fill);
                    }
                    break;
                }

                case Opcode.Skip:
                {
                    var count = arg < 0x1F ? arg + 1 : 0x20 + data.ReadByte(dataIndex++);
                    destIndex += count;
                    break;
                }
                }
            }
        }