C# structs, byte swapping for conversion from big to little endian using reflection to enumerate members


/ Published in: C#
Save to your folder(s)

<p>This example uses a Swap member to enumerate the struct&#8217;s fields and swap multi-byte fields. It doesn&#8217;t traverse nested structs.</p>

<p>It would be nice if dot.net has something equivalent to &#8216;#pragma endian big&#8217; 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&#8201;&#215;&#8201;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&#8217;t work on structs. It failed quietly.</p>


Copy this code and paste it in your HTML
  1. public struct MyStruct
  2. {
  3. public UInt32 u4;
  4. public int s4;
  5. public UInt16 u2;
  6. public short s2;
  7. public UInt64 u8;
  8. public Int64 s8;
  9.  
  10. // byte-swap members of this struct.
  11. public MyStruct Swap()
  12. {
  13. // The copy is made becuase SetValue won't work on a struct.
  14. // Boxing was used because SetValue works on classes/objects.
  15. // Unfortunately, it results in 2 copy operations.
  16. object thisBoxed = this; // Why make a copy?
  17.  
  18. // System.Net.IPAddress.NetworkToHostOrder is used to perform byte swapping.
  19. // To convert unsigned to signed, 'unchecked()' was used.
  20. // See http://stackoverflow.com/questions/1131843/how-do-i-convert-uint-to-int-in-c
  21.  
  22. // Enumerate each structure field using reflection.
  23. foreach (var field in typeof(MyStruct).GetFields())
  24. {
  25. // field.Name has the field's name.
  26.  
  27. object fieldValue = field.GetValue(thisBoxed); // Get value
  28.  
  29. // Get the TypeCode enumeration. Multiple types get mapped to a common typecode.
  30. TypeCode typeCode = Type.GetTypeCode(fieldValue.GetType());
  31.  
  32. switch (typeCode)
  33. {
  34. case TypeCode.Int32:
  35. {
  36. Int32 i = System.Net.IPAddress.NetworkToHostOrder((Int32)fieldValue);
  37. field.SetValue(thisBoxed, (Int32)i);
  38. break;
  39. }
  40. case TypeCode.UInt32:
  41. {
  42. Int32 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int32)(UInt32)fieldValue));
  43. field.SetValue(thisBoxed, (UInt32)i);
  44. break;
  45. }
  46. case TypeCode.Int16:
  47. {
  48. Int16 i = System.Net.IPAddress.NetworkToHostOrder((Int16)fieldValue);
  49. field.SetValue(thisBoxed, (Int16)i);
  50. break;
  51. }
  52. case TypeCode.UInt16:
  53. {
  54. Int16 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int16)(UInt16)fieldValue));
  55. field.SetValue(thisBoxed, (UInt16)i);
  56. break;
  57. }
  58. case TypeCode.Int64:
  59. {
  60. Int64 i = System.Net.IPAddress.NetworkToHostOrder((Int64)fieldValue);
  61. field.SetValue(thisBoxed, i);
  62. break;
  63. }
  64. case TypeCode.UInt64:
  65. {
  66. Int64 i = System.Net.IPAddress.NetworkToHostOrder(unchecked((Int64)(UInt64)fieldValue));
  67. field.SetValue(thisBoxed, (UInt64)i);
  68. break;
  69. }
  70. default:
  71. {
  72. System.Diagnostics.Debug.Fail("No conversion provided for this type");
  73. break;
  74. }
  75. }; // switch
  76.  
  77. } // foreach
  78. return (MyStruct)thisBoxed;
  79. } // Swap
  80. }; // MyStruct
  81.  
  82.  
  83. // Usage example:
  84. MyStruct s = new MyStruct();
  85.  
  86. s.u4 = 0x78563412;
  87. s.s4 = 0x21436587;
  88. s.u2 = 0x2143;
  89. s.s2 = 0x3412;
  90. s.u8 = 0xFF007856341200FF;
  91. s.s8 = 0x7700785634120077;
  92.  
  93. s = s.Swap();

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.