Beispiel #1
0
        private void WriteStructure(MetaDataWriter writer, MetaStructure value)
        {
            var updateStack = new Stack <IMetaValue>();

            // build stack for update...
            var structuresToCheck = new Stack <MetaStructure>();

            structuresToCheck.Push(value);
            while (structuresToCheck.Count > 0)
            {
                var structureToCheck = structuresToCheck.Pop();

                // add structure to list of occurring structures
                usedStructureKeys.Add(structureToCheck.info.StructureKey);

                foreach (var structureEntryToCheck in structureToCheck.Values)
                {
                    if (structureEntryToCheck.Value is MetaArray)
                    {
                        updateStack.Push(structureEntryToCheck.Value);

                        var arrayStructureEntryToCheck = structureEntryToCheck.Value as MetaArray;
                        if (arrayStructureEntryToCheck.Entries != null)
                        {
                            for (int k = arrayStructureEntryToCheck.Entries.Count - 1; k >= 0; k--)
                            {
                                var x = arrayStructureEntryToCheck.Entries[k];
                                if (x is MetaStructure)
                                {
                                    structuresToCheck.Push(x as MetaStructure);
                                }
                                if (x is MetaGeneric)
                                {
                                    updateStack.Push(x);
                                    structuresToCheck.Push((MetaStructure)(x as MetaGeneric).Value);
                                }
                            }
                        }
                    }
                    if (structureEntryToCheck.Value is MetaCharPointer)
                    {
                        updateStack.Push(structureEntryToCheck.Value);
                    }
                    if (structureEntryToCheck.Value is MetaDataBlockPointer)
                    {
                        updateStack.Push(structureEntryToCheck.Value);
                    }
                    if (structureEntryToCheck.Value is MetaGeneric)
                    {
                        updateStack.Push(structureEntryToCheck.Value);

                        var genericStructureEntryToCheck = structureEntryToCheck.Value as MetaGeneric;
                        structuresToCheck.Push((MetaStructure)genericStructureEntryToCheck.Value);
                    }
                    if (structureEntryToCheck.Value is MetaStructure)
                    {
                        structuresToCheck.Push((MetaStructure)structureEntryToCheck.Value);
                    }
                }
            }

            // update structures...
            while (updateStack.Count > 0)
            {
                var v = updateStack.Pop();
                if (v is MetaArray)
                {
                    var arrayValue = (MetaArray)v;
                    if (arrayValue.Entries != null)
                    {
                        if (arrayValue.info.DataType == StructureEntryDataType.Structure)
                        {
                            // WORKAROUND
                            if (arrayValue.IsAlwaysAtZeroOffset)
                            {
                                writer.CreateBlockByNameHash(arrayValue.info.ReferenceKey);
                                writer.Position = writer.Length;
                            }
                            else
                            {
                                writer.SelectBlockByNameHash(arrayValue.info.ReferenceKey);
                                writer.Position = writer.Length;
                            }
                        }
                        else
                        {
                            writer.SelectBlockByNameHash((int)arrayValue.info.DataType);
                            writer.Position = writer.Length;
                        }
                        arrayValue.BlockIndex      = writer.BlockIndex + 1;
                        arrayValue.Offset          = (int)writer.Position;
                        arrayValue.NumberOfEntries = arrayValue.Entries.Count;
                        foreach (var entry in arrayValue.Entries)
                        {
                            entry.Write(writer);
                        }
                    }
                    else
                    {
                        arrayValue.BlockIndex      = 0;
                        arrayValue.Offset          = 0;
                        arrayValue.NumberOfEntries = 0;
                    }
                }
                if (v is MetaCharPointer)
                {
                    var charPointerValue = (MetaCharPointer)v;
                    if (charPointerValue.Value != null)
                    {
                        writer.SelectBlockByNameHash(0x10);
                        writer.Position = writer.Length;
                        charPointerValue.DataBlockIndex = writer.BlockIndex + 1;
                        charPointerValue.DataOffset     = (int)writer.Position;
                        charPointerValue.StringLength   = charPointerValue.Value.Length;
                        charPointerValue.StringCapacity = charPointerValue.Value.Length + 1;
                        writer.Write(charPointerValue.Value);
                    }
                    else
                    {
                        charPointerValue.DataBlockIndex = 0;
                        charPointerValue.DataOffset     = 0;
                        charPointerValue.StringLength   = 0;
                        charPointerValue.StringCapacity = 0;
                    }
                }
                if (v is MetaDataBlockPointer)
                {
                    var charPointerValue = (MetaDataBlockPointer)v;
                    if (charPointerValue.Data != null)
                    {
                        writer.CreateBlockByNameHash(0x11);
                        writer.Position             = 0;
                        charPointerValue.BlockIndex = writer.BlockIndex + 1;
                        writer.Write(charPointerValue.Data);
                    }
                    else
                    {
                        charPointerValue.BlockIndex = 0;
                    }
                }
                if (v is MetaGeneric)
                {
                    var genericValue = (MetaGeneric)v;
                    writer.SelectBlockByNameHash(((MetaStructure)genericValue.Value).info.StructureNameHash);
                    writer.Position         = writer.Length;
                    genericValue.BlockIndex = writer.BlockIndex + 1;
                    genericValue.Offset     = (int)writer.Position / 16;
                    genericValue.Value.Write(writer);
                }
            }

            // now only the root itself is left...
            writer.SelectBlockByNameHash(value.info.StructureNameHash);
            writer.Position = writer.Length;
            value.Write(writer);
        }