using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Text; using IL2CPU.API.Attribs; namespace Cosmos.Core_Plugs.System { [Plug(typeof(BitConverter))] public class BitConverterImpl { public static byte[] GetBytes(bool value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 1); byte[] r = new byte[1]; r[0] = (value ? (byte)1 : (byte)0); return r; } public static byte[] GetBytes(char value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 2); return GetBytes((short)value); } public unsafe static byte[] GetBytes(short value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 2); byte[] bytes = new byte[2]; fixed (byte* b = bytes) *((short*)b) = value; return bytes; } public unsafe static byte[] GetBytes(int value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 4); byte[] bytes = new byte[4]; fixed (byte* b = bytes) *((int*)b) = value; return bytes; } public unsafe static byte[] GetBytes(long value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 8); byte[] bytes = new byte[8]; fixed (byte* b = bytes) *((long*)b) = value; return bytes; } public static byte[] GetBytes(ushort value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 2); return GetBytes((short)value); } public static byte[] GetBytes(uint value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 4); return GetBytes((int)value); } public static byte[] GetBytes(ulong value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 8); return GetBytes((long)value); } public unsafe static byte[] GetBytes(float value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 4); return GetBytes(*(int*)&value); } public unsafe static byte[] GetBytes(double value) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == 8); return GetBytes(*(long*)&value); } public static unsafe short ToInt16(byte[] value, int startIndex) { if (value == null) ThrowValueArgumentNull(); if ((uint)startIndex >= value.Length) ThrowStartIndexArgumentOutOfRange(); if (startIndex > value.Length - 2) ThrowValueArgumentTooSmall(); Contract.EndContractBlock(); fixed (byte* pbyte = &value[startIndex]) { if (startIndex % 2 == 0) { // data is aligned return *((short*)pbyte); } else if (BitConverter.IsLittleEndian) { return (short)((*pbyte) | (*(pbyte + 1) << 8)); } else { return (short)((*pbyte << 8) | (*(pbyte + 1))); } } } public static unsafe int ToInt32(byte[] value, int startIndex) { if (value == null) ThrowValueArgumentNull(); if ((uint)startIndex >= value.Length) ThrowStartIndexArgumentOutOfRange(); if (startIndex > value.Length - 4) ThrowValueArgumentTooSmall(); Contract.EndContractBlock(); fixed (byte* pbyte = &value[startIndex]) { if (startIndex % 4 == 0) { // data is aligned return *((int*)pbyte); } else if (BitConverter.IsLittleEndian) { return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24); } else { return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)); } } } public static unsafe long ToInt64(byte[] value, int startIndex) { if (value == null) ThrowValueArgumentNull(); if ((uint)startIndex >= value.Length) ThrowStartIndexArgumentOutOfRange(); if (startIndex > value.Length - 8) ThrowValueArgumentTooSmall(); Contract.EndContractBlock(); fixed (byte* pbyte = &value[startIndex]) { if (startIndex % 8 == 0) { // data is aligned return *((long*)pbyte); } else if (BitConverter.IsLittleEndian) { int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24); int i2 = (*(pbyte + 4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24); return (uint)i1 | ((long)i2 << 32); } else { int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)); int i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7)); return (uint)i2 | ((long)i1 << 32); } } } public static unsafe double ToDouble(byte[] value, int startIndex) { if (value == null) throw new ArgumentNullException("value"); if ((uint)startIndex > value.Length) throw new ArgumentOutOfRangeException("startIndex"); if (startIndex > value.Length - 8) throw new ArgumentException("Array with offset is too short"); Contract.EndContractBlock(); long val = ToInt64(value, startIndex); return *(double*)&val; } private static void ThrowValueArgumentNull() { throw new ArgumentNullException("value"); } private static void ThrowStartIndexArgumentOutOfRange() { throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); } private static void ThrowValueArgumentTooSmall() { throw new ArgumentException("Arg_ArrayPlusOffTooSmall", "value"); } } }