138 lines
5.8 KiB
Plaintext
138 lines
5.8 KiB
Plaintext
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define LITTLE_ENDIAN
|
|
|
|
using System;
|
|
|
|
namespace Smb.Shared
|
|
{
|
|
/// <summary>
|
|
/// <para>
|
|
/// This class provides static methods for swapping byte order.
|
|
/// You might think this was overkill for such a simple purpose -- why not just have two methods?
|
|
/// The reason for providing so many methods is to allow developers to document what they are doing
|
|
/// by choosing an appropriate method. "x = HostToBe(y)" clearly shows that y is in big-endian,
|
|
/// and is being converted to host order.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// I have avoided the traditional terminology of "host order" vs "network order", and instead have
|
|
/// used "host order", "big endian" (Be), and "little endian" (Le). This is because not all network
|
|
/// protocols use big-endian order. The TCP/IP family does, but many others do not, especially those
|
|
/// involving Microsoft products, such as SMB.
|
|
/// </para>
|
|
/// </summary>
|
|
/*static*/ sealed class ByteOrder
|
|
{
|
|
private ByteOrder() {}
|
|
|
|
public static ushort Swap(ushort value)
|
|
{
|
|
return unchecked((ushort)((value >> 8) | (value << 8)));
|
|
}
|
|
|
|
public static short Swap(short value)
|
|
{
|
|
ushort uvalue = unchecked((ushort)value);
|
|
return unchecked((short)((uvalue >> 8) | (uvalue << 8)));
|
|
}
|
|
|
|
public static uint Swap(uint value)
|
|
{
|
|
return ((value & 0xff000000u) >> 24)
|
|
| ((value & 0x00ff0000u) >> 8)
|
|
| ((value & 0x0000ff00u) << 8)
|
|
| ((value & 0x000000ffu) << 24);
|
|
}
|
|
|
|
public static int Swap(int value)
|
|
{
|
|
return unchecked((int)Swap((uint)value));
|
|
}
|
|
|
|
public static ulong Swap(ulong value)
|
|
{
|
|
value = (value >> 32) | (value << 32);
|
|
value = ((value >> 16) & 0x0000ffff0000ffffUL) | ((value << 16) & 0xffff0000ffff0000UL);
|
|
value = ((value >> 8) & 0x00ff00ff00ff00ffUL) | ((value << 8 ) & 0xff00ff00ff00ff00UL);
|
|
return value;
|
|
}
|
|
|
|
public static long Swap(long value)
|
|
{
|
|
ulong uvalue = unchecked((ulong)value);
|
|
uvalue = (uvalue >> 32) | (uvalue << 32);
|
|
uvalue = ((uvalue >> 16) & 0x0000ffff0000ffffUL) | ((uvalue << 16) & 0xffff0000ffff0000UL);
|
|
uvalue = ((uvalue >> 8 ) & 0x00ff00ff00ff00ffUL) | ((uvalue << 8 ) & 0xff00ff00ff00ff00UL);
|
|
return unchecked((long)uvalue);
|
|
}
|
|
|
|
#if LITTLE_ENDIAN
|
|
|
|
// Host order is little-endian, so these are swaps.
|
|
public static ushort HostToBe(ushort value) { return Swap(value); }
|
|
public static ushort BeToHost(ushort value) { return Swap(value); }
|
|
public static short HostToBe(short value) { return Swap(value); }
|
|
public static short BeToHost(short value) { return Swap(value); }
|
|
public static uint HostToBe(uint value) { return Swap(value); }
|
|
public static uint BeToHost(uint value) { return Swap(value); }
|
|
public static int HostToBe(int value) { return Swap(value); }
|
|
public static int BeToHost(int value) { return Swap(value); }
|
|
public static ulong HostToBe(ulong value) { return Swap(value); }
|
|
public static ulong BeToHost(ulong value) { return Swap(value); }
|
|
public static long HostToBe(long value) { return Swap(value); }
|
|
public static long BeToHost(long value) { return Swap(value); }
|
|
|
|
// Host order is little-endian, so these are no-ops.
|
|
public static ushort HostToLe(ushort value) { return value; }
|
|
public static ushort LeToHost(ushort value) { return value; }
|
|
public static short HostToLe(short value) { return value; }
|
|
public static short LeToHost(short value) { return value; }
|
|
public static uint HostToLe(uint value) { return value; }
|
|
public static uint LeToHost(uint value) { return value; }
|
|
public static int HostToLe(int value) { return value; }
|
|
public static int LeToHost(int value) { return value; }
|
|
public static long HostToLe(long value) { return value; }
|
|
public static long LeToHost(long value) { return value; }
|
|
public static ulong HostToLe(ulong value) { return value; }
|
|
public static ulong LeToHost(ulong value) { return value; }
|
|
|
|
#else
|
|
|
|
// If host order is big-endian, then these are no-ops.
|
|
public static ushort HostToBe(ushort value) { return value; }
|
|
public static ushort BeToHost(ushort value) { return value; }
|
|
public static short HostToBe(short value) { return value; }
|
|
public static short BeToHost(short value) { return value; }
|
|
public static uint HostToBe(uint value) { return value; }
|
|
public static uint BeToHost(uint value) { return value; }
|
|
public static int HostToBe(int value) { return value; }
|
|
public static int BeToHost(int value) { return value; }
|
|
public static long HostToBe(long value) { return value; }
|
|
public static long BeToHost(long value) { return value; }
|
|
public static ulong HostToBe(ulong value) { return value; }
|
|
public static ulong BeToHost(ulong value) { return value; }
|
|
|
|
// Host order is big-endian, so these are swaps.
|
|
public static ushort HostToLe(ushort value) { return Swap(value); }
|
|
public static ushort LeToHost(ushort value) { return Swap(value); }
|
|
public static short HostToLe(short value) { return Swap(value); }
|
|
public static short LeToHost(short value) { return Swap(value); }
|
|
public static uint HostToLe(uint value) { return Swap(value); }
|
|
public static uint LeToHost(uint value) { return Swap(value); }
|
|
public static int HostToLe(int value) { return Swap(value); }
|
|
public static int LeToHost(int value) { return Swap(value); }
|
|
public static ulong HostToLe(ulong value) { return Swap(value); }
|
|
public static ulong LeToHost(ulong value) { return Swap(value); }
|
|
public static long HostToLe(long value) { return Swap(value); }
|
|
public static long LeToHost(long value) { return Swap(value); }
|
|
|
|
#endif
|
|
|
|
}
|
|
}
|