1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-21 17:28:00 +02:00

Initial checkin

This commit is contained in:
Brian Fiete 2019-08-23 11:56:54 -07:00
parent c74712dad9
commit 078564ac9e
3242 changed files with 1616395 additions and 0 deletions

View file

@ -0,0 +1,555 @@
// This file contains portions of code released by Microsoft under the MIT license as part
// of an open-sourcing initiative in 2014 of the C# core libraries.
// The original source was submitted to https://github.com/Microsoft/referencesource
using System.Collections.Generic;
using System.Diagnostics;
namespace System
{
typealias int_arsize = int;
class Array
{
protected int_arsize mLength;
public int Count
{
[Inline]
set
{
// We only allow reducing the length - consider using System.Collections.Generic.List<T> when dynamic sizing is required
Runtime.Assert(value <= mLength);
mLength = value;
}
[Inline]
get
{
return mLength;
}
}
public bool IsEmpty
{
get
{
return mLength == 0;
}
}
public static int BinarySearch<T>(T* arr, int idx, int length, T value) where T : IComparable<T>
{
int lo = idx;
int hi = idx + length - 1;
while (lo <= hi)
{
int i = (lo + hi) / 2;
T midVal = arr[i];
int c = midVal.CompareTo(value);
if (c == 0) return i;
if (c < 0)
lo = i + 1;
else
hi = i - 1;
}
return ~lo;
}
public static int BinarySearch<T>(T* arr, int idx, int length, T value, IComparer<T> comp)
{
int lo = idx;
int hi = idx + length - 1;
while (lo <= hi)
{
int i = (lo + hi) / 2;
T midVal = arr[i];
int c = comp.Compare(midVal, value);
if (c == 0) return i;
if (c < 0)
lo = i + 1;
else
hi = i - 1;
}
return ~lo;
}
public static void Clear<T>(T[] arr, int idx, int length)
{
for (int i = idx; i < idx + length; i++)
arr[i] = default(T);
}
public static void Copy<T, T2>(T[] arrayFrom, int srcOffset, T2[] arrayTo, int dstOffset, int length) where T : var where T2 : var
{
if (((Object)arrayTo == (Object)arrayFrom) && (dstOffset > srcOffset))
{
for (int i = length - 1; i >= 0; i--)
arrayTo.getRef(i + dstOffset) = (T2)arrayFrom.getRef(i + srcOffset);
return;
}
for (int i = 0; i < length; i++)
arrayTo.getRef(i + dstOffset) = (T2)arrayFrom.getRef(i + srcOffset);
}
public static void Sort<T>(T[] array, Comparison<T> comp)
{
var sorter = Sorter<T, void>(&array.[Friend]mFirstElement, null, array.[Friend]mLength, comp);
sorter.Sort(0, array.[Friend]mLength);
}
public static void Sort<T, T2>(T[] keys, T2[] items, Comparison<T> comp)
{
var sorter = Sorter<T, T2>(&keys.[Friend]mFirstElement, &items.[Friend]mFirstElement, keys.[Friend]mLength, comp);
sorter.Sort(0, keys.[Friend]mLength);
}
public static void Sort<T>(T[] array, int index, int count, Comparison<T> comp)
{
var sorter = Sorter<T, void>(&array.[Friend]mFirstElement, null, array.[Friend]mLength, comp);
sorter.Sort(index, count);
}
}
class Array1<T> : Array
{
T mFirstElement;
public this()
{
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx]
{
[Checked, Inline]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
public void CopyTo(T[] arrayTo)
{
Debug.Assert(arrayTo.mLength >= mLength);
Internal.MemCpy(&arrayTo.getRef(0), &getRef(0), strideof(T) * mLength, alignof(T));
}
public void CopyTo(T[] arrayTo, int srcOffset, int dstOffset, int length)
{
Debug.Assert(length >= 0);
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.mLength);
Internal.MemCpy(&arrayTo.getRef(dstOffset), &getRef(srcOffset), strideof(T) * length, alignof(T));
}
public void CopyTo<T2>(T2[] arrayTo, int srcOffset, int dstOffset, int length) where T2 : var
{
Debug.Assert(length >= 0);
Debug.Assert((uint)srcOffset + (uint)length <= (uint)mLength);
Debug.Assert((uint)dstOffset + (uint)length <= (uint)arrayTo.[Friend]mLength);
if (((Object)arrayTo == (Object)this) && (dstOffset > srcOffset))
{
for (int i = length - 1; i >= 0; i--)
arrayTo.getRef(i + dstOffset) = (T2)getRef(i + srcOffset);
return;
}
for (int i = 0; i < length; i++)
arrayTo.getRef(i + dstOffset) = (T2)getRef(i + srcOffset);
}
protected override void GCMarkMembers()
{
let type = typeof(T);
if ((type.mTypeFlags & .WantsMark) == 0)
return;
for (int i = 0; i < mLength; i++)
{
GC.Mark((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array2<T> : Array
{
int_arsize mLength1;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / mLength1;
else if (dim == 1)
return mLength1;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1)
{
return ref (&mFirstElement)[idx0*mLength1 + idx1];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1)
{
int idx = idx0*mLength1 + idx1;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx0*mLength1 + idx1];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1]
{
[Checked]
get
{
int idx = idx0*mLength1 + idx1;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array3<T> : Array
{
int_arsize mLength1;
int_arsize mLength2;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / (mLength1*mLength2);
else if (dim == 1)
return mLength1;
else if (dim == 2)
return mLength2;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1, int idx2)
{
return ref (&mFirstElement)[(idx0*mLength1 + idx1)*mLength2 + idx2];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1, int idx2)
{
int idx = (idx0*mLength1 + idx1)*mLength2 + idx2;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[(idx0*mLength1 + idx1)*mLength2 + idx2];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2]
{
[Checked]
get
{
int idx = (idx0*mLength1 + idx1)*mLength2 + idx2;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
[Ordered]
class Array4<T> : Array
{
int_arsize mLength1;
int_arsize mLength2;
int_arsize mLength3;
T mFirstElement;
Array GetSelf()
{
return this;
}
public this()
{
}
public int GetLength(int dim)
{
if (dim == 0)
return mLength / (mLength1*mLength2*mLength3);
else if (dim == 1)
return mLength1;
else if (dim == 2)
return mLength2;
else if (dim == 3)
return mLength3;
Runtime.FatalError();
}
[Inline]
public ref T getRef(int idx)
{
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRef(int idx0, int idx1, int idx2, int idx3)
{
return ref (&mFirstElement)[((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3];
}
[Inline]
public ref T getRefChecked(int idx)
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Inline]
public ref T getRefChecked(int idx0, int idx1, int idx2, int idx3)
{
int idx = ((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2) ||
((uint)idx3 >= (uint)mLength3))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
public ref T this[int idx]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2, int idx3]
{
[Unchecked, Inline]
get
{
return ref (&mFirstElement)[((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3];
}
}
public ref T this[int idx]
{
[Checked]
get
{
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
public ref T this[int idx0, int idx1, int idx2, int idx3]
{
[Checked]
get
{
int idx = ((idx0*mLength1 + idx1)*mLength2 + idx2)*mLength3 + idx3;
if (((uint)idx >= (uint)mLength) ||
((uint)idx1 >= (uint)mLength1) ||
((uint)idx2 >= (uint)mLength2) ||
((uint)idx3 >= (uint)mLength3))
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
}
[Inline]
public T* CArray()
{
return &mFirstElement;
}
protected override void GCMarkMembers()
{
for (int i = 0; i < mLength; i++)
{
GC.Mark_Unbound((&mFirstElement)[i]);
}
}
}
}

View file

@ -0,0 +1,370 @@
namespace System
{
public struct Attribute
{
}
public enum AttributeTargets
{
Assembly = 0x0001,
Module = 0x0002,
Class = 0x0004,
Struct = 0x0008,
Enum = 0x0010,
Constructor = 0x0020,
Method = 0x0040,
Property = 0x0080,
Field = 0x0100,
StaticField = 0x0200,
Interface = 0x0400,
Parameter = 0x0800,
Delegate = 0x1000,
Function = 0x2000,
ReturnValue = 0x4000,
//@todo GENERICS: document GenericParameter
GenericParameter = 0x8000,
Invocation = 0x10000,
MemberAccess = 0x20000,
All = Assembly | Module | Class | Struct | Enum | Constructor |
Method | Property | Field | StaticField | Interface | Parameter |
Delegate | Function | ReturnValue | GenericParameter | Invocation | MemberAccess,
}
public enum ReflectKind
{
None = 0,
Type = 1,
NonStaticFields = 2,
StaticFields = 4,
DefaultConstructor = 8,
Constructors = 0x10,
StaticMethods = 0x20,
Methods = 0x40,
All = 0x7F,
ApplyToInnerTypes = 0x80,
}
public enum AttributeFlags
{
None,
DisallowAllowMultiple = 1,
NotInherited = 2,
ReflectAttribute = 4,
AlwaysIncludeTarget = 8
}
public sealed struct AttributeUsageAttribute : Attribute
{
internal AttributeTargets mAttributeTarget = AttributeTargets.All;
internal AttributeFlags mAttributeFlags = .None;
internal ReflectKind mReflectUser = .None;
public this(AttributeTargets validOn)
{
mAttributeTarget = validOn;
}
internal this(AttributeTargets validOn, AttributeFlags flags)
{
mAttributeTarget = validOn;
mAttributeFlags = flags;
}
internal this(AttributeTargets validOn, bool allowMultiple, bool inherited)
{
mAttributeTarget = validOn;
if (!allowMultiple)
mAttributeFlags |= .DisallowAllowMultiple;
if (!inherited)
mAttributeFlags |= .NotInherited;
}
public AttributeTargets ValidOn
{
get { return mAttributeTarget; }
}
public ReflectKind ReflectUser
{
get { return mReflectUser; }
set mut { mReflectUser = value; }
}
}
[AttributeUsage(AttributeTargets.All)]
public struct ReflectAttribute : Attribute
{
public this(ReflectKind reflectKind = .All)
{
}
}
[AttributeUsage(AttributeTargets.Method /*1*/ | .Invocation | .Property)]
public struct InlineAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Invocation)]
public struct UnboundAttribute : Attribute
{
}
[AttributeUsage(.Class | .Struct | .Interface | .Method | .Constructor)]
public struct AlwaysIncludeAttribute : Attribute
{
bool mAssumeInstantiated;
public bool AssumeInstantiated
{
get { return mAssumeInstantiated; }
set mut { mAssumeInstantiated = value; }
}
}
[AttributeUsage(AttributeTargets.MemberAccess)]
public struct FriendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.MemberAccess)]
public struct SkipAccessCheckAttribute : Attribute
{
}
[AttributeUsage(.Method | .Class | .Struct | .Enum)]
public struct OptimizeAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
public struct CLinkAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
public struct LinkNameAttribute : Attribute
{
public this(String linkName)
{
}
}
[AttributeUsage(AttributeTargets.Method | .Delegate | .Function)]
public struct StdCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
public struct CVarArgsAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
public struct NoReturnAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
public struct SkipCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
public struct IntrinsicAttribute : Attribute
{
public this(String intrinName)
{
}
public this(String intrinName, Type t0)
{
}
public this(String intrinName, Type t0, Type t1)
{
}
public this(String intrinName, Type t0, Type t1, Type t2)
{
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct /*2*/)]
public struct StaticInitPriorityAttribute : Attribute
{
public this(int priority)
{
}
}
[AttributeUsage(AttributeTargets.Class /*2*/ | AttributeTargets.Struct /*2*/)]
public struct StaticInitAfterAttribute : Attribute
{
public this()
{
}
public this(Type afterType)
{
}
}
[AttributeUsage(AttributeTargets.Struct)]
public struct ForceAddrAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Constructor)]
public struct AllowAppendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public struct PackedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public struct UnionAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public struct CReprAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public struct OrderedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
public struct HideAttribute : Attribute
{
}
[AttributeUsage(.Parameter)]
public struct HideNameAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
public struct TestAttribute : Attribute
{
public bool ShouldFail;
public bool Ignore;
public bool Profile;
}
namespace Runtime.InteropServices
{
public enum CallingConvention
{
Winapi = 1,
Cdecl = 2,
StdCall = 3,
ThisCall = 4,
FastCall = 5,
Default = Cdecl
}
[AttributeUsage(AttributeTargets.Method /*3*/)]
public struct DllImportAttribute : Attribute
{
public this(String dllName)
{
CallingConvention = .Default;
CLink = false;
}
public CallingConvention CallingConvention;
public bool CLink;
}
}
public struct ImportAttribute : Attribute
{
public this(String libName)
{
}
}
[AttributeUsage(AttributeTargets.StaticField | AttributeTargets.Field, .NotInherited)]
public struct ThreadStaticAttribute : Attribute
{
public this()
{
}
}
[AttributeUsage(.Invocation | .Method | .Property)]
public struct CheckedAttribute : Attribute
{
}
[AttributeUsage(.Invocation | .Method | .Property)]
public struct UncheckedAttribute : Attribute
{
}
[AttributeUsage(.Method | .Constructor)]
public struct DisableChecksAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
public struct DisableObjectAccessChecksAttribute : Attribute
{
}
[AttributeUsage(.Method | .Class | .Struct)]
public struct NoDiscardAttribute : Attribute
{
public this()
{
}
public this(String message)
{
}
}
}

View file

@ -0,0 +1,470 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: BitConverter
**
**
** Purpose: Allows developers to view the base data types as
** an arbitrary array of bits.
**
**
===========================================================*/
namespace System
{
using System;
using System.Diagnostics.Contracts;
// The BitConverter class contains methods for
// converting an array of bytes to one of the base data
// types, as well as for converting a base data type to an
// array of bytes.
//
// Only statics, does not need to be marked with the serializable attribute
public static class BitConverter
{
// This field indicates the "endianess" of the architecture.
// The value is set to true if the architecture is
// little endian; false if it is big endian.
#if BIGENDIAN
public static readonly bool IsLittleEndian /* = false */;
#else
public static readonly bool IsLittleEndian = true;
#endif
/*
// Converts a byte into an array of bytes with length one.
public static byte[] GetBytes(bool value) {
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 1);
byte[] r = new byte[1];
r[0] = (value ? (byte)Boolean.True : (byte)Boolean.False );
return r;
}
// Converts a char into an array of bytes with length two.
public static byte[] GetBytes(char value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 2);
return GetBytes((short)value);
}
// Converts a short into an array of bytes with length
// two.
[System.Security.SecuritySafeCritical] // auto-generated
public static byte[] GetBytes(short value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 2);
byte[] bytes = new byte[2];
fixed(byte* b = bytes)
*((short*)b) = value;
return bytes;
}
// Converts an int into an array of bytes with length
// four.
[System.Security.SecuritySafeCritical] // auto-generated
public static byte[] GetBytes(int value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 4);
byte[] bytes = new byte[4];
fixed(byte* b = bytes)
*((int*)b) = value;
return bytes;
}
// Converts a long into an array of bytes with length
// eight.
[System.Security.SecuritySafeCritical] // auto-generated
public static byte[] GetBytes(long value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 8);
byte[] bytes = new byte[8];
fixed(byte* b = bytes)
*((long*)b) = value;
return bytes;
}
// Converts an ushort into an array of bytes with
// length two.
[CLSCompliant(false)]
public static byte[] GetBytes(ushort value) {
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 2);
return GetBytes((short)value);
}
// Converts an uint into an array of bytes with
// length four.
[CLSCompliant(false)]
public static byte[] GetBytes(uint value) {
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 4);
return GetBytes((int)value);
}
// Converts an unsigned long into an array of bytes with
// length eight.
[CLSCompliant(false)]
public static byte[] GetBytes(ulong value) {
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 8);
return GetBytes((long)value);
}
// Converts a float into an array of bytes with length
// four.
[System.Security.SecuritySafeCritical] // auto-generated
public static byte[] GetBytes(float value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 4);
return GetBytes(*(int*)&value);
}
// Converts a double into an array of bytes with length
// eight.
[System.Security.SecuritySafeCritical] // auto-generated
public static byte[] GetBytes(double value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 8);
return GetBytes(*(long*)&value);
}
// Converts an array of bytes into a char.
public static char ToChar(byte[] value, int startIndex)
{
if (value == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
}
if ((uint)startIndex >= value.Length) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
}
if (startIndex > value.Length - 2) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
Contract.EndContractBlock();
return (char)ToInt16(value, startIndex);
}
// Converts an array of bytes into a short.
[System.Security.SecuritySafeCritical] // auto-generated
public static short ToInt16(byte[] value, int startIndex) {
if( value == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
}
if ((uint) startIndex >= value.Length) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
}
if (startIndex > value.Length -2) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
Contract.EndContractBlock();
byte * pbyte = &value[startIndex];
{
if( startIndex % 2 == 0) { // data is aligned
return *((short *) pbyte);
}
else {
if( IsLittleEndian) {
return (short)((*pbyte) | (*(pbyte + 1) << 8)) ;
}
else {
return (short)((*pbyte << 8) | (*(pbyte + 1)));
}
}
}
}
// Converts an array of bytes into an int.
[System.Security.SecuritySafeCritical] // auto-generated
public static int ToInt32 (byte[] value, int startIndex) {
if( value == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
}
if ((uint) startIndex >= value.Length) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
}
if (startIndex > value.Length -4) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
Contract.EndContractBlock();
fixed( byte * pbyte = &value[startIndex]) {
if( startIndex % 4 == 0) { // data is aligned
return *((int *) pbyte);
}
else {
if( IsLittleEndian) {
return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
}
else {
return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
}
}
}
}
// Converts an array of bytes into a long.
[System.Security.SecuritySafeCritical] // auto-generated
public static long ToInt64 (byte[] value, int startIndex) {
if (value == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
}
if ((uint) startIndex >= value.Length) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
}
if (startIndex > value.Length -8) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
Contract.EndContractBlock();
byte * pbyte = &value[startIndex];
{
if( startIndex % 8 == 0) { // data is aligned
return *((long *) pbyte);
}
else {
if( 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);
}
}
}
}
// Converts an array of bytes into an ushort.
//
[CLSCompliant(false)]
public static ushort ToUInt16(byte[] value, int startIndex)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
if ((uint)startIndex >= value.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
if (startIndex > value.Length - 2)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
Contract.EndContractBlock();
return (ushort)ToInt16(value, startIndex);
}
// Converts an array of bytes into an uint.
//
[CLSCompliant(false)]
public static uint ToUInt32(byte[] value, int startIndex)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
if ((uint)startIndex >= value.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
if (startIndex > value.Length - 4)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
Contract.EndContractBlock();
return (uint)ToInt32(value, startIndex);
}
// Converts an array of bytes into an unsigned long.
//
[CLSCompliant(false)]
public static ulong ToUInt64(byte[] value, int startIndex)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
if ((uint)startIndex >= value.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
if (startIndex > value.Length - 8)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
Contract.EndContractBlock();
return (ulong)ToInt64(value, startIndex);
}
// Converts an array of bytes into a float.
[System.Security.SecuritySafeCritical] // auto-generated
public static float ToSingle (byte[] value, int startIndex)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
if ((uint)startIndex >= value.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
if (startIndex > value.Length - 4)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
Contract.EndContractBlock();
int val = ToInt32(value, startIndex);
return *(float*)&val;
}
// Converts an array of bytes into a double.
[System.Security.SecuritySafeCritical] // auto-generated
public static double ToDouble (byte[] value, int startIndex)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
if ((uint)startIndex >= value.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
if (startIndex > value.Length - 8)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
Contract.EndContractBlock();
long val = ToInt64(value, startIndex);
return *(double*)&val;
}
private static char GetHexValue(int i) {
Contract.Assert( i >=0 && i <16, "i is out of range.");
if (i<10) {
return (char)(i + '0');
}
return (char)(i - 10 + 'A');
}
// Converts an array of bytes into a String.
public static String ToString (byte[] value, int startIndex, int length) {
if (value == null) {
throw new ArgumentNullException("byteArray");
}
if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array.
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
}
if (length < 0) {
throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
}
if (startIndex > value.Length - length) {
throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
}
Contract.EndContractBlock();
if (length == 0) {
return string.Empty;
}
if (length > (Int32.MaxValue / 3)) {
// (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB
throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthTooLarge", (Int32.MaxValue / 3)));
}
int chArrayLength = length * 3;
char[] chArray = new char[chArrayLength];
int i = 0;
int index = startIndex;
for (i = 0; i < chArrayLength; i += 3) {
byte b = value[index++];
chArray[i]= GetHexValue(b/16);
chArray[i+1] = GetHexValue(b%16);
chArray[i+2] = '-';
}
// We don't need the last '-' character
return new String(chArray, 0, chArray.Length - 1);
}
// Converts an array of bytes into a String.
public static String ToString(byte [] value) {
if (value == null)
throw new ArgumentNullException("value");
Contract.Ensures(Contract.Result<String>() != null);
Contract.EndContractBlock();
return ToString(value, 0, value.Length);
}
// Converts an array of bytes into a String.
public static String ToString (byte [] value, int startIndex) {
if (value == null)
throw new ArgumentNullException("value");
Contract.Ensures(Contract.Result<String>() != null);
Contract.EndContractBlock();
return ToString(value, startIndex, value.Length - startIndex);
}
/*==================================ToBoolean===================================
**Action: Convert an array of bytes to a boolean value. We treat this array
** as if the first 4 bytes were an Int4 an operate on this value.
**Returns: True if the Int4 value of the first 4 bytes is non-zero.
**Arguments: value -- The byte array
** startIndex -- The position within the array.
**Exceptions: See ToInt4.
==============================================================================*/
// Converts an array of bytes into a boolean.
public static bool ToBoolean(byte[] value, int startIndex) {
if (value==null)
throw new ArgumentNullException("value");
if (startIndex < 0)
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
if (startIndex > value.Length - 1)
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
Contract.EndContractBlock();
return (value[startIndex]==0)?false:true;
}*/
public static int64 DoubleToInt64Bits(double value)
{
// If we're on a big endian machine, what should this method do? You could argue for
// either big endian or little endian, depending on whether you are writing to a file that
// should be used by other programs on that processor, or for compatibility across multiple
// formats. Because this is ambiguous, we're excluding this from the Portable Library & Win8 Profile.
// If we ever run on big endian machines, produce two versions where endianness is specified.
Contract.Assert(IsLittleEndian, "This method is implemented assuming little endian with an ambiguous spec.");
double val = value;
return *((int64*)&val);
}
public static double Int64BitsToDouble(int64 value)
{
// If we're on a big endian machine, what should this method do? You could argue for
// either big endian or little endian, depending on whether you are writing to a file that
// should be used by other programs on that processor, or for compatibility across multiple
// formats. Because this is ambiguous, we're excluding this from the Portable Library & Win8 Profile.
// If we ever run on big endian machines, produce two versions where endianness is specified.
Contract.Assert(IsLittleEndian, "This method is implemented assuming little endian with an ambiguous spec.");
double val = value;
return *((double*)&val);
}
}
}

View file

@ -0,0 +1,651 @@
// This file contains portions of code released by Microsoft under the MIT license as part
// of an open-sourcing initiative in 2014 of the C# core libraries.
// The original source was submitted to https://github.com/Microsoft/referencesource
#if PARANOID
#define VERSION_LIST
#endif
using System;
using System.Runtime;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Reflection;
namespace System.Collections.Generic
{
interface IList
{
Variant this[int index]
{
get;
set;
}
}
public class List<T> : IEnumerable<T>, IList
{
private const int_cosize cDefaultCapacity = 4;
const int_cosize SizeFlags = 0x7FFFFFFF;
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
#if BF_ENABLE_REALTIME_LEAK_CHECK
static DbgRawAllocData sRawAllocData;
public static this()
{
sRawAllocData.mMarkFunc = null;
sRawAllocData.mMaxStackTrace = 1;
sRawAllocData.mType = typeof(T);
}
#endif
private T* mItems;
private int_cosize mSize;
private int_cosize mAllocSizeAndFlags;
#if VERSION_LIST
private int32 mVersion;
const String cVersionError = "List changed during enumeration";
#endif
public int AllocSize
{
[Inline]
get
{
return mAllocSizeAndFlags & SizeFlags;
}
}
public bool IsDynAlloc
{
[Inline]
get
{
return (mAllocSizeAndFlags & DynAllocFlag) != 0;
}
}
public this()
{
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
{
NOP!();
}
}
public this(IEnumerator<T> enumerator)
{
for (var item in enumerator)
Add(item);
}
[AllowAppend]
public this(int capacity)
{
Debug.Assert((uint)capacity <= (uint)SizeFlags);
T* items = append T[capacity]*;
if (capacity > 0)
{
mItems = items;
mAllocSizeAndFlags = (int_cosize)(capacity & SizeFlags);
}
}
/*public this(int capacity)
{
Debug.Assert((uint)capacity <= (uint)SizeFlags);
if (capacity > 0)
{
mItems = Alloc(capacity);
mAllocSizeAndFlags = (int_cosize)(capacity | DynAllocFlag);
}
}*/
public ~this()
{
#if DBG
int typeId = typeof(T).GetTypeId();
if (typeId == sDebugTypeId)
{
Debug.WriteLine("Dealloc {0} {1}", scope Object[] { this, mItems } );
}
#endif
if (IsDynAlloc)
Free(mItems);
}
public T* Ptr
{
get
{
return mItems;
}
}
#if DBG
static int_cosize sDebugTypeId = 470;
static int_cosize sDebugIdx = 0;
#endif
public int Capacity
{
get
{
return mAllocSizeAndFlags & SizeFlags;
}
set
{
Debug.Assert((uint)value <= (uint)SizeFlags);
if (value != AllocSize)
{
if (value > 0)
{
T* newItems = Alloc(value);
#if DBG
int typeId = typeof(T).GetTypeId();
if (typeId == sDebugTypeId)
{
Debug.WriteLine("Alloc {0} {1} {2}", scope Object[] { this, newItems, sDebugIdx } );
sDebugIdx++;
}
#endif
if (mSize > 0)
Internal.MemCpy(newItems, mItems, mSize * strideof(T), alignof(T));
if (IsDynAlloc)
Free(mItems);
mItems = newItems;
mAllocSizeAndFlags = (.)(value | DynAllocFlag);
}
else
{
if (IsDynAlloc)
Free(mItems);
mItems = null;
mAllocSizeAndFlags = 0;
}
}
}
}
public int Count
{
get
{
return mSize;
}
}
public bool IsEmpty
{
get
{
return mSize == 0;
}
}
public ref T this[int index]
{
[Checked]
get
{
Debug.Assert((uint)index < (uint)mSize);
return ref mItems[index];
}
[Checked]
set
{
Debug.Assert((uint)index < (uint)mSize);
mItems[index] = value;
#if VERSION_LIST
mVersion++;
#endif
}
}
public ref T this[int index]
{
[Unchecked, Inline]
get
{
return ref mItems[index];
}
[Unchecked, Inline]
set
{
mItems[index] = value;
#if VERSION_LIST
mVersion++;
#endif
}
}
public ref T Back
{
get
{
Debug.Assert(mSize != 0);
return ref mItems[mSize - 1];
}
}
Variant IList.this[int index]
{
get
{
return [Unbound]Variant.Create(this[index]);
}
set
{
ThrowUnimplemented();
}
}
protected T* Alloc(int size)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
// We don't want to use the default mark function because it will mark the entire array,
// whereas we have a custom marking routine because we only want to mark up to mSize
return (T*)Internal.Dbg_RawAlloc(size * strideof(T), &sRawAllocData);
#else
return new T[size]*(?);
#endif
}
protected void Free(T* val)
{
delete val;
}
/*protected T[] Alloc(int size)
{
return new:this T[size];
}
protected void Free(Object obj)
{
delete:this obj;
}
protected virtual Object AllocObject(TypeInstance type, int size)
{
return Internal.ObjectAlloc(type, size);
}
protected virtual void FreeObject(Object obj)
{
delete obj;
}*/
/// Adds an item to the back of the list.
public void Add(T item)
{
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
{
NOP!();
}
if (mSize == AllocSize) EnsureCapacity(mSize + 1);
mItems[mSize++] = item;
#if VERSION_LIST
mVersion++;
#endif
}
/// Returns a pointer to the start of the added uninitialized section
public T* GrowUnitialized(int addSize)
{
if (mSize + addSize > AllocSize) EnsureCapacity(mSize + addSize);
mSize += (int_cosize)addSize;
#if VERSION_LIST
mVersion++;
#endif
if (addSize == 0)
return null;
return &mItems[mSize - addSize];
}
public void Clear()
{
if (mSize > 0)
{
mSize = 0;
}
#if VERSION_LIST
mVersion++;
#endif
}
/*public static void DeleteItemsAndClear<T>(List<T> list) where T : delete
{
foreach (var item in list)
delete item;
list.Clear();
}*/
public bool Contains(T item)
{
if (item == null)
{
for (int i = 0; i < mSize; i++)
if (mItems[i] == null)
return true;
return false;
}
else
{
for (int i = 0; i < mSize; i++)
if (mItems[i] == item)
return true;
return false;
}
}
public void CopyTo(T[] array)
{
CopyTo(array, 0);
}
public void CopyTo(List<T> destList)
{
destList.EnsureCapacity(mSize);
destList.mSize = mSize;
if (mSize > 0)
Internal.MemCpy(destList.mItems, mItems, mSize * strideof(T), alignof(T));
}
public void CopyTo(T[] array, int arrayIndex)
{
// Delegate rest of error checking to Array.Copy.
for (int_cosize i = 0; i < mSize; i++)
array[i + arrayIndex] = mItems[i];
}
public void EnsureCapacity(int min)
{
int allocSize = AllocSize;
if (allocSize < min)
{
int_cosize newCapacity = (int_cosize)(allocSize == 0 ? cDefaultCapacity : allocSize * 2);
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when mItems.Length overflowed thanks to the (uint) cast
//if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
if (newCapacity < min) newCapacity = (int_cosize)min;
Capacity = newCapacity;
}
}
public void Reserve(int size)
{
EnsureCapacity(size);
}
public Enumerator GetEnumerator()
{
return Enumerator(this);
}
public int_cosize IndexOf(T item)
{
//return Array.IndexOf(mItems, item, 0, mSize);
for (int i = 0; i < mSize; i++)
if (mItems[i] == item)
return (int_cosize)i;
return -1;
}
public int_cosize IndexOf(T item, int index)
{
for (int i = index; i < mSize; i++)
if (mItems[i] == item)
return (int_cosize)i;
return -1;
}
public int_cosize IndexOf(T item, int index, int count)
{
for (int i = index; i < index + count; i++)
if (mItems[i] == item)
return (int_cosize)i;
return -1;
}
public void Insert(int index, T item)
{
if (mSize == AllocSize) EnsureCapacity(mSize + 1);
if (index < mSize)
{
Internal.MemCpy(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
}
mItems[index] = item;
mSize++;
#if VERSION_LIST
mVersion++;
#endif
}
public void RemoveAt(int index)
{
if (((int)Internal.UnsafeCastToPtr(this) & 0xFFFF) == 0x4BA0)
{
NOP!();
}
Debug.Assert((uint)index < (uint)mSize);
if (index < mSize - 1)
{
Internal.MemCpy(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
}
mSize--;
#if VERSION_LIST
mVersion++;
#endif
}
public void RemoveRange(int index, int count)
{
Debug.Assert((uint)index + (uint)count <= (uint)mSize);
if (index + count < mSize - 1)
{
for (int i = index; i < mSize - count; i++)
mItems[i] = mItems[i + count];
}
mSize -= (.)count;
#if VERSION_LIST
mVersion++;
#endif
}
public void RemoveAtFast(int index)
{
Debug.Assert((uint32)index < (uint32)mSize);
mSize--;
if (mSize > 0)
mItems[index] = mItems[mSize];
#if VERSION_LIST
mVersion++;
#endif
}
public void Sort(Comparison<T> comp)
{
var sorter = Sorter<T, void>(mItems, null, mSize, comp);
sorter.Sort(0, mSize);
}
public T PopBack()
{
T backVal = mItems[mSize - 1];
mSize--;
return backVal;
}
public T PopFront()
{
T backVal = mItems[0];
RemoveAt(0);
return backVal;
}
public bool Remove(T item)
{
int_cosize index = IndexOf(item);
if (index >= 0)
{
RemoveAt(index);
return true;
}
return false;
}
public static operator Span<T>(List<T> list)
{
return Span<T>(list.mItems, list.mSize);
}
protected override void GCMarkMembers()
{
for (int i < mSize)
{
GC.Mark_Unbound(mItems[i]);
}
}
public struct Enumerator : IRefEnumerator<T>
{
private List<T> mList;
private int mIndex;
#if VERSION_LIST
private int32 mVersion;
#endif
private T* mCurrent;
internal this(List<T> list)
{
mList = list;
mIndex = 0;
#if VERSION_LIST
mVersion = list.mVersion;
#endif
mCurrent = null;
}
#if VERSION_LIST
void CheckVersion()
{
if (mVersion != mList.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public void Dispose()
{
}
public bool MoveNext() mut
{
List<T> localList = mList;
if ((uint(mIndex) < uint(localList.mSize)))
{
mCurrent = &localList.mItems[mIndex];
mIndex++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare() mut
{
#if VERSION_LIST
CheckVersion();
#endif
mIndex = mList.mSize + 1;
mCurrent = null;
return false;
}
public T Current
{
get
{
return *mCurrent;
}
}
public ref T CurrentRef
{
get
{
return ref *mCurrent;
}
}
public int Index
{
get
{
return mIndex - 1;
}
}
public int Count
{
get
{
return mList.Count;
}
}
public void Remove() mut
{
int curIdx = mIndex - 1;
mList.RemoveAt(curIdx);
#if VERSION_LIST
mVersion = mList.mVersion;
#endif
mIndex = curIdx;
}
public void RemoveFast() mut
{
int curIdx = mIndex - 1;
int lastIdx = mList.Count - 1;
if (curIdx < lastIdx)
mList[curIdx] = mList[lastIdx];
mList.RemoveAt(lastIdx);
#if VERSION_LIST
mVersion = mList.mVersion;
#endif
mIndex = curIdx;
}
public void Reset() mut
{
mIndex = 0;
mCurrent = null;
}
public Result<T> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
public Result<T*> GetNextRef() mut
{
if (!MoveNext())
return .Err;
return &CurrentRef;
}
}
}
}

View file

@ -0,0 +1,302 @@
// This file contains portions of code released by Microsoft under the MIT license as part
// of an open-sourcing initiative in 2014 of the C# core libraries.
// The original source was submitted to https://github.com/Microsoft/referencesource
namespace System.Collections.Generic
{
struct Sorter<T, T2>
{
// This is the threshold where Introspective sort switches to Insertion sort.
// Empirically, 16 seems to speed up most cases without slowing down others, at least for integers.
// Large value types may benefit from a smaller number.
const int IntrosortSizeThreshold = 16;
private T* keys;
private T2* items;
private int mCount;
private Comparison<T> comparer;
internal this(T* keys, T2* items, int count, Comparison<T> comparer)
{
this.keys = keys;
this.items = items;
mCount = count;
this.comparer = comparer;
}
internal static int FloorLog2(int n)
{
int result = 0;
int val = n;
while (val >= 1)
{
result++;
val = val / 2;
}
return result;
}
private static int GetMedian(int low, int hi)
{
// Note both may be negative, if we are dealing with arrays w/ negative lower bounds.
//Contract.Requires(low <= hi);
//Contract.Assert( hi - low >= 0, "Length overflow!");
return low + ((hi - low) >> 1);
}
internal void SwapIfGreaterWithItems(int a, int b)
{
if (a != b)
{
if (comparer(keys[a], keys[b]) > 0)
{
T temp = keys[a];
keys[a] = keys[b];
keys[b] = temp;
if ((items != null) && (sizeof(T2) != 0))
{
T2 item = items[a];
items[a] = items[b];
items[b] = item;
}
}
}
}
private void Swap(int i, int j)
{
T t = keys[i];
keys[i] = keys[j];
keys[j] = t;
if (items != null)
{
T2 item = items[i];
items[i] = items[j];
items[j] = item;
}
}
internal void Sort(int left, int length)
{
IntrospectiveSort(left, length);
}
private void DepthLimitedQuickSort(int left, int right, int depthLimit)
{
// Can use the much faster jit helpers for array access.
repeat
{
if (depthLimit == 0)
{
Heapsort(left, right);
return;
}
int curLeft = left;
int curRight = right;
int curDepthLimit = depthLimit;
int i = curLeft;
int j = curRight;
// pre-sort the low, middle (pivot), and high values in place.
// this improves performance in the face of already sorted data, or
// data that is made up of multiple sorted runs appended together.
int middle = GetMedian(i, j);
SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
SwapIfGreaterWithItems(i, j); // swap the low with the high
SwapIfGreaterWithItems(middle, j); // swap the middle with the high
T x = keys[middle];
repeat
{
while (comparer(keys[i], x) < 0) i++;
while (comparer(x, keys[j]) < 0) j--;
//Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
if (i > j) break;
if (i < j)
{
T key = keys[i];
keys[i] = keys[j];
keys[j] = key;
if (items != null)
{
T2 item = items[i];
items[i] = items[j];
items[j] = item;
}
}
i++;
j--;
} while (i <= j);
// The next iteration of the while loop is to "recursively" sort the larger half of the array and the
// following calls recrusively sort the smaller half. So we subtrack one from depthLimit here so
// both sorts see the new value.
curDepthLimit--;
if (j - curLeft <= curRight - i)
{
if (curLeft < j) DepthLimitedQuickSort(curLeft, j, curDepthLimit);
curLeft = i;
}
else
{
if (i < curRight) DepthLimitedQuickSort(i, curRight, curDepthLimit);
curRight = j;
}
} while (left < right);
}
private void IntrospectiveSort(int left, int length)
{
if (length < 2)
return;
IntroSort(left, length + left - 1, 2 * FloorLog2(mCount));
}
private void IntroSort(int lo, int hi, int depthLimit)
{
int curHi = hi;
int curDepthLimit = depthLimit;
while (curHi > lo)
{
int partitionSize = curHi - lo + 1;
if (partitionSize <= IntrosortSizeThreshold)
{
if (partitionSize == 1)
{
return;
}
if (partitionSize == 2)
{
SwapIfGreaterWithItems(lo, curHi);
return;
}
if (partitionSize == 3)
{
SwapIfGreaterWithItems(lo, curHi-1);
SwapIfGreaterWithItems(lo, curHi);
SwapIfGreaterWithItems(curHi-1, curHi);
return;
}
InsertionSort(lo, curHi);
return;
}
if (curDepthLimit == 0)
{
Heapsort(lo, curHi);
return;
}
curDepthLimit--;
int p = PickPivotAndPartition(lo, curHi);
IntroSort(p + 1, curHi, curDepthLimit);
curHi = p - 1;
}
}
private int PickPivotAndPartition(int lo, int hi)
{
// Compute median-of-three. But also partition them, since we've done the comparison.
int mid = lo + (hi - lo) / 2;
// Sort lo, mid and hi appropriately, then pick mid as the pivot.
SwapIfGreaterWithItems(lo, mid);
SwapIfGreaterWithItems(lo, hi);
SwapIfGreaterWithItems(mid, hi);
T pivot = keys[mid];
Swap(mid, hi - 1);
int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
while (left < right)
{
while (comparer(keys[++left], pivot) < 0) {}
while (comparer(pivot, keys[--right]) < 0) {}
if(left >= right)
break;
Swap(left, right);
}
// Put pivot in the right location.
Swap(left, (hi - 1));
return left;
}
private void Heapsort(int lo, int hi)
{
int n = hi - lo + 1;
for (int i = n / 2; i >= 1; i = i - 1)
{
DownHeap(i, n, lo);
}
for (int i = n; i > 1; i = i - 1)
{
Swap(lo, lo + i - 1);
DownHeap(1, i - 1, lo);
}
}
private void DownHeap(int i, int n, int lo)
{
int curI = i;
T d = keys[lo + curI - 1];
//T dt = (items != null) ? items[lo + i - 1] : null;
T2* dt = (items != null) ? &items[lo + curI - 1] : null;
int child;
while (curI <= n / 2)
{
child = 2 * curI;
if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0)
{
child++;
}
if (!(comparer(d, keys[lo + child - 1]) < 0))
break;
keys[lo + curI - 1] = keys[lo + child - 1];
if(items != null)
items[lo + curI - 1] = items[lo + child - 1];
curI = child;
}
keys[lo + curI - 1] = d;
if (items != null)
items[lo + curI - 1] = *dt;
}
private void InsertionSort(int lo, int hi)
{
int i, j;
T t;
T2* ti = null;
for (i = lo; i < hi; i++)
{
j = i;
t = keys[i + 1];
//ti = (items != null) ? items[i + 1] : null;
if (items != null)
ti = &items[i + 1];
while (j >= lo && comparer(t, keys[j]) < 0)
{
keys[j + 1] = keys[j];
if(items != null)
items[j + 1] = items[j];
j--;
}
keys[j + 1] = t;
if (items != null)
items[j + 1] = *ti;
}
}
}
}

View file

@ -0,0 +1,36 @@
using System;
using System.Runtime.InteropServices;
namespace System.Collections
{
interface IEnumerator
{
Object Current { get; }
bool MoveNext();
void Reset();
void Dispose();
}
interface IEnumerable
{
IEnumerator GetEnumerator();
}
}
namespace System.Collections.Generic
{
interface IEnumerator<T>
{
Result<T> GetNext() mut;
}
interface IRefEnumerator<T> : IEnumerator<T>
{
Result<T*> GetNextRef() mut;
}
concrete interface IEnumerable<T>
{
concrete IEnumerator<T> GetEnumerator();
}
}

View file

@ -0,0 +1,61 @@
namespace System.Diagnostics.Contracts
{
class Contract
{
public enum ContractFailureKind
{
Precondition,
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
Postcondition,
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
PostconditionOnException,
Invariant,
Assert,
Assume,
}
static extern void ReportFailure(ContractFailureKind failureKind, char8* userMessage, int32 userMessageLen, char8* conditionText, int32 conditionTextLen);
/// <summary>
/// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
/// It is NEVER used to indicate failure of actual contracts at runtime.
/// </summary>
static void AssertMustUseRewriter(ContractFailureKind kind, String contractKind)
{
}
public static void Assume(bool condition, StringView userMessage)
{
if (!condition)
{
ReportFailure(ContractFailureKind.Assume, userMessage.Ptr, (int32)userMessage.Length, null, 0);
}
}
public static void Assert(bool condition)
{
if (!condition)
ReportFailure(ContractFailureKind.Assert, null, 0, null, 0);
}
public static void Assert(bool condition, String userMessage)
{
if (!condition)
ReportFailure(ContractFailureKind.Assert, userMessage.Ptr, (int32)userMessage.Length, null, 0);
}
public static void Requires(bool condition)
{
if (!condition)
ReportFailure(ContractFailureKind.Assert, null, 0, null, 0);
//AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
public static void Requires(bool condition, StringView userMessage)
{
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
public static void EndContractBlock() { }
}
}

View file

@ -0,0 +1,6 @@
namespace System.Diagnostics.Contracts
{
class ContractsBcl
{
}
}

View file

@ -0,0 +1,50 @@
namespace System.Diagnostics
{
class Debug
{
//[System.Diagnostics.Conditional("DEBUG")]
#if !DEBUG
[SkipCall]
#endif
public static void Assert(bool condition)
{
if (!condition)
Internal.FatalError("Assert failed", 1);
}
#if !DEBUG
[SkipCall]
#endif
public static void Assert(bool condition, StringView error)
{
if (!condition)
Internal.FatalError("Assert failed", 1);
}
#if !DEBUG
[SkipCall]
#endif
static extern void Write(char8* str, int strLen);
public static void WriteLine(StringView line)
{
Write(line.Ptr, line.Length);
Write("\n", 1);
}
/*public static void WriteLine(StringView strFormat, params Object[] args)
{
String paramStr = scope String();
paramStr.FormatInto(strFormat, args);
paramStr.Append('\n');
Write(paramStr.Ptr, paramStr.Length);
}*/
[NoReturn]
public static void FatalError(String str = "")
{
Internal.FatalError(str, 1);
}
}
}

View file

@ -0,0 +1,95 @@
using System.Threading;
namespace System.Diagnostics
{
enum ProfilerScope
{
Thread,
Process
}
struct ProfileId : int32
{
}
class Profiler
{
public enum Priority
{
Low,
Normal,
High
}
static int32 gProfileId = 1;
public struct AutoLeave
{
//Profiler mProfiler;
public this(/*Profiler profiler*/)
{
//mProfiler = profiler;
}
void Dispose()
{
Profiler.LeaveSection();
}
}
static Result<ProfileId> StartSampling(int32 threadId, StringView profileDesc)
{
//int32 curId = Interlocked.Increment(ref gProfileId);
int32 curId = gProfileId++;
String str = scope String();
str.Append("StartSampling\t");
curId.ToString(str);
str.Append("\t");
threadId.ToString(str);
str.Append("\t");
str.Append(profileDesc);
Internal.ProfilerCmd(str);
return (ProfileId)curId;
}
public static void StopSampling(ProfileId profileId)
{
String str = scope String();
str.Append("StopSampling\t");
((int32)profileId).ToString(str);
Internal.ProfilerCmd(str);
}
public static Result<ProfileId> StartSampling(Thread thread, StringView profileDesc = default)
{
return StartSampling(thread.Id, profileDesc);
}
public static Result<ProfileId> StartSampling(StringView profileDesc = default)
{
return StartSampling(0, profileDesc);
}
public static void ClearSampling()
{
Internal.ProfilerCmd("ClearSampling");
}
public void Mark()
{
}
public static AutoLeave EnterSection(StringView name, Priority priority = Priority.Normal)
{
return AutoLeave();
}
public static void LeaveSection()
{
}
}
}

View file

@ -0,0 +1,135 @@
// ==++== b
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: Stopwatch
**
** Purpose: Implementation for Stopwatch class.
**
** Date: Nov 27, 2002
**
===========================================================*/
namespace System.Diagnostics
{
using System;
public class Stopwatch
{
private const int64 TicksPerMillisecond = 1000;
private const int64 TicksPerSecond = TicksPerMillisecond * 1000;
private int64 elapsed;
private int64 startTimeStamp;
private bool isRunning;
public this()
{
}
public void Start()
{
// Calling start on a running Stopwatch is a no-op.
if (!isRunning)
{
startTimeStamp = GetTimestamp();
isRunning = true;
}
}
public static Stopwatch StartNew()
{
Stopwatch s = new Stopwatch();
s.Start();
return s;
}
public void Stop()
{
// Calling stop on a stopped Stopwatch is a no-op.
if (isRunning)
{
int64 endTimeStamp = GetTimestamp();
int64 elapsedThisPeriod = endTimeStamp - startTimeStamp;
elapsed += elapsedThisPeriod;
isRunning = false;
if (elapsed < 0)
{
// When measuring small time periods the StopWatch.Elapsed*
// properties can return negative values. This is due to
// bugs in the basic input/output system (BIOS) or the hardware
// abstraction layer (HAL) on machines with variable-speed CPUs
// (e.g. Intel SpeedStep).
elapsed = 0;
}
}
}
public void Reset()
{
elapsed = 0;
isRunning = false;
startTimeStamp = 0;
}
// Convenience method for replacing {sw.Reset(); sw.Start();} with a single sw.Restart()
public void Restart()
{
elapsed = 0;
startTimeStamp = GetTimestamp();
isRunning = true;
}
public bool IsRunning
{
get { return isRunning; }
}
public TimeSpan Elapsed
{
get { return TimeSpan(GetElapsedDateTimeTicks()); }
}
public int64 ElapsedMilliseconds
{
get { return GetRawElapsedTicks() / TicksPerMillisecond; }
}
public int64 ElapsedMicroseconds
{
get { return GetRawElapsedTicks(); }
}
public static int64 GetTimestamp()
{
return Internal.GetTickCountMicro();
}
// Get the elapsed ticks.
private int64 GetRawElapsedTicks()
{
int64 timeElapsed = elapsed;
if (isRunning)
{
// If the StopWatch is running, add elapsed time since
// the Stopwatch is started last time.
int64 currentTimeStamp = GetTimestamp();
int64 elapsedUntilNow = currentTimeStamp - startTimeStamp;
timeElapsed += elapsedUntilNow;
}
return timeElapsed;
}
// Get the elapsed ticks.
private int64 GetElapsedDateTimeTicks()
{
return GetRawElapsedTicks() * 10;
}
}
}

View file

@ -0,0 +1,343 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: Double
**
**
** Purpose: A representation of an IEEE double precision
** floating point number.
**
**
===========================================================*/
namespace System
{
using System;
///#if GENERICS_WORK
/// using System.Numerics;
///#endif
using System.Runtime.InteropServices;
using System.Diagnostics.Contracts;
public struct Double : double, IHashable, IOpComparable, IOpNegatable, ICanBeNaN /*: IComparable, IFormattable, IConvertible
, IComparable<Double>, IEquatable<Double>*/
{
//
// Public Constants
//
public const double MinValue = -1.7976931348623157E+308;
public const double MaxValue = 1.7976931348623157E+308;
// Note Epsilon should be a double whose hex representation is 0x1
// on little endian machines.
public const double Epsilon = 4.9406564584124654E-324;
public const double NegativeInfinity = (double)(- 1.0 / (double)(0.0));
public const double PositiveInfinity = (double)1.0 / (double)(0.0);
public const double NaN = (double)0.0 / (double)0.0;
internal static double NegativeZero = BitConverter.Int64BitsToDouble((int64)(0x8000000000000000UL));
public static int operator<=>(Double lhs, Double rhs)
{
return (double)lhs <=> (double)rhs;
}
public static Double operator-(Double value)
{
return -(double)value;
}
int IHashable.GetHashCode()
{
double d = (double)this;
if (d == 0)
{
// Ensure that 0 and -0 have the same hash code
return 0;
}
if (sizeof(int) == sizeof(double))
{
var val = (double)this;
return *(int*)(&val);
}
else
{
int64 value = *(int64*)(&d);
return ((int32)value) ^ ((int32)(value >> 32));
}
}
public bool IsInfinity
{
get
{
double val = (double)this;
return (*(int64*)(&val) & 0x7FFFFFFFFFFFFFFFL) == 0x7FF0000000000000L;
}
}
public bool IsPositiveInfinity
{
get
{
return (double)this == double.PositiveInfinity;
}
}
public bool IsNegativeInfinity
{
get
{
return (double)this == double.NegativeInfinity;
}
}
internal bool IsNegative
{
get
{
double val = (double)this;
return (*(uint64*)(&val) & 0x8000000000000000UL) == 0x8000000000000000UL;
}
}
public bool IsNaN
{
get
{
double val = (double)this;
return (*(uint64*)(&val) & 0x7FFFFFFFFFFFFFFFUL) > 0x7FF0000000000000UL;
}
}
// Compares this object to another object, returning an instance of System.Relation.
// Null is considered less than any instance.
//
// If object is not of type Double, this method throws an ArgumentException.
//
// Returns a value less than zero if this object
//
public int32 CompareTo(Object value)
{
if (value == null)
{
return 1;
}
if (value is double)
{
double d = (double)value;
if ((double)this < d) return -1;
if ((double)this > d) return 1;
if ((double)this == d) return 0;
// At least one of the values is NaN.
if (IsNaN)
return (d.IsNaN ? 0 : -1);
else
return 1;
}
Runtime.FatalError();
}
public int32 CompareTo(double value)
{
if ((double)this < value) return -1;
if ((double)this > value) return 1;
if ((double)this == value) return 0;
// At least one of the values is NaN.
if (IsNaN)
return (value.IsNaN) ? 0 : -1;
else
return 1;
}
public bool Equals(double obj)
{
if (obj == (double)this)
{
return true;
}
return obj.IsNaN && IsNaN;
}
[CLink]
static extern double strtod(char8* str, char8** endPtr);
public static Result<double> Parse(String val)
{
return .Ok(strtod(val, null));
}
//TODO:
/*[System.Security.SecuritySafeCritical] // auto-generated
public override String ToString() {
Contract.Ensures(Contract.Result<String>() != null);
return Number.FormatDouble((double)this, null, NumberFormatInfo.CurrentInfo);
}
[System.Security.SecuritySafeCritical] // auto-generated
public String ToString(String format) {
Contract.Ensures(Contract.Result<String>() != null);
return Number.FormatDouble((double)this, format, NumberFormatInfo.CurrentInfo);
}
[System.Security.SecuritySafeCritical] // auto-generated
public String ToString(IFormatProvider provider) {
Contract.Ensures(Contract.Result<String>() != null);
return Number.FormatDouble((double)this, null, NumberFormatInfo.GetInstance(provider));
}
[System.Security.SecuritySafeCritical] // auto-generated
public String ToString(String format, IFormatProvider provider) {
Contract.Ensures(Contract.Result<String>() != null);
return Number.FormatDouble((double)this, format, NumberFormatInfo.GetInstance(provider));
}
public static double Parse(String s) {
return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
public static double Parse(String s, NumberStyles style) {
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Parse(s, style, NumberFormatInfo.CurrentInfo);
}
public static double Parse(String s, IFormatProvider provider) {
return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
public static double Parse(String s, NumberStyles style, IFormatProvider provider) {
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Parse(s, style, NumberFormatInfo.GetInstance(provider));
}
// Parses a double from a String in the given style. If
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
// This method will not throw an OverflowException, but will return
// PositiveInfinity or NegativeInfinity for a number that is too
// large or too small.
//
private static double Parse(String s, NumberStyles style, NumberFormatInfo info) {
return Number.ParseDouble(s, style, info);
}
public static bool TryParse(String s, out double result) {
return TryParse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
}
public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result) {
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out double result) {
if (s == null) {
result = 0;
return false;
}
bool success = Number.TryParseDouble(s, style, info, out result);
if (!success) {
String sTrim = s.Trim();
if (sTrim.Equals(info.PositiveInfinitySymbol)) {
result = PositiveInfinity;
} else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
result = NegativeInfinity;
} else if (sTrim.Equals(info.NaNSymbol)) {
result = NaN;
} else
return false; // We really failed
}
return true;
}
//
// IConvertible implementation
//
public TypeCode GetTypeCode() {
return TypeCode.Double;
}
/// <internalonly/>
bool IConvertible.ToBoolean(IFormatProvider provider) {
return Convert.ToBoolean((double)this);
}
/// <internalonly/>
char8 IConvertible.ToChar(IFormatProvider provider) {
Runtime.FatalError();
}
/// <internalonly/>
sbyte IConvertible.ToSByte(IFormatProvider provider) {
return Convert.ToSByte((double)this);
}
/// <internalonly/>
byte IConvertible.ToByte(IFormatProvider provider) {
return Convert.ToByte((double)this);
}
/// <internalonly/>
short IConvertible.ToInt16(IFormatProvider provider) {
return Convert.ToInt16((double)this);
}
/// <internalonly/>
ushort IConvertible.ToUInt16(IFormatProvider provider) {
return Convert.ToUInt16((double)this);
}
/// <internalonly/>
int IConvertible.ToInt32(IFormatProvider provider) {
return Convert.ToInt32((double)this);
}
/// <internalonly/>
uint IConvertible.ToUInt32(IFormatProvider provider) {
return Convert.ToUInt32((double)this);
}
/// <internalonly/>
long IConvertible.ToInt64(IFormatProvider provider) {
return Convert.ToInt64((double)this);
}
/// <internalonly/>
ulong IConvertible.ToUInt64(IFormatProvider provider) {
return Convert.ToUInt64((double)this);
}
/// <internalonly/>
float IConvertible.ToSingle(IFormatProvider provider) {
return Convert.ToSingle((double)this);
}
/// <internalonly/>
double IConvertible.ToDouble(IFormatProvider provider) {
return (double)this;
}
/// <internalonly/>
Decimal IConvertible.ToDecimal(IFormatProvider provider) {
return Convert.ToDecimal((double)this);
}
/// <internalonly/>
DateTime IConvertible.ToDateTime(IFormatProvider provider) {
Runtime.FatalError();
}
/// <internalonly/>
Object IConvertible.ToType(Type type, IFormatProvider provider) {
return Convert.DefaultToType((IConvertible)this, type, provider);
}*/
}
}

View file

@ -0,0 +1,31 @@
namespace System
{
class Environment
{
#if !PLATFORM_UNIX
public static readonly String NewLine = "\r\n";
#else
static readonly string NewLine = new string("\n");
#endif // !PLATFORM_UNIX
internal static String GetResourceString(String key)
{
return key;
//return GetResourceFromDefault(key);
}
internal static String GetResourceString(String key, params Object[] values)
{
return key;
//return GetResourceFromDefault(key);
}
internal static String GetRuntimeResourceString(String key, String defaultValue = null)
{
if (defaultValue != null)
return defaultValue;
return key;
//return GetResourceFromDefault(key);
}
}
}

View file

@ -0,0 +1,306 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace System
{
// Event owns the delegates it contains
// Event supports removals and additions while enumerating without invalidating the enumerator.
// Event can also safely be Disposed and even have its memory reclaimed during enumeration
// Event is not thread-safe: access must be protected during modification, and during enumeration
struct Event<T> where T : Delegate
{
// mData can be null with no listeners, T for one listener, or List<T> for multiple
// If we are enumerating then mData points to the enumerator.
int mData;
const int sIsEnumerating = 1;
const int sHadEnumRemoves = 2;
const int sFlagsMask = 3;
const int sDataMask = ~sFlagsMask;
public bool HasListeners
{
get
{
return (mData & sDataMask) != 0;
}
}
public int32 Count
{
get
{
Object data = Internal.UnsafeCastToObject((void*)(mData & sDataMask));
if (data == null)
return 0;
var type = data.GetType();
if (type == typeof(List<T>))
{
var list = (List<T>)data;
return (int32)list.Count;
}
return 1;
}
}
public Object Target
{
get
{
if (mData & sIsEnumerating != 0)
{
Enumerator* enumerator = (Enumerator*)(void*)(mData & sDataMask);
return enumerator.[Friend]mTarget;
}
return Internal.UnsafeCastToObject((void*)mData);
}
set mut
{
if (mData & sIsEnumerating != 0)
{
Enumerator* enumerator = (Enumerator*)(void*)(mData & sDataMask);
enumerator.[Friend]mTarget = value;
}
else
{
mData = (int)Internal.UnsafeCastToPtr(value);
}
}
}
protected override void GCMarkMembers()
{
if (mData & sDataMask != 0)
GC.Mark(Internal.UnsafeCastToObject((void*)mData));
}
public void Add(T dlg) mut
{
Object data = Target;
if (data == null)
{
Target = dlg;
return;
}
var type = data.GetType();
if (type == typeof(List<T>))
{
var list = (List<T>)data;
list.Add(dlg);
}
else
{
var list = new List<T>();
list.Add((T)data);
list.Add(dlg);
Target = list;
}
}
public void Remove(T dlg, bool deleteListener = false) mut
{
Object data = Target;
var type = data.GetType();
if (type == typeof(List<T>))
{
var list = (List<T>)data;
int32 idx = -1;
for (int32 i = 0; i < list.Count; i++)
if (Delegate.Equals(list[i], dlg))
{
idx = i;
break;
}
if (idx == -1)
{
Runtime.FatalError("Not found");
}
if (deleteListener)
delete list[idx];
if (mData & sIsEnumerating != 0)
{
// In order to avoid invalidating the enumerator's index during enumeration, we
// just null this entry out and then we physically remove the entries upon
// Dispose of the enumerator
list[idx] = null;
mData |= sHadEnumRemoves;
}
else
list.RemoveAt(idx);
if (list.Count == 0)
{
delete list;
Target = null;
}
}
else
{
T dlgMember = (T)data;
if (Delegate.Equals(dlg, dlgMember))
{
if (deleteListener)
delete dlgMember;
Target = null;
return;
}
else
{
Runtime.FatalError("Not found");
}
}
}
public rettype(T) Invoke(params T p) mut
{
var result = default(rettype(T));
for (var dlg in this)
{
result = dlg(params p);
}
return result;
}
public void Dispose() mut
{
if (mData == 0)
return;
var data = Target;
if (data.GetType() == typeof(List<T>))
{
var list = (List<T>)data;
for (var dlg in list)
delete dlg;
}
delete data;
Target = null;
}
public Enumerator GetEnumerator() mut
{
return Enumerator(ref this);
}
public struct Enumerator : IEnumerator<T>
{
Event<T>* mEvent;
Object mTarget;
int32 mIdx;
Enumerator* mRootEnumerator;
T mCurrent;
public this(ref Event<T> event)
{
mEvent = &event;
mIdx = -2;
mRootEnumerator = null;
mCurrent = null;
mTarget = null;
}
public void Dispose() mut
{
if (mRootEnumerator == &this)
{
if ((mEvent.mData & Event<T>.sHadEnumRemoves != 0) && (mTarget != null))
{
var list = (List<T>)mTarget;
// Remove nulls
for (int32 i = 0; i < list.Count; i++)
{
if (list[i] == null)
{
list.RemoveAt(i);
i--;
}
}
if (list.Count == 0)
{
delete list;
mEvent.mData = 0;
return;
}
}
mEvent.mData = (int)Internal.UnsafeCastToPtr(mTarget);
}
}
public void Reset() mut
{
mIdx = -1;
}
public bool MoveNext() mut
{
if (mIdx == -2)
{
// Attach
if (mEvent.mData & sIsEnumerating == 0)
{
mTarget = mEvent.Target;
mEvent.mData = (int)(void*)(&this) | sIsEnumerating;
mRootEnumerator = &this;
}
else
{
mRootEnumerator = (Enumerator*)(void*)(mEvent.mData & Event<T>.sDataMask);
}
mIdx = -1;
}
var data = mRootEnumerator.mTarget;
if (data == null)
return false;
var type = data.GetType();
if (type == typeof(List<T>))
{
var list = (List<T>)data;
repeat
{
mIdx++;
if (mIdx >= list.Count)
return false;
mCurrent = list[mIdx];
}
while (mCurrent == null);
}
else
{
mIdx++;
if (mIdx > 0)
return false;
mCurrent = (T)data;
}
return true;
}
public T Current
{
get
{
return mCurrent;
}
}
public Result<T> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
}

View file

@ -0,0 +1,196 @@
using System;
using System.Threading;
namespace System
{
public interface ILeakIdentifiable
{
void ToLeakString(String str);
}
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
[AlwaysInclude]
#endif
public static class GC
{
enum RootResult
{
Ok
}
public delegate Result<void> RootCallback();
#if BF_ENABLE_REALTIME_LEAK_CHECK
static Event<RootCallback> sRootCallbacks ~ _.Dispose();
static Thread sThread;
static Monitor sMonitor = new Monitor() ~ delete _;
static this()
{
FindAllTLSMembers();
Init();
}
static ~this()
{
StopCollecting();
}
#elif BF_DEBUG_ALLOC
static ~this()
{
//Report();
}
#endif
public static void AddRootCallback(RootCallback rootDelegate)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
sRootCallbacks.Add(rootDelegate);
#endif
}
public static void RemoveRootCallback(RootCallback rootDelegate)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
sRootCallbacks.Remove(rootDelegate);
#endif
}
static bool CallRootCallbacks()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
{
var result = sRootCallbacks();
if (result case .Err)
return false;
}
#endif
return true;
}
extern static void ReportTLSMember(int moduleTLSIndex, void* addr, void* markFunc);
static void ReportTLSMember(void* addr, void* markFunc)
{
ReportTLSMember(Thread.ModuleTLSIndex, addr, markFunc);
}
extern static void Run();
static void ThreadProc(Object param)
{
Run();
}
public static void Start()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
sThread = new Thread(new => ThreadProc);
sThread.Start(true);
#endif
}
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
public extern static void Report();
public extern static void Shutdown();
public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage);
#else
public static void Report() {}
public static void Shutdown() {}
public static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage) {}
#endif
#if BF_ENABLE_REALTIME_LEAK_CHECK
private extern static void Init();
public extern static void Collect(bool async = true);
private extern static void StopCollecting();
private extern static void AddStackMarkableObject(Object obj);
private extern static void RemoveStackMarkableObject(Object obj);
[AlwaysInclude]
private extern static void MarkAllStaticMembers();
private extern static void FindAllTLSMembers();
public extern static void DebugDumpLeaks();
public extern static void Mark(Object obj);
public extern static void Mark(void* ptr, int size);
public extern static void SetAutoCollectPeriod(int periodMS); // <= -1 to disable, 0 to constantly run. Defaults to -1
public extern static void SetCollectFreeThreshold(int freeBytes); // -1 to disable, 0 to trigger collection after every single free. Defaults to 64MB
public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
#else
public static void Collect(bool async = true) {}
private static void MarkAllStaticMembers() {}
public static void DebugDumpLeaks() {}
public static void Mark(Object obj) {}
public static void Mark(void* ptr, int size) {}
public static void SetAutoCollectPeriod(int periodMS) {}
public static void SetCollectFreeThreshold(int freeBytes) {}
public static void SetMaxPausePercentage(int maxPausePercentage) {}
#endif
static void MarkDerefedObject(Object* obj)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
Mark(*obj);
#endif
}
public static void Mark<T>(T val) where T : class
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
Mark((Object)val);
#endif
}
public static void Mark<T>(T val) where T : struct
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
val.[Friend]GCMarkMembers();
#endif
}
public static void Mark<T>(T val) where T : struct*
{
// Memory pointed to by struct*'s will already-scanned stack memory,
// or the memory would already be registered with the GC
}
public static void Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
for (var element in val)
{
Mark(element);
}
#endif
}
public static void Mark_Enumerate<T>(T val) where T : var
{
/*for (var element in val)
{
Mark(element);
}*/
}
public static void Mark_Unbound<T>(T val) where T : var
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
Mark(val);
#endif
}
public static void ToLeakString(Object obj, String strBuffer)
{
obj.GetType().GetName(strBuffer);
/*strBuffer.Append("@");
((intptr)(void*)obj).ToString(strBuffer, "X", null);
var leakIdentifier = obj as ILeakIdentifiable;
if (leakIdentifier != null)
{
strBuffer.Append(" : ");
leakIdentifier.ToLeakString(strBuffer);
}*/
}
}
}

View file

@ -0,0 +1,57 @@
namespace System
{
interface IComparable<T>
{
int32 CompareTo(T other);
}
public interface IComparer<T>
{
int Compare(T x, T y);
}
interface IOpEquatable
{
static bool operator==(Self lhs, Self other);
}
interface IOpEquatable<TRight>
{
static bool operator==(Self lhs, TRight other);
}
interface IOpComparable
{
static int operator<=>(Self lhs, Self rhs);
}
interface IOpAddable
{
static Self operator+(Self lhs, Self rhs);
}
interface IOpNegatable
{
static Self operator-(Self value);
}
interface IOpConvertibleTo<T>
{
static operator T(Self value);
}
interface IOpConvertibleFrom<T>
{
static operator Self(T value);
}
interface IIsNaN
{
bool IsNaN { get; }
}
interface ICanBeNaN : IIsNaN
{
}
}

View file

@ -0,0 +1,25 @@
namespace System
{
interface IHashable
{
int GetHashCode();
}
/*extension IHashable where Self : class
{
}*/
static class HashHelper
{
public static int GetHashCode<T>(T val) where T : class
{
return (int)(void*)(val);
}
public static int GetHashCode<T>(T val) where T : IHashable
{
return val.GetHashCode();
}
}
}

View file

@ -0,0 +1,221 @@
using System.Collections.Generic;
using System.Reflection;
namespace System
{
struct DbgRawAllocData
{
public Type mType;
public void* mMarkFunc;
public int32 mMaxStackTrace;
}
[AlwaysInclude]
static class Internal
{
public static extern Object UnsafeCastToObject(void* ptr);
public static extern void* UnsafeCastToPtr(Object obj);
[NoReturn]
public static extern void ThrowIndexOutOfRange(int stackOffset = 0);
[NoReturn]
public static extern void FatalError(String error, int stackOffset = 0);
[Intrinsic("memcpy")]
public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false);
[Intrinsic("memmove")]
public static extern void MemMove(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false);
[Intrinsic("memset")]
public static extern void MemSet(void* addr, uint8 val, int length, int32 align = 1, bool isVolatile = false);
[Intrinsic("malloc")]
public static extern void* Malloc(int size);
[Intrinsic("free")]
public static extern void Free(void* ptr);
[LinkName("malloc")]
public static extern void* StdMalloc(int size);
[LinkName("free")]
public static extern void StdFree(void* ptr);
public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite);
public static extern int32 CStrLen(char8* charPtr);
public static extern int64 GetTickCountMicro();
public static extern void BfDelegateTargetCheck(void* target);
[AlwaysInclude]
public static extern void* LoadSharedLibrary(char8* filePath);
[AlwaysInclude]
public static extern void LoadSharedLibraryInto(char8* filePath, void** libDest);
[AlwaysInclude]
public static extern void* GetSharedProcAddress(void* libHandle, char8* procName);
[AlwaysInclude]
public static extern void GetSharedProcAddressInto(void* libHandle, char8* procName, void** procDest);
public static extern char8* GetCommandLineArgs();
public static extern void ProfilerCmd(char8* str);
public static extern void ReportMemory();
public static extern void ObjectDynCheck(Object obj, int32 typeId, bool allowNull);
public static extern void ObjectDynCheckFailed(Object obj, int32 typeId);
public static extern void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData);
public static extern void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData);
public static extern int Dbg_PrepareStackTrace(int maxDepth);
public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData);
public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size);
public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth);
public static extern void Dbg_ObjectPreDelete(Object obj);
public static extern void Dbg_ObjectPreCustomDelete(Object obj);
public static extern void Dbg_MarkObjectDeleted(Object obj);
public static extern void* Dbg_RawAlloc(int size);
public static extern void* Dbg_RawObjectAlloc(int size);
public static extern void* Dbg_RawAlloc(int size, DbgRawAllocData* rawAllocData);
public static extern void Dbg_RawFree(void* ptr);
[AlwaysInclude]
static extern void Shutdown();
static extern void Test_Init(char8* testData);
static extern int32 Test_Query();
static extern void Test_Finish();
public static Object ObjectAlloc(TypeInstance typeInst, int size)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
return Dbg_ObjectAlloc(typeInst, size);
#else
void* ptr = Malloc(size);
return *(Object*)(&ptr);
#endif
}
static void SetDeleted1(void* dest)
{
*((uint8*)dest) = 0xDD;
}
static void SetDeleted4(void* dest)
{
*((uint32*)dest) = 0xDDDDDDDD;
}
static void SetDeleted8(void* dest)
{
*((uint64*)dest) = 0xDDDDDDDDDDDDDDDDUL;
}
static void SetDeleted16(void* dest)
{
*((uint64*)dest) = 0xDDDDDDDDDDDDDDDDUL;
*((uint64*)dest + 1) = 0xDDDDDDDDDDDDDDDDUL;
}
public static int MemCmp(void* memA, void* memB, int length)
{
uint8* p0 = (uint8*)memA;
uint8* p1 = (uint8*)memB;
uint8* end0 = p0 + length;
while (p0 < end0)
{
int diff = *(p0++) - *(p1++);
if (diff != 0)
return diff;
}
return 0;
}
[Inline]
public static int GetArraySize<T>(int length)
{
if (sizeof(T) == strideof(T))
{
return length * sizeof(T);
}
else
{
int size = strideof(T) * (length - 1) + sizeof(T);
if (size < 0)
return 0;
return size;
}
}
public static String[] CreateParamsArray()
{
char8* cmdLine = GetCommandLineArgs();
String[] strVals = null;
for (int pass = 0; pass < 2; pass++)
{
int argIdx = 0;
void HandleArg(int idx, int len)
{
if (pass == 1)
{
var str = new String(len);
char8* outStart = str.Ptr;
char8* outPtr = outStart;
for (int i < len)
{
char8 c = cmdLine[idx + i];
if (c == '\"')
{
if ((cmdLine[idx + i + 1] == '\"') &&
(cmdLine[idx + i + 2] == '\"'))
{
*(outPtr++) = '\"';
i += 2;
continue;
}
continue;
}
*(outPtr++) = c;
}
str.[Friend]mLength = (.)(outPtr - outStart);
strVals[argIdx] = str;
}
++argIdx;
}
int firstCharIdx = -1;
bool inQuote = false;
int i = 0;
while (true)
{
char8 c = cmdLine[i];
if (c == 0)
break;
if ((c.IsWhiteSpace) && (!inQuote))
{
if (firstCharIdx != -1)
{
HandleArg(firstCharIdx, i - firstCharIdx);
firstCharIdx = -1;
}
}
else
{
if (firstCharIdx == -1)
firstCharIdx = i;
if (c == '"')
inQuote = !inQuote;
else if ((inQuote) && (c == '\\'))
{
c = cmdLine[i + 1];
if (c == '"')
i++;
}
}
i++;
}
if (firstCharIdx != -1)
HandleArg(firstCharIdx, i - firstCharIdx);
if (pass == 0)
strVals = new String[argIdx];
}
return strVals;
}
public static void DeleteStringArray(String[] arr)
{
for (var str in arr)
delete str;
delete arr;
}
extern static this();
extern static ~this();
}
}

