示例#1
0
        public Node?ReadNode()
        {
            if (NodeStream.Position >= NodeStream.Length)
            {
                return(null);
            }

            var(nodeType, isArray) = ReadNodeType();

            var name = nodeType switch {
                NodeType.NodeEnd => "",
                NodeType.FileEnd => "",
                _ => _compression switch {
                    Compression.Compressed => Sixbit.Unpack(NodeStream),
                    Compression.Uncompressed => NodeStream.ReadString(NodeStream.ReadUInt8(), _encoding),
                    _ => throw new ArgumentOutOfRangeException()
                }
            };

            return(new Node(name, nodeType, isArray));
        }
示例#2
0
        public KBinReader(byte[] data)
        {
            var document = new XDocument();
            var node     = document.Root;

            var nodeBuffer = new ByteBuffer(data);

            Assert(nodeBuffer.GetU8(), 0xA0);
            var compressedValue = nodeBuffer.GetU8();

            if (compressedValue != 0x42 && compressedValue != 0x45)
            {
                throw new Exception();
            }

            var compressed = compressedValue == 0x42;

            var encodingIndex = nodeBuffer.GetU8();
            var encodingCheck = nodeBuffer.GetU8();

            Assert(encodingCheck, (byte)(encodingIndex ^ 0xFF));

            var encoding = Encodings[encodingIndex >> 5];
            var nodeEnd  = (int)nodeBuffer.GetU32() + 8;

            var dataBuffer = new ByteBuffer(data, nodeEnd);
            var dataSize   = dataBuffer.GetU32();

            var dataByteBuffer = new ByteBuffer(data, nodeEnd);
            var dataWordBuffer = new ByteBuffer(data, nodeEnd);

            document.Declaration = new XDeclaration("1.0", encoding.WebName, "");

            var nodesLeft = true;

            while (nodesLeft)
            {
                while (nodeBuffer.PeekU8() == 0)
                {
                    nodeBuffer.GetU8();
                }

                var nodeType = nodeBuffer.GetU8();
                var isArray  = nodeType >> 6 == 1;
                nodeType &= 0b10111111;

                Formats.TryGetValue(nodeType, out var format);

                var name = "";
                if (nodeType != (byte)Control.NodeEnd && nodeType != (byte)Control.SectionEnd)
                {
                    if (compressed)
                    {
                        name = Sixbit.Decode(nodeBuffer);
                    }
                    else
                    {
                        var length = (nodeBuffer.GetU8() & 0b10111111) + 1;
                        name = encoding.GetString(nodeBuffer.GetBytes(length)).Trim('\0');
                    }
                }

                var skip = true;

                if (nodeType == (byte)Control.Attribute)
                {
                    var readDataAuto = ReadDataAuto(dataBuffer);
                    Array.Reverse(readDataAuto);

                    var value = encoding.GetString(readDataAuto).Trim('\0');
                    node?.SetAttributeValue(name, value);
                }
                else if (nodeType == (byte)Control.NodeEnd)
                {
                    if (node?.Parent != null)
                    {
                        node = node.Parent;
                    }
                }
                else if (nodeType == (byte)Control.SectionEnd)
                {
                    nodesLeft = false;
                }
                else
                {
                    skip = false;
                }

                if (skip)
                {
                    continue;
                }

                var child = new XElement(name);
                node?.Add(child);
                node = child;

                if (nodeType == (byte)Control.NodeStart)
                {
                    continue;
                }

                node.SetAttributeValue("__type", format.Name);

                var count      = format.Count;
                var arrayCount = 1;

                if (count == -1)
                {
                    count   = (int)dataBuffer.GetU32();
                    isArray = true;
                }
                else if (isArray)
                {
                    arrayCount = (int)(dataBuffer.GetU32() / (format.Size * count));
                    node.SetAttributeValue("__count", arrayCount);
                }

                var totalCount = arrayCount * count;

                byte[] nodeData;
                if (isArray)
                {
                    nodeData = dataBuffer.GetBytes(totalCount);
                    dataBuffer.RealignRead();
                }
                else
                {
                    nodeData = ReadDataAligned(dataBuffer, dataByteBuffer, dataWordBuffer, format.Size, format.Count);
                }

                var text = "";
                if (format.Equals(Format.Binary))
                {
                    node.SetAttributeValue("__size", totalCount);

                    Array.Reverse(nodeData);
                    for (var i = 0; i < nodeData.Length; i++)
                    {
                        text += nodeData[i].ToString("x2");
                    }
                }
                else if (format.Equals(Format.String))
                {
                    Array.Reverse(nodeData);
                    text = encoding.GetString(nodeData);
                }
                else if (isArray)
                {
                    for (var i = 0; i < arrayCount; i++)
                    {
                        text = format.FormatToString(nodeData[(i * count)..((i + 1) * count)]) + " " + text;