/// <summary> /// Writes an enumerable of <see cref="Int32"/> values to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="values">The values to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> public static void WriteInt32s(this Stream stream, IEnumerable <Int32> values, ByteConverter converter = null) { Write(stream, values, converter); }
/// <summary> /// Writes an enumerable of <see cref="Int32"/> values asynchronously to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="values">The values to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> public static async Task WriteInt32sAsync(this Stream stream, IEnumerable <Int32> values, ByteConverter converter = null, CancellationToken cancellationToken = default(CancellationToken)) { await WriteAsync(stream, values, converter, cancellationToken); }
/// <summary> /// Writes an <see cref="Int32"/> value to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> public static void WriteInt32(this Stream stream, Int32 value, ByteConverter converter = null) { Write(stream, value, converter); }
/// <summary> /// Writes an <see cref="Int32"/> value asynchronously to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> public static async Task WriteInt32Async(this Stream stream, Int32 value, ByteConverter converter = null, CancellationToken cancellationToken = default(CancellationToken)) { await WriteAsync(stream, value, converter, cancellationToken); }
// ---- Write ---- /// <summary> /// Writes an <see cref="Enum"/> value of type <typeparamref name="T"/> to the <paramref name="stream"/>. /// </summary> /// <typeparam name="T">The type of the enum.</typeparam> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> /// <param name="strict"><c>true</c> to raise an <see cref="ArgumentOutOfRangeException"/> if the value is not /// defined in the enum type.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> public static void WriteEnum <T>(this Stream stream, T value, bool strict = false, ByteConverter converter = null) where T : struct, IComparable, IFormattable { WriteEnum(stream, typeof(T), value, strict, converter); }
// ---- Write ---- /// <summary> /// Writes a <see cref="Decimal"/> value to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> public static void Write(this Stream stream, Decimal value) { byte[] buffer = Buffer; ByteConverter.GetBytes(value, buffer, 0); stream.Write(buffer, 0, sizeof(Decimal)); }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- private static void WriteEnum(Stream stream, Type enumType, object value, bool strict, ByteConverter converter) { converter = converter ?? ByteConverter.System; Type valueType = Enum.GetUnderlyingType(enumType); // Write the enum value. byte[] buffer = Buffer; if (valueType == typeof(Byte)) { Buffer[0] = (byte)value; } else if (valueType == typeof(SByte)) { Buffer[0] = (byte)(sbyte)value; } else if (valueType == typeof(Int16)) { converter.GetBytes((Int16)value, buffer, 0); } else if (valueType == typeof(Int32)) { converter.GetBytes((Int32)value, buffer, 0); } else if (valueType == typeof(Int64)) { converter.GetBytes((Int64)value, buffer, 0); } else if (valueType == typeof(UInt16)) { converter.GetBytes((UInt16)value, buffer, 0); } else if (valueType == typeof(UInt32)) { converter.GetBytes((UInt32)value, buffer, 0); } else if (valueType == typeof(UInt64)) { converter.GetBytes((UInt64)value, buffer, 0); } else { throw new NotImplementedException($"Unsupported enum type {valueType}."); } // Check if the value is defined in the enumeration, if requested. if (strict) { EnumTools.IsValid(enumType, value); } stream.Write(buffer, 0, Marshal.SizeOf(valueType)); }
/// <summary> /// Returns an array of <see cref="Int32"/> instances read asynchronously from the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="count">The number of values to read.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>The array of values read from the current stream.</returns> public static async Task <Int32[]> ReadInt32sAsync(this Stream stream, int count, ByteConverter converter = null, CancellationToken cancellationToken = default(CancellationToken)) { converter = converter ?? ByteConverter.System; return(await ReadManyAsync(stream, count, () => ReadInt32Async(stream, converter, cancellationToken))); }
private static void WriteMember(Stream stream, object instance, long startOffset, ByteConverter converter, MemberData member) { // If possible, reposition the stream according to offset. if (stream.CanSeek) { if (member.Attribute.OffsetOrigin == OffsetOrigin.Begin) { stream.Position = startOffset + member.Attribute.Offset; } else { stream.Position += member.Attribute.Offset; } } else { if (member.Attribute.OffsetOrigin == OffsetOrigin.Begin || member.Attribute.Offset < 0) { throw new NotSupportedException("Cannot reposition the stream as it is not seekable."); } else if (member.Attribute.Offset > 0) // Simulate moving forward by writing bytes. { stream.Write(new byte[member.Attribute.Offset]); } } // Get the value to write. object value; switch (member.MemberInfo) { case FieldInfo field: value = field.GetValue(instance); break; case PropertyInfo property: value = property.GetValue(instance); break; default: throw new InvalidOperationException($"Tried to write an invalid member {member.MemberInfo}."); } // Write the value and respect settings stored in the member attribute. Type elementType = member.Type.GetEnumerableElementType(); if (elementType == null) { WriteObject(stream, instance, member.Attribute, member.Type, value, converter); } else { foreach (object element in (IEnumerable)value) { WriteObject(stream, instance, member.Attribute, elementType, element, converter); } } }
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- Object ---- /// <summary> /// Writes an object or enumerable of objects to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The object or enumerable of objects to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> public static void WriteObject(this Stream stream, object value, ByteConverter converter = null) => WriteObject(stream, null, BinaryMemberAttribute.Default, value.GetType(), value, converter);
/// <summary> /// Returns an <see cref="Enum"/> instance of the given <paramref name="type"/> read from the /// <paramref name="stream"/>. /// </summary> /// <param name="type">The type of the enum.</param> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="strict"><c>true</c> to raise an <see cref="ArgumentOutOfRangeException"/> if a value is not /// defined in the enum type.</param> /// <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 object ReadEnum(this Stream stream, Type type, bool strict = false, ByteConverter converter = null) { converter = converter ?? ByteConverter.System; // Read enough bytes to form an enum value. Type valueType = Enum.GetUnderlyingType(type); object value; if (valueType == typeof(Byte)) { FillBuffer(stream, sizeof(Byte)); value = Buffer[0]; } else if (valueType == typeof(SByte)) { FillBuffer(stream, sizeof(SByte)); value = (SByte)Buffer[0]; } else if (valueType == typeof(Int16)) { FillBuffer(stream, sizeof(Int16)); value = converter.ToInt16(Buffer); } else if (valueType == typeof(Int32)) { FillBuffer(stream, sizeof(Int32)); value = converter.ToInt32(Buffer); } else if (valueType == typeof(Int64)) { FillBuffer(stream, sizeof(Int64)); value = converter.ToInt64(Buffer); } else if (valueType == typeof(UInt16)) { FillBuffer(stream, sizeof(UInt16)); value = converter.ToUInt16(Buffer); } else if (valueType == typeof(UInt32)) { FillBuffer(stream, sizeof(UInt32)); value = converter.ToUInt32(Buffer); } else if (valueType == typeof(UInt64)) { FillBuffer(stream, sizeof(UInt64)); value = converter.ToUInt64(Buffer); } else { throw new NotImplementedException($"Unsupported enum type {valueType}."); } // Check if the value is defined in the enumeration, if requested. if (strict) { ValidateEnumValue(type, value); } return(value); }
/// <summary> /// Returns an <see cref="Enum"/> instance of type <typeparamref name="T"/> read asynchronously from the /// <paramref name="stream"/>. /// </summary> /// <typeparam name="T">The type of the enum.</typeparam> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="strict"><c>true</c> to raise an <see cref="ArgumentOutOfRangeException"/> if a value is not /// defined in the enum type.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>The value read from the current stream.</returns> public static async Task <T> ReadEnumAsync <T>(this Stream stream, bool strict = false, ByteConverter converter = null, CancellationToken cancellationToken = default(CancellationToken)) where T : struct, IComparable, IFormattable { return((T) await ReadEnumAsync(stream, typeof(T), strict, converter, cancellationToken)); }
/// <summary> /// Writes an <see cref="Enum"/> value of type <typeparamref name="T"/> asynchronously to the /// <paramref name="stream"/>. /// </summary> /// <typeparam name="T">The type of the enum.</typeparam> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> /// <param name="strict"><c>true</c> to raise an <see cref="ArgumentOutOfRangeException"/> if the value is not /// defined in the enum type.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> public static async Task WriteEnumAsync <T>(this Stream stream, T value, bool strict = false, ByteConverter converter = null, CancellationToken cancellationToken = default(CancellationToken)) where T : struct, IComparable, IFormattable { await WriteEnumAsync(stream, typeof(T), value, strict, converter, cancellationToken); }
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- Read ---- /// <summary> /// Returns an <see cref="Int32"/> instance read from the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <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 Int32 ReadInt32(this Stream stream, ByteConverter converter = null) { FillBuffer(stream, sizeof(Int32)); return((converter ?? ByteConverter.System).ToInt32(Buffer)); }
private static void WriteObject(Stream stream, object instance, BinaryMemberAttribute attribute, Type type, object value, ByteConverter converter) { converter = converter ?? ByteConverter.System; if (attribute.Converter == null) { if (value == null) { return; } else if (type == typeof(String)) { stream.Write((String)value, attribute.StringFormat, converter: converter); } else if (type.TryGetEnumerableElementType(out Type elementType)) { foreach (object element in (IEnumerable)value) { WriteObject(stream, null, BinaryMemberAttribute.Default, elementType, element, converter); } } else if (type == typeof(Boolean)) { stream.Write((Boolean)value, attribute.BooleanFormat, converter); } else if (type == typeof(Byte)) { stream.Write((Byte)value); } else if (type == typeof(DateTime)) { stream.Write((DateTime)value, attribute.DateTimeFormat, converter); } else if (type == typeof(Decimal)) { stream.Write((Decimal)value); } else if (type == typeof(Double)) { stream.Write((Double)value, converter); } else if (type == typeof(Int16)) { stream.Write((Int16)value, converter); } else if (type == typeof(Int32)) { stream.Write((Int32)value, converter); } else if (type == typeof(Int64)) { stream.Write((Int64)value, converter); } else if (type == typeof(SByte)) { stream.Write((SByte)value); } else if (type == typeof(Single)) { stream.Write((Single)value, converter); } else if (type == typeof(UInt16)) { stream.Write((UInt16)value, converter); } else if (type == typeof(UInt32)) { stream.Write((UInt32)value, converter); } else if (type == typeof(UInt64)) { stream.Write((UInt64)value, converter); } else if (type.IsEnum) { WriteEnum(stream, type, value, attribute.Strict, converter); } else { if (stream.CanSeek) { WriteCustomObject(stream, type, value, stream.Position, converter); } else { WriteCustomObject(stream, type, value, -1, converter); } } } else { // Let a binary converter do all the work. IBinaryConverter binaryConverter = BinaryConverterCache.GetConverter(attribute.Converter); binaryConverter.Write(stream, instance, attribute, value, converter); } }
/// <summary> /// Returns an array of <see cref="Int32"/> instances read from the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="count">The number of values to read.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> /// <returns>The array of values read from the current stream.</returns> public static Int32[] ReadInt32s(this Stream stream, int count, ByteConverter converter = null) { converter = converter ?? ByteConverter.System; return(ReadMany(stream, count, () => ReadInt32(stream, converter))); }
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- Read ---- /// <summary> /// Returns a <see cref="Decimal"/> instance read from the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <returns>The value read from the current stream.</returns> public static Decimal ReadDecimal(this Stream stream) { FillBuffer(stream, sizeof(Decimal)); return(ByteConverter.ToDecimal(Buffer)); }
// ---- Write ---- /// <summary> /// Writes an <see cref="Int32"/> value to the <paramref name="stream"/>. /// </summary> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="value">The value to write.</param> /// <param name="converter">The <see cref="ByteConverter"/> to use for converting multibyte data.</param> public static void Write(this Stream stream, Int32 value, ByteConverter converter = null) { byte[] buffer = Buffer; (converter ?? ByteConverter.System).GetBytes(value, buffer, 0); stream.Write(buffer, 0, sizeof(Int32)); }
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- Read ---- /// <summary> /// Returns an <see cref="Enum"/> instance of type <typeparamref name="T"/> read from the /// <paramref name="stream"/>. /// </summary> /// <typeparam name="T">The type of the enum.</typeparam> /// <param name="stream">The extended <see cref="Stream"/> instance.</param> /// <param name="strict"><c>true</c> to raise an <see cref="ArgumentOutOfRangeException"/> if a value is not /// defined in the enum type.</param> /// <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 ReadEnum <T>(this Stream stream, bool strict = false, ByteConverter converter = null) where T : struct, IComparable, IFormattable { return((T)ReadEnum(stream, typeof(T), strict, converter)); }