View file

@ -0,0 +1,259 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: Math
**
**
** Purpose: Some floating-point math operations
**
**
===========================================================*/
namespace System
{
//This class contains only static members and doesn't require serialization.
using System;
using System.Runtime;
using System.Diagnostics.Contracts;
using System.Diagnostics;
public static class Math
{
private static double doubleRoundLimit = 1e16d;
private const int32 maxRoundingDigits = 15;
public const double PI = 3.14159265358979323846;
public const double E = 2.7182818284590452354;
private static double[16] sRoundPower10Double = .(
1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,
1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15);
public static extern double Acos(double d);
public static extern double Asin(double d);
public static extern double Atan(double d);
public static extern double Atan2(double y, double x);
public static extern double Ceiling(double a);
public static extern double Cos(double d);
public static extern double Cosh(double value);
public static extern double Floor(double d);
public static extern double Sin(double a);
public static extern double Tan(double a);
public static extern double Sinh(double value);
public static extern double Tanh(double value);
public static extern double Round(double a);
[CLink]
private static extern double modf(double x, out double intpart);
public static double Truncate(double d)
{
double intPart;
modf(d, out intPart);
return intPart;
}
public static extern float Sqrt(float f);
public static extern double Sqrt(double d);
public static extern double Log(double d);
public static extern double Log10(double d);
public static extern double Exp(double d);
public static extern double Pow(double x, double y);
public static double IEEERemainder(double x, double y)
{
if (x.IsNaN)
{
return x; // IEEE 754-2008: NaN payload must be preserved
}
if (y.IsNaN)
{
return y; // IEEE 754-2008: NaN payload must be preserved
}
double regularMod = x % y;
if (regularMod.IsNaN)
{
return Double.NaN;
}
if (regularMod == 0)
{
if (x.IsNegative)
{
return Double.NegativeZero;
}
}
double alternativeResult;
alternativeResult = regularMod - (Math.Abs(y) * Math.Sign(x));
if (Math.Abs(alternativeResult) == Math.Abs(regularMod))
{
double divisionResult = x / y;
double roundedResult = Math.Round(divisionResult);
if (Math.Abs(roundedResult) > Math.Abs(divisionResult))
{
return alternativeResult;
}
else
{
return regularMod;
}
}
if (Math.Abs(alternativeResult) < Math.Abs(regularMod))
{
return alternativeResult;
}
else
{
return regularMod;
}
}
[Inline]
public static T Abs<T>(T value) where T : IOpComparable, IOpNegatable
{
if (value < default)
return (T)-value;
else
return value;
}
//extern public static float Abs(float value);
// This is special code to handle NaN (We need to make sure NaN's aren't
// negated). In CSharp, the else clause here should always be taken if
// value is NaN, since the normal case is taken if and only if value < 0.
// To illustrate this completely, a compiler has translated this into:
// "load value; load 0; bge; ret -value ; ret value".
// The bge command branches for comparisons with the unordered NaN. So
// it runs the else case, which returns +value instead of negating it.
// return (value < 0) ? -value : value;
//extern public static double Abs(double value);
// This is special code to handle NaN (We need to make sure NaN's aren't
// negated). In CSharp, the else clause here should always be taken if
// value is NaN, since the normal case is taken if and only if value < 0.
// To illustrate this completely, a compiler has translated this into:
// "load value; load 0; bge; ret -value ; ret value".
// The bge command branches for comparisons with the unordered NaN. So
// it runs the else case, which returns +value instead of negating it.
// return (value < 0) ? -value : value;
public static T Clamp<T>(T val, T min, T max) where T : IOpComparable
{
if (val < min)
return min;
else if (val > max)
return max;
return val;
}
public static float Distance(float dX, float dY)
{
return (float)Math.Sqrt(dX * dX + dY * dY);
}
public static float Lerp(float val1, float val2, float pct)
{
return val1 + (val2 - val1) * pct;
}
public static double Lerp(double val1, double val2, double pct)
{
return val1 + (val2 - val1) * pct;
}
public static T Min<T>(T val1, T val2) where T : IOpComparable, IIsNaN
{
if (val1 < val2)
return val1;
if (val1.IsNaN)
return val1;
return val2;
}
public static T Max<T>(T val1, T val2) where T : IOpComparable, IIsNaN
{
if (val1 > val2)
return val1;
if (val1.IsNaN)
return val1;
return val2;
}
/*=====================================Log======================================
**
==============================================================================*/
public static double Log(double a, double newBase)
{
if (a.IsNaN)
{
return a; // IEEE 754-2008: NaN payload must be preserved
}
if (newBase.IsNaN)
{
return newBase; // IEEE 754-2008: NaN payload must be preserved
}
if (newBase == 1)
return Double.NaN;
if (a != 1 && (newBase == 0 || newBase.IsPositiveInfinity))
return Double.NaN;
return (Log(a) / Log(newBase));
}
public static int Sign<T>(T value) where T : IOpComparable
{
if (value < default)
return -1;
else if (value > default)
return 1;
else
return 0;
}
public static int Sign<T>(T value) where T : IOpComparable, ICanBeNaN
{
if (value < default)
return -1;
else if (value > default)
return 1;
else if (value == default)
return 0;
Runtime.FatalError("Cannot be used on NaN");
}
public static int32 DivRem(int32 a, int32 b, out int32 result)
{
result = a % b;
return a / b;
}
public static int64 DivRem(int64 a, int64 b, out int64 result)
{
result = a % b;
return a / b;
}
public static int32 Align(int32 val, int32 align)
{
return ((val) + (align - 1)) & ~(align - 1);
}
public static int64 Align(int64 val, int64 align)
{
return ((val) + (align - 1)) & ~(align - 1);
}
}
}

