//******************************************************************************************************// EndianOrderTest.cs - Gbtc//// Copyright © 2010, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://www.opensource.org/licenses/MIT//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 02/13/2014 - J. Ritchie Carroll// Generated original version of source code.////****************************************************************************************************** // Uncomment only for hard coded testing of BigEndian architecture code//#define ForceBigEndianTesting using System;using System.Collections.Generic;using System.Diagnostics.CodeAnalysis;using Microsoft.VisualStudio.TestTools.UnitTesting; namespace GSF.Core.Tests{ [TestClass] public class EndianOrderTest { #region [ Byte Swap/Copy Only Endian Order Testing Classes ] // These classes represent a brute-force approach to Endian order handling // that are used as a base-line for testing other optimized approaches /// <summary> /// Represents a big-endian byte order interoperability class. /// </summary> private class BigEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="BigEndianOrderTester"/> class. /// </summary> public BigEndianOrderTester() : base(Endianness.BigEndian) { } #endregion #region [ Static ] private static BigEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="BigEndianOrderTester"/> class. /// </summary> public static BigEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new BigEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents a little-endian byte order interoperability class. /// </summary> private class LittleEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="LittleEndianOrderTester"/> class. /// </summary> public LittleEndianOrderTester() : base(Endianness.LittleEndian) { } #endregion #region [ Static ] private static LittleEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="LittleEndianOrderTester"/> class. /// </summary> public static LittleEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new LittleEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents a native-endian byte order interoperability class. /// </summary> private class NativeEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="NativeEndianOrderTester"/> class. /// </summary> public NativeEndianOrderTester() : base(BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian) { } #endregion #region [ Static ] private static NativeEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="NativeEndianOrderTester"/> class. /// </summary> public static NativeEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new NativeEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents an endian byte order interoperability class. /// </summary> /// <remarks> /// Intel systems use little-endian byte order, other systems, such as Unix, use big-endian byte ordering. /// Little-endian ordering means bits are ordered such that the bit whose in-memory representation is right-most is the most-significant-bit in a byte. /// Big-endian ordering means bits are ordered such that the bit whose in-memory representation is left-most is the most-significant-bit in a byte. /// </remarks> private class EndianOrderTester { #region [ Members ] // Delegates private delegate void CopyBufferFunction(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length); private delegate byte[] CoerceByteOrderFunction(byte[] buffer); // Fields private readonly Endianness m_targetEndianness; private readonly CopyBufferFunction m_copyBuffer; private readonly CoerceByteOrderFunction m_coerceByteOrder; #endregion #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="EndianOrderTester"/> class. /// </summary> /// <param name="targetEndianness">Endianness parameter.</param> protected EndianOrderTester(Endianness targetEndianness) { m_targetEndianness = targetEndianness; // We perform this logic only once for speed in conversions - we can do this because neither // the target nor the OS endian order will change during the lifecycle of this class... if (targetEndianness == Endianness.BigEndian) {#if ForceBigEndianTesting if (!BitConverter.IsLittleEndian) // <- Hard coded test for alternate architecture#else if (BitConverter.IsLittleEndian)#endif { // If OS is little endian and we want big endian, we swap the bytes m_copyBuffer = SwapCopy; m_coerceByteOrder = ReverseBuffer; } else { // If OS is big endian and we want big endian, we just copy the bytes m_copyBuffer = BlockCopy; m_coerceByteOrder = PassThroughBuffer; } } else {#if ForceBigEndianTesting if (!BitConverter.IsLittleEndian) // <- Hard coded test for alternate architecture#else if (BitConverter.IsLittleEndian)#endif { // If OS is little endian and we want little endian, we just copy the bytes m_copyBuffer = BlockCopy; m_coerceByteOrder = PassThroughBuffer; } else { // If OS is big endian and we want little endian, we swap the bytes m_copyBuffer = SwapCopy; m_coerceByteOrder = ReverseBuffer; } } } #endregion #region [ Properties ] /// <summary> /// Returns the target endian-order of this <see cref="EndianOrderTester"/> representation. /// </summary> public Endianness TargetEndianness { get { return m_targetEndianness; } } #endregion #region [ Methods ] private void BlockCopy(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length) { Buffer.BlockCopy(sourceBuffer, sourceIndex, destinationBuffer, destinationIndex, length); } // This function behaves just like Array.Copy but takes a little-endian source array and copies it in big-endian order, // or if the source array is big-endian it will copy it in little-endian order private void SwapCopy(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length) { int offset = destinationIndex + length - 1; for (int x = sourceIndex; x <= sourceIndex + length - 1; x++) { destinationBuffer[offset - (x - sourceIndex)] = sourceBuffer[x]; } } private byte[] PassThroughBuffer(byte[] buffer) { return buffer; } private byte[] ReverseBuffer(byte[] buffer) { Array.Reverse(buffer); return buffer; } /// <summary> /// Returns a <see cref="Boolean"/> value converted from one byte at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes.</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> [SuppressMessage("Microsoft.Performance", "CA1822")] public bool ToBoolean(byte[] value, int startIndex) { return BitConverter.ToBoolean(value, startIndex); } /// <summary> /// Returns a Unicode character converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A character formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public char ToChar(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToChar(buffer, 0); } /// <summary> /// Returns a double-precision floating point number converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A double-precision floating point number formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public double ToDouble(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToDouble(buffer, 0); } /// <summary> /// Returns a 16-bit signed integer converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public short ToInt16(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToInt16(buffer, 0); } /// <summary> /// Returns a 24-bit signed integer converted from three bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 24-bit signed integer formed by three bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public Int24 ToInt24(byte[] value, int startIndex) { byte[] buffer = new byte[3]; m_copyBuffer(value, startIndex, buffer, 0, 3); return Int24.GetValue(buffer, 0); } /// <summary> /// Returns a 32-bit signed integer converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public int ToInt32(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToInt32(buffer, 0); } /// <summary> /// Returns a 64-bit signed integer converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public long ToInt64(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToInt64(buffer, 0); } /// <summary> /// Returns a single-precision floating point number converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A single-precision floating point number formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public float ToSingle(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToSingle(buffer, 0); } /// <summary> /// Returns a 16-bit unsigned integer converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public ushort ToUInt16(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToUInt16(buffer, 0); } /// <summary> /// Returns a 24-bit unsigned integer converted from three bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 24-bit unsigned integer formed by three bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public UInt24 ToUInt24(byte[] value, int startIndex) { byte[] buffer = new byte[3]; m_copyBuffer(value, startIndex, buffer, 0, 3); return UInt24.GetValue(buffer, 0); } /// <summary> /// Returns a 32-bit unsigned integer converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public uint ToUInt32(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToUInt32(buffer, 0); } /// <summary> /// Returns a 64-bit unsigned integer converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public ulong ToUInt64(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToUInt64(buffer, 0); } /// <summary> /// Returns the specified value as an array of bytes in the target endian-order. /// </summary> /// <param name="value">The value to convert.</param> /// <returns>An array of bytes with length 1.</returns> /// <typeparam name="T">Native value type to get bytes for.</typeparam> /// <exception cref="ArgumentException"><paramref name="value"/> type is not primitive.</exception> /// <exception cref="InvalidOperationException">Cannot get bytes for <paramref name="value"/> type.</exception> public byte[] GetBytes<T>(T value) where T : struct, IConvertible { if (!typeof(T).IsPrimitive) throw new ArgumentException("Value type is not primitive", "value"); IConvertible nativeValue = (IConvertible)value; switch (nativeValue.GetTypeCode()) { case TypeCode.Char: return GetBytes(nativeValue.ToChar(null)); case TypeCode.Boolean: return GetBytes(nativeValue.ToBoolean(null)); case TypeCode.Int16:Lines 1–500 of 1383. Load more
//****************************************************************************************************** // EndianOrderTest.cs - Gbtc // // Copyright © 2010, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 02/13/2014 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** // Uncomment only for hard coded testing of BigEndian architecture code //#define ForceBigEndianTesting using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace GSF.Core.Tests { [TestClass] public class EndianOrderTest { #region [ Byte Swap/Copy Only Endian Order Testing Classes ] // These classes represent a brute-force approach to Endian order handling // that are used as a base-line for testing other optimized approaches /// <summary> /// Represents a big-endian byte order interoperability class. /// </summary> private class BigEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="BigEndianOrderTester"/> class. /// </summary> public BigEndianOrderTester() : base(Endianness.BigEndian) { } #endregion #region [ Static ] private static BigEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="BigEndianOrderTester"/> class. /// </summary> public static BigEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new BigEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents a little-endian byte order interoperability class. /// </summary> private class LittleEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="LittleEndianOrderTester"/> class. /// </summary> public LittleEndianOrderTester() : base(Endianness.LittleEndian) { } #endregion #region [ Static ] private static LittleEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="LittleEndianOrderTester"/> class. /// </summary> public static LittleEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new LittleEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents a native-endian byte order interoperability class. /// </summary> private class NativeEndianOrderTester : EndianOrderTester { #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="NativeEndianOrderTester"/> class. /// </summary> public NativeEndianOrderTester() : base(BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian) { } #endregion #region [ Static ] private static NativeEndianOrderTester s_endianOrder; /// <summary> /// Returns the default instance of the <see cref="NativeEndianOrderTester"/> class. /// </summary> public static NativeEndianOrderTester Default { get { if ((object)s_endianOrder == null) s_endianOrder = new NativeEndianOrderTester(); return s_endianOrder; } } #endregion } /// <summary> /// Represents an endian byte order interoperability class. /// </summary> /// <remarks> /// Intel systems use little-endian byte order, other systems, such as Unix, use big-endian byte ordering. /// Little-endian ordering means bits are ordered such that the bit whose in-memory representation is right-most is the most-significant-bit in a byte. /// Big-endian ordering means bits are ordered such that the bit whose in-memory representation is left-most is the most-significant-bit in a byte. /// </remarks> private class EndianOrderTester { #region [ Members ] // Delegates private delegate void CopyBufferFunction(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length); private delegate byte[] CoerceByteOrderFunction(byte[] buffer); // Fields private readonly Endianness m_targetEndianness; private readonly CopyBufferFunction m_copyBuffer; private readonly CoerceByteOrderFunction m_coerceByteOrder; #endregion #region [ Constructors ] /// <summary> /// Constructs a new instance of the <see cref="EndianOrderTester"/> class. /// </summary> /// <param name="targetEndianness">Endianness parameter.</param> protected EndianOrderTester(Endianness targetEndianness) { m_targetEndianness = targetEndianness; // We perform this logic only once for speed in conversions - we can do this because neither // the target nor the OS endian order will change during the lifecycle of this class... if (targetEndianness == Endianness.BigEndian) { #if ForceBigEndianTesting if (!BitConverter.IsLittleEndian) // <- Hard coded test for alternate architecture #else if (BitConverter.IsLittleEndian) #endif { // If OS is little endian and we want big endian, we swap the bytes m_copyBuffer = SwapCopy; m_coerceByteOrder = ReverseBuffer; } else { // If OS is big endian and we want big endian, we just copy the bytes m_copyBuffer = BlockCopy; m_coerceByteOrder = PassThroughBuffer; } } else { #if ForceBigEndianTesting if (!BitConverter.IsLittleEndian) // <- Hard coded test for alternate architecture #else if (BitConverter.IsLittleEndian) #endif { // If OS is little endian and we want little endian, we just copy the bytes m_copyBuffer = BlockCopy; m_coerceByteOrder = PassThroughBuffer; } else { // If OS is big endian and we want little endian, we swap the bytes m_copyBuffer = SwapCopy; m_coerceByteOrder = ReverseBuffer; } } } #endregion #region [ Properties ] /// <summary> /// Returns the target endian-order of this <see cref="EndianOrderTester"/> representation. /// </summary> public Endianness TargetEndianness { get { return m_targetEndianness; } } #endregion #region [ Methods ] private void BlockCopy(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length) { Buffer.BlockCopy(sourceBuffer, sourceIndex, destinationBuffer, destinationIndex, length); } // This function behaves just like Array.Copy but takes a little-endian source array and copies it in big-endian order, // or if the source array is big-endian it will copy it in little-endian order private void SwapCopy(byte[] sourceBuffer, int sourceIndex, byte[] destinationBuffer, int destinationIndex, int length) { int offset = destinationIndex + length - 1; for (int x = sourceIndex; x <= sourceIndex + length - 1; x++) { destinationBuffer[offset - (x - sourceIndex)] = sourceBuffer[x]; } } private byte[] PassThroughBuffer(byte[] buffer) { return buffer; } private byte[] ReverseBuffer(byte[] buffer) { Array.Reverse(buffer); return buffer; } /// <summary> /// Returns a <see cref="Boolean"/> value converted from one byte at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes.</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>true if the byte at startIndex in value is nonzero; otherwise, false.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> [SuppressMessage("Microsoft.Performance", "CA1822")] public bool ToBoolean(byte[] value, int startIndex) { return BitConverter.ToBoolean(value, startIndex); } /// <summary> /// Returns a Unicode character converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A character formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public char ToChar(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToChar(buffer, 0); } /// <summary> /// Returns a double-precision floating point number converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A double-precision floating point number formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public double ToDouble(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToDouble(buffer, 0); } /// <summary> /// Returns a 16-bit signed integer converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 16-bit signed integer formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public short ToInt16(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToInt16(buffer, 0); } /// <summary> /// Returns a 24-bit signed integer converted from three bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 24-bit signed integer formed by three bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public Int24 ToInt24(byte[] value, int startIndex) { byte[] buffer = new byte[3]; m_copyBuffer(value, startIndex, buffer, 0, 3); return Int24.GetValue(buffer, 0); } /// <summary> /// Returns a 32-bit signed integer converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 32-bit signed integer formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public int ToInt32(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToInt32(buffer, 0); } /// <summary> /// Returns a 64-bit signed integer converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 64-bit signed integer formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public long ToInt64(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToInt64(buffer, 0); } /// <summary> /// Returns a single-precision floating point number converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A single-precision floating point number formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public float ToSingle(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToSingle(buffer, 0); } /// <summary> /// Returns a 16-bit unsigned integer converted from two bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 16-bit unsigned integer formed by two bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public ushort ToUInt16(byte[] value, int startIndex) { byte[] buffer = new byte[2]; m_copyBuffer(value, startIndex, buffer, 0, 2); return BitConverter.ToUInt16(buffer, 0); } /// <summary> /// Returns a 24-bit unsigned integer converted from three bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 24-bit unsigned integer formed by three bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public UInt24 ToUInt24(byte[] value, int startIndex) { byte[] buffer = new byte[3]; m_copyBuffer(value, startIndex, buffer, 0, 3); return UInt24.GetValue(buffer, 0); } /// <summary> /// Returns a 32-bit unsigned integer converted from four bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 32-bit unsigned integer formed by four bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public uint ToUInt32(byte[] value, int startIndex) { byte[] buffer = new byte[4]; m_copyBuffer(value, startIndex, buffer, 0, 4); return BitConverter.ToUInt32(buffer, 0); } /// <summary> /// Returns a 64-bit unsigned integer converted from eight bytes, accounting for target endian-order, at a specified position in a byte array. /// </summary> /// <param name="value">An array of bytes (i.e., buffer containing binary image of value).</param> /// <param name="startIndex">The starting position within value.</param> /// <returns>A 64-bit unsigned integer formed by eight bytes beginning at startIndex.</returns> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception> public ulong ToUInt64(byte[] value, int startIndex) { byte[] buffer = new byte[8]; m_copyBuffer(value, startIndex, buffer, 0, 8); return BitConverter.ToUInt64(buffer, 0); } /// <summary> /// Returns the specified value as an array of bytes in the target endian-order. /// </summary> /// <param name="value">The value to convert.</param> /// <returns>An array of bytes with length 1.</returns> /// <typeparam name="T">Native value type to get bytes for.</typeparam> /// <exception cref="ArgumentException"><paramref name="value"/> type is not primitive.</exception> /// <exception cref="InvalidOperationException">Cannot get bytes for <paramref name="value"/> type.</exception> public byte[] GetBytes<T>(T value) where T : struct, IConvertible { if (!typeof(T).IsPrimitive) throw new ArgumentException("Value type is not primitive", "value"); IConvertible nativeValue = (IConvertible)value; switch (nativeValue.GetTypeCode()) { case TypeCode.Char: return GetBytes(nativeValue.ToChar(null)); case TypeCode.Boolean: return GetBytes(nativeValue.ToBoolean(null)); case TypeCode.Int16: