Browse Source

Refactor DecodeArrayInitializer to support enums.

Remove code duplication.
pull/306/head
Jb Evain 14 years ago
parent
commit
11c99f778f
  1. 153
      ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

153
ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

@ -135,8 +135,7 @@ namespace ICSharpCode.Decompiler.ILAst
FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule(); FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule();
if (fieldDef != null && fieldDef.InitialValue != null) { if (fieldDef != null && fieldDef.InitialValue != null) {
ILExpression[] newArr = new ILExpression[arrayLength]; ILExpression[] newArr = new ILExpression[arrayLength];
if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType.GetElementType()), if (DecodeArrayInitializer(arrayType.GetElementType(), fieldDef.InitialValue, newArr))
fieldDef.InitialValue, newArr))
{ {
values = newArr; values = newArr;
foundPos = pos; foundPos = pos;
@ -149,81 +148,101 @@ namespace ICSharpCode.Decompiler.ILAst
return false; return false;
} }
static bool DecodeArrayInitializer(TypeCode elementType, byte[] initialValue, ILExpression[] output) static bool DecodeArrayInitializer(TypeReference elementTypeRef, byte[] initialValue, ILExpression[] output)
{ {
TypeCode elementType = TypeAnalysis.GetTypeCode(elementTypeRef);
switch (elementType) { switch (elementType) {
case TypeCode.Boolean: case TypeCode.Boolean:
case TypeCode.Byte: case TypeCode.Byte:
if (initialValue.Length >= output.Length) { return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)d[i]);
for (int j = 0; j < output.Length; j++) { case TypeCode.SByte:
output[j] = new ILExpression(ILCode.Ldc_I4, (int)initialValue[j]); return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)unchecked((sbyte)d[i]));
} case TypeCode.Int16:
return true; return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToInt16(d, i));
}
return false;
case TypeCode.SByte:
if (initialValue.Length >= output.Length) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)unchecked((sbyte)initialValue[j]));
}
return true;
}
return false;
case TypeCode.Int16:
if (initialValue.Length >= output.Length * 2) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToInt16(initialValue, j * 2));
}
return true;
}
return false;
case TypeCode.Char: case TypeCode.Char:
case TypeCode.UInt16: case TypeCode.UInt16:
if (initialValue.Length >= output.Length * 2) { return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToUInt16(d, i));
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToUInt16(initialValue, j * 2));
}
return true;
}
return false;
case TypeCode.Int32: case TypeCode.Int32:
case TypeCode.UInt32: case TypeCode.UInt32:
if (initialValue.Length >= output.Length * 4) { return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt32);
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, BitConverter.ToInt32(initialValue, j * 4));
}
return true;
}
return false;
case TypeCode.Int64: case TypeCode.Int64:
case TypeCode.UInt64: case TypeCode.UInt64:
if (initialValue.Length >= output.Length * 8) { return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt64);
for (int j = 0; j < output.Length; j++) { case TypeCode.Single:
output[j] = new ILExpression(ILCode.Ldc_I8, BitConverter.ToInt64(initialValue, j * 8)); return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToSingle);
} case TypeCode.Double:
return true; return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToDouble);
} case TypeCode.Object:
return false; var typeDef = elementTypeRef.ResolveWithinSameModule();
case TypeCode.Single: if (typeDef != null && typeDef.IsEnum)
if (initialValue.Length >= output.Length * 4) { return DecodeArrayInitializer(typeDef.GetEnumUnderlyingType(), initialValue, output);
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_R4, BitConverter.ToSingle(initialValue, j * 4));
}
return true;
}
return false;
case TypeCode.Double:
if (initialValue.Length >= output.Length * 8) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_R8, BitConverter.ToDouble(initialValue, j * 8));
}
return true;
}
return false; return false;
default: default:
return false; return false;
} }
} }
static bool DecodeArrayInitializer<T>(byte[] initialValue, ILExpression[] output, TypeCode elementType, Func<byte[], int, T> decoder)
{
int elementSize = ElementSizeOf(elementType);
if (initialValue.Length < (output.Length * elementSize))
return false;
ILCode code = LoadCodeFor(elementType);
for (int i = 0; i < output.Length; i++)
output[i] = new ILExpression(code, decoder(initialValue, i * elementSize));
return true;
}
private static ILCode LoadCodeFor(TypeCode elementType)
{
switch (elementType) {
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Char:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
return ILCode.Ldc_I4;
case TypeCode.Int64:
case TypeCode.UInt64:
return ILCode.Ldc_I8;
case TypeCode.Single:
return ILCode.Ldc_R4;
case TypeCode.Double:
return ILCode.Ldc_R8;
default:
throw new ArgumentOutOfRangeException("elementType");
}
}
private static int ElementSizeOf(TypeCode elementType)
{
switch (elementType) {
case TypeCode.Boolean:
case TypeCode.Byte:
case TypeCode.SByte:
return 1;
case TypeCode.Char:
case TypeCode.Int16:
case TypeCode.UInt16:
return 2;
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Single:
return 4;
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Double:
return 8;
default:
throw new ArgumentOutOfRangeException("elementType");
}
}
#endregion #endregion
/// <summary> /// <summary>

Loading…
Cancel
Save