View file

@ -0,0 +1,14 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System
{
public enum MidpointRounding
{
ToEven = 0,
AwayFromZero = 1,
}
}

View file

@ -0,0 +1,112 @@
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace System
{
public struct Nullable<T> where T : struct
{
internal T mValue;
internal bool mHasValue;
public this(T value)
{
mHasValue = true;
mValue = value;
}
[Inline]
public bool HasValue
{
get { return mHasValue; }
}
[Inline]
public T Value
{
get
{
if (!mHasValue)
{
Debug.FatalError("Nullable object must have a value.");
}
return mValue;
}
}
[Inline]
public ref T ValueRef
{
get mut
{
if (!mHasValue)
{
Debug.FatalError("Nullable object must have a value.");
}
return ref mValue;
}
}
/*public override bool Equals(Object other)
{
if (other == null)
return mHasValue == false;
if (!(other is Nullable<T>))
return false;
return Equals((Nullable<T>)other);
}*/
/*bool Equals(Nullable<T> other)
{
if (other.mHasValue != mHasValue)
return false;
if (mHasValue == false)
return true;
return other.mValue.Equals(mValue);
}*/
/*public override int GetHashCode()
{
if (!mHasValue)
return 0;
return mValue.GetHashCode();
}*/
public T GetValueOrDefault()
{
return mValue;
}
public T GetValueOrDefault(T defaultmValue)
{
return mHasValue ? mValue : defaultmValue;
}
public override void ToString(String str)
{
if (mHasValue)
mValue.ToString(str);
else
str.Clear();
}
//[Inline]
public static implicit operator Nullable<T>(T value)
{
return Nullable<T>(value);
}
//[Inline]
public static explicit operator T(Nullable<T> value)
{
return value.mValue;
}
}
}

View file

@ -0,0 +1,584 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
namespace System
{
interface IDisposable
{
void Dispose() mut;
}
interface IPrintable
{
void Print(String outString);
}
typealias int_cosize = int32;
[AlwaysInclude]
static class CompilerSettings
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
public const bool cHasDebugFlags = true;
#else
public const bool cHasDebugFlags = false;
#endif
public const bool cHasVDataExtender = true;
public const int32 cVDataIntefaceSlotCount = 16;
}
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
[AlwaysInclude]
#endif
struct CallStackAddr : int
{
}
class Object : IHashable
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
int mClassVData;
int mDbgAllocInfo;
#else
ClassVData* mClassVData;
#endif
public virtual ~this()
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
mClassVData = ((mClassVData & ~0x08) | 0x80);
#endif
}
int IHashable.GetHashCode()
{
return (int)(void*)this;
}
public Type GetType()
{
Type type;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else
type = mClassVData.mType;
#endif
if ((type.mTypeFlags & TypeFlags.Boxed) != 0)
{
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
type = Type.GetType(((TypeInstance)type).mUnderlyingType);
}
return type;
}
[NoShow]
internal Type RawGetType()
{
Type type;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else
type = mClassVData.mType;
#endif
return type;
}
#if BF_ALLOW_HOT_SWAPPING
[NoShow]
public virtual Object DynamicCastToTypeId(int32 typeId)
{
if (typeId == (int32)RawGetType().mTypeId)
return this;
return null;
}
[NoShow]
public virtual Object DynamicCastToInterface(int32 typeId)
{
return null;
}
#endif
public virtual void ToString(String strBuffer)
{
//strBuffer.Set(stack string(GetType().mName));
RawGetType().GetName(strBuffer);
}
/*public virtual int GetHashCode()
{
return (int)(intptr)(void*)this;
}*/
[NoShow, SkipCall]
protected virtual void GCMarkMembers()
{
//PrintF("Object.GCMarkMembers %08X\n", this);
}
public static Object ManualInit(void* ptr, TypeInstance typeInst)
{
void* addr = ptr;
let obj = *((Object*)&addr);
*(int*)&obj.mClassVData = *(int*)&typeInst.mTypeClassVData;
return obj;
}
static void ToString(Object obj, String strBuffer)
{
if (obj == null)
strBuffer.Append("null");
else
obj.ToString(strBuffer);
}
}
interface IResult<T>
{
T GetBaseResult();
}
struct ValueType
{
public static extern bool Equals<T>(T val1, T val2);
}
struct Function : int
{
}
struct Pointer
{
}
struct Pointer<T> : Pointer
{
T* mVal;
}
struct MethodReference<T>
{
T mVal;
}
struct SizedArray<T, CSize> where CSize : const int
{
T[CSize] mVal;
public int Count
{
[Inline]
get
{
return CSize;
}
}
public explicit static operator T[CSize] (Self val)
{
return val.mVal;
}
public override void ToString(String strBuffer) mut
{
if (typeof(T) == typeof(char8))
{
strBuffer.Append((char8*)&mVal, CSize);
return;
}
strBuffer.Append('(');
for (int i < CSize)
{
if (i != 0)
strBuffer.Append(", ");
mVal[i].ToString(strBuffer);
}
strBuffer.Append(')');
}
}
struct Void : void
{
}
struct Boolean : bool
{
}
struct Char8 : char8
{
public bool IsWhiteSpace
{
get
{
switch (this)
{
case ' ', '\t', '\n', '\r', '\xa0', '\x85': return true;
default: return false;
}
}
}
}
struct Char16 : char16
{
}
struct Char32 : char32
{
public extern bool IsLower
{
get;
}
}
struct Int8 : int8
{
}
struct UInt8 : uint8
{
}
struct Int16 : int16, IOpComparable, IIsNaN
{
public static int operator<=>(Int16 a, Int16 b)
{
return (int16)a <=> (int16)b;
}
bool IIsNaN.IsNaN
{
[SkipCall]
get
{
return false;
}
}
}
struct UInt16 : uint16
{
}
struct UInt32 : uint32, IHashable, IOpComparable, IIsNaN, IOpNegatable
{
public const int32 MaxValue = 0x7FFFFFFF;
public const int32 MinValue = -0x80000000;
public static int operator<=>(UInt32 a, UInt32 b)
{
return (uint32)a <=> (uint32)b;
}
public static UInt32 operator-(UInt32 value)
{
if (value != 0)
Runtime.FatalError("Cannot negate positive unsigned integer");
return 0;
}
public this()
{
}
bool IIsNaN.IsNaN
{
[SkipCall]
get
{
return false;
}
}
public int GetHashCode()
{
return (.)this;
}
}
struct Int64 : int64
{
public const int64 MaxValue = 0x7FFFFFFFFFFFFFFFL;
//public const long MinValue = -0x8000000000000000L;
public const int64 MinValue = -0x7FFFFFFFFFFFFFFFL; //TODO: Should be one lower!
public override void ToString(String strBuffer)
{
// Dumb, make better.
char8[] strChars = scope:: char8[16];
int32 charIdx = 14;
int64 valLeft = (int64)this;
while (valLeft > 0)
{
strChars[charIdx] = (char8)('0' + (valLeft % 10));
valLeft /= 10;
charIdx--;
}
if (charIdx == 14)
strChars[charIdx--] = '0';
char8* charPtr = &strChars[charIdx + 1];
strBuffer.Append(scope:: String(charPtr));
}
}
struct UInt64 : uint64
{
}
struct Float : float
{
public bool IsNegative
{
get
{
return this < 0;
}
}
[StdCall, CLink]
static extern int32 ftoa(float val, char8* str);
static extern int32 ToString(float val, char8* str);
public override void ToString(String strBuffer)
{
char8[128] outBuff = ?;
//ftoa((float)this, &outBuff);
int len = ToString((float)this, &outBuff);
strBuffer.Append(&outBuff, len);
}
}
struct Int : int, IOpComparable, IOpAddable, IIsNaN
{
public static int operator<=>(Int a, Int b)
{
return (int)a <=> (int)b;
}
public static Int operator+(Int a, Int b)
{
return (int)a + (int)b;
}
bool IIsNaN.IsNaN
{
[SkipCall]
get
{
return false;
}
}
}
struct UInt : uint, IOpComparable, IIsNaN
{
public static int operator<=>(UInt a, UInt b)
{
return (uint)a <=> (uint)b;
}
bool IIsNaN.IsNaN
{
[SkipCall]
get
{
return false;
}
}
}
struct Int32 : int32, IHashable, IOpComparable, IIsNaN
{
public const int32 MaxValue = 0x7FFFFFFF;
public const int32 MinValue = -0x80000000;
public static int operator<=>(Int32 a, Int32 b)
{
return (int32)a <=> (int32)b;
}
public this()
{
this = (Int32)345;
}
bool IIsNaN.IsNaN
{
[SkipCall]
get
{
return false;
}
}
public int GetHashCode()
{
return (int32)this;
}
public int32 GetBaseResult()
{
return (int32)this + 4;
}
public override void ToString(String strBuffer)
{
// Dumb, make better.
char8[] strChars = scope:: char8[16];
int32 charIdx = 14;
int32 valLeft = (int32)this;
while (valLeft > 0)
{
strChars[charIdx] = (char8)('0' + (valLeft % 10));
valLeft /= 10;
charIdx--;
}
if (charIdx == 14)
strChars[charIdx--] = '0';
char8* charPtr = &strChars[charIdx + 1];
strBuffer.Append(scope:: String(charPtr));
}
}
struct Enum
{
public static Result<T> Parse<T>(String str) where T : Enum
{
var typeInst = (TypeInstance)typeof(T);
for (var field in typeInst.GetFields())
{
if (str == field.mFieldData.mName)
return .Ok(*((T*)(&field.mFieldData.mConstValue)));
}
return .Err;
}
}
class Delegate
{
void* mFuncPtr;
void* mTarget;
public static bool Equals(Delegate a, Delegate b)
{
if ((Object)a == (Object)b)
return true;
if ((Object)a == null || (Object)b == null)
return false;
return (a.mFuncPtr == b.mFuncPtr) && (a.mTarget == b.mTarget);
}
public Result<void*> GetFuncPtr()
{
if (mTarget != null)
return .Err;//("Delegate target method must be static");
return mFuncPtr;
}
public void SetFuncPtr(void* ptr, void* target = null)
{
mTarget = target;
mFuncPtr = ptr;
}
}
struct DeferredCall
{
public int64 mMethodId;
public DeferredCall* mNext;
public void Cancel() mut
{
mMethodId = 0;
}
}
delegate void Action();
delegate void Action<T1>(T1 p1);
delegate void Action<T1, T2>(T1 p1, T2 p2);
delegate TResult Func<TResult>();
delegate TResult Func<T1, TResult>(T1 p1);
delegate TResult Func<T1, T2, TResult>(T1 p1, T2 p2);
delegate int32 Comparison<T>(T a, T b);
}
static
{
public static mixin NOP()
{
}
public static mixin ToStackString(var obj)
{
var str = scope:: String();
obj.ToString(str);
str
}
public static mixin Try(var result)
{
if (result case .Err(var err))
return .Err((.)err);
result.Get()
}
public static mixin DeleteContainerAndItems(var container)
{
if (container != null)
{
for (var value in container)
delete value;
delete container;
}
}
public static mixin DeleteContainerItems(var container)
{
if (container != null)
{
for (var value in container)
delete value;
}
}
public static mixin DeleteAndNullify(var val)
{
delete val;
val = null;
}
[NoReturn]
public static void ThrowUnimplemented()
{
Debug.FatalError();
}
public static mixin ScopedAlloc(int size, int align)
{
void* data;
if (size <= 128)
{
data = scope:mixin uint8[size]* { ? };
}
else
{
data = new uint8[size]* { ? };
defer:mixin delete data;
}
data
}
}

View file

@ -0,0 +1,415 @@
namespace System
{
static class Platform
{
public const bool IsSingleProcessor = false;
public const int ProcessorCount = 8;
public struct BfpTimeStamp : uint64
{
}
public enum Result : int32
{
Ok,
UnknownError,
InsufficientBuffer,
NotSupported,
NoResults,
InvalidParameter,
Locked,
AlreadyExists,
NotFound,
ShareError,
AccessError,
PartialData,
TempFileError,
Timeout
};
public struct BfpCritSect {}
public struct BfpSpawn {}
public struct BfpFile {}
public struct BfpFindFileData {}
public struct BfpDynLib {}
public struct BfpEvent {};
public struct BfpFileWatcher {}
public struct BfpProcess {}
public enum BfpSystemResult
{
Ok = (int)Result.Ok,
UnknownError = (int)Result.UnknownError,
TempFileError = (int)Result.TempFileError
}
[StdCall, CLink]
public static extern uint32 BfpSystem_TickCount();
[StdCall, CLink]
public static extern void BfpSystem_GetEnvironmentStrings(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult);
[StdCall, CLink]
public static extern uint32 BfpSystem_InterlockedExchange32(uint32* ptr, uint32 val); // Returns the initial value in 'ptr'
[StdCall, CLink]
public static extern uint64 BfpSystem_InterlockedExchange64(uint64* ptr, uint64 val);
[StdCall, CLink]
public static extern uint32 BfpSystem_InterlockedExchangeAdd32(uint32* ptr, uint32 val); // Returns the initial value in 'ptr'
[StdCall, CLink]
public static extern uint64 BfpSystem_InterlockedExchangeAdd64(uint64* ptr, uint64 val);
[StdCall, CLink]
public static extern uint32 BfpSystem_InterlockedCompareExchange32(uint32* ptr, uint32 oldVal, uint32 newVal);
[StdCall, CLink]
public static extern uint64 BfpSystem_InterlockedCompareExchange64(uint64* ptr, uint64 oldVal, uint64 newVal);
public enum BfpFileWatcherFlags : int32
{
None = 0,
IncludeSubdirectories = 1
};
public enum BfpFileChangeKind : int32
{
BfpFileChangeKind_Added,
BfpFileChangeKind_Removed,
BfpFileChangeKind_Modified,
BfpFileChangeKind_Renamed,
BfpFileChangeKind_Failed
};
public function void BfpDirectoryChangeFunc(BfpFileWatcher* watcher, void* userData, BfpFileChangeKind changeKind, char8* directory, char8* fileName, char8* oldName);
[StdCall, CLink]
public static extern BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher);
public enum BfpProcessResult
{
Ok = (int)Result.Ok,
InsufficientBuffer = (int)Result.InsufficientBuffer
}
[StdCall, CLink]
public static extern bool BfpProcess_IsRemoteMachine(char8* machineName);
[StdCall, CLink]
public static extern BfpProcess* BfpProcess_GetById(char8* machineName, int32 processId, BfpProcessResult* outResult);
[StdCall, CLink]
public static extern void BfpProcess_Enumerate(char8* machineName, BfpProcess** outProcesses, int32* inOutProcessesSize, BfpProcessResult* outResult);
[StdCall, CLink]
public static extern void BfpProcess_Release(BfpProcess* process);
[StdCall, CLink]
public static extern void BfpProcess_GetMainWindowTitle(BfpProcess* process, char8* outTitle, int32* inOutTitleSize, BfpProcessResult* outResult);
[StdCall, CLink]
public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult);
[StdCall, CLink]
public static extern int32 BfpProcess_GetProcessId(BfpProcess* process);
public enum BfpSpawnFlags
{
None = 0,
ArgsIncludesTarget = 1, // Otherwise most platforms prepend targetPath to the args
UseArgsFile = 2,
UseArgsFile_Native = 4,
UseArgsFile_UTF8 = 8,
UseArgsFile_BOM = 0x10,
UseShellExecute = 0x20, // Allows opening non-executable files by file association (ie: documents)
RedirectStdInput = 0x40,
RedirectStdOutput = 0x80,
RedirectStdError = 0x100,
NoWindow = 0x200,
ErrorDialog = 0x400,
Window_Hide = 0x800,
Window_Maximized = 0x1000,
};
public enum BfpKillFlags
{
None = 0,
KillChildren = 1
}
public enum BfpSpawnResult : int32
{
Ok = (int)Result.Ok,
UnknownError = (int)Result.UnknownError
};
[StdCall, CLink]
public static extern BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult);
[StdCall, CLink]
public static extern void BfpSpawn_Release(BfpSpawn* spawn);
[StdCall, CLink]
public static extern void BfpSpawn_Kill(BfpSpawn* spawn, int32 exitCode, BfpKillFlags killFlags, BfpSpawnResult* outResult);
[StdCall, CLink]
public static extern bool BfpSpawn_WaitFor(BfpSpawn* spawn, int waitMS, int* outExitCode, BfpSpawnResult* outResult);
[StdCall, CLink]
public static extern void BfpSpawn_GetStdHandles(BfpSpawn* spawn, BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr);
[StdCall, CLink]
public static extern int BfpProcess_GetCurrentId();
[StdCall, CLink]
public static extern BfpCritSect* BfpCritSect_Create();
[StdCall, CLink]
public static extern void BfpCritSect_Release(BfpCritSect* critSect);
[StdCall, CLink]
public static extern void BfpCritSect_Enter(BfpCritSect* critSect);
[StdCall, CLink]
public static extern bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS);
[StdCall, CLink]
public static extern void BfpCritSect_Leave(BfpCritSect* critSect);
public enum BfpEventFlags : int32
{
None = 0,
AllowAutoReset = 1,
AllowManualReset = 2,
InitiallySet_Auto = 4,
InitiallySet_Manual = 8
};
public enum BfpEventResult : int32
{
BfpEventResult_Ok = (int)Result.Ok,
BfpEventResult_NotSupported = (int)Result.NotSupported
};
[StdCall, CLink]
public static extern BfpEvent* BfpEvent_Create(BfpEventFlags flags);
[StdCall, CLink]
public static extern void BfpEvent_Release(BfpEvent* event);
[StdCall, CLink]
public static extern void BfpEvent_Set(BfpEvent* event, bool requireManualReset);
[StdCall, CLink]
public static extern void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult);
[StdCall, CLink]
public static extern bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS);
public enum BfpLibResult : int32
{
Ok = (int)Result.Ok,
UnknownError = (int)Result.UnknownError,
InsufficientBuffer = (int)Result.InsufficientBuffer
};
[StdCall, CLink]
public static extern BfpDynLib* BfpDynLib_Load(char8* fileName);
[StdCall, CLink]
public static extern void BfpDynLib_Release(BfpDynLib* lib);
[StdCall, CLink]
public static extern void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult);
[StdCall, CLink]
public static extern void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name);
public enum BfpFileResult : int32
{
Ok = (int)Result.Ok,
NoResults = (int)Result.NoResults,
UnknownError = (int)Result.UnknownError,
InvalidParameter = (int)Result.InvalidParameter,
Locked = (int)Result.Locked,
AlreadyExists = (int)Result.AlreadyExists,
NotFound = (int)Result.NotFound,
ShareError = (int)Result.ShareError,
AccessError = (int)Result.AccessError,
PartialData = (int)Result.PartialData,
InsufficientBuffer = (int)Result.InsufficientBuffer
};
[StdCall, CLink]
public static extern void BfpDirectory_Create(char8* name, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpDirectory_Rename(char8* oldName, char8* newName, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpDirectory_Delete(char8* name, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpDirectory_GetCurrent(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpDirectory_SetCurrent(char8* path, BfpFileResult* outResult);
[StdCall, CLink]
public static extern bool BfpDirectory_Exists(char8* path);
public enum BfpFileCreateKind : int32
{
CreateAlways,
CreateIfNotExists,
OpenExisting,
};
public enum BfpFileCreateFlags : int32
{
None = 0,
Read = 1,
Write = 2,
ShareRead = 4,
ShareWrite = 8,
ShareDelete = 0x10,
Append = 0x20,
Truncate = 0x40,
WriteThrough = 0x80,
DeleteOnClose = 0x100,
NoBuffering = 0x200,
NonBlocking = 0x400,
AllowTimeouts = 0x800,
Pipe = 0x1000,
};
public enum BfpFileSeekKind : int32
{
Absolute,
Relative,
FromEnd
};
public enum BfpFileAttributes : int32
{
None = 0,
Normal = 1,
Directory = 2,
SymLink = 4,
Device = 8,
ReadOnly = 0x10,
Hidden = 0x20,
System = 0x40,
Temporary = 0x80,
Offline = 0x100,
Encrypted = 0x200,
Archive = 0x400,
};
public enum BfpFileCopyKind : int32
{
Always,
IfNotExists,
IfNewer,
};
[StdCall, CLink]
public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_Release(BfpFile* file);
[StdCall, CLink]
public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
[StdCall, CLink]
public static extern int BfpFile_Read(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_Flush(BfpFile* file);
[StdCall, CLink]
public static extern int64 BfpFile_GetFileSize(BfpFile* file);
[StdCall, CLink]
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
[StdCall, CLink]
public static extern void BfpFile_Truncate(BfpFile* file);
[StdCall, CLink]
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
[StdCall, CLink]
public static extern BfpFileAttributes BfpFile_GetAttributes(char8* path, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_SetAttributes(char8* path, BfpFileAttributes attribs, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_Copy(char8* oldPath, char8* newPath, BfpFileCopyKind copyKind, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_Rename(char8* oldPath, char8* newPath, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_Delete(char8* path, BfpFileResult* outResult);
[StdCall, CLink]
public static extern bool BfpFile_Exists(char8* path);
[StdCall, CLink]
public static extern void BfpFile_GetTempPath(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_GetTempFileName(char8* outName, int32* inOutNameSize, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[StdCall, CLink]
public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
public enum BfpFindFileFlags : int32
{
None = 0,
Files = 1,
Directories = 2,
};
[StdCall, CLink]
public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult);
[StdCall, CLink]
public static extern bool BfpFindFileData_FindNextFile(BfpFindFileData* findData);
[StdCall, CLink]
public static extern void BfpFindFileData_GetFileName(BfpFindFileData* findData, char8* outName, int32* inOutNameSize, BfpFileResult* outResult);
[StdCall, CLink]
public static extern BfpTimeStamp BfpFindFileData_GetTime_LastWrite(BfpFindFileData* findData);
[StdCall, CLink]
public static extern BfpTimeStamp BfpFindFileData_GetTime_Created(BfpFindFileData* findData);
[StdCall, CLink]
public static extern BfpTimeStamp BfpFindFileData_GetTime_Access(BfpFindFileData* findData);
[StdCall, CLink]
public static extern BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData);
[StdCall, CLink]
public static extern void BfpFindFileData_Release(BfpFindFileData* findData);
public enum SysDirectory : int32
{
Default, // Home on Linux, Desktop on Windows, etc.
Home,
Desktop
}
public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func)
{
let initSize = 4096;
char8* localBuf = scope char8[initSize]*;
int32 strSize = initSize;
Result result = .Ok;
func(localBuf, &strSize, &result);
if (result == .Ok)
{
outStr.Append(localBuf, strSize - 1);
return .Ok;
}
else if (result == .InsufficientBuffer)
{
while (true)
{
localBuf = scope char8[strSize]*;
func(localBuf, &strSize, &result);
if (result == .InsufficientBuffer)
continue;
outStr.Append(localBuf, strSize - 1);
return .Ok;
}
}
return .Err(result);
}
public static Result<Span<T>, Platform.Result> GetSizedHelper<T>(delegate void (T* outPtr, int32* outSize, Result* outResult) func)
{
T* vals;
int32 trySize = 64;
while (true)
{
vals = new T[trySize]*;
int32 inOutSize = trySize;
Result result = .Ok;
func(vals, &inOutSize, &result);
if ((result != .InsufficientBuffer) && (result != .Ok))
return .Err(result);
if (result == .Ok)
return .Ok(Span<T>(vals, inOutSize));
delete vals;
trySize = inOutSize;
}
}
}
}

View file

@ -0,0 +1,65 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// BindingFlags are a set of flags that control the binding and invocation process
//
// <OWNER>[....]</OWNER>
// in Reflection. There are two processes. The first is selection of a Member which
// is the binding phase. The second, is invocation. These flags control how this
// process works.
//
// <EMAIL>Author: darylo</EMAIL>
// Date: June 99
//
namespace System.Reflection
{
using System;
public enum BindingFlags
{
// NOTES: We have lookup masks defined in RuntimeType and Activator. If we
// change the lookup values then these masks may need to change also.
// a place holder for no flag specifed
Default = 0x00,
// These flags indicate what to search for when binding
IgnoreCase = 0x01, // Ignore the case of Names while searching
DeclaredOnly = 0x02, // Only look at the members declared on the Type
Instance = 0x04, // Include Instance members in search
Static = 0x08, // Include Static members in search
Public = 0x10, // Include Public members in search
NonPublic = 0x20, // Include Non-Public members in search
FlattenHierarchy = 0x40, // Rollup the statics into the class.
// These flags are used by InvokeMember to determine
// what type of member we are trying to Invoke.
// BindingAccess = 0xFF00;
InvokeMethod = 0x0100,
CreateInstance = 0x0200,
GetField = 0x0400,
SetField = 0x0800,
GetProperty = 0x1000,
SetProperty = 0x2000,
// These flags are also used by InvokeMember but they should only
// be used when calling InvokeMember on a COM object.
PutDispProperty = 0x4000,
PutRefDispProperty = 0x8000,
ExactBinding = 0x010000, // Bind with Exact Type matching, No Change type
SuppressChangeType = 0x020000,
// DefaultValueBinding will return the set of methods having ArgCount or
// more parameters. This is used for default values, etc.
OptionalParamBinding = 0x040000,
// These are a couple of misc attributes used
IgnoreReturn = 0x01000000, // This is used in COM Interop
}
}

View file

@ -0,0 +1,381 @@
using System.Collections.Generic;
namespace System.Reflection
{
[CRepr, AlwaysInclude]
public struct FieldInfo
{
internal TypeInstance mTypeInstance;
internal TypeInstance.FieldData* mFieldData;
public this(TypeInstance typeInstance, TypeInstance.FieldData* fieldData)
{
mTypeInstance = typeInstance;
mFieldData = fieldData;
}
public int32 MemberOffset
{
get
{
return mFieldData.mDataOffset;
}
}
public Type FieldType
{
get
{
return Type.GetType(mFieldData.mFieldTypeId);
}
}
public StringView Name
{
get
{
return mFieldData.mName;
}
}
public Result<void> SetValue(Object obj, Object value)
{
int32 dataOffsetAdjust = 0;
if (mTypeInstance.IsStruct)
{
Type boxedType = obj.RawGetType();
bool typeMatched = false;
if (boxedType.IsBoxed)
{
if (mTypeInstance == boxedType.UnderlyingType)
{
dataOffsetAdjust = boxedType.mMemberDataOffset;
typeMatched = true;
}
}
if (!typeMatched)
return .Err; // "Invalid target type");
}
Type fieldType = Type.GetType(mFieldData.mFieldTypeId);
//Type objType = obj.GetType();
void* dataAddr = ((uint8*)(void*)obj) + mFieldData.mDataOffset + dataOffsetAdjust;
switch (fieldType.mTypeCode)
{
case TypeCode.Int32:
if (!value is int32)
return .Err; //("Invalid type");
*(int32*)(uint8*)dataAddr = (int32)value;
break;
default:
return .Err; //("Invalid type");
}
return .Ok;
}
public Result<void> SetValue(Object obj, Variant value)
{
int32 dataOffsetAdjust = 0;
if (mTypeInstance.IsStruct)
{
Type boxedType = obj.RawGetType();
bool typeMatched = false;
if (boxedType.IsBoxed)
{
if (mTypeInstance == boxedType.UnderlyingType)
{
dataOffsetAdjust = boxedType.mMemberDataOffset;
typeMatched = true;
}
}
if (!typeMatched)
return .Err;//("Invalid target type");
}
Type fieldType = Type.GetType(mFieldData.mFieldTypeId);
//Type objType = obj.GetType();
void* dataAddr = ((uint8*)(void*)obj) + mFieldData.mDataOffset + dataOffsetAdjust;
if (value.VariantType != fieldType)
return .Err;//("Invalid type");
value.CopyValueData(dataAddr);
//TypeCode typeCode = fieldType.mTypeCode;
/*if (typeCode == TypeCode.Enum)
typeCode = fieldType.GetUnderlyingType().mTypeCode;
switch (typeCode)
{
case TypeCode.Int32:
*(int32*)dataAddr = value.Get<int32>();
break;
case TypeCode.Boolean:
*(bool*)dataAddr = value.Get<bool>();
break;
case TypeCode.Object:
*(Object*)dataAddr = value.Get<Object>();
break;
default:
return .Err;//("Invalid type");
}*/
return .Ok;
}
static mixin Decode<T2>(void* data)
{
*((*(T2**)&data)++)
}
public Result<T> GetCustomAttribute<T>() where T : Attribute
{
return .Err;
/*if (mFieldData.mCustomAttributesIdx == -1)
return .Err;
void* data = mTypeInstance.mCustomAttrDataPtr[mFieldData.mCustomAttributesIdx];
T attrInst = ?;
switch (AttributeInfo.GetCustomAttribute(data, typeof(T), &attrInst))
{
case .Ok: return .Ok(attrInst);
default:
return .Err;
}*/
}
void* GetDataPtrAndType(Object value, out Type type)
{
type = value.RawGetType();
/*if (type.IsStruct)
return &value;*/
if (type.IsStruct)
{
NOP!();
}
if (type.IsBoxed)
return ((uint8*)(void*)value) + type.mMemberDataOffset;
return ((uint8*)(void*)value);
}
public Result<void> GetValue<TMember>(Object target, out TMember value)
{
value = default(TMember);
Type tTarget;
void* targetDataAddr = GetDataPtrAndType(target, out tTarget);
//Type tTarget = target.RawGetType();
//void* targetDataAddr = (void*)&target;
Type tMember = typeof(TMember);
targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
Type fieldType = Type.GetType(mFieldData.mFieldTypeId);
if (tMember.mTypeCode == TypeCode.Object)
{
if (!tTarget.IsSubtypeOf(mTypeInstance))
Runtime.FatalError();
value = *(TMember*)targetDataAddr;
}
else if (tMember.mTypeCode == TypeCode.Int32)
{
if (fieldType.mTypeCode == TypeCode.Int32)
{
if (tMember.mTypeCode != TypeCode.Int32)
Runtime.FatalError("Expected int");
*(int32*)&value = *(int32*)targetDataAddr;
}
else
{
return .Err;//("Invalid type");
}
}
else
{
return .Err;//("Invalid type");
}
return .Ok;
}
public Result<Variant> GetValue(Object target)
{
Variant value = Variant();
Type tTarget;
void* targetDataAddr = GetDataPtrAndType(target, out tTarget);
//Type tTarget = target.RawGetType();
//void* targetDataAddr = (void*)&target;
if (!tTarget.IsSubtypeOf(mTypeInstance))
Runtime.FatalError("Invalid type");
targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
Type fieldType = Type.GetType(mFieldData.mFieldTypeId);
/*if (fieldType.IsNullable)
{
var specializedType = (SpecializedGenericType)fieldType;
var genericArg = specializedType.GetGenericArg(0);
bool hasValue = *(bool*)((uint8*)targetDataAddr + genericArg.mSize);
if (!hasValue)
return .Err;
fieldType = genericArg;
}*/
//value.mStructType = (int)(void*)fieldType;
TypeCode typeCode = fieldType.mTypeCode;
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.mTypeCode;
/*if (typeCode == TypeCode.Int32)
{
*(int32*)&value.mData = *(int32*)targetDataAddr;
}
else if (typeCode == TypeCode.Boolean)
{
*(bool*)&value.mData = *(bool*)targetDataAddr;
}
else */if (typeCode == TypeCode.Object)
{
value.mStructType = 0;
value.mData = *(int*)targetDataAddr;
}
else
{
value = Variant.Create(fieldType, targetDataAddr);
}
/*else if (fieldType.mSize <= sizeof(int))
{
value.mStructType = (int)(void*)fieldType;
Internal.MemCpy(&value.mData, targetDataAddr, fieldType.mSize);
}
else
{
value.mStructType = (int)(void*)fieldType;
void* data = new uint8[fieldType.mSize]*;
Internal.MemCpy(data, targetDataAddr, fieldType.mSize);
value.mData = (int)data;
}*/
/*{
return .Err;
}*/
return value;
}
public Result<Variant> GetValue()
{
Variant value = Variant();
//TODO: Assert static
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mConstValue);
}
ThrowUnimplemented();
//Type tTarget;
#unwarn
void* targetDataAddr = (void*)(int)mFieldData.mConstValue;
Type fieldType = Type.GetType(mFieldData.mFieldTypeId);
value.mStructType = (int)(void*)fieldType;
TypeCode typeCode = fieldType.mTypeCode;
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.mTypeCode;
if (typeCode == TypeCode.Int32)
{
*(int32*)&value.mData = *(int32*)targetDataAddr;
}
else if (typeCode == TypeCode.Object)
{
value.mStructType = 0;
value.mData = (int)targetDataAddr;
}
else
{
return .Err;
}
return value;
}
internal struct Enumerator : IEnumerator<FieldInfo>
{
BindingFlags mBindingFlags;
TypeInstance mTypeInstance;
int32 mIdx;
internal this(TypeInstance typeInst, BindingFlags bindingFlags)
{
mTypeInstance = typeInst;
mBindingFlags = bindingFlags;
mIdx = -1;
}
public void Reset() mut
{
mIdx = -1;
}
public void Dispose()
{
}
public bool MoveNext() mut
{
if (mTypeInstance == null)
return false;
for (;;)
{
mIdx++;
if (mIdx == mTypeInstance.mFieldDataCount)
return false;
var fieldData = &mTypeInstance.mFieldDataPtr[mIdx];
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));
if (matches)
break;
}
return true;
}
public FieldInfo Current
{
get
{
var fieldData = &mTypeInstance.mFieldDataPtr[mIdx];
return FieldInfo(mTypeInstance, fieldData);
}
}
public Result<FieldInfo> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
}

View file

@ -0,0 +1,126 @@
namespace System
{
enum Result<T>
{
case Ok(T _val);
case Err(void _err);
T Unwrap()
{
switch (this)
{
case .Ok(var val): return val;
case .Err:
{
Internal.FatalError("Unhandled error in result", 2);
}
}
}
public static implicit operator Result<T>(T value)
{
return .Ok(value);
}
public static implicit operator T(Result<T> result)
{
return result.Unwrap();
}
public void IgnoreError()
{
}
public T Get()
{
return Unwrap();
}
public T Get(T defaultVal)
{
if (this case .Ok(var val))
return val;
return defaultVal;
}
public T GetValueOrDefault()
{
if (this case .Ok(var val))
return val;
return default(T);
}
public void ReturnValueDiscarded()
{
if (this case .Err)
Internal.FatalError("Unhandled error in result", 1);
}
}
enum Result<T, TErr>
{
case Ok(T val);
case Err(TErr err);
T Unwrap()
{
switch (this)
{
case .Ok(var val): return val;
case .Err(var err):
{
String errStr = scope String();
err.ToString(errStr);
String showErr = scope String();
showErr.ConcatInto("Unhandled error in result:\n ", errStr);
Internal.FatalError(showErr, 2);
}
}
}
public static implicit operator Result<T, TErr>(T value)
{
return .Ok(value);
}
public static implicit operator T(Result<T, TErr> result)
{
return result.Unwrap();
}
public void IgnoreError()
{
}
public T Get()
{
return Unwrap();
}
public T Get(T defaultVal)
{
if (this case .Ok(var val))
return val;
return defaultVal;
}
public T GetValueOrDefault()
{
if (this case .Ok(var val))
return val;
return default(T);
}
public void ReturnValueDiscarded()
{
if (this case .Err(var err))
{
String errStr = scope String();
err.ToString(errStr);
String showErr = scope String();
showErr.ConcatInto("Unhandled error in result:\n ", errStr);
Internal.FatalError(showErr, 1);
}
}
}
}

View file

@ -0,0 +1,329 @@
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
#define BF_DBG_RUNTIME
#endif
namespace System
{
[StaticInitPriority(100)]
class Runtime
{
const int32 cVersion = 8;
[CRepr, AlwaysInclude]
struct BfDebugMessageData
{
enum MessageType : int32
{
None = 0,
Error = 1,
ProfilerCmd = 2
};
MessageType mMessageType;
int32 mStackWindbackCount;
int32 mBufferParamLen;
char8* mBufferParam;
void* mPCOverride;
char8* mBufferPtr = null;
int mStrSize = 0;
[CLink]
public static BfDebugMessageData gBfDebugMessageData;
public static ~this()
{
if (gBfDebugMessageData.mBufferPtr != null)
{
Internal.Free(gBfDebugMessageData.mBufferPtr);
gBfDebugMessageData.mBufferPtr = null;
gBfDebugMessageData.mStrSize = 0;
}
}
public void SetupError(char8* str, int32 stackWindbackCount = 0) mut
{
mMessageType = .Error;
mStackWindbackCount = stackWindbackCount;
int size = Internal.CStrLen(str) + 1;
if (mStrSize < size)
{
if (mBufferPtr != null)
Internal.Free(mBufferPtr);
mStrSize = size;
mBufferPtr = (char8*)Internal.Malloc(mStrSize);
}
Internal.MemCpy(mBufferPtr, str, size);
mBufferParam = mBufferPtr;
mBufferParamLen = (int32)size - 1;
mPCOverride = null;
}
public void SetupProfilerCmd(char8* str) mut
{
mMessageType = .ProfilerCmd;
mStackWindbackCount = 0;
int size = Internal.CStrLen(str) + 1;
if (mStrSize < size)
{
if (mBufferPtr != null)
Internal.Free(mBufferPtr);
mStrSize = size;
mBufferPtr = (char8*)Internal.Malloc(mStrSize);
}
Internal.MemCpy(mBufferPtr, str, size);
mBufferParam = mBufferPtr;
mBufferParamLen = (int32)size - 1;
mPCOverride = null;
}
public void Fatal() mut
{
var str = scope String();
str.Reference(mBufferPtr, mBufferParamLen, 0);
Internal.FatalError(str, -1);
}
public void Clear() mut
{
mMessageType = .None;
if (mBufferPtr != null)
mBufferPtr[0] = 0;
mBufferParamLen = 0;
}
}
struct BfRtCallbacks
{
public static BfRtCallbacks sCallbacks = .();
function void* (int size) mAlloc;
function void (void* ptr) mFree;
function void (Object obj) mObject_Delete;
function void (Object obj, String str) mObject_ToString;
function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
function void (Type type, String str) mType_GetFullName;
function String () mString_Alloc;
function char8* (String str) mString_ToCStr;
function Object () mThread_Alloc;
function Object () mThread_GetMainThread;
function void (Object thread) mThread_ThreadProc;
function void* (Object thread) mThread_GetInternalThread;
function void (Object thread, void* internalThread) mThread_SetInternalThread;
function bool (Object thread) mThread_IsAutoDelete;
function void (Object thread) mThread_AutoDelete;
function int32 (Object thread) mThread_GetMaxStackSize;
function void () mGC_MarkAllStaticMembers;
function bool () mGC_CallRootCallbacks;
function void () mGC_Shutdown;
function void (char8* str) mSetErrorString;
function void (char8* str, int32 stackWindbackCount) mDebugMessageData_SetupError;
function void (char8* str) mDebugMessageData_SetupProfilerCmd;
function void () mDebugMessageData_Fatal;
function void () mDebugMessageData_Clear;
static void* Alloc(int size)
{
return Internal.Malloc(size);
}
static void Free(void* ptr)
{
Internal.Free(ptr);
}
static void Object_Delete(Object obj)
{
delete obj;
}
static void Object_ToString(Object obj, String str)
{
#if BF_DBG_RUNTIME
obj.ToString(str);
#endif
}
static Type Object_GetType(Object obj)
{
#if BF_DBG_RUNTIME
return obj.RawGetType();
#else
return null;
#endif
}
static void Object_GCMarkMembers(Object obj)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
obj.[Friend, SkipAccessCheck]GCMarkMembers();
#endif
}
static Object Object_DynamicCastToTypeId(Object obj, int32 typeId)
{
#if BF_DYNAMIC_CAST_CHECK
return obj.[Friend]DynamicCastToTypeId(typeId);
#else
return null;
#endif
}
static void Type_GetFullName(Type type, String str)
{
#if BF_DBG_RUNTIME
type.GetFullName(str);
#else
//
#endif
}
static String String_Alloc()
{
return new String();
}
static char8* String_ToCStr(String str)
{
return str.CStr();
}
static void GC_MarkAllStaticMembers()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
GC.[Friend]MarkAllStaticMembers();
#endif
}
static bool GC_CallRootCallbacks()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
return GC.[Friend]CallRootCallbacks();
#else
return true;
#endif
}
static void GC_Shutdown()
{
#if BF_DBG_RUNTIME
GC.Shutdown();
#endif
}
static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount)
{
BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount);
}
static void DebugMessageData_SetupProfilerCmd(char8* str)
{
BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str);
}
static void DebugMessageData_Fatal()
{
BfDebugMessageData.gBfDebugMessageData.Fatal();
}
static void DebugMessageData_Clear()
{
BfDebugMessageData.gBfDebugMessageData.Clear();
}
public void Init() mut
{
mAlloc = => Alloc;
mFree = => Free;
mObject_Delete = => Object_Delete;
mObject_ToString = => Object_ToString;
mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers;
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
mType_GetFullName = => Type_GetFullName;
mString_Alloc = => String_Alloc;
mString_ToCStr = => String_ToCStr;
mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers;
mGC_CallRootCallbacks = => GC_CallRootCallbacks;
mGC_Shutdown = => GC_Shutdown;
mSetErrorString = => SetErrorString;
mDebugMessageData_SetupError = => DebugMessageData_SetupError;
mDebugMessageData_SetupProfilerCmd = => DebugMessageData_SetupProfilerCmd;
mDebugMessageData_Fatal = => DebugMessageData_Fatal;
mDebugMessageData_Clear = => DebugMessageData_Clear;
}
};
private static extern void Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void AddCrashInfoFunc(void* func);
private static extern void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void SetErrorString(char8* error);
private static extern void* Dbg_GetCrashInfoFunc();
public static extern void SetCrashReportKind(RtCrashReportKind crashReportKind);
public enum RtCrashReportKind : int32
{
Default,
GUI,
Console,
PrintOnly,
None
}
enum RtFlags : int32
{
ObjectHasDebugFlags = 1,
LeakCheck = 2,
SilentCrash = 4,
DebugAlloc = 8
}
public static this()
{
BfRtCallbacks.sCallbacks.Init();
RtFlags flags = default;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
flags |= .ObjectHasDebugFlags;
#endif
#if BF_ENABLE_REALTIME_LEAK_CHECK
flags |= .LeakCheck;
#endif
#if BF_DEBUG_ALLOC
flags |= .DebugAlloc;
#endif
Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#if BF_DBG_RUNTIME
Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#endif
}
[NoReturn]
public static void FatalError(String msg = "Fatal error encountered")
{
Internal.FatalError(msg, 1);
}
[NoReturn]
public static void NotImplemented()
{
Internal.FatalError("Not Implemented", 1);
}
public static void Assert(bool condition)
{
if (!condition)
Internal.FatalError("Assert failed", 1);
}
public static void Assert(bool condition, String error)
{
if (!condition)
Internal.FatalError("Assert failed", 1);
}
}
}

View file

@ -0,0 +1,218 @@
using System.Diagnostics;
using System.Collections.Generic;
namespace System
{
struct Span<T>
{
protected T* mPtr;
protected int mLength;
public this()
{
mPtr = null;
mLength = 0;
}
public this(T[] array)
{
mPtr = &array.getRef(0);
mLength = array.[Friend]mLength;
}
public this(T[] array, int index)
{
mPtr = &array[index];
mLength = array.[Friend]mLength - index;
}
public this(T[] array, int index, int length)
{
if (length == 0)
mPtr = null;
else
mPtr = &array[index];
mLength = length;
}
public this(T* memory, int length)
{
mPtr = memory;
mLength = length;
}
/*public static implicit operator Span<T> (ArraySegment<T> arraySegment)
{
}*/
public static implicit operator Span<T> (T[] array)
{
return Span<T>(array);
}
[Inline]
public int Length
{
get
{
return mLength;
}
}
[Inline]
public T* Ptr
{
get
{
return mPtr;
}
}
[Inline]
public T* EndPtr
{
get
{
return mPtr + mLength;
}
}
[Inline]
public ref T this[int index]
{
get
{
return ref mPtr[index];
}
}
public Span<T> Slice(int index)
{
Debug.Assert((uint)index <= (uint)mLength);
Span<T> span;
span.mPtr = mPtr + index;
span.mLength = mLength - index;
return span;
}
public Span<T> Slice(int index, int length)
{
Debug.Assert((uint)index + (uint)length <= (uint)mLength);
Span<T> span;
span.mPtr = mPtr + index;
span.mLength = length;
return span;
}
public void Adjust(int ofs) mut
{
Debug.Assert((uint)ofs <= (uint)mLength);
mPtr += ofs;
mLength -= ofs;
}
public void CopyTo(T[] destination)
{
Internal.MemMove(&destination[0], mPtr, Internal.GetArraySize<T>(mLength), (int32)alignof(T));
}
public void CopyTo(Span<T> destination)
{
Internal.MemMove(destination.mPtr, mPtr, Internal.GetArraySize<T>(mLength), (int32)alignof(T));
}
public Span<uint8> ToRawData()
{
return Span<uint8>((uint8*)mPtr, mLength * sizeof(T));
}
public Enumerator GetEnumerator()
{
return Enumerator(this);
}
public struct Enumerator : IEnumerator<T>
{
private Span<T> mList;
private int mIndex;
private T* mCurrent;
internal this(Span<T> list)
{
mList = list;
mIndex = 0;
mCurrent = null;
}
public void Dispose()
{
}
public bool MoveNext() mut
{
if ((uint(mIndex) < uint(mList.mLength)))
{
mCurrent = &mList.mPtr[mIndex];
mIndex++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare() mut
{
mIndex = mList.mLength + 1;
mCurrent = null;
return false;
}
public T Current
{
get
{
return *mCurrent;
}
}
public ref T CurrentRef
{
get
{
return ref *mCurrent;
}
}
public int Index
{
get
{
return mIndex - 1;
}
}
public int Length
{
get
{
return mList.mLength;
}
}
public void Reset() mut
{
mIndex = 0;
mCurrent = null;
}
public Result<T> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
//TODO: Make a ReadOnlySpan
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
#pragma warning disable 168
using System;
class Foogie<T> where T : IHashable
{
public void Do()
{
T val = default;
val.GetHashCode();
}
}

View file

@ -0,0 +1,127 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>[....]</OWNER>
/*=============================================================================
**
** Class: Monitor
**
**
** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
** program.
**
**
=============================================================================*/
namespace System.Threading
{
using System;
using System.Runtime;
using System.Threading;
using System.Diagnostics.Contracts;
using System.Diagnostics;
public class Monitor
{
public struct MonitorLockInstance
{
public Monitor mMonitor;
public void Dispose()
{
mMonitor.Exit();
}
}
Platform.BfpCritSect* mCritSect;
public this()
{
mCritSect = Platform.BfpCritSect_Create();
}
public ~this()
{
Platform.BfpCritSect_Release(mCritSect);
}
/*=========================================================================
** Obtain the monitor lock of obj. Will block if another thread holds the lock
** Will not block if the current thread holds the lock,
** however the caller must ensure that the same number of Exit
** calls are made as there were Enter calls.
**
** Exceptions: ArgumentNullException if object is null.
=========================================================================*/
public MonitorLockInstance Enter()
{
MonitorLockInstance monitorLockInstance;
monitorLockInstance.mMonitor = this;
Platform.BfpCritSect_Enter(mCritSect);
return monitorLockInstance;
}
private static void ThrowLockTakenException()
{
Debug.FatalError();
}
/*=========================================================================
** Release the monitor lock. If one or more threads are waiting to acquire the
** lock, and the current thread has executed as many Exits as
** Enters, one of the threads will be unblocked and allowed to proceed.
**
** Exceptions: ArgumentNullException if object is null.
** SynchronizationLockException if the current thread does not
** own the lock.
=========================================================================*/
public void Exit()
{
Platform.BfpCritSect_Leave(mCritSect);
}
/*=========================================================================
** Similar to Enter, but will never block. That is, if the current thread can
** acquire the monitor lock without blocking, it will do so and TRUE will
** be returned. Otherwise FALSE will be returned.
**
** Exceptions: ArgumentNullException if object is null.
=========================================================================*/
public bool TryEnter()
{
return Platform.BfpCritSect_TryEnter(mCritSect, 0);
}
/*=========================================================================
** Version of TryEnter that will block, but only up to a timeout period
** expressed in milliseconds. If timeout == Timeout.Infinite the method
** becomes equivalent to Enter.
**
** Exceptions: ArgumentNullException if object is null.
** ArgumentException if timeout < 0.
=========================================================================*/
public bool TryEnter(int millisecondsTimeout)
{
return Platform.BfpCritSect_TryEnter(mCritSect, (int32)millisecondsTimeout);
}
private static int32 MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
{
int64 tm = int64(timeout.TotalMilliseconds);
if (tm < -1 || tm > int64(Int32.MaxValue))
Debug.FatalError();
return int32(tm);
}
public bool TryEnter(TimeSpan timeout)
{
return TryEnter(MillisecondsTimeoutFromTimeSpan(timeout));
}
}
}

View file

@ -0,0 +1,352 @@
namespace System.Threading
{
using System;
using System.Diagnostics;
internal delegate Object InternalCrossContextDelegate(Object[] args);
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(Object obj);
public sealed class Thread
{
private int mInternalThread;
private int32 mPriority;
public int32 mMaxStackSize;
private String mName ~ delete _;
private Delegate mDelegate;
private Object mThreadStartArg;
bool mAutoDelete;
public static Thread sMainThread = new Thread() ~ delete _;
[StaticInitPriority(101)]
struct RuntimeThreadInit
{
static Object Thread_Alloc()
{
return Thread.[Friend]CreateEmptyThread();
}
static Object Thread_GetMainThread()
{
return Thread.[Friend]sMainThread;
}
static void* Thread_GetInternalThread(Object thread)
{
return (void*)((Thread)thread).[Friend]mInternalThread;
}
static void Thread_SetInternalThread(Object thread, void* internalThread)
{
((Thread)thread).[Friend]mInternalThread = (int)internalThread;
}
static bool Thread_IsAutoDelete(Object thread)
{
return ((Thread)thread).[Friend]mAutoDelete;
}
static void Thread_AutoDelete(Object thread)
{
delete thread;
}
static int32 Thread_GetMaxStackSize(Object thread)
{
return ((Thread)thread).mMaxStackSize;
}
static void Thread_StartProc(Object threadObj)
{
Thread thread = (Thread)threadObj;
if (thread.mName != null)
thread.InformThreadNameChange(thread.mName);
int32 stackStart = 0;
thread.SetStackStart((void*)&stackStart);
if (thread.mDelegate is ThreadStart)
{
((ThreadStart)thread.mDelegate)();
}
else
{
((ParameterizedThreadStart)thread.mDelegate)(thread.mThreadStartArg);
}
}
public static this()
{
var cb = ref Runtime.BfRtCallbacks.sCallbacks;
cb.[Friend]mThread_Alloc = => Thread_Alloc;
cb.[Friend]mThread_GetMainThread = => Thread_GetMainThread;
cb.[Friend]mThread_ThreadProc = => Thread_StartProc;
cb.[Friend]mThread_GetInternalThread = => Thread_GetInternalThread;
cb.[Friend]mThread_SetInternalThread = => Thread_SetInternalThread;
cb.[Friend]mThread_IsAutoDelete = => Thread_IsAutoDelete;
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
}
}
public this(ThreadStart start)
{
Debug.Assert(start != null);
SetStart((Delegate)start, 0); //0 will setup Thread with default stackSize
}
public this(ThreadStart start, int32 maxStackSize)
{
Debug.Assert(start != null);
if (0 > maxStackSize)
Runtime.FatalError();
SetStart((Delegate)start, maxStackSize);
}
public this(ParameterizedThreadStart start)
{
Debug.Assert(start != null);
SetStart((Delegate)start, 0);
}
public this(ParameterizedThreadStart start, int32 maxStackSize)
{
Debug.Assert(start != null);
Debug.Assert(maxStackSize > 0);
SetStart((Delegate)start, maxStackSize);
}
static this()
{
#unwarn
RuntimeThreadInit runtimeThreadInitRef = ?;
sMainThread.ManualThreadInit();
}
static Thread CreateEmptyThread()
{
return new Thread();
}
public bool AutoDelete
{
set
{
// Changing AutoDelete from another thread while we are running is a race condition
Runtime.Assert((CurrentThread == this) || (!IsAlive));
mAutoDelete = value;
}
get
{
return mAutoDelete;
}
}
extern void ManualThreadInit();
extern void StartInternal();
extern void SetStackStart(void* ptr);
public void Start(bool autoDelete = true)
{
mAutoDelete = autoDelete;
StartInternal();
}
public void Start(Object parameter, bool autoDelete = true)
{
mAutoDelete = autoDelete;
if (mDelegate is ThreadStart)
{
Runtime.FatalError();
}
mThreadStartArg = parameter;
StartInternal();
}
#if PLATFORM_WINDOWS
[CLink]
static extern int32 _tls_index;
#endif
public static int ModuleTLSIndex
{
get
{
#if PLATFORM_WINDOWS
return _tls_index;
#else
return 0;
#endif
}
}
public void Suspend() { SuspendInternal(); }
private extern void SuspendInternal();
public void Resume() { ResumeInternal(); }
private extern void ResumeInternal();
public void Interrupt() { InterruptInternal(); }
private extern void InterruptInternal();
public ThreadPriority Priority
{
get { return (ThreadPriority)GetPriorityNative(); }
set { SetPriorityNative((int32)value); }
}
private extern int32 GetPriorityNative();
private extern void SetPriorityNative(int32 priority);
extern bool GetIsAlive();
public bool IsAlive
{
get
{
return GetIsAlive();
}
}
extern bool GetIsThreadPoolThread();
public bool IsThreadPoolThread
{
get
{
return GetIsThreadPoolThread();
}
}
private extern bool JoinInternal(int32 millisecondsTimeout);
public void Join()
{
JoinInternal(Timeout.Infinite);
}
public bool Join(int32 millisecondsTimeout)
{
return JoinInternal(millisecondsTimeout);
}
public bool Join(TimeSpan timeout)
{
int64 tm = (int64)timeout.TotalMilliseconds;
if (tm < -1 || tm > (int64)Int32.MaxValue)
Runtime.FatalError();
return Join((int32)tm);
}
private static extern void SleepInternal(int32 millisecondsTimeout);
public static void Sleep(int32 millisecondsTimeout)
{
SleepInternal(millisecondsTimeout);
}
public static void Sleep(TimeSpan timeout)
{
int64 tm = (int64)timeout.TotalMilliseconds;
if (tm < -1 || tm > (int64)Int32.MaxValue)
Runtime.FatalError();
Sleep((int32)tm);
}
private static extern void SpinWaitInternal(int32 iterations);
public static void SpinWait(int iterations)
{
SpinWaitInternal((int32)iterations);
}
private static extern bool YieldInternal();
public static bool Yield()
{
return YieldInternal();
}
public static Thread CurrentThread
{
get
{
return GetCurrentThreadNative();
}
}
extern int32 GetThreadId();
public int32 Id
{
get
{
return GetThreadId();
}
}
private static extern Thread GetCurrentThreadNative();
void SetStart(Delegate start, int32 maxStackSize)
{
mDelegate = start;
mMaxStackSize = maxStackSize;
}
public ~this()
{
// Make sure we're not deleting manually it mAutoDelete is set
Debug.Assert((!mAutoDelete) || (CurrentThread == this));
// Delegate to the unmanaged portion.
InternalFinalize();
// Thread owns delegate
delete mDelegate;
}
private extern void InternalFinalize();
public bool IsBackground
{
get { return IsBackgroundNative(); }
set { SetBackgroundNative(value); }
}
private extern bool IsBackgroundNative();
private extern void SetBackgroundNative(bool isBackground);
public extern void SetJoinOnDelete(bool joinOnDelete);
public ThreadState ThreadState
{
get { return (ThreadState)GetThreadStateNative(); }
}
private extern int32 GetThreadStateNative();
public void SetName(String name)
{
if (name == null)
{
delete mName;
mName = null;
}
else
{
String.NewOrSet!(mName, name);
}
if (mInternalThread != 0)
InformThreadNameChange(name);
}
public void GetName(String outName)
{
if (mName != null)
outName.Append(mName);
}
private extern void InformThreadNameChange(String name);
public static extern void MemoryBarrier();
}
}

View file

@ -0,0 +1,34 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>[....]</OWNER>
/*=============================================================================
**
** Class: ThreadPriority
**
**
** Purpose: Enums for the priorities of a Thread
**
**
=============================================================================*/
namespace System.Threading
{
using System.Threading;
//[Serializable]
public enum ThreadPriority
{
/*=========================================================================
** Constants for thread priorities.
=========================================================================*/
Lowest = 0,
BelowNormal = 1,
Normal = 2,
AboveNormal = 3,
Highest = 4
}
}

View file

@ -0,0 +1,37 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>[....]</OWNER>
/*=============================================================================
**
** Class: ThreadState
**
**
** Purpose: Enum to represent the different thread states
**
**
=============================================================================*/
namespace System.Threading
{
//[Flags]
public enum ThreadState
{
/*=========================================================================
** Constants for thread states.
=========================================================================*/
Running = 0,
StopRequested = 1,
SuspendRequested = 2,
Background = 4,
Unstarted = 8,
Stopped = 16,
WaitSleepJoin = 32,
Suspended = 64,
AbortRequested = 128,
Aborted = 256
}
}

View file

@ -0,0 +1,25 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>[....]</OWNER>
namespace System.Threading {
using System.Threading;
using System;
// A constant used by methods that take a timeout (Object.Wait, Thread.Sleep
// etc) to indicate that no timeout should occur.
//
// <
public static class Timeout
{
//public static readonly TimeSpan InfiniteTimeSpan = TimeSpan(0, 0, 0, 0, Timeout.Infinite);
public const int32 Infinite = -1;
internal const uint32 UnsignedInfinite = unchecked((uint32)-1);
}
}

View file

@ -0,0 +1,132 @@
namespace System
{
public struct TimeSpan
{
public const int64 TicksPerMillisecond = 10000;
private const double MillisecondsPerTick = 1.0 / (double)TicksPerMillisecond;
public const int64 TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
private const double SecondsPerTick = 1.0 / (double)TicksPerSecond; // 0.0001
public const int64 TicksPerMinute = TicksPerSecond * 60; // 600,000,000
private const double MinutesPerTick = 1.0 / (double)TicksPerMinute; // 1.6666666666667e-9
public const int64 TicksPerHour = TicksPerMinute * 60; // 36,000,000,000
private const double HoursPerTick = 1.0 / (double)TicksPerHour; // 2.77777777777777778e-11
public const int64 TicksPerDay = TicksPerHour * 24; // 864,000,000,000
private const double DaysPerTick = 1.0 / (double)TicksPerDay; // 1.1574074074074074074e-12
private const int32 MillisPerSecond = 1000;
private const int32 MillisPerMinute = MillisPerSecond * 60; // 60,000
private const int32 MillisPerHour = MillisPerMinute * 60; // 3,600,000
private const int32 MillisPerDay = MillisPerHour * 24; // 86,400,000
internal const int64 MaxSeconds = Int64.MaxValue / TicksPerSecond;
internal const int64 MinSeconds = Int64.MinValue / TicksPerSecond;
internal const int64 MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
internal const int64 MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
internal const int64 TicksPerTenthSecond = TicksPerMillisecond * 100;
//public static readonly TimeSpan Zero = new TimeSpan(0);
//public static readonly TimeSpan MaxValue = new TimeSpan(Int64.MaxValue);
//public static readonly TimeSpan MinValue = new TimeSpan(Int64.MinValue);
internal int64 _ticks;
//public TimeSpan() {
// _ticks = 0;
//}
public this(int64 ticks)
{
this._ticks = ticks;
}
/*public this(int hours, int minutes, int seconds) {
_ticks = TimeToTicks(hours, minutes, seconds);
}*/
//TODO: This fails too
/*public this(int days, int hours, int minutes, int seconds)
: this(days,hours,minutes,seconds,0)
{
}*/
public this(int32 days, int32 hours, int32 minutes, int32 seconds, int32 milliseconds)
{
int64 totalMilliSeconds = ((int64)days * 3600 * 24 + (int64)hours * 3600 + (int64)minutes * 60 + seconds) * 1000 + milliseconds;
/*if (totalMilliSeconds > MaxMilliSeconds || totalMilliSeconds < MinMilliSeconds)
throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("Overflow_TimeSpanTooLong"));*/
_ticks = (int64)totalMilliSeconds * TicksPerMillisecond;
}
public int64 Ticks
{
get { return _ticks; }
}
public int32 Days
{
get { return (int32)(_ticks / TicksPerDay); }
}
public int32 Hours
{
get { return (int32)((_ticks / TicksPerHour) % 24); }
}
public int32 Milliseconds
{
get { return (int32)((_ticks / TicksPerMillisecond) % 1000); }
}
public int32 Minutes
{
get { return (int32)((_ticks / TicksPerMinute) % 60); }
}
public int32 Seconds
{
get { return (int32)((_ticks / TicksPerSecond) % 60); }
}
public double TotalDays
{
get { return ((double)_ticks) * DaysPerTick; }
}
public double TotalHours
{
get { return (double)_ticks * HoursPerTick; }
}
public double TotalMilliseconds
{
get
{
double temp = (double)_ticks * MillisecondsPerTick;
if (temp > (double)MaxMilliSeconds)
return (double)MaxMilliSeconds;
if (temp < (double)MinMilliSeconds)
return (double)MinMilliSeconds;
return temp;
}
}
public double TotalMinutes
{
get { return (double)_ticks * MinutesPerTick; }
}
public double TotalSeconds
{
get { return (double)_ticks * SecondsPerTick; }
}
}
}

View file

@ -0,0 +1,873 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
namespace System
{
struct ClassVData
{
public Type mType;
// The rest of this structured is generated by the compiler,
// including the vtable and interface slots
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
public class Type
{
internal extern const Type* sTypes;
protected const BindingFlags cDefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
internal int32 mSize;
internal TypeId mTypeId;
internal TypeFlags mTypeFlags;
internal int32 mMemberDataOffset;
internal TypeCode mTypeCode;
internal uint8 mAlign;
public int32 Size
{
get
{
return mSize;
}
}
public int32 Align
{
get
{
return mAlign;
}
}
public int32 Stride
{
get
{
return Math.Align(mSize, mAlign);
}
}
public TypeId TypeId
{
get
{
return mTypeId;
}
}
public bool IsPrimitive
{
get
{
return (mTypeFlags & TypeFlags.Primitive) != 0;
}
}
public bool IsInteger
{
get
{
switch (mTypeCode)
{
case .Int8,
.Int16,
.Int32,
.Int64,
.Int,
.UInt8,
.UInt16,
.UInt32,
.UInt64,
.UInt:
return true;
default:
return false;
}
}
}
public bool IsIntegral
{
get
{
switch (mTypeCode)
{
case .Int8,
.Int16,
.Int32,
.Int64,
.Int,
.UInt8,
.UInt16,
.UInt32,
.UInt64,
.UInt,
.Char8,
.Char16,
.Char32:
return true;
default:
return false;
}
}
}
public bool IsFloatingPoint
{
get
{
switch (mTypeCode)
{
case .Float,
.Double:
return true;
default:
return false;
}
}
}
public bool IsSigned
{
get
{
switch (mTypeCode)
{
case .Int8,
.Int16,
.Int32,
.Int64,
.Float,
.Double:
return true;
default:
return false;
}
}
}
public bool IsChar
{
get
{
switch (mTypeCode)
{
case .Char8,
.Char16,
.Char32:
return true;
default:
return false;
}
}
}
public bool IsTypedPrimitive
{
get
{
return (mTypeFlags & TypeFlags.TypedPrimitive) != 0;
}
}
public bool IsObject
{
get
{
return (mTypeFlags & TypeFlags.Object) != 0;
}
}
public bool IsValueType
{
get
{
return (mTypeFlags & (.Struct | .Primitive | .TypedPrimitive)) != 0;
}
}
public bool IsStruct
{
get
{
return (mTypeFlags & TypeFlags.Struct) != 0;
}
}
public bool IsSplattable
{
get
{
return (mTypeFlags & TypeFlags.Splattable) != 0;
}
}
public bool IsUnion
{
get
{
return (mTypeFlags & TypeFlags.Union) != 0;
}
}
public bool IsBoxed
{
get
{
return (mTypeFlags & TypeFlags.Boxed) != 0;
}
}
public bool IsEnum
{
get
{
return mTypeCode == TypeCode.Enum;
}
}
public bool IsTuple
{
get
{
return mTypeFlags.HasFlag(TypeFlags.Tuple);
}
}
public bool IsNullable
{
get
{
return mTypeFlags.HasFlag(.Nullable);
}
}
public bool WantsMark
{
get
{
return (mTypeFlags & .WantsMark) != 0;
}
}
public bool HasDestructor
{
get
{
return (mTypeFlags & .HasDestructor) != 0;
}
}
public bool IsGenericType
{
get
{
return (mTypeFlags & (TypeFlags.SpecializedGeneric | TypeFlags.UnspecializedGeneric)) != 0;
}
}
public virtual int32 GenericParamCount
{
get
{
return 0;
}
}
public virtual int32 InstanceSize
{
get
{
return mSize;
}
}
public virtual int32 InstanceAlign
{
get
{
return mAlign;
}
}
public virtual int32 InstanceStride
{
get
{
return Math.Align(mSize, mAlign);
}
}
public virtual TypeInstance BaseType
{
get
{
return null;
}
}
public virtual TypeInstance OuterType
{
get
{
return null;
}
}
public virtual Type UnderlyingType
{
get
{
return null;
}
}
public virtual int32 FieldCount
{
get
{
return 0;
}
}
public int32 GetTypeId()
{
return (int32)mTypeId;
}
internal static Type GetType(TypeId typeId)
{
return sTypes[(int32)typeId];
}
internal static Type GetType_(int32 typeId)
{
return sTypes[typeId];
}
void GetBasicName(String strBuffer)
{
switch (mTypeCode)
{
case .None: strBuffer.Append("void");
case .CharPtr: strBuffer.Append("char8*");
case .Pointer: strBuffer.Append("void*");
case .NullPtr: strBuffer.Append("void*");
case .Var: strBuffer.Append("var");
case .Let: strBuffer.Append("let");
case .Boolean: strBuffer.Append("bool");
case .Int8: strBuffer.Append("int8");
case .UInt8: strBuffer.Append("uint8");
case .Int16: strBuffer.Append("int16");
case .UInt16: strBuffer.Append("uint16");
case .Int32: strBuffer.Append("int32");
case .UInt32: strBuffer.Append("uint32");
case .Int64: strBuffer.Append("int64");
case .UInt64: strBuffer.Append("uint64");
case .Int: strBuffer.Append("int");
case .UInt: strBuffer.Append("uint");
case .Char8: strBuffer.Append("char8");
case .Char16: strBuffer.Append("char16");
case .Char32: strBuffer.Append("char32");
case .Float: strBuffer.Append("float");
case .Double: strBuffer.Append("double");
default: ((int32)mTypeCode).ToString(strBuffer);
}
}
public virtual void GetFullName(String strBuffer)
{
GetBasicName(strBuffer);
}
public virtual void GetName(String strBuffer)
{
GetBasicName(strBuffer);
}
// Putting this in causes sTypes to be required when Object.ToString is reified
/*public override void ToString(String strBuffer)
{
GetFullName(strBuffer);
}*/
public virtual Type GetBaseType()
{
//return mBaseType;
return null;
}
protected this()
{
}
public virtual bool IsSubtypeOf(Type type)
{
return type == this;
}
public virtual FieldInfo? GetField(String fieldName)
{
return null;
}
public virtual FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup)
{
return FieldInfo.Enumerator(null, bindingFlags);
}
}
enum TypeCode : uint8
{
None,
CharPtr,
Pointer,
NullPtr,
Self,
Dot,
Var,
Let,
Boolean,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
Int,
UInt,
IntUnknown,
UIntUnknown,
Char8,
Char16,
Char32,
Float,
Double,
Object,
Interface,
Struct,
Enum,
TypeAlias,
Extension
}
}
namespace System.Reflection
{
internal struct TypeId : int32
{
public Type ToType()
{
return Type.sTypes[(int32)this];
}
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class TypeInstance : Type
{
[CRepr, AlwaysInclude]
internal struct FieldData
{
internal String mName;
internal int64 mConstValue;
internal int32 mDataOffset;
internal TypeId mFieldTypeId;
internal FieldFlags mFlags;
internal int32 mCustomAttributesIdx;
}
// This is only valid if there is no FieldData on a splattable struct
[CRepr, AlwaysInclude]
internal struct FieldSplatData
{
internal TypeId[3] mSplatTypes;
internal int32[3] mSplatOffsets;
}
[CRepr, AlwaysInclude]
internal struct MethodData
{
internal String mName; // mName
internal void* mFuncPtr;
internal ParamData* mParamData;
internal TypeId mReturnType;
internal int16 mParamCount;
internal MethodFlags mFlags;
internal int32 mVirtualIdx;
internal int32 mCustomAttributesIdx;
}
internal enum ParamFlags : int16
{
None = 0,
Splat = 1,
Implicit = 2
}
[CRepr, AlwaysInclude]
internal struct ParamData
{
internal String mName;
internal TypeId mType;
internal ParamFlags mParamFlags;
internal int32 mDefaultIdx;
}
internal ClassVData* mTypeClassVData;
internal String mName;
internal String mNamespace;
internal int32 mInstSize;
internal int32 mInstAlign;
internal int32 mCustomAttributesIdx;
internal TypeId mBaseType;
internal TypeId mUnderlyingType;
internal TypeId mOuterType;
internal int32 mInheritanceId;
internal int32 mInheritanceCount;
internal uint8 mInterfaceSlot;
internal uint8 mInterfaceCount;
internal int16 mMethodDataCount;
internal int16 mPropertyDataCount;
internal int16 mFieldDataCount;
internal int16 mConstructorDataCount;
internal void* mInterfaceDataPtr;
internal MethodData* mMethodDataPtr;
internal void* mPropertyDataPtr;
internal FieldData* mFieldDataPtr;
internal void* mConstructorDataPtr;
internal void** mCustomAttrDataPtr;
public override int32 InstanceSize
{
get
{
return mInstSize;
}
}
public override int32 InstanceAlign
{
get
{
return mInstAlign;
}
}
public override int32 InstanceStride
{
get
{
return Math.Align(mInstSize, mInstAlign);
}
}
public override TypeInstance BaseType
{
get
{
return (TypeInstance)Type.GetType(mBaseType);
}
}
public override TypeInstance OuterType
{
get
{
return (TypeInstance)Type.GetType(mOuterType);
}
}
public override Type UnderlyingType
{
get
{
return Type.GetType(mUnderlyingType);
}
}
public override int32 FieldCount
{
get
{
return mFieldDataCount;
}
}
public override bool IsSubtypeOf(Type checkBaseType)
{
TypeInstance curType = this;
while (true)
{
if (curType == checkBaseType)
return true;
if (curType.mBaseType == 0)
return false;
curType = (TypeInstance)Type.GetType(curType.mBaseType);
}
}
public override void GetFullName(String strBuffer)
{
if (mTypeFlags.HasFlag(TypeFlags.Tuple))
{
strBuffer.Append('(');
for (int fieldIdx < mFieldDataCount)
{
if (fieldIdx > 0)
strBuffer.Append(", ");
GetType(mFieldDataPtr[fieldIdx].mFieldTypeId).GetFullName(strBuffer);
}
strBuffer.Append(')');
}
else
{
if (mOuterType != 0)
{
GetType(mOuterType).GetFullName(strBuffer);
strBuffer.Append(".");
}
else
{
if (!String.IsNullOrEmpty(mNamespace))
strBuffer.Append(mNamespace, ".");
}
strBuffer.Append(mName);
}
}
public override void GetName(String strBuffer)
{
strBuffer.Append(mName);
}
public override FieldInfo? GetField(String fieldName)
{
for (int32 i = 0; i < mFieldDataCount; i++)
{
FieldData* fieldData = &mFieldDataPtr[i];
if (fieldData.mName == fieldName)
return FieldInfo(this, fieldData);
}
return null;
}
public override FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup)
{
return FieldInfo.Enumerator(this, bindingFlags);
}
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class PointerType : Type
{
internal TypeId mElementType;
public override Type UnderlyingType
{
get
{
return Type.GetType(mElementType);
}
}
public override void GetFullName(String strBuffer)
{
UnderlyingType.GetFullName(strBuffer);
strBuffer.Append("*");
}
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class SizedArrayType : Type
{
internal TypeId mElementType;
internal int32 mElementCount;
public override Type UnderlyingType
{
get
{
return Type.GetType(mElementType);
}
}
public int ElementCount
{
get
{
return mElementCount;
}
}
public override void GetFullName(String strBuffer)
{
UnderlyingType.GetFullName(strBuffer);
strBuffer.Append("[");
mElementCount.ToString(strBuffer);
strBuffer.Append("]");
}
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class UnspecializedGenericType : TypeInstance
{
[CRepr, AlwaysInclude]
internal struct GenericParam
{
internal String mName;
}
internal uint8 mGenericParamCount;
}
// Only for resolved types
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class SpecializedGenericType : TypeInstance
{
internal TypeId mUnspecializedType;
internal TypeId* mResolvedTypeRefs;
public override int32 GenericParamCount
{
get
{
var unspecializedTypeG = Type.GetType(mUnspecializedType);
var unspecializedType = (UnspecializedGenericType)unspecializedTypeG;
return unspecializedType.mGenericParamCount;
}
}
public Type GetGenericArg(int argIdx)
{
return mResolvedTypeRefs[argIdx].ToType();
}
public override void GetFullName(String strBuffer)
{
var unspecializedTypeG = Type.GetType(mUnspecializedType);
var unspecializedType = (UnspecializedGenericType)unspecializedTypeG;
base.GetFullName(strBuffer);
int32 outerGenericCount = 0;
var outerType = OuterType;
if (outerType != null)
outerGenericCount = outerType.GenericParamCount;
if (outerGenericCount < unspecializedType.mGenericParamCount)
{
strBuffer.Append('<');
for (int i = outerGenericCount; i < unspecializedType.mGenericParamCount; i++)
{
if (i > 0)
strBuffer.Append(", ");
Type.GetType(mResolvedTypeRefs[i]).GetFullName(strBuffer);
}
strBuffer.Append('>');
}
}
}
[CRepr, AlwaysInclude(AssumeInstantiated=true)]
internal class ArrayType : SpecializedGenericType
{
internal int32 mElementSize;
internal uint8 mRank;
internal uint8 mElementsDataOffset;
public override void GetFullName(String strBuffer)
{
Type.GetType(mResolvedTypeRefs[0]).GetFullName(strBuffer);
strBuffer.Append('[');
for (int commaNum < mRank - 1)
strBuffer.Append(',');
strBuffer.Append(']');
}
}
public enum TypeFlags : uint32
{
UnspecializedGeneric = 0x0001,
SpecializedGeneric = 0x0002,
Array = 0x0004,
Object = 0x0008,
Boxed = 0x0010,
Pointer = 0x0020,
Struct = 0x0040,
Primitive = 0x0080,
TypedPrimitive = 0x0100,
Tuple = 0x0200,
Nullable = 0x0400,
SizedArray = 0x0800,
Splattable = 0x1000,
Union = 0x2000,
Sys_PointerT = 0x4000, // System.Pointer<T>
WantsMark = 0x8000,
Delegate = 0x10000,
HasDestructor = 0x20000,
}
public enum FieldFlags : uint16
{
// member access mask - Use this mask to retrieve accessibility information.
FieldAccessMask = 0x0007,
PrivateScope = 0x0000, // Member not referenceable.
Private = 0x0001, // Accessible only by the parent type.
FamAndProject = 0x0002, // Accessible by sub-types only in this Assembly.
Project = 0x0003, // Accessibly by anyone in the Assembly.
Family = 0x0004, // Accessible only by type and sub-types.
FamOrProject = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// field contract attributes.
Static = 0x0010, // Defined on type, else per instance.
InitOnly = 0x0020, // Field may only be initialized, not written to after init.
Const = 0x0040, // Value is compile time constant.
SpecialName = 0x0080, // field is special. Name describes how.
EnumPayload = 0x0100,
EnumDiscriminator = 0x0200
}
public enum MethodFlags : int16
{
MethodAccessMask = 0x0007,
PrivateScope = 0x0000, // Member not referenceable.
Private = 0x0001, // Accessible only by the parent type.
FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
Assembly = 0x0003, // Accessibly by anyone in the Assembly.
Family = 0x0004, // Accessible only by type and sub-types.
FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// method contract attributes.
Static = 0x0010, // Defined on type, else per instance.
Final = 0x0020, // Method may not be overridden.
Virtual = 0x0040, // Method virtual.
HideBySig = 0x0080, // Method hides by name+sig, else just by name.
CheckAccessOnOverride = 0x0200,
// vtable layout mask - Use this mask to retrieve vtable attributes.
VtableLayoutMask = 0x0100,
ReuseSlot = 0x0000, // The default.
NewSlot = 0x0100, // Method always gets a new slot in the vtable.
// end vtable layout mask
// method implementation attributes.
Abstract = 0x0400, // Method does not provide an implementation.
SpecialName = 0x0800, // Method is special. Name describes how.
StdCall = 0x1000,
FastCall = 0x2000,
Mutating = 0x4000
}
}

View file

@ -0,0 +1,287 @@
using System.Diagnostics;
namespace System
{
struct Variant
{
internal int mStructType; // 0 = unowned object, 1 = owned object, 2 = null value (mData is type), otherwise is struct type
internal int mData; // This is either an Object reference, struct data, or a pointer to struct data
public bool OwnsMemory
{
get
{
if (mStructType <= 2)
return mStructType == 1;
return VariantType.Size > sizeof(int);
}
}
public bool IsObject
{
get
{
return mStructType <= 2;
}
}
public Type VariantType
{
get
{
if (mStructType == 2)
{
return (Type)Internal.UnsafeCastToObject((void*)mData);
}
if (mStructType <= 1)
{
return Internal.UnsafeCastToObject((void*)mData).GetType();
}
return (Type)Internal.UnsafeCastToObject((void*)mStructType);
}
}
public bool HasValue
{
get
{
return (mStructType != 0) || (mData != 0);
}
}
#if BF_ENABLE_REALTIME_LEAK_CHECK
protected override void GCMarkMembers()
{
if ((mStructType == 1) || (mStructType == 0))
{
var obj = Internal.UnsafeCastToObject((void*)mData);
GC.Mark(obj);
}
}
#endif
public void Dispose() mut
{
if (mStructType == 1)
{
delete Internal.UnsafeCastToObject((void*)mData);
}
else if (OwnsMemory)
{
delete (void*)mData;
}
mStructType = 0;
mData = 0;
}
public static Variant Create<T>(T val, bool owns = false) where T : class
{
Variant variant;
if (val == null)
{
variant.mStructType = 2;
variant.mData = (int)(void*)typeof(T);
}
else
{
variant.mStructType = (int)(owns ? 1 : 0);
variant.mData = (int)(void*)val;
}
return variant;
}
public static Variant Create<T>(T val) where T : struct
{
Variant variant;
Type type = typeof(T);
variant.mStructType = (int)(void*)type;
if (sizeof(T) <= sizeof(int))
{
variant.mData = 0;
*(T*)&variant.mData = val;
}
else
{
T* newVal = (T*)new uint8[sizeof(T)]*;
*newVal = val;
variant.mData = (int)(void*)newVal;
}
return variant;
}
public static Variant Create<T>(T val) where T : struct*
{
Variant variant;
Type type = typeof(T);
variant.mStructType = (int)(void*)type;
if (type.Size <= sizeof(int))
{
variant.mData = 0;
*(T*)&variant.mData = val;
}
else
{
T* newVal = (T*)new uint8[sizeof(T)]*;
*newVal = val;
variant.mData = (int)(void*)newVal;
}
return variant;
}
public static Variant Create(Type type, void* val)
{
Variant variant;
Debug.Assert(!type.IsObject);
//Debug.Assert((type.GetUnderlyingType() == typeof(T)) || (type == typeof(T)));
variant.mStructType = (int)(void*)type;
if (type.Size <= sizeof(int))
{
variant.mData = 0;
Internal.MemCpy(&variant.mData, val, type.mSize);
}
else
{
void* data = new uint8[type.mSize]*;
Internal.MemCpy(data, val, type.mSize);
variant.mData = (int)data;
}
return variant;
}
public static void* Alloc(Type type, out Variant variant)
{
variant = .();
if (type.IsObject)
{
return &variant.mData;
}
else
{
variant.mStructType = (int)(void*)type;
if (type.Size <= sizeof(int))
{
variant.mData = 0;
return &variant.mData;
}
else
{
void* data = new uint8[type.mSize]*;
variant.mData = (int)data;
return data;
}
}
}
public void Get<T>(ref T val)
{
if (VariantType != typeof(T))
return;
val = Get<T>();
}
public T Get<T>() where T : class
{
Debug.Assert(IsObject);
if (mStructType == 2)
return (T)null;
T obj = (T)Internal.UnsafeCastToObject((void*)mData);
Debug.Assert(obj.GetType().IsSubtypeOf(typeof(T)));
return obj;
}
public T Get<T>() where T : struct
{
Debug.Assert(!IsObject);
var type = VariantType;
//Debug.Assert((typeof(T) == type) || (typeof(T) == type.GetUnderlyingType()));
if (type.Size <= sizeof(int))
{
int data = mData;
return *(T*)&data;
}
else
return *(T*)(void*)mData;
}
public T Get<T>() where T : struct*
{
Debug.Assert(!IsObject);
var type = VariantType;
//Debug.Assert((typeof(T) == type) || (typeof(T) == type.GetUnderlyingType()));
if (type.Size <= sizeof(int))
{
int data = mData;
return *(T*)&data;
}
else
return *(T*)(void*)mData;
}
public void CopyValueData(void* dest)
{
if (IsObject)
{
if (mStructType == 2)
*((Object*)dest) =null;
*((Object*)dest) = Internal.UnsafeCastToObject((void*)mData);
return;
}
var type = VariantType;
if (type.Size <= sizeof(int))
{
int data = mData;
Internal.MemCpy(dest, &data, type.Size);
}
else
{
Internal.MemCpy(dest, (void*)mData, type.Size);
}
}
public void* GetValueData() mut
{
Debug.Assert(!IsObject);
var type = VariantType;
if (type.Size <= sizeof(int))
{
return (void*)&mData;
}
else
{
return (void*)mData;
}
}
public static bool operator==(Variant v1, Variant v2)
{
if (v1.IsObject)
{
if (!v2.IsObject)
return false;
if ((v1.mStructType == 2) != (v2.mStructType == 2))
return false; // If one is null but the other isn't
return v1.mData == v2.mData;
}
if (v1.mStructType != v2.mStructType)
return false;
let type = v1.VariantType;
if (type.mSize <= sizeof(int))
return v1.mData == v2.mData;
for (int i < type.mSize)
{
if (((uint8*)(void*)v1.mData)[i] != ((uint8*)(void*)v2.mData)[i])
return false;
}
return true;
}
public static mixin Equals<T>(var v1, var v2)
{
v1.Get<T>() == v2.Get<T>()
}
}
}