Return to Snippet

Revision: 16786
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
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&#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>

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

Initial Tags


Initial Language
C#