Beispiel #1
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Little);

            if (magic != Signature && magic.Swap() != Signature)
            {
                throw new FormatException();
            }
            var endian = magic == Signature ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);

            if (version != 1)
            {
                throw new FormatException();
            }

            var rawRootNode = RawNode.Read(input, endian);
            var rootNode    = new Node();

            rootNode.NameHash = rawRootNode.NameHash;

            var instanceQueue = new Queue <Tuple <Node, RawNode> >();

            instanceQueue.Enqueue(new Tuple <Node, RawNode>(rootNode, rawRootNode));

            var propertyQueue = new Queue <Tuple <Node, RawProperty[]> >();

            while (instanceQueue.Count > 0)
            {
                var item    = instanceQueue.Dequeue();
                var node    = item.Item1;
                var rawNode = item.Item2;

                input.Position = basePosition + rawNode.DataOffset;
                var rawProperties = new RawProperty[rawNode.PropertyCount];
                for (int i = 0; i < rawNode.PropertyCount; i++)
                {
                    rawProperties[i] = RawProperty.Read(input, endian);
                }

                input.Position = basePosition +
                                 (rawNode.DataOffset + (RawProperty.Size * rawNode.PropertyCount)).Align(4);
                for (int i = 0; i < rawNode.InstanceCount; i++)
                {
                    var rawChildNode = RawNode.Read(input, endian);
                    var childNode    = new Node();
                    childNode.NameHash = rawChildNode.NameHash;
                    node.Children.Add(childNode);
                    instanceQueue.Enqueue(new Tuple <Node, RawNode>(childNode, rawChildNode));
                }

                propertyQueue.Enqueue(new Tuple <Node, RawProperty[]>(node, rawProperties));
            }

            while (propertyQueue.Count > 0)
            {
                var item          = propertyQueue.Dequeue();
                var node          = item.Item1;
                var rawProperties = item.Item2;

                foreach (var rawProperty in rawProperties)
                {
                    var variant = VariantFactory.GetVariant(rawProperty.Type);

                    if (variant.IsPrimitive == true)
                    {
                        using (var temp = new MemoryStream(rawProperty.Data, false))
                        {
                            variant.Deserialize(temp, endian);

                            if (temp.Position != temp.Length)
                            {
                                throw new InvalidOperationException();
                            }
                        }
                    }
                    else
                    {
                        if (rawProperty.Data.Length != 4)
                        {
                            throw new InvalidOperationException();
                        }

                        uint offset;
                        using (var temp = new MemoryStream(rawProperty.Data, false))
                        {
                            offset = temp.ReadValueU32(endian);
                        }

                        input.Position = basePosition + offset;
                        variant.Deserialize(input, endian);
                    }

                    node.Properties.Add(rawProperty.NameHash, (IVariant)variant);
                }
            }

            this._Root = rootNode;
        }