public void Write(
     Stream data,
     Endian endian,
     DataFormats.PropertySet resource,
     long ownerOffset,
     PropertySetSchemaProvider schemaProvider)
 {
     Write(data, this, endian, resource, ownerOffset, schemaProvider);
 }
示例#2
0
 void IHandler.Write(
     Stream output,
     object value,
     Endian endian,
     long ownerOffset,
     PropertySetSchemaProvider schemaProvider)
 {
     this.Write(output, (T)value, endian, ownerOffset);
 }
        public static PropertySet Read(
            Stream input,
            DataFormats.PropertySet resource,
            Endian endian,
            PropertySetSchemaProvider schemaProvider)
        {
            var instance = new PropertySet();

            instance._Name           = resource.Name;
            instance._ReferenceCount = resource.ReferenceCount;
            instance._SchemaName     = resource.SchemaName;
            instance._Flags          = resource.Flags;

            var parentHandles = new ResourceHandle[resource.ParentCount];

            if (resource.ParentCount > 0)
            {
                input.Position = resource.ParentsOffset;
                for (uint i = 0; i < resource.ParentCount; i++)
                {
                    parentHandles[i] = ResourceHandle.Read(input, endian);
                }
            }
            instance._Parents.Clear();
            instance._Parents.AddRange(parentHandles);

            PropertySetSchema schema;

            if (resource.SchemaName == Symbol.Invalid || resource.SchemaName == resource.Name)
            {
                if ((resource.Flags & PropertyCollectionFlags.InheritSchema) != 0)
                {
                    throw new InvalidOperationException();
                }

                var properties = new PropertySchema[resource.PropertyCount];
                if (resource.PropertyCount > 0)
                {
                    input.Position = resource.PropertiesOffset;
                    for (uint i = 0; i < resource.PropertyCount; i++)
                    {
                        properties[i] = PropertySchema.Read(input, endian);
                    }
                }

                schema = new PropertySetSchema(properties, resource.DataSize);

                if (resource.Name != Symbol.Invalid && resource.SchemaName == resource.Name)
                {
                    schemaProvider.Add(resource.Name.Id, schema);
                }

                instance._DefinedSchema = schema;
            }
            else
            {
                if (resource.PropertyCount != 0)
                {
                    throw new NotSupportedException();
                }

                schema = schemaProvider.Get(resource.SchemaName.Id);
            }

            instance._Properties.Clear();
            instance._DefaultProperties.Clear();

            if (schema.Count > 0)
            {
                if (resource.DataOffset == 0)
                {
                    throw new InvalidOperationException();
                }

                input.Position = resource.DefaultBitsOffset;

                var defaultBits = new uint[(schema.Count + 31) >> 5];
                for (int i = 0; i < defaultBits.Length; i++)
                {
                    defaultBits[i] = input.ReadValueU32(endian);
                }

                input.Position = resource.DataOffset;
                using (var data = input.ReadToMemoryStream(schema.DataSize))
                {
                    for (int i = 0; i < schema.Count; i++)
                    {
                        var property  = schema[i];
                        var isDefault = (defaultBits[i >> 5] & (1u << (i % 32))) != 0;

                        var handler = HandlerFactory.Get(property.Type);

                        data.Position = property.Offset;

                        object value;
                        if (handler.UsesPointer == false)
                        {
                            value = handler.Read(data, endian, schemaProvider);
                        }
                        else
                        {
                            var pointerOffset = data.ReadOffset(endian);
                            if (pointerOffset == 0)
                            {
                                throw new InvalidOperationException();
                            }

                            input.Position = resource.DataOffset + pointerOffset;
                            value          = handler.Read(input, endian, schemaProvider);
                        }

                        instance._Properties.Add(property.Id, value);

                        if (isDefault == true)
                        {
                            instance._DefaultProperties.Add(property.Id);
                        }
                    }
                }
            }

            return(instance);
        }
        public static void Write(
            Stream output,
            PropertySet instance,
            Endian endian,
            DataFormats.PropertySet resource,
            long ownerOffset,
            PropertySetSchemaProvider schemaProvider)
        {
            resource.Flags          = instance._Flags;
            resource.Name           = instance._Name;
            resource.ReferenceCount = instance._ReferenceCount;
            resource.ParentCount    = (ushort)instance._Parents.Count;
            resource.ParentMask     = 0xFFFFFFFFu;
            resource.SchemaName     = instance._SchemaName;
            resource.PropertyMask   = 0xFFFFFFFFu;

            if (resource.ParentCount == 0)
            {
                resource.ParentsOffset = 0;
            }
            else
            {
                resource.ParentsOffset = output.Position;
                foreach (var parentHandle in instance._Parents)
                {
                    parentHandle.Write(output, endian);
                }
            }

            bool writeSchema;
            PropertySetSchema schema;

            if (resource.SchemaName == Symbol.Invalid || resource.SchemaName == resource.Name)
            {
                if ((resource.Flags & PropertyCollectionFlags.InheritSchema) != 0)
                {
                    throw new InvalidOperationException();
                }

                /*
                 * var properties = new List<PropertySchema>();
                 * uint runningOffset = 0;
                 * foreach (var kv in instance.Properties)
                 * {
                 *  var propertyValue = kv.Value;
                 *  if (propertyValue == null)
                 *  {
                 *      throw new InvalidOperationException();
                 *  }
                 *  var handler = HandlerFactory.Get(propertyValue.GetType());
                 *
                 *  runningOffset = runningOffset.Align((uint)handler.Alignment);
                 *
                 *  var propertyId = kv.Key;
                 *  var propertyType = handler.Id;
                 *  var propertyOffset = runningOffset;
                 *
                 *  properties.Add(new PropertySchema(propertyId, propertyType, propertyOffset));
                 *
                 *  if (handler.UsesPointer == false)
                 *  {
                 *      runningOffset += (uint)handler.ByteSize;
                 *  }
                 *  else
                 *  {
                 *      runningOffset += 8;
                 *  }
                 * }
                 *
                 * if (runningOffset > ushort.MaxValue)
                 * {
                 *  throw new InvalidOperationException();
                 * }
                 */

                schema      = instance._DefinedSchema;
                writeSchema = true;

                if (resource.Name != Symbol.Invalid && resource.SchemaName == resource.Name)
                {
                    schemaProvider.Add(resource.Name.Id, schema);
                }

                resource.PropertyCount = (ushort)instance._Properties.Count;
                resource.DataSize      = schema.DataSize;
            }
            else
            {
                if (resource.PropertyCount != 0)
                {
                    throw new NotSupportedException();
                }

                schema      = schemaProvider.Get(resource.SchemaName.Id);
                writeSchema = false;

                resource.PropertyCount = 0;
                resource.DataSize      = 0;
            }

            if (schema.Count == 0)
            {
                resource.PropertiesOffset  = 0;
                resource.DefaultBitsOffset = 0;
                resource.DataOffset        = 0;
            }
            else
            {
                if (writeSchema == true)
                {
                    resource.PropertiesOffset  = output.Position;
                    resource.DefaultBitsOffset = resource.PropertiesOffset + (8 * schema.Count);
                }
                else
                {
                    resource.PropertiesOffset  = 0;
                    resource.DefaultBitsOffset = output.Position;
                }

                resource.DataOffset = resource.DefaultBitsOffset + (((schema.Count + 31) >> 5) * 4);

                var defaultBits = new uint[(schema.Count + 31) >> 5];

                output.Position = (resource.DataOffset + schema.DataSize).Align(16);
                using (var data = new MemoryStream(schema.DataSize))
                {
                    for (int i = 0; i < schema.Count; i++)
                    {
                        var property = schema[i];

                        if (instance.Properties.ContainsKey(property.Id) == false)
                        {
                            throw new InvalidOperationException();
                        }

                        var value   = instance.Properties[property.Id];
                        var handler = HandlerFactory.Get(property.Type);

                        if (instance.DefaultProperties.Contains(property.Id) == true)
                        {
                            defaultBits[i >> 5] |= 1u << (i % 32);
                        }

                        data.Position = property.Offset;

                        if (handler.UsesPointer == false)
                        {
                            handler.Write(data, value, endian, ownerOffset, schemaProvider);
                        }
                        else
                        {
                            output.Position = output.Position.Align(handler.Alignment);
                            var pointerOffset = output.Position - resource.DataOffset;
                            handler.Write(output, value, endian, ownerOffset, schemaProvider);

                            data.WriteOffset(pointerOffset, endian);
                        }
                    }

                    data.Flush();

                    if (data.Length != schema.DataSize)
                    {
                        throw new InvalidOperationException();
                    }

                    var endPosition = output.Position;

                    if (writeSchema == true)
                    {
                        output.Position = resource.PropertiesOffset;
                        for (int i = 0; i < schema.Count; i++)
                        {
                            var property = schema[i];
                            property.Write(output, endian);
                        }
                    }

                    output.Position = resource.DefaultBitsOffset;
                    foreach (var defaultBit in defaultBits)
                    {
                        output.WriteValueU32(defaultBit, endian);
                    }

                    output.Position = resource.DataOffset;
                    data.Position   = 0;
                    output.WriteFromStream(data, schema.DataSize);

                    output.Position = endPosition;
                }
            }
        }
