using System;
using System.Net;
namespace Org.SbeTool.Sbe.Dll
{
///
/// Utility class to manipulate endianess
///
public static class EndianessConverter
{
// TODO: we could assume the system is always little endian and have two methods for each
// TODO: (one no-op and another one which reverse, so we do not have branching)
private static readonly ByteOrder NativeByteOrder = BitConverter.IsLittleEndian
? ByteOrder.LittleEndian
: ByteOrder.BigEndian;
///
/// Applies the specified endianess to an int16 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static short ApplyInt16(ByteOrder byteOrder, short value)
{
if (byteOrder == NativeByteOrder) return value;
return (short)((value & 0xFFU) << 8 | (value & 0xFF00U) >> 8);
}
///
/// Applies the specified endianess to an uint16 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static ushort ApplyUint16(ByteOrder byteOrder, ushort value)
{
if (byteOrder == NativeByteOrder) return value;
return (ushort)((value & 0xFFU) << 8 | (value & 0xFF00U) >> 8);
}
///
/// Applies the specified endianess to an int32 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static int ApplyInt32(ByteOrder byteOrder, int value)
{
if (byteOrder == NativeByteOrder) return value;
return (int)((value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
(value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24);
}
///
/// Applies the specified endianess to an uint32 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static uint ApplyUint32(ByteOrder byteOrder, uint value)
{
if (byteOrder == NativeByteOrder) return value;
return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
(value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
}
///
/// Applies the specified endianess to an uint64 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static ulong ApplyUint64(ByteOrder byteOrder, ulong value)
{
if (byteOrder == NativeByteOrder) return value;
return (value & 0x00000000000000FFUL) << 56 | (value & 0x000000000000FF00UL) << 40 |
(value & 0x0000000000FF0000UL) << 24 | (value & 0x00000000FF000000UL) << 8 |
(value & 0x000000FF00000000UL) >> 8 | (value & 0x0000FF0000000000UL) >> 24 |
(value & 0x00FF000000000000UL) >> 40 | (value & 0xFF00000000000000UL) >> 56;
}
///
/// Applies the specified endianess to an int64 (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static long ApplyInt64(ByteOrder byteOrder, long value)
{
if (byteOrder == NativeByteOrder) return value;
return IPAddress.HostToNetworkOrder(value);
}
///
/// Applies the specified endianess to a double (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public static double ApplyDouble(ByteOrder byteOrder, double value)
{
if (byteOrder == NativeByteOrder) return value;
return BitConverter.Int64BitsToDouble(IPAddress.HostToNetworkOrder(BitConverter.DoubleToInt64Bits(value)));
}
///
/// Applies the specified endianess to an float (reverse bytes if input endianess is different from system's endianess)
///
/// the endianess to apply
/// the value to be converted
/// The value with applied endainess
public unsafe static float ApplyFloat(ByteOrder byteOrder, float value)
{
if (byteOrder == NativeByteOrder) return value;
int valueInt = *(int*) &value;
int applied = ApplyInt32(byteOrder, valueInt);
return *(float*) &applied;
}
}
}