using System;
//using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
namespace Gibbed.IO
{
public static partial class StreamHelpers
{
#region Cache
private static class EnumTypeCache
{
/*private static Dictionary<Type, EnumUnderlyingType> _Lookup;
static EnumTypeCache()
{
_Lookup = new Dictionary<Type, EnumUnderlyingType>();
}*/
private static TypeCode TranslateType(Type type)
{
if (type.IsEnum == true)
{
var underlyingType = Enum.GetUnderlyingType(type);
var underlyingTypeCode = Type.GetTypeCode(underlyingType);
switch (underlyingTypeCode)
{
case TypeCode.SByte:
case TypeCode.Byte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
{
return underlyingTypeCode;
}
}
}
throw new ArgumentException("unknown enum type", "type");
}
public static TypeCode Get(Type type)
{
/*if (Lookup.ContainsKey(type) == true)
{
return Lookup[type];
}*/
return /*Lookup[type] =*/ TranslateType(type);
}
}
#endregion
#region ReadValueEnum
public static T ReadValueEnum<T>(this Stream stream, Endian endian)
{
var type = typeof(T);
object value;
switch (EnumTypeCache.Get(type))
{
case TypeCode.SByte:
{
value = stream.ReadValueS8();
break;
}
case TypeCode.Byte:
{
value = stream.ReadValueU8();
break;
}
case TypeCode.Int16:
{
value = stream.ReadValueS16(endian);
break;
}
case TypeCode.UInt16:
{
value = stream.ReadValueU16(endian);
break;
}
case TypeCode.Int32:
{
value = stream.ReadValueS32(endian);
break;
}
case TypeCode.UInt32:
{
value = stream.ReadValueU32(endian);
break;
}
case TypeCode.Int64:
{
value = stream.ReadValueS64(endian);
break;
}
case TypeCode.UInt64:
{
value = stream.ReadValueU64(endian);
break;
}
default:
{
throw new NotSupportedException();
}
}
return (T)Enum.ToObject(type, value);
}
public static T ReadValueEnum<T>(this Stream stream)
{
return stream.ReadValueEnum<T>(Endian.Little);
}
#endregion
#region WriteValueEnum
public static void WriteValueEnum<T>(this Stream stream, object value, Endian endian)
{
var type = typeof(T);
switch (EnumTypeCache.Get(type))
{
case TypeCode.SByte:
{
stream.WriteValueS8((sbyte)value);
break;
}
case TypeCode.Byte:
{
stream.WriteValueU8((byte)value);
break;
}
case TypeCode.Int16:
{
stream.WriteValueS16((short)value, endian);
break;
}
case TypeCode.UInt16:
{
stream.WriteValueU16((ushort)value, endian);
break;
}
case TypeCode.Int32:
{
stream.WriteValueS32((int)value, endian);
break;
}
case TypeCode.UInt32:
{
stream.WriteValueU32((uint)value, endian);
break;
}
case TypeCode.Int64:
{
stream.WriteValueS64((long)value, endian);
break;
}
case TypeCode.UInt64:
{
stream.WriteValueU64((ulong)value, endian);
break;
}
default:
{
throw new NotSupportedException();
}
}
}
public static void WriteValueEnum<T>(this Stream stream, object value)
{
stream.WriteValueEnum<T>(value, Endian.Little);
}
#endregion
#region Obsolete
[Obsolete("use Endian enum instead of boolean to represent endianness")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T ReadValueEnum<T>(this Stream stream, bool littleEndian)
{
return stream.ReadValueEnum<T>(littleEndian == true ? Endian.Little : Endian.Big);
}
[Obsolete("use Endian enum instead of boolean to represent endianness")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static void WriteValueEnum<T>(this Stream stream, object value, bool littleEndian)
{
stream.WriteValueEnum<T>(value, littleEndian == true ? Endian.Little : Endian.Big);
}
#endregion
}
}