488 lines
18 KiB
Plaintext
488 lines
18 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|