Ejemplo n.º 1
0
        /// <summary>
        /// Serializes a data reference composed of raw bytes.
        /// </summary>
        /// <param name="tagStream">The stream to write completed blocks of tag data to.</param>
        /// <param name="block">The temporary block to write incomplete tag data to.</param>
        /// <param name="data">The data.</param>
        /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
        private static void SerializeDataReference(MemoryStream tagStream, IDataBlock block, byte[] data, TagFieldAttribute valueInfo)
        {
            var writer = block.Writer;
            uint offset = 0;
            uint size = 0;
            if (data != null && data.Length > 0)
            {
                // Ensure the block is aligned correctly
                var align = Math.Max(DefaultBlockAlign, (valueInfo != null) ? valueInfo.DataAlign : 0);
                StreamUtil.Align(tagStream, (int)align);

                // Write its data
                offset = (uint)tagStream.Position;
                size = (uint)data.Length;
                tagStream.Write(data, 0, data.Length);
                StreamUtil.Align(tagStream, DefaultBlockAlign);
            }

            // Write the reference data
            writer.Write(size);
            writer.Write(0);
            writer.Write(0);
            if (size > 0)
                block.WritePointer(offset, typeof(byte[]));
            else
                writer.Write(0);
            writer.Write(0);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Determines whether a field exists in the given CacheVersion. Defines a priority : Version, Gen, Min/Max.
 /// </summary>
 /// <param name="attr"></param>
 /// <param name="compare"></param>
 /// <returns></returns>
 public static bool AttributeInCacheVersion(TagFieldAttribute attr, CacheVersion compare)
 {
     if (attr.Version != CacheVersion.Unknown)
     {
         // has a specific version specified.
         return(attr.Version == compare);
     }
     else if (attr.Gen != CacheGeneration.Unknown)
     {
         // Has a generation specified
         return(IsInGen(attr.Gen, compare));
     }
     else if (attr.MinVersion != CacheVersion.Unknown || attr.MaxVersion != CacheVersion.Unknown)
     {
         // Has a min or a max or both specified.
         return(IsBetween(compare, attr.MinVersion, attr.MaxVersion));
     }
     else
     {
         // has no version attribute therefore it's valid in all cache versions
         return(true);
     }
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Determines whether a field exists in the given CacheVersion. Defines a priority : Version, Gen, Min/Max.
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="compare"></param>
        /// <returns></returns>
        public static bool AttributeInCacheVersion(TagFieldAttribute attr, CacheVersion compare)
        {
            if (attr.Version != CacheVersion.Unknown)
            {
                if (attr.Version != compare)
                {
                    return(false);
                }
            }

            if (attr.Gen != CacheGeneration.Unknown)
            {
                if (!IsInGen(attr.Gen, compare))
                {
                    return(false);
                }
            }

            if (attr.Platform != CachePlatform.All)
            {
                if (!IsInPlatform(attr.Platform, compare))
                {
                    return(false);
                }
            }

            if (attr.MinVersion != CacheVersion.Unknown || attr.MaxVersion != CacheVersion.Unknown)
            {
                if (!IsBetween(compare, attr.MinVersion, attr.MaxVersion))
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Serializes a value.
        /// </summary>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="tagStream">The stream to write completed blocks of tag data to.</param>
        /// <param name="block">The temporary block to write incomplete tag data to.</param>
        /// <param name="val">The value.</param>
        /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
        /// <param name="valueType">Type of the value.</param>
        private void SerializeValue(ISerializationContext context, MemoryStream tagStream, IDataBlock block, object val, TagFieldAttribute valueInfo, Type valueType)
        {
            // Call the data block's PreSerialize callback to determine if the value should be mutated
            val = block.PreSerialize(valueInfo, val);
            if (val != null)
                valueType = val.GetType(); // TODO: Fix hax

            if (valueType.IsPrimitive)
                SerializePrimitiveValue(block.Writer, val, valueType);
            else
                SerializeComplexValue(context, tagStream, block, val, valueInfo, valueType);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Serializes a tag block.
        /// </summary>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="tagStream">The stream to write completed blocks of tag data to.</param>
        /// <param name="block">The temporary block to write incomplete tag data to.</param>
        /// <param name="list">The list of values in the tag block.</param>
        /// <param name="listType">Type of the list.</param>
        /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
        private void SerializeTagBlock(ISerializationContext context, MemoryStream tagStream, IDataBlock block, object list, Type listType, TagFieldAttribute valueInfo)
        {
            var writer = block.Writer;
            var listCount = 0;
            if (list != null)
            {
                // Use reflection to get the number of elements in the list
                var countProperty = listType.GetProperty("Count");
                listCount = (int)countProperty.GetValue(list);
            }
            if (listCount == 0)
            {
                writer.Write(0);
                writer.Write(0);
                writer.Write(0);
                return;
            }

            // Serialize each value in the list to a data block
            var tagBlock = context.CreateBlock();
            var enumerableList = (System.Collections.IEnumerable)list;
            var valueType = listType.GenericTypeArguments[0];
            foreach (var val in enumerableList)
                SerializeValue(context, tagStream, tagBlock, val, null, valueType);

            // Ensure the block is aligned correctly
            var align = Math.Max(DefaultBlockAlign, (valueInfo != null) ? valueInfo.DataAlign : 0);
            StreamUtil.Align(tagStream, (int)align);

            // Finalize the block and write the tag block reference
            writer.Write(listCount);
            block.WritePointer(tagBlock.Finalize(tagStream), listType);
            writer.Write(0);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Serializes an inline array.
        /// </summary>
        /// <param name="context">The serialization context to use.</param>
        /// <param name="tagStream">The stream to write completed blocks of tag data to.</param>
        /// <param name="block">The temporary block to write incomplete tag data to.</param>
        /// <param name="data">The array.</param>
        /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
        private void SerializeInlineArray(ISerializationContext context, MemoryStream tagStream, IDataBlock block, Array data, TagFieldAttribute valueInfo)
        {
            if (valueInfo == null || valueInfo.Count == 0)
                throw new ArgumentException("Cannot serialize an inline array with no count set");
            if (data == null || data.Length != valueInfo.Count)
                throw new ArgumentException("Array length does not match the fixed count of " + valueInfo.Count);

            // Serialize each element into the current block
            var elementType = data.GetType().GetElementType();
            foreach (var elem in data)
                SerializeValue(context, tagStream, block, elem, null, elementType);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Serializes a complex value.
 /// </summary>
 /// <param name="context">The serialization context to use.</param>
 /// <param name="tagStream">The stream to write completed blocks of tag data to.</param>
 /// <param name="block">The temporary block to write incomplete tag data to.</param>
 /// <param name="val">The value.</param>
 /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
 /// <param name="valueType">Type of the value.</param>
 private void SerializeComplexValue(ISerializationContext context, MemoryStream tagStream, IDataBlock block, object val, TagFieldAttribute valueInfo, Type valueType)
 {
     if (valueInfo != null && ((valueInfo.Flags & TagFieldFlags.Indirect) != 0 || valueType == typeof(ResourceReference)))
         SerializeIndirectValue(context, tagStream, block, val, valueType);
     else if (valueType.IsEnum)
         SerializePrimitiveValue(block.Writer, val, valueType.GetEnumUnderlyingType());
     else if (valueType == typeof(string))
         SerializeString(block.Writer, (string)val, valueInfo);
     else if (valueType == typeof(Tag))
         SerializeTag(block, (Tag)val);
     else if (valueType == typeof(TagInstance))
         SerializeTagReference(block.Writer, (TagInstance)val, valueInfo);
     else if (valueType == typeof(ResourceAddress))
         block.Writer.Write(((ResourceAddress)val).Value);
     else if (valueType == typeof(byte[]))
         SerializeDataReference(tagStream, block, (byte[])val, valueInfo);
     else if (valueType == typeof(Euler2))
         SerializeEulerAngles(block, (Euler2)val);
     else if (valueType == typeof(Euler3))
         SerializeEulerAngles(block, (Euler3)val);
     else if (valueType == typeof(Vector2))
         SerializeVector(block, (Vector2)val);
     else if (valueType == typeof(Vector3))
         SerializeVector(block, (Vector3)val);
     else if (valueType == typeof(Vector4))
         SerializeVector(block, (Vector4)val);
     else if (valueType == typeof(RealQuaternion))
         SerializeRealQuaternion(block, (RealQuaternion)val);
     else if (valueType == typeof(Matrix4x3))
         SerializeMatrix(block, (Matrix4x3)val);
     else if (valueType == typeof(StringID))
         block.Writer.Write(((StringID)val).Value);
     else if (valueType == typeof(Angle))
         block.Writer.Write(((Angle)val).Radians);
     else if (valueType.IsArray)
         SerializeInlineArray(context, tagStream, block, (Array)val, valueInfo);
     else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>))
         SerializeTagBlock(context, tagStream, block, val, valueType, valueInfo);
     else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Range<>))
         SerializeRange(block, val);
     else
         SerializeStruct(context, tagStream, block, new TagStructureInfo(val.GetType(), _version), val);
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Serializes a tag reference.
 /// </summary>
 /// <param name="writer">The writer to write to.</param>
 /// <param name="referencedTag">The referenced tag.</param>
 /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param>
 private static void SerializeTagReference(BinaryWriter writer, TagInstance referencedTag, TagFieldAttribute valueInfo)
 {
     // Write the reference out
     if (valueInfo == null || (valueInfo.Flags & TagFieldFlags.Short) == 0)
     {
         writer.Write((referencedTag != null) ? referencedTag.Group.Tag.Value : -1);
         writer.Write(0);
         writer.Write(0);
     }
     writer.Write((referencedTag != null) ? referencedTag.Index : -1);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Serializes a string.
 /// </summary>
 /// <param name="writer">The writer to write to.</param>
 /// <param name="str">The string to serialize.</param>
 /// <param name="valueInfo">Information about the value.</param>
 private static void SerializeString(BinaryWriter writer, string str, TagFieldAttribute valueInfo)
 {
     if (valueInfo == null || valueInfo.Length == 0)
         throw new ArgumentException("Cannot serialize a string with no length set");
     var clampedLength = 0;
     if (str != null)
     {
         var bytes = Encoding.ASCII.GetBytes(str);
         clampedLength = Math.Min(valueInfo.Length - 1, bytes.Length);
         writer.Write(bytes, 0, clampedLength);
     }
     for (var i = clampedLength; i < valueInfo.Length; i++)
         writer.Write((byte)0);
 }
Ejemplo n.º 10
0
            public object PreSerialize(TagFieldAttribute info, object obj)
            {
                if (obj == null)
                    return null;

                // Get the object type and make sure it's supported
                var type = obj.GetType();
                if (type == typeof(ResourceDataReference) ||
                    (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer<>)))
                    throw new InvalidOperationException(type + " cannot be serialized as tag data");

                // HACK: If the object is a ResourceReference, fix the Owner property
                var resource = obj as ResourceReference;
                if (resource != null)
                    resource.Owner = _context.Tag;

                if (type == typeof(TagInstance))
                {
                    // Object is a tag reference - add it as a dependency
                    var referencedTag = obj as TagInstance;
                    if (referencedTag != null && referencedTag != _context.Tag)
                        _context._data.Dependencies.Add(referencedTag.Index);
                }
                return obj;
            }
            public object PreSerialize(TagFieldAttribute info, object obj)
            {
                if (obj == null)
                    return null;

                // When serializing a resource address, just add a fixup for it and serialize a null pointer
                if (obj is ResourceAddress)
                {
                    _fixups.Add(MakeDefinitionFixup((ResourceAddress)obj));
                    return 0U;
                }

                var type = obj.GetType();
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(D3DPointer<>))
                {
                    // Add a D3D fixup for D3DPointers based on the type of object being pointed to
                    var d3dType = GetD3DObjectType(type.GenericTypeArguments[0]);
                    _d3dFixups.Add(MakeD3DFixup((uint)Stream.Position, d3dType));
                }
                return obj;
            }
 public object PreSerialize(TagFieldAttribute info, object obj)
 {
     return(obj);
 }