Exemple #1
0
        object IHandler.Read(Stream input, Endian endian, PropertySetSchemaProvider schemaProvider)
        {
            var resource = new DataFormats.PropertySet();

            resource.Deserialize(input, endian);
            return(PropertySet.Read(input, resource, endian, schemaProvider));
        }
 public void Write(
     Stream data,
     Endian endian,
     DataFormats.PropertySet resource,
     long ownerOffset,
     PropertySetSchemaProvider schemaProvider)
 {
     Write(data, this, endian, resource, ownerOffset, schemaProvider);
 }
Exemple #3
0
        public void Write(Stream output, object value, Endian endian, long ownerOffset, PropertySetSchemaProvider schemaProvider)
        {
            var startPosition = output.Position;
            var resource      = new DataFormats.PropertySet();

            output.Position += resource.Size;

            ((PropertySet)value).Write(output, endian, resource, startPosition, schemaProvider);

            var endPosition = output.Position;

            output.Position      = startPosition;
            resource.OwnerOffset = ownerOffset;
            resource.Serialize(output, endian);

            output.Position = endPosition;
        }
        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;
                }
            }
        }