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#