Commit db98523f authored by Ray Koopa's avatar Ray Koopa

Further WIP changes

parent b366c4cd
......@@ -24,7 +24,7 @@ Core functionality:
- [Syroot.BinaryData](https://www.nuget.org/packages/Syroot.BinaryData) (unsigned)
- [Syroot.BinaryData.Signed](https://www.nuget.org/packages/Syroot.BinaryData.Signed) (signed assembly)
Serialization functionality (includes the core package):
Serialization functionality (adds the core package dependency):
- [Syroot.BinaryData.Serialization](https://www.nuget.org/packages/Syroot.BinaryData.Serialization) (unsigned)
- [Syroot.BinaryData.Serialization.Signed](https://www.nuget.org/packages/Syroot.BinaryData.Serialization.Signed) (signed assembly)
......
using System;
using System.Collections.Generic;
namespace Syroot.BinaryData
{
/// <summary>
/// Represents a cache for <see cref="IDataConverter"/> instances.
/// </summary>
internal static class ConverterCache
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly Dictionary<Type, IDataConverter> _cache = new Dictionary<Type, IDataConverter>();
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
/// <summary>
/// Gets a possibly cached instance of a <see cref="IDataConverter"/> of the given <paramref name="type"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> of the <see cref="IDataConverter"/> to return.</param>
/// <returns>An instance of the <see cref="IDataConverter"/>.</returns>
internal static IDataConverter GetConverter(Type type)
{
if (!_cache.TryGetValue(type, out IDataConverter converter))
{
converter = (IDataConverter)Activator.CreateInstance(type);
_cache.Add(type, converter);
}
return converter;
}
}
}
......@@ -7,35 +7,35 @@ namespace Syroot.BinaryData
/// Configures how many elements in an <see cref="IEnumerable"/> member are read through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ArrayAttribute : Attribute
public class DataArrayAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="ArrayAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataArrayAttribute"/> class with the given configuration.
/// </summary>
/// <param name="count">The number of elements to read.</param>
public ArrayAttribute(int count)
public DataArrayAttribute(int count)
{
Count = count;
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataArrayAttribute"/> class with the given configuration.
/// </summary>
/// <param name="countProvider">The name of the member or method to use for retrieving the number of elements to
/// read.</param>
public ArrayAttribute(string countProvider)
public DataArrayAttribute(string countProvider)
{
CountProvider = countProvider;
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataArrayAttribute"/> class with the given configuration.
/// </summary>
/// <param name="coding">The <see cref="ArrayLengthCoding"/> to read or write the value in.</param>
/// <param name="endian">The <see cref="Endian"/> of this value.</param>
public ArrayAttribute(ArrayLengthCoding coding, Endian endian = Endian.None)
public DataArrayAttribute(ArrayLengthCoding coding, Endian endian = Endian.None)
{
Coding = coding;
CodingEndian = endian;
......
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures how a <see cref="Boolean"/> member is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class BooleanAttribute : Attribute
public class DataBooleanAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="BooleanAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataBooleanAttribute"/> class with the given configuration.
/// </summary>
/// <param name="coding">The <see cref="BooleanCoding"/> to read or write the value in.</param>
public BooleanAttribute(BooleanCoding coding)
public DataBooleanAttribute(BooleanCoding coding)
{
Coding = coding;
}
......
......@@ -6,7 +6,7 @@ namespace Syroot.BinaryData
/// Configures a class or struct for reading and writing it through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class ClassAttribute : Attribute
public class DataClassAttribute : Attribute
{
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
......
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures an <see cref="IDataConverter"/> to read or write the member with through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ConverterAttribute : Attribute
public class DataConverterAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="ConverterAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataConverterAttribute"/> class with the given configuration.
/// </summary>
/// <param name="converterType">The type of the <see cref="IDataConverter"/> to use.</param>
public ConverterAttribute(Type converterType)
public DataConverterAttribute(Type converterType)
{
ConverterType = converterType;
}
......
......@@ -7,15 +7,15 @@ namespace Syroot.BinaryData
/// Configures how a <see cref="DateTime"/> member is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class DateTimeAttribute : Attribute
public class DataDateTimeAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="DateTimeAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataDateTimeAttribute"/> class with the given configuration.
/// </summary>
/// <param name="coding">The <see cref="DateTimeCoding"/> to read or write the value in.</param>
public DateTimeAttribute(DateTimeCoding coding)
public DataDateTimeAttribute(DateTimeCoding coding)
{
Coding = coding;
}
......
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures in which endianness a value is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class EndianAttribute : Attribute
public class DataEndianAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="EndianAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataEndianAttribute"/> class with the given configuration.
/// </summary>
/// <param name="endian">The endianness in which to read or write the value.</param>
public EndianAttribute(Endian endian)
public DataEndianAttribute(Endian endian)
{
Endian = endian;
}
......
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures how an <see cref="Enum"/> member is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class EnumAttribute : Attribute
public class DataEnumAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="EnumAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataEnumAttribute"/> class with the given configuration.
/// </summary>
/// <param name="strict"><c>true</c> to validate the value when it is read or written.</param>
public EnumAttribute(bool strict)
public DataEnumAttribute(bool strict)
{
Strict = strict;
}
......
......@@ -4,9 +4,9 @@ namespace Syroot.BinaryData
{
/// <summary>
/// Configures that a member is explicitly read or written through binary serialization. Use this attribute if the
/// owning instance is marked as <see cref="ClassAttribute.Explicit"/> and no other attributes are meaningful
/// owning instance is marked as <see cref="DataClassAttribute.Explicit"/> and no other attributes are meaningful
/// for the member.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class MemberAttribute : Attribute { }
public class DataMemberAttribute : Attribute { }
}
......@@ -6,16 +6,16 @@ namespace Syroot.BinaryData
/// Configures an offset at which the value is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class OffsetAttribute : Attribute
public class DataOffsetAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="OffsetAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataOffsetAttribute"/> class with the given configuration.
/// </summary>
/// <param name="origin">The anchor from which to manipulate the stream position by the given delta.</param>
/// <param name="delta">The number of bytes to manipulate the stream position with.</param>
public OffsetAttribute(Origin origin, long delta)
public DataOffsetAttribute(Origin origin, long delta)
{
Origin = origin;
Delta = delta;
......
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures an offset which is seeked to after reading the instance through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class OffsetEndAttribute : OffsetAttribute
public class DataOffsetEndAttribute : DataOffsetAttribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="OffsetEndAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataOffsetEndAttribute"/> class with the given configuration.
/// </summary>
/// <param name="origin">The anchor from which to manipulate the stream position by the given delta.</param>
/// <param name="delta">The number of bytes to manipulate the stream position with.</param>
public OffsetEndAttribute(Origin origin, long delta) : base(origin, delta) { }
public DataOffsetEndAttribute(Origin origin, long delta) : base(origin, delta) { }
}
}
......@@ -6,15 +6,15 @@ namespace Syroot.BinaryData
/// Configures an offset which is seeked to before reading the instance through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class OffsetStartAttribute : OffsetAttribute
public class DataOffsetStartAttribute : DataOffsetAttribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="OffsetStartAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataOffsetStartAttribute"/> class with the given configuration.
/// </summary>
/// <param name="origin">The anchor from which to manipulate the stream position by the given delta.</param>
/// <param name="delta">The number of bytes to manipulate the stream position with.</param>
public OffsetStartAttribute(Origin origin, long delta) : base(origin, delta) { }
public DataOffsetStartAttribute(Origin origin, long delta) : base(origin, delta) { }
}
}
......@@ -7,15 +7,15 @@ namespace Syroot.BinaryData
/// serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class OrderAttribute : Attribute
public class DataOrderAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="OrderAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataOrderAttribute"/> class with the given configuration.
/// </summary>
/// <param name="index">The index determining the order when the value is read or written.</param>
public OrderAttribute(int index)
public DataOrderAttribute(int index)
{
Index = index;
}
......
......@@ -7,28 +7,28 @@ namespace Syroot.BinaryData
/// Configures how a <see cref="String"/> member is read or written through binary serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class StringAttribute : Attribute
public class DataStringAttribute : Attribute
{
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="StringAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataStringAttribute"/> class with the given configuration.
/// </summary>
/// <param name="coding">The <see cref="StringCoding"/> to read or write the value in.</param>
/// <param name="codePage">The code page of the <see cref="Encoding"/> to use.</param>
public StringAttribute(StringCoding coding, int codePage = 0)
public DataStringAttribute(StringCoding coding, int codePage = 0)
{
Coding = coding;
CodePage = codePage;
}
/// <summary>
/// Initializes a new instance of the <see cref="StringAttribute"/> class with the given configuration.
/// Initializes a new instance of the <see cref="DataStringAttribute"/> class with the given configuration.
/// </summary>
/// <param name="length">The length of the string to read. Handles the string with
/// <see cref="StringCoding.Raw"/>.</param>
/// <param name="codePage">The code page of the <see cref="Encoding"/> to use.</param>
public StringAttribute(int length, int codePage = 0)
public DataStringAttribute(int length, int codePage = 0)
{
Length = length;
CodePage = codePage;
......
using System;
namespace Syroot.BinaryData
{
/// <summary>
/// Represents a collection of extension methods for the <see cref="BinaryDataReader"/> class.
/// </summary>
public static class BinaryDataReaderExtensions
{
// ---- Object ----
/// <summary>
/// Reads an object of type <typeparamref name="T"/> from the current stream.
/// </summary>
/// <typeparam name="T">The type of the object to load.</typeparam>
/// <param name="self">The extended <see cref="BinaryDataReader"/> instance.</param>
/// <returns>The object read from the current stream.</returns>
public static T ReadObject<T>(this BinaryDataReader self)
=> self.BaseStream.ReadObject<T>(self.ByteConverter);
/// <summary>
/// Reads the specified number of objects of type <typeparamref name="T"/> from the current stream.
/// </summary>
/// <typeparam name="T">The type of the objects to load.</typeparam>
/// <param name="self">The extended <see cref="BinaryDataReader"/> instance.</param>
/// <param name="count">The number of objects to read.</param>
/// <returns>The objects array read from the current stream.</returns>
public static T[] ReadObjects<T>(this BinaryDataReader self, int count)
=> self.BaseStream.ReadObjects<T>(count, self.ByteConverter);
/// <summary>
/// Reads an object of the given <paramref name="type"/> from the current stream.
/// </summary>
/// <param name="self">The extended <see cref="BinaryDataReader"/> instance.</param>
/// <param name="type">The type of the object to load.</param>
/// <returns>The object read from the current stream.</returns>
public static object ReadObject(this BinaryDataReader self, Type type)
=> self.BaseStream.ReadObject(type, self.ByteConverter);
/// <summary>
/// Reads the specified number of objects of the given <paramref name="type"/> from the current stream.
/// </summary>
/// <param name="self">The extended <see cref="BinaryDataReader"/> instance.</param>
/// <param name="type">The type of the object to load.</param>
/// <param name="count">The number of objects to read.</param>
/// <returns>The objects array read from the current stream.</returns>
public static object[] ReadObjects(this BinaryDataReader self, Type type, int count)
=> self.BaseStream.ReadObjects(type, count, self.ByteConverter);
}
}
namespace Syroot.BinaryData
{
/// <summary>
/// Represents a collection of extension methods for the <see cref="BinaryDataWriter"/> class.
/// </summary>
public static class BinaryDataWriterExtensions
{
// ---- Object ----
/// <summary>
/// Writes an object or enumerable of objects to this stream.
/// </summary>
/// <param name="self">The extended <see cref="BinaryDataWriter"/> instance.</param>
/// <param name="value">The object or enumerable of objects to write.</param>
public static void WriteObject(this BinaryDataWriter self, object value)
=> self.BaseStream.WriteObject(value, self.ByteConverter);
}
}
......@@ -28,7 +28,7 @@ namespace Syroot.BinaryData
MemberInfo = memberInfo;
// Get any possible attribute.
ArrayAttribute arrayAttrib = MemberInfo.GetCustomAttribute<ArrayAttribute>();
DataArrayAttribute arrayAttrib = MemberInfo.GetCustomAttribute<DataArrayAttribute>();
if (arrayAttrib != null)
{
IsExported = true;
......@@ -37,55 +37,55 @@ namespace Syroot.BinaryData
ArrayCountCoding = arrayAttrib.Coding;
ArrayCountCodingEndian = arrayAttrib.CodingEndian;
}
BooleanAttribute booleanAttrib = MemberInfo.GetCustomAttribute<BooleanAttribute>();
DataBooleanAttribute booleanAttrib = MemberInfo.GetCustomAttribute<DataBooleanAttribute>();
if (booleanAttrib != null)
{
IsExported = true;
BooleanCoding = booleanAttrib.Coding;
}
ConverterAttribute converterAttrib = MemberInfo.GetCustomAttribute<ConverterAttribute>();
DataConverterAttribute converterAttrib = MemberInfo.GetCustomAttribute<DataConverterAttribute>();
if (converterAttrib != null)
{
IsExported = true;
ConverterType = converterAttrib.ConverterType;
}
DateTimeAttribute dateTimeAttrib = MemberInfo.GetCustomAttribute<DateTimeAttribute>();
DataDateTimeAttribute dateTimeAttrib = MemberInfo.GetCustomAttribute<DataDateTimeAttribute>();
if (dateTimeAttrib != null)
{
IsExported = true;
DateTimeCoding = dateTimeAttrib.Coding;
}
EndianAttribute endianAttrib = MemberInfo.GetCustomAttribute<EndianAttribute>();
DataEndianAttribute endianAttrib = MemberInfo.GetCustomAttribute<DataEndianAttribute>();
if (endianAttrib != null)
{
IsExported = true;
Endian = endianAttrib.Endian;
}
EnumAttribute enumAttrib = MemberInfo.GetCustomAttribute<EnumAttribute>();
DataEnumAttribute enumAttrib = MemberInfo.GetCustomAttribute<DataEnumAttribute>();
if (enumAttrib != null)
{
IsExported = true;
EnumStrict = enumAttrib.Strict;
}
MemberAttribute memberAttrib = MemberInfo.GetCustomAttribute<MemberAttribute>();
DataMemberAttribute memberAttrib = MemberInfo.GetCustomAttribute<DataMemberAttribute>();
if (memberAttrib != null)
{
IsExported = true;
}
OffsetAttribute offsetAttrib = MemberInfo.GetCustomAttribute<OffsetAttribute>();
DataOffsetAttribute offsetAttrib = MemberInfo.GetCustomAttribute<DataOffsetAttribute>();
if (offsetAttrib != null)
{
IsExported = true;
OffsetDelta = offsetAttrib.Delta;
OffsetOrigin = offsetAttrib.Origin;
}
OrderAttribute orderAttrib = MemberInfo.GetCustomAttribute<OrderAttribute>();
DataOrderAttribute orderAttrib = MemberInfo.GetCustomAttribute<DataOrderAttribute>();
if (orderAttrib != null)
{
IsExported = true;
Index = orderAttrib.Index;
}
StringAttribute stringAttrib = MemberInfo.GetCustomAttribute<StringAttribute>();
DataStringAttribute stringAttrib = MemberInfo.GetCustomAttribute<DataStringAttribute>();
if (stringAttrib != null)
{
IsExported = true;
......@@ -98,7 +98,7 @@ namespace Syroot.BinaryData
if (Type.IsEnumerable() && arrayAttrib == null)
{
throw new InvalidOperationException(
$"Enumerable member \"{MemberInfo}\" must be decorated with a {nameof(ArrayAttribute)}.");
$"Enumerable member \"{MemberInfo}\" must be decorated with a {nameof(DataArrayAttribute)}.");
}
}
......
......@@ -9,9 +9,9 @@ namespace Syroot.BinaryData
/// <summary>
/// Represents logic to serialize and deserialize objects of any type.
/// </summary>
internal static class BinarySerialization
internal class Serializer
{
// ---- FIELDS -------------------------------------------------------------------------------------------------
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
private static readonly Dictionary<RuntimeTypeHandle, Func<Stream, ByteConverter, MemberData, object>>
_typeReaders = new Dictionary<RuntimeTypeHandle, Func<Stream, ByteConverter, MemberData, object>>
......@@ -32,35 +32,103 @@ namespace Syroot.BinaryData
[typeof(UInt64).TypeHandle] = ReadUInt64
};
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
// ---- FIELDS -------------------------------------------------------------------------------------------------
internal static object ReadClass(Stream stream, TypeData typeData, object instance, ByteConverter byteConverter)
private readonly Dictionary<Type, TypeData> _typeCache;
private readonly Dictionary<Type, IDataConverter> _converterCache;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
internal Serializer()
{
instance = instance ?? typeData.Instantiate();
long instanceOffset = stream.CanSeek ? stream.Position : -1;
_typeCache = new Dictionary<Type, TypeData>();
_converterCache = new Dictionary<Type, IDataConverter>();
}
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
/// <summary>
/// Reads the object of the given <paramref name="type"/> from the <paramref name="stream"/> and overrides the
/// <paramref name="byteConverter"/> used.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to read the data from.</param>
/// <param name="type">The <see cref="Type"/> of the object to read.</param>
/// <param name="byteConverter">The <see cref="ByteConverter"/> to use.</param>
/// <returns>The read instance.</returns>
internal object ReadObject(Stream stream, Type type, ByteConverter byteConverter)
=> ReadObject(stream, GetTypeData(type), byteConverter, null);
/// <summary>
/// Writes the <paramref name="value"/> to the <paramref name="stream"/> and overrides the
/// <paramref name="byteConverter"/> used.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to write the data to.</param>
/// <param name="value">The object to write.</param>
/// <param name="byteConverter">The <see cref="ByteConverter"/> to use.</param>
internal void WriteObject(Stream stream, object value, ByteConverter byteConverter)
=> throw new NotImplementedException();
// Read inherited members.
if (typeData.Inherit && typeData.Type.BaseType != null)
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
// ---- Caches ----
private TypeData GetTypeData(Type type)
{
lock (_typeCache)
{
ReadClass(stream, TypeData.Get(typeData.Type.BaseType), instance, byteConverter);
if (!_typeCache.TryGetValue(type, out TypeData typeData))
{
typeData = new TypeData(type);
_typeCache.Add(type, typeData);
}
return typeData;
}
}
// Read ordered members.
foreach (KeyValuePair<int, MemberData> orderedMember in typeData.OrderedMembers)
private IDataConverter GetConverter(Type type)
{
lock (_converterCache)
{
ReadMember(stream, orderedMember.Value, instance, byteConverter, instanceOffset);
if (!_converterCache.TryGetValue(type, out IDataConverter converter))
{
converter = (IDataConverter)Activator.CreateInstance(type);
_converterCache.Add(type, converter);
}
return converter;
}
}
// ---- Reading ----
private object ReadObject(Stream stream, TypeData typeData, ByteConverter byteConverter, object instance)
{
// Instantiate the object if no child class instance was passed.
instance = instance ?? typeData.Instantiate();
// Read unordered / alphabetically sorted members.
foreach (KeyValuePair<string, MemberData> unorderedMember in typeData.UnorderedMembers)
// Read inherited members first.
lock (stream)
{
ReadMember(stream, unorderedMember.Value, instance, byteConverter, instanceOffset);
if (typeData.Inherit && typeData.Type.BaseType != null)
{
ReadObject(stream, GetTypeData(typeData.Type.BaseType), byteConverter, instance);
}
// Read members.
long offset = stream.CanSeek ? stream.Position : -1;
foreach (KeyValuePair<int, MemberData> orderedMember in typeData.OrderedMembers)
{
ReadAndSetMember(stream, orderedMember.Value, instance, byteConverter, offset);
}
foreach (KeyValuePair<string, MemberData> unorderedMember in typeData.UnorderedMembers)
{
ReadAndSetMember(stream, unorderedMember.Value, instance, byteConverter, offset);
}
}
return instance;
}
private static void ReadMember(Stream stream, MemberData memberData, object instance,
private void ReadAndSetMember(Stream stream, MemberData memberData, object instance,
ByteConverter byteConverter, long instanceOffset)
{
object value;
......@@ -68,7 +136,7 @@ namespace Syroot.BinaryData
if (arrayCount == 0)
{
// Read a single value.
value = ReadClass(stream, TypeData.Get(memberData.Type), null, byteConverter);
value = ReadObject(stream, GetTypeData(memberData.Type), byteConverter, null);
}
else
{
......@@ -93,10 +161,8 @@ namespace Syroot.BinaryData
break;
}
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private static object ReadMemberValue(Stream stream, ByteConverter byteConverter, Type type, MemberData memberData,
private object ReadMemberValue(Stream stream, ByteConverter byteConverter, Type type, MemberData memberData,
long parentOffset)
{
byteConverter = memberData.Endian == 0 ? byteConverter : ByteConverter.GetConverter(memberData.Endian);
......@@ -109,7 +175,7 @@ namespace Syroot.BinaryData
if (memberData.ConverterType == null)
{
// Let a converter handle all the data after adjusting to the offset.
TypeData typeData = TypeData.Get(type);
TypeData typeData = GetTypeData(type);
ApplyOffset(stream, parentOffset, typeData.StartOrigin, typeData.StartDelta);
value = null;// TODO: memberData.ConverterAttrib.Read(stream, memberData);
ApplyOffset(stream, parentOffset, typeData.EndOrigin, typeData.EndDelta);
......@@ -127,9 +193,9 @@ namespace Syroot.BinaryData
else
{
// Read a custom type.
TypeData typeData = TypeData.Get(type);
TypeData typeData = GetTypeData(type);
ApplyOffset(stream, parentOffset, typeData.StartOrigin, typeData.StartDelta);
value = ReadClass(stream, typeData, typeData.Instantiate(), byteConverter);
value = ReadObject(stream, type, byteConverter);
ApplyOffset(stream, parentOffset, typeData.EndOrigin, typeData.EndDelta);
}
return value;
......@@ -140,13 +206,9 @@ namespace Syroot.BinaryData
Encoding encoding = memberData.StringCodePage == 0 ? null : Encoding.GetEncoding(memberData.StringCodePage);
if (memberData.StringCoding == StringCoding.Raw)
{
return stream.ReadString(memberData.StringLength, encoding);
}
else
{
return stream.ReadString(memberData.StringCoding, encoding, byteConverter);
}
}
private static object ReadBoolean(Stream stream, ByteConverter byteConverter, MemberData memberData)
......
using System.IO;
using System;
using System.IO;
namespace Syroot.BinaryData
{
......@@ -14,8 +15,17 @@ namespace Syroot.BinaryData
/// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param>
/// <returns>The value read from the current stream.</returns>
public static T ReadObject<T>(this Stream stream, ByteConverter converter = null)
=> (T)BinarySerialization.ReadClass(stream, TypeData.Get(typeof(T)), null,
converter ?? ByteConverter.System);
=> (T)_serializer.ReadObject(stream, typeof(T), converter ?? ByteConverter.