示例#5
0
 object IHandler.Read(Stream input, Endian endian, PropertySetSchemaProvider schemaProvider)
 {
     return(this.Read(input, endian));
 }
示例#6
0
        public static PropertyList Read(
            Stream input,
            DataFormats.PropertyList resource,
            Endian endian,
            PropertySetSchemaProvider schemaProvider)
        {
            var instance = new PropertyList();

            instance._Flags       = resource.Flags;
            instance._TypeId      = (byte)resource.TypeId;
            instance._TotalWeight = resource.TotalWeight;

            instance.Items.Clear();
            instance.Weights.Clear();

            if (resource.ItemCount > 0)
            {
                var handler = HandlerFactory.Get(resource.TypeId);
                if (handler.ByteSize != resource.ItemSize)
                {
                    throw new InvalidOperationException();
                }

                if (resource.DataOffset == 0)
                {
                    throw new InvalidOperationException();
                }

                input.Position = resource.DataOffset;
                using (var data = input.ReadToMemoryStream(resource.ItemCount * resource.ItemSize))
                {
                    for (uint i = 0, o = 0; i < resource.ItemCount; i++, o += resource.ItemSize)
                    {
                        data.Position = o;

                        object item;
                        if (handler.UsesPointer == false)
                        {
                            item = handler.Read(data, endian, schemaProvider);
                        }
                        else
                        {
                            var pointerOffset = data.ReadOffset(endian);
                            if (pointerOffset == 0)
                            {
                                throw new InvalidOperationException();
                            }

                            input.Position = resource.DataOffset + pointerOffset;
                            item           = handler.Read(input, endian, schemaProvider);
                        }
                        instance.Items.Add(item);
                    }
                }

                if (resource.WeightsOffset != 0)
                {
                    input.Position = resource.WeightsOffset;
                    for (uint i = 0; i < resource.ItemCount; i++)
                    {
                        var weight = input.ReadValueU32(endian);
                        instance.Weights.Add(weight);
                    }
                }
            }

            return(instance);
        }
