mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-21 17:28:00 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
555
IDE/mintest/minlib/src/System/Array.bf
Normal file
555
IDE/mintest/minlib/src/System/Array.bf
Normal 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
370
IDE/mintest/minlib/src/System/Attribute.bf
Normal file
370
IDE/mintest/minlib/src/System/Attribute.bf
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
470
IDE/mintest/minlib/src/System/BitConverter.bf
Normal file
470
IDE/mintest/minlib/src/System/BitConverter.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
651
IDE/mintest/minlib/src/System/Collections/Generic/List.bf
Normal file
651
IDE/mintest/minlib/src/System/Collections/Generic/List.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
302
IDE/mintest/minlib/src/System/Collections/Generic/Sorter.bf
Normal file
302
IDE/mintest/minlib/src/System/Collections/Generic/Sorter.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
IDE/mintest/minlib/src/System/Collections/IEnumerator.bf
Normal file
36
IDE/mintest/minlib/src/System/Collections/IEnumerator.bf
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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() { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace System.Diagnostics.Contracts
|
||||
{
|
||||
class ContractsBcl
|
||||
{
|
||||
}
|
||||
}
|
50
IDE/mintest/minlib/src/System/Diagnostics/Debug.bf
Normal file
50
IDE/mintest/minlib/src/System/Diagnostics/Debug.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
95
IDE/mintest/minlib/src/System/Diagnostics/Profiler.bf
Normal file
95
IDE/mintest/minlib/src/System/Diagnostics/Profiler.bf
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
135
IDE/mintest/minlib/src/System/Diagnostics/Stopwatch.bf
Normal file
135
IDE/mintest/minlib/src/System/Diagnostics/Stopwatch.bf
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
343
IDE/mintest/minlib/src/System/Double.bf
Normal file
343
IDE/mintest/minlib/src/System/Double.bf
Normal 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);
|
||||
}*/
|
||||
}
|
||||
}
|
31
IDE/mintest/minlib/src/System/Environment.bf
Normal file
31
IDE/mintest/minlib/src/System/Environment.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
306
IDE/mintest/minlib/src/System/Event.bf
Normal file
306
IDE/mintest/minlib/src/System/Event.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
196
IDE/mintest/minlib/src/System/GC.bf
Normal file
196
IDE/mintest/minlib/src/System/GC.bf
Normal 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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
57
IDE/mintest/minlib/src/System/IComparable.bf
Normal file
57
IDE/mintest/minlib/src/System/IComparable.bf
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
25
IDE/mintest/minlib/src/System/IHashable.bf
Normal file
25
IDE/mintest/minlib/src/System/IHashable.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
221
IDE/mintest/minlib/src/System/Internal.bf
Normal file
221
IDE/mintest/minlib/src/System/Internal.bf
Normal 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();
|
||||
}
|
||||
}
|
259
IDE/mintest/minlib/src/System/Math.bf
Normal file
259
IDE/mintest/minlib/src/System/Math.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
14
IDE/mintest/minlib/src/System/MidpointRounding.bf
Normal file
14
IDE/mintest/minlib/src/System/MidpointRounding.bf
Normal file
|
@ -0,0 +1,14 @@
|
|||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
namespace System
|
||||
{
|
||||
public enum MidpointRounding
|
||||
{
|
||||
ToEven = 0,
|
||||
AwayFromZero = 1,
|
||||
}
|
||||
}
|
112
IDE/mintest/minlib/src/System/Nullable.bf
Normal file
112
IDE/mintest/minlib/src/System/Nullable.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
584
IDE/mintest/minlib/src/System/Object.bf
Normal file
584
IDE/mintest/minlib/src/System/Object.bf
Normal 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
|
||||
}
|
||||
}
|
||||
|
415
IDE/mintest/minlib/src/System/Platform.bf
Normal file
415
IDE/mintest/minlib/src/System/Platform.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
65
IDE/mintest/minlib/src/System/Reflection/BindingFlags.bf
Normal file
65
IDE/mintest/minlib/src/System/Reflection/BindingFlags.bf
Normal 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
|
||||
}
|
||||
}
|
381
IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf
Normal file
381
IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf
Normal 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*)⌖
|
||||
|
||||
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*)⌖
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
126
IDE/mintest/minlib/src/System/Result.bf
Normal file
126
IDE/mintest/minlib/src/System/Result.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
329
IDE/mintest/minlib/src/System/Runtime.bf
Normal file
329
IDE/mintest/minlib/src/System/Runtime.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
218
IDE/mintest/minlib/src/System/Span.bf
Normal file
218
IDE/mintest/minlib/src/System/Span.bf
Normal 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
|
||||
}
|
1003
IDE/mintest/minlib/src/System/String.bf
Normal file
1003
IDE/mintest/minlib/src/System/String.bf
Normal file
File diff suppressed because it is too large
Load diff
12
IDE/mintest/minlib/src/System/TClass.bf
Normal file
12
IDE/mintest/minlib/src/System/TClass.bf
Normal 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();
|
||||
}
|
||||
}
|
127
IDE/mintest/minlib/src/System/Threading/Monitor.bf
Normal file
127
IDE/mintest/minlib/src/System/Threading/Monitor.bf
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
352
IDE/mintest/minlib/src/System/Threading/Thread.bf
Normal file
352
IDE/mintest/minlib/src/System/Threading/Thread.bf
Normal 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();
|
||||
}
|
||||
}
|
34
IDE/mintest/minlib/src/System/Threading/ThreadPriority.bf
Normal file
34
IDE/mintest/minlib/src/System/Threading/ThreadPriority.bf
Normal 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
|
||||
}
|
||||
}
|
37
IDE/mintest/minlib/src/System/Threading/ThreadState.bf
Normal file
37
IDE/mintest/minlib/src/System/Threading/ThreadState.bf
Normal 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
|
||||
}
|
||||
}
|
25
IDE/mintest/minlib/src/System/Threading/Timeout.bf
Normal file
25
IDE/mintest/minlib/src/System/Threading/Timeout.bf
Normal 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);
|
||||
}
|
||||
|
||||
}
|
132
IDE/mintest/minlib/src/System/TimeSpan.bf
Normal file
132
IDE/mintest/minlib/src/System/TimeSpan.bf
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
873
IDE/mintest/minlib/src/System/Type.bf
Normal file
873
IDE/mintest/minlib/src/System/Type.bf
Normal 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
|
||||
}
|
||||
}
|
287
IDE/mintest/minlib/src/System/Variant.bf
Normal file
287
IDE/mintest/minlib/src/System/Variant.bf
Normal 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>()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue