Revision: 16786
Updated Code
at August 15, 2009 19:36 by jimfred
Updated Code
public struct MyStruct
{
public UInt32 u4;
public int s4;
public UInt16 u2;
public short s2;
public UInt64 u8;
public Int64 s8;
// byte-swap members of this struct.
public MyStruct Swap()
{
// The copy is made becuase SetValue won't work on a struct.
// Boxing was used because SetValue works on classes/objects.
// Unfortunately, it results in 2 copy operations.
object thisBoxed = this; // Why make a copy?
// System.Net.IPAddress.NetworkToHostOrder is used to perform byte swapping.
// To convert unsigned to signed, 'unchecked()' was used.
// See http://stackoverflow.com/questions/1131843/how-do-i-convert-uint-to-int-in-c
// Enumerate each structure field using reflection.
foreach (var field in typeof(MyStruct).GetFields())
{
// field.Name has the field's name.
object fieldValue = field.GetValue(thisBoxed); // Get value
// Get the TypeCode enumeration. Multiple types get mapped to a common typecode.
TypeCode typeCode = Type.GetTypeCode(fieldValue.GetType());
switch (typeCode)
{
case TypeCode.Int32:
{
Int32 i = System.Net.IPAddress.NetworkToHostOrder((Int32)fieldValue);
field.SetValue(thisBoxed, (Int32)i);
break;
}
case TypeCode.UInt32:
{
Int32 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int32)(UInt32)fieldValue));
field.SetValue(thisBoxed, (UInt32)i);
break;
}
case TypeCode.Int16:
{
Int16 i = System.Net.IPAddress.NetworkToHostOrder((Int16)fieldValue);
field.SetValue(thisBoxed, (Int16)i);
break;
}
case TypeCode.UInt16:
{
Int16 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int16)(UInt16)fieldValue));
field.SetValue(thisBoxed, (UInt16)i);
break;
}
case TypeCode.Int64:
{
Int64 i = System.Net.IPAddress.NetworkToHostOrder((Int64)fieldValue);
field.SetValue(thisBoxed, i);
break;
}
case TypeCode.UInt64:
{
Int64 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int64)(UInt64)fieldValue));
field.SetValue(thisBoxed, (UInt64)i);
break;
}
default:
{
System.Diagnostics.Debug.Fail("No conversion provided for this type");
break;
}
}; // switch
} // foreach
return (MyStruct)thisBoxed;
} // Swap
}; // MyStruct
// Usage example:
MyStruct s = new MyStruct();
s.u4 = 0x78563412;
s.s4 = 0x21436587;
s.u2 = 0x2143;
s.s2 = 0x3412;
s.u8 = 0xFF007856341200FF;
s.s8 = 0x7700785634120077;
s = s.Swap();
Revision: 16785
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at August 15, 2009 19:31 by jimfred
Initial Code
public struct MyStruct
{
public UInt32 u4;
public int s4;
public UInt16 u2;
public short s2;
public UInt64 u8;
public Int64 s8;
public MyStruct Swap()
{
// The copy is made becuase SetValue won't work on a struct.
// Boxing was used because SetValue works on classes/objects.
// Unfortunately, it results in 2 copy operations.
object thisBoxed = this; // Why make a copy?
// System.Net.IPAddress.NetworkToHostOrder is used to perform byte swapping.
// To convert unsigned to signed, 'unchecked()' was used.
// See http://stackoverflow.com/questions/1131843/how-do-i-convert-uint-to-int-in-c
// Enumerate each structure field using reflection.
foreach (var field in typeof(MyStruct).GetFields())
{
// field.Name has the field's name.
object fieldValue = field.GetValue(thisBoxed); // Get value
// Get the TypeCode enumeration. Multiple types get mapped to a common typecode.
TypeCode typeCode = Type.GetTypeCode(fieldValue.GetType());
switch (typeCode)
{
case TypeCode.Int32:
{
Int32 i = System.Net.IPAddress.NetworkToHostOrder((Int32)fieldValue);
field.SetValue(thisBoxed, (Int32)i);
break;
}
case TypeCode.UInt32:
{
Int32 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int32)(UInt32)fieldValue));
field.SetValue(thisBoxed, (UInt32)i);
break;
}
case TypeCode.Int16:
{
Int16 i = System.Net.IPAddress.NetworkToHostOrder((Int16)fieldValue);
field.SetValue(thisBoxed, (Int16)i);
break;
}
case TypeCode.UInt16:
{
Int16 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int16)(UInt16)fieldValue));
field.SetValue(thisBoxed, (UInt16)i);
break;
}
case TypeCode.Int64:
{
Int64 i = System.Net.IPAddress.NetworkToHostOrder((Int64)fieldValue);
field.SetValue(thisBoxed, i);
break;
}
case TypeCode.UInt64:
{
Int64 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int64)(UInt64)fieldValue));
field.SetValue(thisBoxed, (UInt64)i);
break;
}
default:
{
System.Diagnostics.Debug.Fail("No conversion provided for this type");
break;
}
}; // switch
} // foreach
return (MyStruct)thisBoxed;
} // Swap
}; // MyStruct
// Usage example:
MyStruct s = new MyStruct();
s.u4 = 0x78563412;
s.s4 = 0x21436587;
s.u2 = 0x2143;
s.s2 = 0x3412;
s.u8 = 0xFF007856341200FF;
s.s8 = 0x7700785634120077;
s = s.Swap();
Initial URL
Initial Description
<p>This example uses a Swap member to enumerate the struct’s fields and swap multi-byte fields. It doesn’t traverse nested structs.</p> <p>It would be nice if dot.net has something equivalent to ‘#pragma endian big’ as seen in some compilers. There might be a way to leverage marshaling to automatically endianize multi-byte values.</p> <p>This example uses: * System.Net.IPAddress.NetworkToHostOrder for byte swapping * unchecked() to convert a value of, say, 0 × 87654321 to a Int32 without a runtime error * foreach (System.Reflection.FieldInfo field in typeof(MyStruct).GetFields()) to enumerate structure members * TypeCode typeCode = Type.GetTypeCode(fieldValue.GetType()); to get the underlying type enumeration (typeof of verbose). * SetValue and GetValue to access struct members. * Boxed object of struct - this was necessary only because SetValue didn’t work on structs. It failed quietly.</p>
Initial Title
C# structs, byte swapping for conversion from big to little endian using reflection to enumerate members
Initial Tags
Initial Language
C#