示例#7
0
        public static void Write(
            Stream output,
            PropertyList instance,
            Endian endian,
            DataFormats.PropertyList resource,
            long ownerOffset,
            PropertySetSchemaProvider schemaProvider)
        {
            if (instance.TypeId == 29)
            {
                resource.Flags         = instance._Flags;
                resource.DataOffset    = 0;
                resource.TypeId        = instance._TypeId;
                resource.ItemSize      = 0;
                resource.WeightsOffset = 0;
                resource.ItemCount     = 0;
                resource.TotalWeight   = 0;
                return;
            }

            if (instance.Weights.Count > 0 &&
                instance.Weights.Count != instance.Items.Count)
            {
                throw new InvalidOperationException();
            }

            var handler = HandlerFactory.Get(instance._TypeId);

            resource.Flags       = instance._Flags;
            resource.TypeId      = instance._TypeId;
            resource.ItemSize    = (uint)handler.ByteSize;
            resource.ItemCount   = (uint)instance.Items.Count;
            resource.TotalWeight = instance._TotalWeight;

            var dataSize = resource.ItemSize * resource.ItemCount;

            resource.DataOffset    = output.Position;
            resource.WeightsOffset = resource.DataOffset + dataSize;

            long dataOffset;

            if (instance.Weights.Count > 0)
            {
                resource.WeightsOffset = resource.DataOffset + dataSize;
                dataOffset             = resource.WeightsOffset + (4 * resource.ItemCount);
            }
            else
            {
                dataOffset             = resource.WeightsOffset;
                resource.WeightsOffset = 0;
            }

            if (resource.ItemCount > 0)
            {
                output.Position = dataOffset;

                using (var data = new MemoryStream())
                {
                    foreach (var item in instance.Items)
                    {
                        if (handler.UsesPointer == false)
                        {
                            handler.Write(data, item, endian, ownerOffset, schemaProvider);
                            data.Position = data.Position.Align(handler.Alignment);
                            data.SetLength(data.Position);
                        }
                        else
                        {
                            var pointerOffset = output.Position - resource.DataOffset;
                            handler.Write(output, item, endian, ownerOffset, schemaProvider);
                            output.Position = output.Position.Align(handler.Alignment);

                            data.WriteOffset(pointerOffset, endian);
                            data.Position = data.Position.Align(8);
                            data.SetLength(data.Position);
                        }
                    }

                    data.Flush();

                    if (data.Length != dataSize)
                    {
                        throw new InvalidOperationException();
                    }

                    var endPosition = output.Position;

                    output.Position = resource.DataOffset;
                    data.Position   = 0;
                    output.WriteFromStream(data, data.Length);

                    if (instance.Weights.Count > 0)
                    {
                        output.Position = resource.WeightsOffset;
                        foreach (var weight in instance.Weights)
                        {
                            output.WriteValueU32(weight, endian);
                        }
                    }

                    output.Position = endPosition;
                }
            }
        }