//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Bitter.sg // // Helper class for moving values in and out of byte vectors. // using System; using System.Text; using System.Threading; using System.Runtime.CompilerServices; //StructAlign attribute using System.Runtime.InteropServices; //structLayout attribute using System.GCs; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.Singularity.Io; using Microsoft.Singularity.V1.Services; using Microsoft.Singularity.V1.Threads; using Allocation = Microsoft.Singularity.V1.Services.SharedHeapService.Allocation; namespace Microsoft.Singularity { public class Bitter { private static void BoundsCheck(byte[] in ExHeap buffer, int offset, int length) { if (buffer == null) { throw new ArgumentNullException("value"); } if (offset < 0) { throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_NeedNonNegNum"); } if (offset + length > buffer.Length) { throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); } } private static void BoundsCheck(char[] in ExHeap buffer, int offset, int length) { if (buffer == null) { throw new ArgumentNullException("value"); } if (offset < 0) { throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_NeedNonNegNum"); } if (offset + length > buffer.Length) { throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); } } private static void BoundsCheck(byte[] buffer, int offset, int length) { if (buffer == null) { throw new ArgumentNullException("value"); } if (offset < 0) { throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_NeedNonNegNum"); } if (offset + length > buffer.Length) { throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); } } public static unsafe UIntPtr ToAddress(byte[]! in ExHeap buffer, int offset) { unsafe { return (UIntPtr)(byte *)&buffer[offset]; } } unsafe public static byte[]! ToByteArray(byte[]! in ExHeap buffer) { byte[] retval = new byte[buffer.Length]; int length = buffer.Length; fixed (byte *pdst = &retval[0]) { fixed (byte *psrc = &buffer[0]) { Buffer.MoveMemory(pdst, psrc, length); } } return retval; } public static unsafe void ToByteArray(byte[]! in ExHeap buffer, int offset, int length, byte[]! array, int aoffset) { BoundsCheck(buffer, offset, length); BoundsCheck(array, aoffset, length); fixed (byte *pdst = &array[aoffset]) { fixed (byte *psrc = &buffer[offset]) { Buffer.MoveMemory(pdst, psrc, length); } } } public static unsafe void ToIoMemory(byte[] in ExHeap buffer, int offset, int length, IoMemory memory, int aoffset) { if (buffer == null || memory == null || offset < 0 || offset + length > buffer.Length || aoffset < 0 || aoffset + length > memory.Length) { throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); } fixed (byte * src = &buffer[offset]) { memory.Write8(aoffset, src, length); } } public static unsafe char ToChar(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(char)); fixed (byte *ptr = &buffer[offset]) { return *((char *)ptr); } } public static unsafe short ToInt16(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(short)); fixed (byte *ptr = &buffer[offset]) { return *((short *)ptr); } } public static unsafe int ToInt32(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(int)); fixed (byte *ptr = &buffer[offset]) { return *((int *)ptr); } } public static unsafe long ToInt64(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(long)); fixed (byte *ptr = &buffer[offset]) { return *((long *)ptr); } } public static unsafe ushort ToUInt16(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(ushort)); fixed (byte *ptr = &buffer[offset]) { return *((ushort *)ptr); } } public static unsafe uint ToUInt32(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(uint)); fixed (byte *ptr = &buffer[offset]) { return *((uint *)ptr); } } public static unsafe ulong ToUInt64(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(ulong)); fixed (byte *ptr = &buffer[offset]) { return *((ulong *)ptr); } } public static unsafe float ToSingle(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(float)); fixed (byte *ptr = &buffer[offset]) { return *((float *)ptr); } } public static unsafe double ToDouble(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(double)); fixed (byte *ptr = &buffer[offset]) { return *((double *)ptr); } } public static unsafe bool ToBoolean(byte[]! in ExHeap buffer, int offset) { BoundsCheck(buffer, offset, sizeof(int)); fixed (byte *ptr = &buffer[offset]) { return *((int *)ptr) == 0 ? false : true; } } // Converts a character vector to a managed string public static unsafe string ToString(char[] in ExHeap chars) { if (chars == null) return null; else { char[]! in ExHeap nnChars = chars; return ToString2(nnChars); } } // Converts a character vector to a managed string public static unsafe string! ToString2(char[]! in ExHeap chars, int offset, int length) { if ((length == 0) || (chars.Length == 0)) { return (!)String.Empty; } // happens before we have the String contract DebugStub.Assert(offset < chars.Length); DebugStub.Assert(offset + length <= chars.Length); fixed (char *ptr = &chars[0]) { // unnecessary cast, but because we have to build the // runtime first before Kernel.Contracts.dll, we don't know // that StringCTOR always returns non-null value. return (!)String.StringCTOR(ptr, offset, length); } } public static unsafe string! ToString2(char[]! in ExHeap chars) { return ToString2(chars, 0, chars.Length); } // Converts a byte vector to a managed string public static unsafe string ToString(byte[] in ExHeap chars) { if (chars == null) return null; else { return ToString2(chars); } } // Converts a character vector to a managed string public static unsafe string! ToString2(byte[]! in ExHeap chars) { if (chars.Length == 0) { return (!)String.Empty; } // happens before we have the String contract fixed (byte *ptr = &chars[0]) { // unnecessary cast, but because we have to build the // runtime first before Kernel.Contracts.dll, we don't know // that StringCTOR always returns non-null value. return (!)String.StringCTOR(ptr, 0, chars.Length); } } public static byte[]! in ExHeap FromByteArray(byte[]! buffer) { byte[] in ExHeap retval = new[ExHeap] byte[buffer.Length]; int length = buffer.Length; FromByteArray(retval, 0, length, buffer, 0); return retval; } public static byte[]! in ExHeap FromByteArray(byte[]! buffer, int offset, int length) { byte[] in ExHeap retval = new[ExHeap] byte[length]; FromByteArray(retval, 0, length, buffer, offset); return retval; } public static unsafe void FromByteArray(byte[]! in ExHeap buffer, int offset, int length, byte[]! array, int aoffset) { BoundsCheck(buffer, offset, length); BoundsCheck(array, aoffset, length); fixed (byte *pdst = &buffer[offset]) { fixed (byte *psrc = &array[aoffset]) { Buffer.MoveMemory(pdst, psrc, length); } } } public static unsafe void FromIoMemory(byte[] in ExHeap buffer, int offset, int length, IoMemory memory, int aoffset) { if (buffer == null || memory == null || offset < 0 || offset + length > buffer.Length || aoffset < 0 || aoffset + length > memory.Length) { throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); } fixed (byte * src = &buffer[offset]) { memory.Read8(aoffset, src, length); } } public static unsafe void FromChar(byte[]! in ExHeap buffer, int offset, char value) { BoundsCheck(buffer, offset, sizeof(char)); fixed (byte *ptr = &buffer[offset]) { *((char *)ptr) = value; } } public static unsafe void FromInt16(byte[]! in ExHeap buffer, int offset, short value) { BoundsCheck(buffer, offset, sizeof(short)); fixed (byte *ptr = &buffer[offset]) { *((short *)ptr) = value; } } public static unsafe void FromInt32(byte[]! in ExHeap buffer, int offset, int value) { BoundsCheck(buffer, offset, sizeof(int)); fixed (byte *ptr = &buffer[offset]) { *((int *)ptr) = value; } } public static unsafe void FromInt64(byte[]! in ExHeap buffer, int offset, long value) { BoundsCheck(buffer, offset, sizeof(long)); fixed (byte *ptr = &buffer[offset]) { *((long *)ptr) = value; } } public static unsafe void FromUInt16(byte[]! in ExHeap buffer, int offset, ushort value) { BoundsCheck(buffer, offset, sizeof(ushort)); fixed (byte *ptr = &buffer[offset]) { *((ushort *)ptr) = value; } } public static unsafe void FromUInt32(byte[]! in ExHeap buffer, int offset, uint value) { BoundsCheck(buffer, offset, sizeof(uint)); fixed (byte *ptr = &buffer[offset]) { *((uint *)ptr) = value; } } public static unsafe void FromUInt64(byte[]! in ExHeap buffer, int offset, ulong value) { BoundsCheck(buffer, offset, sizeof(ulong)); fixed (byte *ptr = &buffer[offset]) { *((ulong *)ptr) = value; } } public static unsafe void FromSingle(byte[]! in ExHeap buffer, int offset, float value) { BoundsCheck(buffer, offset, sizeof(float)); fixed (byte *ptr = &buffer[offset]) { *((float *)ptr) = value; } } public static unsafe void FromDouble(byte[]! in ExHeap buffer, int offset, double value) { BoundsCheck(buffer, offset, sizeof(double)); fixed (byte *ptr = &buffer[offset]) { *((double *)ptr) = value; } } public static unsafe void FromBoolean(byte[]! in ExHeap buffer, int offset, bool value) { BoundsCheck(buffer, offset, sizeof(int)); fixed (byte *ptr = &buffer[offset]) { *((int *)ptr) = value ? 1 : 0; } } // Converts a managed string to a char vector. public static char[] in ExHeap FromString(string str) { if (str == null) { return null; } return FromString2(str); } // Converts a managed string to a char vector. public static char[]! in ExHeap FromString2(string! str) { return FromString2(str, 0, str.Length); } public static char[]! in ExHeap FromString2(string! str, int start, int length) { if (length == 0) { return new [ExHeap] char[0]; } else { if (start + length > str.Length) { length = str.Length - start; } char [] in ExHeap retval = new [ExHeap] char [length]; for (int i = 0; i < length; i++) { retval[i] = str[start + i]; } return retval; } } public static unsafe void Copy(byte[]! in ExHeap dest, int destOffset, int length, byte[]! in ExHeap source, int sourceOffset) { BoundsCheck(source, sourceOffset, length); BoundsCheck(dest, destOffset, length); fixed (byte *pdst = &dest[destOffset]) { fixed (byte *psrc = &source[sourceOffset]) { Buffer.MoveMemory(pdst, psrc, length); } } } public static unsafe void Copy(char[]! in ExHeap dest, int destOffset, int length, char[]! in ExHeap source, int sourceOffset) { BoundsCheck(source, sourceOffset, length); BoundsCheck(dest, destOffset, length); fixed (char *pdst = &dest[destOffset]) { fixed (char *psrc = &source[sourceOffset]) { Buffer.MoveMemory((byte*)pdst, (byte*)psrc, length*sizeof(char)); } } } public static unsafe void Zero(byte[]! in ExHeap dest, int destOffset, int length) { BoundsCheck(dest, destOffset, length); fixed (byte *pdst = &dest[destOffset]) { Buffer.ZeroMemory(pdst, length); } } public static unsafe byte[]! in ExHeap SplitOff(ref byte[]! in ExHeap original, int offset) { byte[]! in ExHeap vec = original; return (byte[]! in ExHeap)SharedHeapService.Split( (Allocation*)vec, new UIntPtr(offset) ); } public static unsafe char[]! in ExHeap SplitOff(ref char[]! in ExHeap original, int charOffset) { char[]! in ExHeap vec = original; return (char[]! in ExHeap)SharedHeapService.Split( (Allocation*)vec, new UIntPtr(sizeof(char) * charOffset) ); } public static unsafe void Truncate(ref byte[]! in ExHeap buffer, int newLength) { SharedHeapService.Truncate( (Allocation*)buffer, new UIntPtr(newLength) ); } public static unsafe void Truncate(ref char[]! in ExHeap buffer, int newLength) { SharedHeapService.Truncate( (Allocation*)buffer, new UIntPtr(sizeof(char) * newLength) ); } } }