1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-07 08:45:59 +02:00

Merge branch 'master' into bufstream-fixes

This commit is contained in:
EinBurgbauer 2021-12-09 16:13:29 +01:00
commit 92738418eb
243 changed files with 19052 additions and 2933 deletions

View file

@ -35,7 +35,8 @@ namespace System
}
public bool IsEmpty
{
{
[Inline]
get
{
return mLength == 0;
@ -259,6 +260,46 @@ namespace System
}
}
public ref T this[Index index]
{
[Checked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
if ((uint)idx >= (uint)mLength)
Internal.ThrowIndexOutOfRange(1);
return ref (&mFirstElement)[idx];
}
[Unchecked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
return ref (&mFirstElement)[idx];
}
}
public Span<T> this[IndexRange range]
{
#if !DEBUG
[Inline]
#endif
get
{
return Span<T>(&mFirstElement, mLength)[range];
}
}
[Inline]
public T* CArray()
{
@ -276,7 +317,7 @@ namespace System
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));
Internal.MemMove(&arrayTo.GetRef(dstOffset), &GetRef(srcOffset), strideof(T) * length, alignof(T));
}
public void CopyTo<T2>(T2[] arrayTo, int srcOffset, int dstOffset, int length) where T2 : operator explicit T
@ -299,17 +340,18 @@ namespace System
public void CopyTo(Span<T> destination)
{
Debug.Assert(destination.[Friend]mLength >= mLength);
Internal.MemCpy(destination.Ptr, &GetRef(0), strideof(T) * mLength, alignof(T));
Internal.MemMove(destination.Ptr, &GetRef(0), strideof(T) * mLength, alignof(T));
}
public void CopyTo(Span<T> destination, int srcOffset)
{
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
Internal.MemCpy(destination.Ptr, &GetRef(srcOffset), strideof(T) * (destination.[Friend]mLength - srcOffset), alignof(T));
Internal.MemMove(destination.Ptr, &GetRef(srcOffset), strideof(T) * (destination.[Friend]mLength - srcOffset), alignof(T));
}
public void CopyTo<T2>(Span<T2> destination, int srcOffset) where T2 : operator explicit T
{
//TODO: Handle src/dest overlap (MemMove)
Debug.Assert((uint)srcOffset + (uint)destination.[Friend]mLength <= (uint)mLength);
var ptr = destination.[Friend]mPtr;
for (int i = 0; i < destination.[Friend]mLength; i++)

View file

@ -1,6 +1,6 @@
namespace System
{
struct Char16 : char16, IHashable, IIsNaN
struct Char16 : char16, ICharacter, IHashable, IIsNaN
{
const int UNICODE_PLANE00_END = 0x00ffff;
// The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.

View file

@ -1,6 +1,6 @@
namespace System
{
struct Char32 : char32, IHashable, IIsNaN
struct Char32 : char32, ICharacter, IHashable, IIsNaN
{
public int GetHashCode()
{

View file

@ -1,7 +1,7 @@
namespace System
{
#unwarn
struct Char8 : char8, IHashable, IIsNaN
struct Char8 : char8, ICharacter, IHashable, IIsNaN
{
bool IIsNaN.IsNaN
{

View file

@ -26,7 +26,7 @@ namespace System.Collections
{
public TKey mKey; // Key of entry
public TValue mValue; // Value of entry
public int32 mHashCode; // Lower 31 bits of hash code, -1 if unused
public int_cosize mHashCode; // some bits of hash code, -1 if unused
public int_cosize mNext; // Index of next entry, -1 if last
}
@ -34,7 +34,7 @@ namespace System.Collections
Entry* mEntries;
int_cosize mAllocSize;
int_cosize mCount;
int_cosize mFreeList;
int_cosize mFreeList;
int_cosize mFreeCount;
#if VERSION_DICTIONARY
private int32 mVersion;
@ -258,21 +258,9 @@ namespace System.Collections
public bool ContainsValue(TValue value)
{
if (value == null)
for (int_cosize i = 0; i < mCount; i++)
{
for (int_cosize i = 0; i < mCount; i++)
{
if (mEntries[i].mHashCode >= 0 && mEntries[i].mValue == null) return true;
}
}
else
{
//TODO: IMPORTANT!
/*EqualityComparer<TValue> c = EqualityComparer<TValue>.Default;
for (int i = 0; i < count; i++)
{
if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true;
}*/
if (mEntries[i].mHashCode >= 0 && mEntries[i].mValue == value) return true;
}
return false;
}
@ -289,6 +277,19 @@ namespace System.Collections
return false;
}
}
public bool ContainsAlt<TAltKey>((TAltKey key, TValue value) kvPair) where TAltKey : IHashable where bool : operator TKey == TAltKey
{
TValue value;
if (TryGetValueAlt(kvPair.key, out value))
{
return value == kvPair.value;
}
else
{
return false;
}
}
public void CopyTo(Span<KeyValuePair> kvPair)
{
@ -306,12 +307,21 @@ namespace System.Collections
return Enumerator(this, Enumerator.[Friend]KeyValuePair);
}
static int_cosize GetKeyHash(int hashCode)
{
if (sizeof(int) == 4)
return (int32)hashCode & 0x7FFFFFFF;
if (sizeof(int_cosize) == 8)
return (int_cosize)(hashCode & 0x7FFFFFFF'FFFFFFFFL);
return ((int32)hashCode ^ (int32)((int64)hashCode >> 33)) & 0x7FFFFFFF;
}
[DisableObjectAccessChecks]
private int FindEntry(TKey key)
{
if (mBuckets != null)
{
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
for (int i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
@ -329,7 +339,7 @@ namespace System.Collections
{
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
for (int_cosize i = mBuckets[hashCode % mAllocSize]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
@ -350,10 +360,10 @@ namespace System.Collections
private void Insert(TKey key, TValue value, bool add)
{
if (mBuckets == null) Initialize(0);
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int targetBucket = hashCode % mAllocSize;
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
for (int i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
{
@ -402,7 +412,7 @@ namespace System.Collections
private bool Insert(TKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData)
{
if (mBuckets == null) Initialize(0);
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
{
@ -458,9 +468,9 @@ namespace System.Collections
private bool InsertAlt<TAltKey>(TAltKey key, bool add, out TKey* keyPtr, out TValue* valuePtr, Entry** outOldData) where TAltKey : IHashable where bool : operator TKey == TAltKey
{
if (mBuckets == null) Initialize(0);
int32 hashCode = (int32)key.GetHashCode() & 0x7FFFFFFF;
int_cosize targetBucket = hashCode % (int_cosize)mAllocSize;
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int targetBucket = hashCode % (int_cosize)mAllocSize;
for (int i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
{
@ -541,7 +551,7 @@ namespace System.Collections
{
if (newEntries[i].mHashCode != -1)
{
newEntries[i].mHashCode = (int32)newEntries[i].mKey.GetHashCode() & 0x7FFFFFFF;
newEntries[i].mHashCode = GetKeyHash(newEntries[i].mKey.GetHashCode());
}
}
}
@ -572,7 +582,7 @@ namespace System.Collections
{
if (mBuckets != null)
{
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int bucket = hashCode % (int_cosize)mAllocSize;
int last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
@ -609,7 +619,7 @@ namespace System.Collections
{
if (mBuckets != null)
{
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int bucket = hashCode % (int_cosize)mAllocSize;
int last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
@ -653,8 +663,8 @@ namespace System.Collections
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int bucket = hashCode % (int_cosize)mAllocSize;
int_cosize last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
{
@ -694,8 +704,8 @@ namespace System.Collections
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize bucket = hashCode % (int_cosize)mAllocSize;
int_cosize hashCode = GetKeyHash(key.GetHashCode());
int bucket = hashCode % (int_cosize)mAllocSize;
int_cosize last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
{
@ -742,6 +752,18 @@ namespace System.Collections
return false;
}
public bool TryGetValueAlt<TAltKey>(TAltKey key, out TValue value) where TAltKey : IHashable where bool : operator TKey == TAltKey
{
int_cosize i = (int_cosize)FindEntryAlt<TAltKey>(key);
if (i >= 0)
{
value = mEntries[i].mValue;
return true;
}
value = default(TValue);
return false;
}
public bool TryGet(TKey key, out TKey matchKey, out TValue value)
{
int_cosize i = (int_cosize)FindEntry(key);
@ -876,6 +898,16 @@ namespace System.Collections
mDictionary.mEntries[mCurrentIndex].mValue = value;
}
public void Remove() mut
{
int_cosize curIdx = mIndex - 1;
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
#if VERSION_DICTIONARY
mVersion = mDictionary.mVersion;
#endif
mIndex = curIdx;
}
public void Reset() mut
{
#if VERSION_DICTIONARY
@ -1017,6 +1049,16 @@ namespace System.Collections
{
}
public void Remove() mut
{
int_cosize curIdx = mIndex - 1;
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
#if VERSION_DICTIONARY
mVersion = mDictionary.mVersion;
#endif
mIndex = curIdx;
}
public void Reset() mut
{
#if VERSION_DICTIONARY
@ -1113,6 +1155,16 @@ namespace System.Collections
{
}
public void Remove() mut
{
int_cosize curIdx = mIndex - 1;
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
#if VERSION_DICTIONARY
mVersion = mDictionary.mVersion;
#endif
mIndex = curIdx;
}
public void Reset() mut
{
#if VERSION_DICTIONARY

View file

@ -196,7 +196,13 @@ namespace System.Collections
return false;
}
[Obsolete("Method renamed to ContainsAlt", false)]
public bool ContainsWith<TAltKey>(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey
{
return ContainsAlt(item);
}
public bool ContainsAlt<TAltKey>(TAltKey item) where TAltKey : IHashable where bool : operator T == TAltKey
{
if (mBuckets != null)
{
@ -346,6 +352,11 @@ namespace System.Collections
return Add(item, out entryPtr);
}
public bool TryAddAlt<TAltKey>(TAltKey item, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey
{
return AddAlt(item, out entryPtr);
}
public void CopyTo(T[] array) { CopyTo(array, 0, mCount); }
public void CopyTo(T[] array, int32 arrayIndex, int32 count)
@ -632,6 +643,71 @@ namespace System.Collections
mVersion++;
#endif
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
SetCapacity(m_buckets.Length, true);
}
#endif // FEATURE_RANDOMIZED_STRING_HASHING
entryPtr = &mSlots[index].mValue;
return true;
}
/// Adds value to HashSet if not contained already
/// @return true if added and false if already present
/// @param value value to find
/// @param entryPtr ponter to entry
public bool AddAlt<TAltKey>(TAltKey value, out T* entryPtr) where TAltKey : IHashable where bool : operator T == TAltKey
{
if (mBuckets == null)
{
Initialize(0);
}
int32 hashCode = (int32)InternalGetHashCodeAlt(value);
int32 bucket = hashCode % (int32)mBuckets.Count;
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
int collisionCount = 0;
#endif
for (int32 i = mBuckets[hashCode % mBuckets.Count] - 1; i >= 0; i = mSlots[i].mNext)
{
if (mSlots[i].mHashCode == hashCode && /*m_comparer.Equals*/(mSlots[i].mValue == value))
{
entryPtr = &mSlots[i].mValue;
return false;
}
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
collisionCount++;
#endif
}
int32 index;
if (mFreeList >= 0)
{
index = mFreeList;
mFreeList = mSlots[index].mNext;
}
else
{
if (mLastIndex == mSlots.Count)
{
IncreaseCapacity();
// this will change during resize
bucket = hashCode % (int32)mBuckets.Count;
}
index = mLastIndex;
mLastIndex++;
}
mSlots[index].mHashCode = hashCode;
//mSlots[index].mValue = value;
mSlots[index].mNext = mBuckets[bucket] - 1;
mBuckets[bucket] = index + 1;
mCount++;
#if VERSION_HASHSET
mVersion++;
#endif
#if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) {
m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer(m_comparer);
@ -1071,6 +1147,15 @@ namespace System.Collections
return item.GetHashCode() & Lower31BitMask;
}
private int InternalGetHashCodeAlt<TAltKey>(TAltKey item) where TAltKey : IHashable
{
if (item == null)
{
return 0;
}
return item.GetHashCode() & Lower31BitMask;
}
#endregion
// used for set checking operations (using enumerables) that rely on counting

View file

@ -148,6 +148,7 @@ namespace System.Collections
public int Count
{
[Inline]
get
{
return mSize;
@ -210,6 +211,76 @@ namespace System.Collections
}
}
public ref T this[Index index]
{
[Checked]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mSize - offset;
}
Runtime.Assert((uint)idx < (uint)mSize);
return ref mItems[idx];
}
[Unchecked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mSize - offset;
}
return ref mItems[idx];
}
[Checked]
set
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mSize - offset;
}
Runtime.Assert((uint)idx < (uint)mSize);
mItems[idx] = value;
#if VERSION_LIST
mVersion++;
#endif
}
[Unchecked, Inline]
set
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mSize - offset;
}
mItems[idx] = value;
#if VERSION_LIST
mVersion++;
#endif
}
}
public Span<T> this[IndexRange range]
{
#if !DEBUG
[Inline]
#endif
get
{
return Span<T>(mItems, mSize)[range];
}
}
public ref T Front
{
get
@ -534,7 +605,7 @@ namespace System.Collections
if (mSize == AllocSize) EnsureCapacity(mSize + 1, true);
if (index < mSize)
{
Internal.MemCpy(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
Internal.MemMove(mItems + index + 1, mItems + index, (mSize - index) * strideof(T), alignof(T));
}
mItems[index] = item;
mSize++;
@ -553,7 +624,7 @@ namespace System.Collections
if (mSize + addCount > AllocSize) EnsureCapacity(mSize + addCount, true);
if (index < mSize)
{
Internal.MemCpy(mItems + index + addCount, mItems + index, (mSize - index) * strideof(T), alignof(T));
Internal.MemMove(mItems + index + addCount, mItems + index, (mSize - index) * strideof(T), alignof(T));
}
Internal.MemCpy(mItems + index, items.Ptr, addCount * strideof(T));
mSize += (int_cosize)addCount;
@ -567,7 +638,7 @@ namespace System.Collections
Debug.Assert((uint)index < (uint)mSize);
if (index < mSize - 1)
{
Internal.MemCpy(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
Internal.MemMove(mItems + index, mItems + index + 1, (mSize - index - 1) * strideof(T), alignof(T));
}
mSize--;
#if VERSION_LIST
@ -930,6 +1001,59 @@ namespace System.Collections
}
}
extension List<T> where T : String
{
public bool Contains(T item, StringComparison comparison)
{
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].Equals(item, comparison))
return true;
return false;
}
}
public int IndexOf(T item, StringComparison comparison)
{
for (int i = 0; i < mSize; i++)
if (mItems[i].Equals(item, comparison))
return i;
return -1;
}
public int IndexOf(T item, int index, StringComparison comparison)
{
for (int i = index; i < mSize; i++)
if (mItems[i].Equals(item, comparison))
return i;
return -1;
}
public int IndexOf(T item, int index, int count, StringComparison comparison)
{
for (int i = index; i < index + count; i++)
if (mItems[i].Equals(item, comparison))
return i;
return -1;
}
public int LastIndexOf(T item, StringComparison comparison)
{
for (int i = mSize - 1; i >= 0; i--)
if (mItems[i].Equals(item, comparison))
return i;
return -1;
}
}
class ListWithAlloc<T> : List<T>
{
IRawAllocator mAlloc;

View file

@ -18,6 +18,12 @@ namespace System
}
}
public static class Options
{
[LinkName("#AllocStackCount")]
public static extern int32 AllocStackCount;
}
[LinkName("#CallerLineNum")]
public static extern int CallerLineNum;
@ -37,7 +43,7 @@ namespace System
public static extern String CallerProject;
[LinkName("#CallerExpression")]
public static extern String[Int32.MaxValue] CallerExpression;
public static extern String[0x0FFFFFFF] CallerExpression;
[LinkName("#ProjectName")]
public static extern String ProjectName;

View file

@ -7,6 +7,12 @@ namespace System
{
public static class Console
{
public enum CancelKind
{
CtrlC,
CtrlBreak
}
static Encoding InputEncoding = Encoding.ASCII;
static Encoding OutputEncoding = Encoding.ASCII;
@ -16,6 +22,9 @@ namespace System
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
static bool sCancelEventRegistered;
public static ConsoleColor ForegroundColor
{
get { return sForegroundColor; }
@ -42,16 +51,57 @@ namespace System
public uint16[2] mMaximumWindowSize;
}
[CLink, CallingConvention(.Stdcall)]
static extern int SetConsoleTextAttribute(void* hConsoleOutput, uint16 wAttributes);
[CRepr]
struct COORD : this(int16 X, int16 Y)
{
}
[CLink, CallingConvention(.Stdcall)]
static extern int GetConsoleScreenBufferInfo(void* hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
[CLink, CallingConvention(.Stdcall)]
static extern void* GetStdHandle(uint32 nStdHandle);
public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
{
get
{
if (!sCancelEventRegistered)
{
sCancelEventRegistered = true;
#if BF_PLATFORM_WINDOWS
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
#endif
}
return ref sOnCancel;
}
}
#if BF_PLATFORM_WINDOWS
[CallingConvention(.Stdcall)]
public static Windows.IntBool ConsoleCtrlHandler(int32 ctrlType)
{
bool terminate = true;
if ((ctrlType == 0) || (ctrlType == 1))
sOnCancel((.)ctrlType, ref terminate);
return terminate ? false : true;
}
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool SetConsoleTextAttribute(Windows.Handle hConsoleOutput, uint16 wAttributes);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool GetConsoleScreenBufferInfo(Windows.Handle hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.Handle GetStdHandle(uint32 nStdHandle);
[CallingConvention(.Stdcall)]
function Windows.IntBool ConsoleCtrlHandler(int32 ctrlType);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, Windows.IntBool addHandler);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool FillConsoleOutputCharacterW(Windows.Handle hConsoleOutput, char16 cCharacter, uint32 nLength, COORD dwWriteCoord, uint32* lpNumberOfCharsWritten);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool FillConsoleOutputAttribute(Windows.Handle hConsoleOutput, uint16 wAttribute, uint32 nLength, COORD dwWriteCoord, uint32* lpNumberOfAttrsWritten);
[CLink, CallingConvention(.Stdcall)]
static extern Windows.IntBool SetConsoleCursorPosition(Windows.Handle hConsoleOutput, COORD dwCursorPosition);
public static this()
{
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
@ -219,6 +269,49 @@ namespace System
#else
Write("\x1B[{}m", ForegroundColor.AnsiCode);
Write("\x1B[{}m", BackgroundColor.AnsiCode + 10);
#endif
}
public static void Clear()
{
#if BF_PLATFORM_WINDOWS
Windows.Handle hStdOut;
CONSOLE_SCREEN_BUFFER_INFO csbi;
uint32 count;
uint32 cellCount;
COORD homeCoords = .(0, 0);
hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
if (hStdOut == .InvalidHandle)
return;
/* Get the number of cells in the current buffer */
if (!GetConsoleScreenBufferInfo( hStdOut, out csbi ))
return;
cellCount = csbi.mSize[0] * csbi.mSize[1];
/* Fill the entire buffer with spaces */
if (!FillConsoleOutputCharacterW(
hStdOut,
' ',
cellCount,
homeCoords,
&count
)) return;
/* Fill the entire buffer with the current colors and attributes */
if (!FillConsoleOutputAttribute(
hStdOut,
csbi.mAttributes,
cellCount,
homeCoords,
&count
)) return;
/* Move the cursor home */
SetConsoleCursorPosition( hStdOut, homeCoords );
#else
Write("\x1B[H\x1B[J");
#endif
}
}

View file

@ -19,7 +19,7 @@ namespace System.Diagnostics
private char8[] char8Buffer;
// Record the number of valid bytes in the byteBuffer, for a few checks.
// This is the maximum number of char8s we can get from one call to
// This is the maximum number of chars we can get from one call to
// ReadBuffer. Used so ReadBuffer can tell when to copy data into
// a user's char8[] directly, instead of our internal char8[].
private int32 mMaxCharsPerBuffer;
@ -194,7 +194,7 @@ namespace System.Diagnostics
int lineStart = 0;
int len = sb.Length;
// skip a beginning '\n' char8acter of new block if last block ended
// skip a beginning '\n' character of new block if last block ended
// with '\r'
if (bLastCarriageReturn && (len > 0) && sb[0] == '\n')
{
@ -206,7 +206,7 @@ namespace System.Diagnostics
while (currentIndex < len)
{
char8 ch = sb[currentIndex];
// Note the following common line feed char8s:
// Note the following common line feed chars:
// \n - UNIX \r\n - DOS \r - Mac
if (ch == '\r' || ch == '\n')
{
@ -214,7 +214,7 @@ namespace System.Diagnostics
s.Append(sb, lineStart, currentIndex - lineStart);
lineStart = currentIndex + 1;
// skip the "\n" char8acter following "\r" char8acter
// skip the "\n" character following "\r" character
if ((ch == '\r') && (lineStart < len) && (sb[lineStart] == '\n'))
{
lineStart++;
@ -232,7 +232,7 @@ namespace System.Diagnostics
{
bLastCarriageReturn = true;
}
// Keep the rest char8acaters which can't form a new line in string builder.
// Keep the rest characaters which can't form a new line in string builder.
if (lineStart < len)
{
if (lineStart == 0)

View file

@ -1,6 +1,6 @@
namespace System.Diagnostics
{
class Check
static class Check
{
[Unchecked, SkipCall]

View file

@ -1,6 +1,6 @@
namespace System.Diagnostics.Contracts
{
class Contract
static class Contract
{
public enum ContractFailureKind
{

View file

@ -1,6 +1,6 @@
namespace System.Diagnostics
{
class Debug
static class Debug
{
#if !DEBUG
[SkipCall]
@ -44,6 +44,11 @@ namespace System.Diagnostics
Write(line.Ptr, line.Length);
}
public static void Write(StringView sv)
{
Write(sv.[Friend]mPtr, sv.[Friend]mLength);
}
public static void Write(String fmt, params Object[] args)
{
String str = scope String(4096);

View file

@ -136,7 +136,7 @@ namespace System
}
}
public void Remove(T compareDelegate, bool deleteDelegate = false) mut
public Result<void> Remove(T compareDelegate, bool deleteDelegate = false) mut
{
Object data = Target;
@ -150,9 +150,7 @@ namespace System
break;
}
if (idx == -1)
{
Runtime.FatalError("Not found");
}
return .Err;
if (deleteDelegate)
delete list[idx];
@ -177,18 +175,14 @@ namespace System
else
{
T dlgMember = (T)data;
if (Delegate.Equals(compareDelegate, dlgMember))
{
if (deleteDelegate)
delete dlgMember;
Target = null;
return;
}
else
{
Runtime.FatalError("Not found");
}
if (!Delegate.Equals(compareDelegate, dlgMember))
return .Err;
if (deleteDelegate)
delete dlgMember;
Target = null;
}
return .Ok;
}
public rettype(T) Invoke(params T p) mut

View file

@ -175,6 +175,17 @@ namespace System
{
char8 c = val.Ptr[i];
//Exponent prefix used in scientific notation. E.g. 1.2E5
if ((c == 'e') || (c == 'E'))
{
//Error if there are no numbers after the prefix
if(i == val.Length - 1)
return .Err;
var exponent = Try!(int32.Parse(val.Substring(i + 1)));
result *= Math.Pow(10, (double)exponent);
break;
}
if (c == '.')
{
if (decimalMultiplier != 0)

View file

@ -173,6 +173,10 @@ namespace System
// or the memory would already be registered with the GC
}
public static mixin Mark<T>(T val)
{
}
public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
{
#if BF_ENABLE_REALTIME_LEAK_CHECK

View file

@ -29,7 +29,7 @@ namespace System.Globalization
// cache for the invariant culture.
// invariantInfo is constant irrespective of your current culture.
private static volatile DateTimeFormatInfo invariantInfo;
private static volatile DateTimeFormatInfo invariantInfo ~ delete _;
// an index which points to a record in Culture Data Table.
private CultureData m_cultureData;
@ -139,6 +139,8 @@ namespace System.Globalization
List<Object> ownedObjects = new .() ~ DeleteContainerAndItems!(_);
public this()
: this(CultureInfo.InvariantCulture.[Friend]m_cultureData,
GregorianCalendar.[Friend]GetDefaultInstance())
{
}

View file

@ -63,7 +63,7 @@ namespace System.Globalization {
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
) ~ delete _;
private static volatile Calendar s_defaultInstance;
private static volatile Calendar s_defaultInstance ~ delete _;
#region Serialization

View file

@ -23,6 +23,10 @@ namespace System
{
}
interface ICharacter
{
}
[Obsolete("Consider operator constraint such as `where bool : operator T == T`", false)]
interface IOpEquals
{

View file

@ -68,7 +68,7 @@ namespace System.IO
public override Result<int> TryRead(Span<uint8> data)
{
int spaceLeft = (.)(mBufferEnd - mPos);
int64 spaceLeft = (.)(mBufferEnd - mPos);
if (mPos < mBufferPos)
spaceLeft = 0;
if (data.Length <= spaceLeft)
@ -83,19 +83,17 @@ namespace System.IO
var data;
if (spaceLeft > 0)
{
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), spaceLeft);
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), (.)spaceLeft);
mPos += spaceLeft;
data.RemoveFromStart(spaceLeft);
data.RemoveFromStart((.)spaceLeft);
}
if (mWriteDirtyPos >= 0)
Try!(Flush());
Try!(Flush());
if ((mBuffer == null) || (data.Length > mBuffer.Count))
{
var result = TryReadUnderlying(mPos, data);
if (result case .Ok(let len))
mPos += len;
let len = Try!(TryReadUnderlying(mPos, data));
mPos += len;
return (.)(mPos - readStart);
}
@ -148,10 +146,9 @@ namespace System.IO
if ((mBuffer == null) || (data.Length > mBuffer.Count))
{
var result = TryWriteUnderlying(mPos, data);
if (result case .Ok(let len))
mPos += len;
writeCount += result;
let len = Try!(TryWriteUnderlying(mPos, data));
mPos += len;
writeCount += len;
return writeCount;
}

View file

@ -240,7 +240,7 @@ namespace System.IO
}
}
struct FileEnumerator : IEnumerator<FileFindEntry>
struct FileEnumerator : IEnumerator<FileFindEntry>, IDisposable
{
String mSearchStr;
Platform.BfpFindFileData* mFindFileData;

View file

@ -15,6 +15,11 @@ namespace System.IO
mOwnsData = true;
}
public this(List<uint8> data)
{
mData = data;
}
public uint8* Ptr
{
get
@ -112,4 +117,100 @@ namespace System.IO
mData.RemoveRange(0, count);
}
}
class DynMemStreamSequential : Stream
{
List<uint8> mData ~ { if (mOwnsData) delete _; };
bool mOwnsData;
public this()
{
mData = new .();
mOwnsData = true;
}
public this(List<uint8> data)
{
mData = data;
}
public uint8* Ptr
{
get
{
return mData.Ptr;
}
}
public Span<uint8> Content
{
get
{
return mData;
}
}
public override int64 Position
{
get
{
return mData.Count;
}
set
{
Runtime.FatalError();
}
}
public override int64 Length
{
get
{
return mData.Count;
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public List<uint8> TakeOwnership()
{
Debug.Assert(mOwnsData);
mOwnsData = false;
return mData;
}
public override Result<int> TryRead(Span<uint8> data)
{
return .Err;
}
public override Result<int> TryWrite(Span<uint8> data)
{
let count = data.Length;
if (count == 0)
return .Ok(0);
Internal.MemCpy(mData.GrowUnitialized(count), data.Ptr, count);
return .Ok(count);
}
public override Result<void> Close()
{
return .Ok;
}
}
}

View file

@ -23,7 +23,7 @@ namespace System.IO
case FileReadError(FileReadError);
}
class File
static class File
{
public static Result<void, FileError> ReadAll(StringView path, List<uint8> outData)
{
@ -49,7 +49,7 @@ namespace System.IO
public static Result<void> WriteAll(StringView path, Span<uint8> data, bool doAppend = false)
{
FileStream fs = scope FileStream();
UnbufferedFileStream fs = scope UnbufferedFileStream();
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
if (result case .Err)
return .Err;
@ -76,7 +76,7 @@ namespace System.IO
public static Result<void> WriteAllText(StringView path, StringView text, bool doAppend = false)
{
FileStream fs = scope FileStream();
UnbufferedFileStream fs = scope UnbufferedFileStream();
var result = fs.Open(path, doAppend ? .Append : .Create, .Write);
if (result case .Err)
return .Err;
@ -87,7 +87,7 @@ namespace System.IO
public static Result<void> WriteAllText(StringView path, StringView text, Encoding encoding)
{
FileStream fs = scope FileStream();
UnbufferedFileStream fs = scope UnbufferedFileStream();
int len = encoding.GetEncodedSize(text);
uint8* data = new uint8[len]*;

View file

@ -17,16 +17,16 @@ namespace System.IO
/// Opens an existing file. Fails if the file does not exist.
Open = 3,
// Opens the file if it exists. Otherwise, creates a new file.
/// Opens the file if it exists. Otherwise, creates a new file.
OpenOrCreate = 4,
// Opens an existing file. Once opened, the file is truncated so that its
// size is zero bytes. The calling process must open the file with at least
// WRITE access. Fails if the file does not exist.
/// Opens an existing file. Once opened, the file is truncated so that its
/// size is zero bytes. The calling process must open the file with at least
/// WRITE access. Fails if the file does not exist.
Truncate = 5,
// Opens the file if it exists and seeks to the end. Otherwise,
// creates a new file.
/// Opens the file if it exists and seeks to the end. Otherwise,
/// creates a new file.
Append = 6,
}
}

View file

@ -29,6 +29,16 @@ namespace System.IO
}
}
public int Handle
{
get
{
if (mBfpFile == null)
return 0;
return Platform.BfpFile_GetSystemHandle(mBfpFile);
}
}
public ~this()
{
Delete();
@ -165,12 +175,13 @@ namespace System.IO
createKind = .CreateIfNotExists;
case .Create:
createKind = .CreateAlways;
createFlags |= .Truncate;
case .Open:
createKind = .OpenExisting;
case .OpenOrCreate:
createKind = .CreateAlways;
createKind = .OpenAlways;
case .Truncate:
createKind = .CreateAlways;
createKind = .OpenExisting;
createFlags |= .Truncate;
case .Append:
createKind = .CreateAlways;
@ -225,6 +236,32 @@ namespace System.IO
return .Err;
return .Ok;
}
public override Result<void> SetLength(int64 length)
{
int64 pos = Position;
if (pos != length)
Seek(length);
Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok)
{
Seek(pos);
return .Err;
}
if (pos != length)
{
if (pos < length)
Seek(pos);
else
Seek(0, .FromEnd);
}
return .Ok;
}
}
class BufferedFileStream : BufferedStream
@ -233,6 +270,32 @@ namespace System.IO
protected int64 mBfpFilePos;
FileAccess mFileAccess;
public int Handle
{
get
{
if (mBfpFile == null)
return 0;
return Platform.BfpFile_GetSystemHandle(mBfpFile);
}
}
public override bool CanRead
{
get
{
return mFileAccess.HasFlag(FileAccess.Read);
}
}
public override bool CanWrite
{
get
{
return mFileAccess.HasFlag(FileAccess.Write);
}
}
public this()
{
@ -254,22 +317,6 @@ namespace System.IO
mFileAccess = access;
}
public override bool CanRead
{
get
{
return mFileAccess.HasFlag(FileAccess.Read);
}
}
public override bool CanWrite
{
get
{
return mFileAccess.HasFlag(FileAccess.Write);
}
}
public Result<void, FileOpenError> Create(StringView path, FileAccess access = .ReadWrite, FileShare share = .None, int bufferSize = 4096, FileOptions options = .None, SecurityAttributes* secAttrs = null)
{
return Open(path, FileMode.Create, access, share, bufferSize, options, secAttrs);
@ -317,7 +364,7 @@ namespace System.IO
case .Open:
createKind = .OpenExisting;
case .OpenOrCreate:
createKind = .CreateAlways;
createKind = .OpenAlways;
case .Truncate:
createKind = .CreateAlways;
createFlags |= .Truncate;
@ -386,15 +433,20 @@ namespace System.IO
mUnderlyingLength = Platform.BfpFile_GetFileSize(mBfpFile);
}
protected Result<void> SeekUnderlying(int64 offset, Platform.BfpFileSeekKind seekKind = .Absolute)
{
int64 newPos = Platform.BfpFile_Seek(mBfpFile, offset, seekKind);
Result<void> result = ((seekKind == .Absolute) && (newPos != offset)) ? .Err : .Ok;
if (result case .Ok)
mBfpFilePos = newPos;
return result;
}
protected override Result<int> TryReadUnderlying(int64 pos, Span<uint8> data)
{
if (mBfpFilePos != pos)
{
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
if (newPos != pos)
return .Err;
mBfpFilePos = pos;
}
Try!(SeekUnderlying(pos));
Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData))
@ -406,12 +458,8 @@ namespace System.IO
protected override Result<int> TryWriteUnderlying(int64 pos, Span<uint8> data)
{
if (mBfpFilePos != pos)
{
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute);
if (newPos != pos)
return .Err;
mBfpFilePos = pos;
}
Try!(SeekUnderlying(pos));
Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData))
@ -423,12 +471,7 @@ namespace System.IO
public Result<int> TryRead(Span<uint8> data, int timeoutMS)
{
if (mBfpFilePos != mPos)
{
int64 newPos = Platform.BfpFile_Seek(mBfpFile, mPos, .Absolute);
if (newPos != mPos)
return .Err;
mBfpFilePos = mPos;
}
Try!(SeekUnderlying(mPos));
Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
@ -436,6 +479,40 @@ namespace System.IO
return .Err;
return numBytesRead;
}
public override Result<void> SetLength(int64 length)
{
Try!(Flush());
int64 pos = Position;
if (pos != length || pos != mBfpFilePos)
{
Try!(SeekUnderlying(length));
mPos = length;
}
Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok)
{
Try!(SeekUnderlying(pos));
return .Err;
}
mUnderlyingLength = length;
mPos = Math.Min(pos, Length);
if (pos != length)
{
if (pos < length)
Try!(SeekUnderlying(pos));
else
Try!(SeekUnderlying(0, .FromEnd));
}
return .Ok;
}
}
class FileStream : BufferedFileStream

View file

@ -4,7 +4,7 @@ namespace System.IO
{
class MemoryStream : Stream
{
List<uint8> mMemory = new List<uint8>() ~ delete _;
List<uint8> mMemory ~ delete _;
int mPosition = 0;
public override int64 Position
@ -44,6 +44,16 @@ namespace System.IO
}
}
public this()
{
mMemory = new List<uint8>();
}
public this(List<uint8> memory)
{
mMemory = memory;
}
public override Result<int> TryRead(Span<uint8> data)
{
let count = data.Length;

View file

@ -15,7 +15,7 @@ namespace System.IO
public const char8 DirectorySeparatorChar = '/';
#endif //BF_PLATFORM_WINDOWS
// Platform specific alternate directory separator char8acter.
// Platform specific alternate directory separator character.
// This is backslash ('\') on Unix, and slash ('/') on Windows
// and MacOS.
//
@ -25,7 +25,7 @@ namespace System.IO
public const char8 AltDirectorySeparatorChar = '\\';
#endif //BF_PLATFORM_WINDOWS
// Platform specific volume separator char8acter. This is colon (':')
// Platform specific volume separator character. This is colon (':')
// on Windows and MacOS, and slash ('/') on Unix. This is mostly
// useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
//
@ -37,7 +37,7 @@ namespace System.IO
// Make this public sometime.
// The max total path is 260, and the max individual component length is 255.
// For example, D:\<256 char8 file name> isn't legal, even though it's under 260 char8s.
// For example, D:\<256 char file name> isn't legal, even though it's under 260 chars.
protected const int32 MaxPath = 260;
private const int32 MaxDirectoryLength = 255;
@ -297,7 +297,7 @@ namespace System.IO
return .Ok;
}
public static void InternalCombine(String target, params String[] components)
public static void InternalCombine(String target, params StringView[] components)
{
for (var component in components)
{

View file

@ -97,25 +97,32 @@ namespace System.IO
}
}
//Read sized string from stream
public Result<void> ReadStrSized32(int64 size, String output)
/// Read sized string from stream
public Result<void> ReadStrSized32(int size, String output)
{
if (size <= 0)
if (size < 0)
return .Err;
for (int64 i = 0; i < size; i++)
int prevLen = output.Length;
char8* buf = output.PrepareBuffer(size);
switch (TryRead(.((uint8*)buf, size)))
{
Result<char8> char = Read<char8>();
if (char == .Err)
return .Err;
output.Append(char);
case .Ok(let readLen):
if (readLen < size)
output.Length = prevLen + readLen;
return .Ok;
case .Err:
return .Err;
}
return .Ok;
}
//Reads null terminated ASCII string from the stream. Null terminator is read from stream but isn't appended to output string
public Result<void> ReadStrSized32(String output)
{
int size = Try!(Read<int32>());
return ReadStrSized32(size, output);
}
/// Reads null terminated ASCII string from the stream. Null terminator is read from stream but isn't appended to output string
public Result<void> ReadStrC(String output)
{
Result<char8> char0;
@ -197,6 +204,11 @@ namespace System.IO
return .Ok;
}
public virtual Result<void> SetLength(int64 length)
{
return .Err;
}
public void Align(int alignSize)
{
int64 pos = Length;

View file

@ -256,7 +256,7 @@ namespace System.IO
{
char8 ch = tmpCharBuffer[i];
// Note the following common line feed char8s:
// Note the following common line feed chars:
// \n - UNIX \r\n - DOS \r - Mac
if (ch == '\r' || ch == '\n')
{
@ -481,7 +481,7 @@ namespace System.IO
}
while (mCharLen == 0);
//Console.WriteLine("ReadBuffer called. char8s: "+char8Len);
//Console.WriteLine("ReadBuffer called. chars: "+char8Len);
return mCharLen;
}
@ -522,7 +522,7 @@ namespace System.IO
repeat
{
char8 ch = mCharBuffer[i];
// Note the following common line feed char8s:
// Note the following common line feed chars:
// \n - UNIX \r\n - DOS \r - Mac
if (ch == '\r' || ch == '\n')
{

View file

@ -243,6 +243,7 @@ namespace System
}
}
[AlwaysInclude]
public static String[] CreateParamsArray()
{
char8* cmdLine = GetCommandLineArgs();
@ -347,6 +348,7 @@ namespace System
return strVals;
}
[AlwaysInclude]
public static void DeleteStringArray(String[] arr)
{
for (var str in arr)

View file

@ -24,7 +24,9 @@ namespace System
private static float[7] sRoundPower10Single = .(
1E0f, 1E1f, 1E2f, 1E3f, 1E4f, 1E5f, 1E6f);
private static float sMachineEpsilonFloat = GetMachineEpsilonFloat();
public const double PI_d = 3.14159265358979323846;
public const double E_d = 2.7182818284590452354;
public const float PI_f = 3.14159265358979323846f;
@ -48,6 +50,33 @@ namespace System
public static extern float Floor(float f);
public static extern double Floor(double d);
public static bool WithinEpsilon(float a, float b)
{
return Math.Abs(a - b) < sMachineEpsilonFloat;
}
/// <summary>
/// Find the current machine's Epsilon for the float data type.
/// (That is, the largest float, e, where e == 0.0f is true.)
/// </summary>
private static float GetMachineEpsilonFloat()
{
float machineEpsilon = 1.0f;
float comparison;
/* Keep halving the working value of machineEpsilon until we get a number that
* when added to 1.0f will still evaluate as equal to 1.0f.
*/
repeat
{
machineEpsilon *= 0.5f;
comparison = 1.0f + machineEpsilon;
}
while (comparison > 1.0f);
return machineEpsilon;
}
private static float InternalRound(float value, int32 digits, MidpointRounding mode)
{
if (Abs(value) < cSingleRoundLimit)
@ -476,5 +505,125 @@ namespace System
{
return ((val) + (align - 1)) & ~(align - 1);
}
/// Interpolates between two values using a cubic equation.
/// @param name Source value.
/// @param name Source value.
/// @param name Weighting value.
/// @returns Interpolated value.
public static float SmoothStep(float value1, float value2, float amount)
{
/* It is expected that 0 < amount < 1.
* If amount < 0, return value1.
* If amount > 1, return value2.
*/
float result = Clamp(amount, 0f, 1f);
result = Hermite(value1, 0f, value2, 0f, result);
return result;
}
/// Performs a Hermite spline interpolation.
/// @param value1 Source position.
/// @param tangent1 Source tangent.
/// @param value2 Source position.
/// @param tangent2 Source tangent.
/// @param amount Weighting factor.
/// @returns The result of the Hermite spline interpolation.
public static float Hermite(
float value1,
float tangent1,
float value2,
float tangent2,
float amount
) {
/* All transformed to double not to lose precision
* Otherwise, for high numbers of param:amount the result is NaN instead
* of Infinity.
*/
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount;
double result;
double sCubed = s * s * s;
double sSquared = s * s;
if (WithinEpsilon(amount, 0f))
{
result = value1;
}
else if (WithinEpsilon(amount, 1f))
{
result = value2;
}
else
{
result = (
((2 * v1 - 2 * v2 + t2 + t1) * sCubed) +
((3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared) +
(t1 * s) +
v1
);
}
return (float) result;
}
/// Returns the Cartesian coordinate for one axis of a point that is defined by a
/// given triangle and two normalized barycentric (areal) coordinates.
/// <param name="value1">
/// The coordinate on one axis of vertex 1 of the defining triangle.
/// </param>
/// <param name="value2">
/// The coordinate on the same axis of vertex 2 of the defining triangle.
/// </param>
/// <param name="value3">
/// The coordinate on the same axis of vertex 3 of the defining triangle.
/// </param>
/// <param name="amount1">
/// The normalized barycentric (areal) coordinate b2, equal to the weighting factor
/// for vertex 2, the coordinate of which is specified in value2.
/// </param>
/// @param amount2
/// The normalized barycentric (areal) coordinate b3, equal to the weighting factor
/// for vertex 3, the coordinate of which is specified in value3.
/// </param>
/// @returns Cartesian coordinate of the specified point with respect to the axis being used.
public static float Barycentric(
float value1,
float value2,
float value3,
float amount1,
float amount2
) {
return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
}
/// Performs a Catmull-Rom interpolation using the specified positions.
/// @param value1 The first position in the interpolation.
/// @param value2">The second position in the interpolation.
/// @param value3">The third position in the interpolation.
/// @param value4">The fourth position in the interpolation.
/// @param name="amount">Weighting factor.
/// @returns A position that is the result of the Catmull-Rom interpolation.
public static float CatmullRom(
float value1,
float value2,
float value3,
float value4,
float amount
) {
/* Using formula from http://www.mvps.org/directx/articles/catmull/
* Internally using doubles not to lose precision.
*/
double amountSquared = amount * amount;
double amountCubed = amountSquared * amount;
return (float) (
0.5 *
(
((2.0 * value2 + (value3 - value1) * amount) +
((2.0 * value1 - 5.0 * value2 + 4.0 * value3 - value4) * amountSquared) +
(3.0 * value2 - value1 - 3.0 * value3 + value4) * amountCubed)
)
);
}
}
}

View file

@ -5,6 +5,7 @@ namespace System.Net
{
class Socket
{
const uint16 WINSOCK_VERSION = 0x0202;
const int32 WSAENETRESET = 10052;
const int32 WSAECONNABORTED = 10053;
const int32 WSAECONNRESET = 10054;
@ -169,12 +170,22 @@ namespace System.Net
#if BF_PLATFORM_WINDOWS
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
static extern int32 WSAStartup(uint16 versionRequired, WSAData* wsaData);
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
static extern int32 WSACleanup();
[Import("wsock32.lib"), CLink, CallingConvention(.Stdcall)]
static extern int32 WSAGetLastError();
#elif BF_PLATFORM_LINUX
[LinkName("__errno_location")]
static extern int32* _errno();
#elif BF_PLATFORM_MACOS
[LinkName("__error")]
static extern int32* _errno();
#else
[CLink]
static int32 errno;
static int32* _errno() => &errno;
#endif
[CLink, CallingConvention(.Stdcall)]
@ -230,11 +241,22 @@ namespace System.Net
#endif
}
public static void Init()
public static int32 Init(uint16 versionRequired = WINSOCK_VERSION)
{
#if BF_PLATFORM_WINDOWS
WSAData wsaData = default;
WSAStartup(0x202, &wsaData);
return WSAStartup(versionRequired, &wsaData);
#else
return 0;
#endif
}
public static int32 Uninit()
{
#if BF_PLATFORM_WINDOWS
return WSACleanup();
#else
return 0;
#endif
}
@ -243,7 +265,7 @@ namespace System.Net
#if BF_PLATFORM_WINDOWS
return WSAGetLastError();
#else
return errno;
return *_errno();
#endif
}

View file

@ -2675,7 +2675,7 @@ namespace System
return;
int i = sb.Length + (end - start);
sb.Length = i;
sb.PrepareBuffer(i);
var end;
var start;

View file

@ -271,6 +271,7 @@ namespace System
CreateAlways,
CreateIfNotExists,
OpenExisting,
OpenAlways,
};
public enum BfpFileCreateFlags : int32
@ -337,6 +338,8 @@ namespace System
[CallingConvention(.Stdcall), CLink]
public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern int BfpFile_GetSystemHandle(BfpFile* file);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpFile_Release(BfpFile* file);
[CallingConvention(.Stdcall), CLink]
public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
@ -349,7 +352,7 @@ namespace System
[CallingConvention(.Stdcall), CLink]
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpFile_Truncate(BfpFile* file);
public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
[CallingConvention(.Stdcall), CLink]
@ -410,7 +413,8 @@ namespace System
AppData_LocalLow,
AppData_Roaming,
Programs,
Programs_Common
Programs_Common,
Documents
}
public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func)

View file

@ -0,0 +1,468 @@
using System.Collections;
using System.Diagnostics;
namespace System
{
interface RangeExpression
{
}
enum Index
{
case FromFront(int offset);
case FromEnd(int offset);
public override void ToString(String strBuffer)
{
switch (this)
{
case .FromFront(let offset):
offset.ToString(strBuffer);
case .FromEnd(let offset):
strBuffer.Append('^');
offset.ToString(strBuffer);
}
}
}
struct Range : RangeExpression, IEnumerable<int>
{
protected int mStart;
protected int mEnd;
public this()
{
mStart = 0;
mEnd = 0;
}
[Inline]
public this(int start, int end)
{
Debug.Assert(end >= start);
mStart = start;
mEnd = end;
}
public int Length
{
[Inline]
get
{
return mEnd - mStart;
}
[Inline]
set mut
{
mEnd = mStart + value;
}
}
public int Start
{
[Inline]
get
{
return mStart;
}
[Inline]
set mut
{
mStart = value;
}
}
public int End
{
[Inline]
get
{
return mEnd;
}
set mut
{
mEnd = value;
}
}
public bool IsEmpty
{
[Inline]
get
{
return mEnd == mStart;
}
}
public ReverseEnumerator Reversed
{
[Inline]
get
{
return ReverseEnumerator(mEnd - 1, mStart);
}
}
public bool Contains(int idx)
{
return (idx >= mStart) && (idx < mEnd);
}
public bool Contains(Range val)
{
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd);
}
public bool Contains(ClosedRange val)
{
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd - 1);
}
public void Clear() mut
{
mStart = 0;
mEnd = 0;
}
public static operator IndexRange(Range list)
{
return .(.FromFront(list.mStart), .FromFront(list.mEnd), false);
}
[Inline]
public Enumerator GetEnumerator()
{
return Enumerator(this);
}
public override void ToString(String strBuffer)
{
strBuffer.AppendF($"{mStart}..<{mEnd}");
}
public struct Enumerator : IEnumerator<int>
{
private int mEnd;
private int mIndex;
[Inline]
public this(Range range)
{
mIndex = range.mStart - 1;
mEnd = range.mEnd;
}
public void Dispose()
{
}
public ref int Index
{
get mut
{
return ref mIndex;
}
}
public int End => mEnd;
[Inline]
public Result<int> GetNext() mut
{
if (mIndex + 1 >= mEnd)
return .Err;
return ++mIndex;
}
}
public struct ReverseEnumerator : IEnumerator<int>
{
private int mEnd;
private int mIndex;
[Inline]
public this(int start, int end)
{
mIndex = start + 1;
mEnd = end;
}
public void Dispose()
{
}
public ref int Index
{
get mut
{
return ref mIndex;
}
}
public int End => mEnd;
[Inline]
public Result<int> GetNext() mut
{
if (mIndex <= mEnd)
return .Err;
return --mIndex;
}
}
}
struct IndexRange : RangeExpression
{
protected Index mStart;
protected Index mEnd;
protected bool mIsClosed;
public this()
{
this = default;
}
[Inline]
public this(Index start, Index end, bool isClosed=true)
{
mStart = start;
mEnd = end;
mIsClosed = isClosed;
}
[Inline]
public this(int start, Index end, bool isClosed=true)
{
mStart = .FromFront(start);
mEnd = end;
mIsClosed = isClosed;
}
[Inline]
public this(Index start, int end, bool isClosed=true)
{
mStart = start;
mEnd = .FromFront(end);
mIsClosed = isClosed;
}
[Inline]
public this(int start, int end, bool isClosed=true)
{
mStart = .FromFront(start);
mEnd = .FromFront(end);
mIsClosed = isClosed;
}
public Index Start
{
[Inline]
get
{
return mStart;
}
[Inline]
set mut
{
mStart = value;
}
}
public Index End
{
[Inline]
get
{
return mEnd;
}
set mut
{
mEnd = value;
}
}
public bool IsClosed
{
[Inline]
get
{
return mIsClosed;
}
set mut
{
mIsClosed = value;
}
}
public override void ToString(String strBuffer)
{
mStart.ToString(strBuffer);
if (mIsClosed)
strBuffer.Append("...");
else
strBuffer.Append("..<");
mEnd.ToString(strBuffer);
}
}
struct ClosedRange : RangeExpression, IEnumerable<int>
{
protected int mStart;
protected int mEnd;
public this()
{
mStart = 0;
mEnd = 0;
}
[Inline]
public this(int start, int end)
{
Debug.Assert(end >= start);
mStart = start;
mEnd = end;
}
public int Length
{
[Inline]
get
{
return mEnd - mStart;
}
[Inline]
set mut
{
mEnd = mStart + value;
}
}
public int Start
{
[Inline]
get
{
return mStart;
}
[Inline]
set mut
{
mStart = value;
}
}
public int End
{
[Inline]
get
{
return mEnd;
}
set mut
{
mEnd = value;
}
}
public bool IsEmpty
{
[Inline]
get
{
return mEnd == mStart;
}
}
public Range.ReverseEnumerator Reversed
{
[Inline]
get
{
return Range.ReverseEnumerator(mEnd, mStart);
}
}
public bool Contains(int idx)
{
return (idx >= mStart) && (idx <= mEnd);
}
public bool Contains(Range val)
{
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd - 1 <= mEnd);
}
public bool Contains(ClosedRange val)
{
return (val.[Friend]mStart >= mStart) && (val.[Friend]mEnd <= mEnd);
}
public void Clear() mut
{
mStart = 0;
mEnd = 0;
}
public static operator IndexRange(ClosedRange list)
{
return .(.FromFront(list.mStart), .FromFront(list.mEnd), true);
}
[Inline]
public Enumerator GetEnumerator()
{
return Enumerator(this);
}
public override void ToString(String strBuffer)
{
strBuffer.AppendF($"{mStart}...{mEnd}");
}
public struct Enumerator : IEnumerator<int>
{
private int mEnd;
private int mIndex;
[Inline]
public this(ClosedRange range)
{
mIndex = range.mStart - 1;
mEnd = range.mEnd;
}
public void Dispose()
{
}
public ref int Index
{
get mut
{
return ref mIndex;
}
}
public int End => mEnd;
[Inline]
public Result<int> GetNext() mut
{
if (mIndex >= mEnd)
return .Err;
return ++mIndex;
}
}
}
}

View file

@ -92,6 +92,9 @@ namespace System.Reflection
.Double:
let attrData = Decode!<int64>(data);
args[argIdx] = scope:AttrBlock box attrData;
case (TypeCode)51: //BfConstType_TypeOf
let argTypeId = Decode!<int32>(data);
args[argIdx] = Type.[Friend]GetType((.)argTypeId);
case (TypeCode)255:
let stringId = Decode!<int32>(data);
String str = String.[Friend]sIdStringLiterals[stringId];

View file

@ -29,8 +29,8 @@ namespace System.Reflection
get
{
if (Compiler.IsComptime)
Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
return "";
return Type.[Friend]Comptime_Method_GetName(mNativeMethodInstance);
return "?";
}
}
public int ParamCount

View file

@ -20,53 +20,13 @@ namespace System.Reflection
mFieldData = fieldData;
}
public int32 MemberOffset
{
get
{
return (int32)mFieldData.mData;
}
}
public Type FieldType
{
get
{
return Type.[Friend]GetType(mFieldData.mFieldTypeId);
}
}
public bool IsConst
{
get
{
return mFieldData.mFlags.HasFlag(.Const);
}
}
public bool IsStatic
{
get
{
return mFieldData.mFlags.HasFlag(.Static);
}
}
public bool IsInstanceField
{
get
{
return !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
}
}
public StringView Name
{
get
{
return mFieldData.mName;
}
}
public TypeInstance DeclaringType => mTypeInstance;
public int32 MemberOffset => (int32)mFieldData.mData;
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
public bool IsInstanceField => !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
public StringView Name => mFieldData.mName;
public Result<void, Error> SetValue(Object obj, Object value)
{
@ -525,7 +485,15 @@ namespace System.Reflection
{
mIdx++;
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
return false;
{
if (mBindingFlags.HasFlag(.DeclaredOnly))
return false;
if (mTypeInstance.[Friend]mBaseType == 0)
return false;
mTypeInstance = Type.[Friend]GetType(mTypeInstance.[Friend]mBaseType) as TypeInstance;
mIdx = -1;
continue;
}
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));

View file

@ -18,6 +18,7 @@ namespace System.Reflection
mMethodData = methodData;
}
public TypeInstance DeclaringType => mTypeInstance;
public bool IsInitialized => mMethodData != null;
public StringView Name => mMethodData.[Friend]mName;
public int ParamCount => mMethodData.[Friend]mParamCount;
@ -37,11 +38,22 @@ namespace System.Reflection
return mMethodData.mParamData[paramIdx].mName;
}
public Result<T> GetParamCustomAttribute<T>(int paramIdx) where T : Attribute
{
Debug.Assert((uint)paramIdx < (uint)mMethodData.mParamCount);
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mParamData[paramIdx].mCustomAttributesIdx);
}
public Result<T> GetCustomAttribute<T>() where T : Attribute
{
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mCustomAttributesIdx);
}
public Result<T> GetReturnCustomAttribute<T>() where T : Attribute
{
return mTypeInstance.[Friend]GetCustomAttribute<T>(mMethodData.mReturnCustomAttributesIdx);
}
public enum CallError
{
case None;
@ -777,7 +789,15 @@ namespace System.Reflection
{
mIdx++;
if (mIdx == mTypeInstance.[Friend]mMethodDataCount)
return false;
{
if (mBindingFlags.HasFlag(.DeclaredOnly))
return false;
if (mTypeInstance.[Friend]mBaseType == 0)
return false;
mTypeInstance = Type.[Friend]GetType(mTypeInstance.[Friend]mBaseType) as TypeInstance;
mIdx = -1;
continue;
}
var methodData = &mTypeInstance.[Friend]mMethodDataPtr[mIdx];
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (methodData.mFlags.HasFlag(.Static)));
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!methodData.mFlags.HasFlag(.Static)));

View file

@ -32,7 +32,7 @@ namespace System
if (matched.[Friend]mMethodData != null)
return .Err(.MultipleResults);
else
matched = methodInfo;
matched = methodInfo;
}
}
@ -41,6 +41,26 @@ namespace System
return .Ok(matched);
}
[Comptime]
public virtual Result<ComptimeMethodInfo, MethodError> GetMethod(StringView methodName, BindingFlags bindingFlags = cDefaultLookup)
{
ComptimeMethodInfo matched = default;
for (let methodInfo in ComptimeMethodInfo.Enumerator(this as TypeInstance, bindingFlags))
{
if (methodInfo.Name == methodName)
{
if (matched.mNativeMethodInstance != 0)
return .Err(.MultipleResults);
else
matched = methodInfo;
}
}
if (matched.mNativeMethodInstance == 0)
return .Err(.NoResults);
return .Ok(matched);
}
public virtual Result<MethodInfo, MethodError> GetMethod(int methodIdx)
{
return .Err(.NoResults);
@ -123,7 +143,10 @@ namespace System.Reflection
let objType = typeof(Object) as TypeInstance;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, mInstSize, mInstAlign, 1);
int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, mInstSize, mInstAlign, stackCount);
#else
void* mem = new [Align(16)] uint8[mInstSize]* (?);
obj = Internal.UnsafeCastToObject(mem);

View file

@ -20,22 +20,26 @@ namespace System
public T Value
{
[Inline]
get
{
return Unwrap();
}
}
[Inline]
public static implicit operator Result<T>(T value)
{
return .Ok(value);
}
[Inline]
public static implicit operator T(Result<T> result)
{
return result.Unwrap();
}
[Inline]
public void IgnoreError()
{
}

View file

@ -5,8 +5,8 @@ using System.Threading;
namespace System
{
[StaticInitPriority(100)]
class Runtime
[StaticInitPriority(101)]
static class Runtime
{
const int32 cVersion = 8;
@ -102,7 +102,7 @@ namespace System
function void* (int size) mAlloc;
function void (void* ptr) mFree;
function void (Object obj) mObject_Delete;
function void (Object obj, String str) mObject_ToString;
void* mUnused0;
function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
@ -141,13 +141,6 @@ namespace System
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
@ -241,7 +234,6 @@ namespace System
mAlloc = => Alloc;
mFree = => Free;
mObject_Delete = => Object_Delete;
mObject_ToString = => Object_ToString;
mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers;
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;

View file

@ -1,5 +1,35 @@
namespace System.Security.Cryptography
{
struct HashEncode
{
// Only 63 chars - skip zero
const char8[?] cHash64bToChar = .( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_' );
public static void HashEncode64(uint64 val, String outStr)
{
var val;
if ((int64)val < 0)
{
uint64 flippedNum = (uint64)-(int64)val;
// Only flip if the encoded result would actually be shorter
if (flippedNum <= 0x00FFFFFFFFFFFFFFL)
{
val = flippedNum;
outStr.Append('_');
}
}
for (int i = 0; i < 10; i++)
{
int charIdx = (int)((val >> (i * 6)) & 0x3F) - 1;
if (charIdx != -1)
outStr.Append(cHash64bToChar[charIdx]);
}
}
}
struct MD5Hash
{
public uint8[16] mHash;
@ -50,6 +80,14 @@ namespace System.Security.Cryptography
val.ToString(strBuffer, "X2", null);
}
}
public void Encode(String outStr)
{
#unwarn
HashEncode.HashEncode64(((uint64*)&mHash)[0], outStr);
#unwarn
HashEncode.HashEncode64(((uint64*)&mHash)[1], outStr);
}
}
class MD5

View file

@ -16,18 +16,35 @@ namespace System
public this(T[] array)
{
if (array == null)
{
this = default;
return;
}
mPtr = &array.[Friend]GetRef(0);
mLength = array.[Friend]mLength;
}
public this(T[] array, int index)
{
if (array == null)
{
Debug.Assert(index == 0);
this = default;
return;
}
mPtr = &array[index];
mLength = array.[Friend]mLength - index;
}
public this(T[] array, int index, int length)
{
if (array == null)
{
Debug.Assert(index == 0 && length == 0);
this = default;
return;
}
if (length == 0)
mPtr = null;
else
@ -110,13 +127,95 @@ namespace System
public ref T this[int index]
{
[Inline]
[Checked]
get
{
Runtime.Assert((uint)index < (uint)mLength);
return ref mPtr[index];
}
[Unchecked, Inline]
get
{
return ref mPtr[index];
}
}
public ref T this[Index index]
{
[Checked]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
Runtime.Assert((uint)idx < (uint)mLength);
return ref mPtr[idx];
}
[Unchecked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
return ref mPtr[idx];
}
}
public Span<T> this[IndexRange range]
{
#if !DEBUG
[Inline]
#endif
get
{
T* start;
switch (range.[Friend]mStart)
{
case .FromFront(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
start = mPtr + offset;
case .FromEnd(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
start = mPtr + mLength - offset;
}
T* end;
if (range.[Friend]mIsClosed)
{
switch (range.[Friend]mEnd)
{
case .FromFront(let offset):
Debug.Assert((uint)offset < (uint)mLength);
end = mPtr + offset + 1;
case .FromEnd(let offset):
Debug.Assert((uint)(offset - 1) <= (uint)mLength);
end = mPtr + mLength - offset + 1;
}
}
else
{
switch (range.[Friend]mEnd)
{
case .FromFront(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
end = mPtr + offset;
case .FromEnd(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
end = mPtr + mLength - offset;
}
}
return .(start, end - start);
}
}
public Span<T> Slice(int index)
{
Debug.Assert((uint)index <= (uint)mLength);
@ -200,6 +299,8 @@ namespace System
return Enumerator(this);
}
public ReverseEnumerator Reversed => ReverseEnumerator(this);
public override void ToString(String strBuffer)
{
strBuffer.Append("(");
@ -281,6 +382,95 @@ namespace System
}
public Result<T> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
public Result<T*> GetNextRef() mut
{
if (!MoveNext())
return .Err;
return &CurrentRef;
}
}
public struct ReverseEnumerator : IEnumerator<T>, IRefEnumerator<T*>
{
private Span<T> mList;
private int mIndex;
private T* mCurrent;
public this(Span<T> list)
{
mList = list;
mIndex = list.mLength - 1;
mCurrent = null;
}
public void Dispose()
{
}
public bool MoveNext() mut
{
if (mIndex >= 0)
{
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())

View file

@ -329,7 +329,7 @@ namespace System
set
{
Debug.Assert((uint)mLength <= (uint)value);
Debug.Assert((uint)value <= (uint)mLength);
mLength = (int_strsize)value;
}
}
@ -1010,17 +1010,95 @@ namespace System
public ref char8 this[int index]
{
[Checked]
get
{
Debug.Assert((uint)index < (uint)mLength);
return ref Ptr[index];
}
[Unchecked, Inline]
get
{
return ref Ptr[index];
}
[Checked]
set
{
Debug.Assert((uint)index < (uint)mLength);
Ptr[index] = value;
}
[Unchecked, Inline]
set
{
Ptr[index] = value;
}
}
public ref char8 this[Index index]
{
[Checked]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
Debug.Assert((uint)idx < (uint)mLength);
return ref Ptr[idx];
}
[Unchecked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
return ref Ptr[idx];
}
[Checked]
set
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
Debug.Assert((uint)idx < (uint)mLength);
Ptr[idx] = value;
}
[Unchecked, Inline]
set
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
Ptr[idx] = value;
}
}
public StringView this[IndexRange range]
{
#if !DEBUG
[Inline]
#endif
get
{
return StringView(Ptr, Length)[range];
}
}
public void Concat(params Object[] objects)
@ -1351,12 +1429,7 @@ namespace System
return -1;
}
public bool Contains(String str)
{
return IndexOf(str) != -1;
}
public bool Contains(String str, bool ignoreCase)
public bool Contains(StringView str, bool ignoreCase = false)
{
return IndexOf(str, ignoreCase) != -1;
}
@ -1542,7 +1615,7 @@ namespace System
mLength = newLength;
}
public void Insert(int_strsize idx, char8 c)
public void Insert(int idx, char8 c)
{
Contract.Requires(idx >= 0);
@ -1557,7 +1630,7 @@ namespace System
mLength = newLength;
}
public void Insert(int_strsize idx, char8 c, int count)
public void Insert(int idx, char8 c, int count)
{
Contract.Requires(idx >= 0);
@ -1576,7 +1649,7 @@ namespace System
mLength = newLength;
}
public void Insert(int_strsize idx, char32 c)
public void Insert(int idx, char32 c)
{
Contract.Requires(idx >= 0);
@ -1625,7 +1698,7 @@ namespace System
}
}
public void Insert(int_strsize idx, char32 c, int count)
public void Insert(int idx, char32 c, int count)
{
Contract.Requires(idx >= 0);
@ -1700,7 +1773,7 @@ namespace System
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both char8s - notice that we need just one compare per char8
// uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
@ -1708,7 +1781,7 @@ namespace System
if (charA != charB)
return false;
// Next char8
// Next char
curA++;curB++;
curLength--;
}
@ -1733,7 +1806,7 @@ namespace System
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both char8s - notice that we need just one compare per char8
// uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
@ -1741,7 +1814,7 @@ namespace System
if (charA != charB)
return charA - charB;
// Next char8
// Next char
a++;b++;
length--;
}
@ -1761,7 +1834,7 @@ namespace System
int_strsize charB = (int_strsize)*b;
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both char8s - notice that we need just one compare per char8
// uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
@ -1769,7 +1842,7 @@ namespace System
if (charA != charB)
return charA - charB;
// Next char8
// Next char
a++;b++;
length--;
}
@ -2130,6 +2203,82 @@ namespace System
TrimEnd();
}
public void TrimEnd(char32 trimChar)
{
let ptr = Ptr;
for (int i = mLength - 1; i >= 0; i--)
{
char8 c = ptr[i];
if (c >= (char8)0x80)
{
var (c32, idx, len) = GetChar32WithBacktrack(i);
if (c32 != trimChar)
{
if (i < mLength - 1)
RemoveToEnd(i + 1);
return;
}
i = idx;
}
else if ((char32)c != trimChar)
{
if (i < mLength - 1)
RemoveToEnd(i + 1);
return;
}
}
Clear();
}
public void TrimEnd(char8 trimChar)
{
TrimEnd((char32)trimChar);
}
public void TrimStart(char32 trimChar)
{
let ptr = Ptr;
for (int i = 0; i < mLength; i++)
{
char8 c = ptr[i];
if (c >= (char8)0x80)
{
var (c32, len) = GetChar32(i);
if (c32 != trimChar)
{
if (i > 0)
Remove(0, i);
return;
}
i += len - 1;
}
else if ((char32)c != trimChar)
{
if (i > 0)
Remove(0, i);
return;
}
}
Clear();
}
public void TrimStart(char8 trimChar)
{
TrimStart((char32)trimChar);
}
public void Trim(char32 trimChar)
{
TrimStart(trimChar);
TrimEnd(trimChar);
}
public void Trim(char8 trimChar)
{
TrimStart((.)trimChar);
TrimEnd((.)trimChar);
}
public void Join(StringView sep, IEnumerator<String> enumerable)
{
bool isFirst = true;
@ -2271,6 +2420,7 @@ namespace System
public RawEnumerator RawChars
{
[Inline]
get
{
return RawEnumerator(Ptr, 0, mLength);
@ -2279,6 +2429,7 @@ namespace System
public UTF8Enumerator DecodedChars
{
[Inline]
get
{
return UTF8Enumerator(Ptr, 0, mLength);
@ -2440,6 +2591,7 @@ namespace System
int_strsize mIdx;
int_strsize mLength;
[Inline]
public this(char8* ptr, int idx, int length)
{
mPtr = ptr;
@ -2449,11 +2601,13 @@ namespace System
public char8 Current
{
[Inline]
get
{
return mPtr[mIdx];
}
[Inline]
set
{
mPtr[mIdx] = value;
@ -2462,6 +2616,7 @@ namespace System
public ref char8 CurrentRef
{
[Inline]
get
{
return ref mPtr[mIdx];
@ -2470,6 +2625,7 @@ namespace System
public int Index
{
[Inline]
get
{
return mIdx;
@ -2478,42 +2634,29 @@ namespace System
public int Length
{
[Inline]
get
{
return mLength;
}
}
public void Dispose()
{
}
public void Reset()
{
}
public bool MoveNext() mut
[Inline]
public Result<char8> GetNext() mut
{
++mIdx;
if (mIdx >= mLength)
return false;
return true;
}
public Result<char8> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
return mPtr[mIdx];
}
[Inline]
public Result<char8*> GetNextRef() mut
{
if (!MoveNext())
++mIdx;
if (mIdx >= mLength)
return .Err;
return &CurrentRef;
return &mPtr[mIdx];
}
}
@ -2669,6 +2812,14 @@ namespace System
return mMatchPos;
}
}
public int32 MatchIndex
{
get
{
return mCurCount - 1;
}
}
public bool HasMore
{
@ -2821,6 +2972,97 @@ namespace System
mLength = length;
}
public ref char8 this[int index]
{
[Checked]
get
{
Runtime.Assert((uint)index < (uint)mLength);
return ref mPtr[index];
}
[Unchecked, Inline]
get
{
return ref mPtr[index];
}
}
public ref char8 this[Index index]
{
[Checked]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
Runtime.Assert((uint)idx < (uint)mLength);
return ref mPtr[idx];
}
[Unchecked, Inline]
get
{
int idx;
switch (index)
{
case .FromFront(let offset): idx = offset;
case .FromEnd(let offset): idx = mLength - offset;
}
return ref mPtr[idx];
}
}
public StringView this[IndexRange range]
{
#if !DEBUG
[Inline]
#endif
get
{
char8* start;
switch (range.[Friend]mStart)
{
case .FromFront(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
start = mPtr + offset;
case .FromEnd(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
start = mPtr + mLength - offset;
}
char8* end;
if (range.[Friend]mIsClosed)
{
switch (range.[Friend]mEnd)
{
case .FromFront(let offset):
Debug.Assert((uint)offset < (uint)mLength);
end = mPtr + offset + 1;
case .FromEnd(let offset):
Debug.Assert((uint)(offset - 1) <= (uint)mLength);
end = mPtr + mLength - offset + 1;
}
}
else
{
switch (range.[Friend]mEnd)
{
case .FromFront(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
end = mPtr + offset;
case .FromEnd(let offset):
Debug.Assert((uint)offset <= (uint)mLength);
end = mPtr + mLength - offset;
}
}
return .(start, end - start);
}
}
public String.RawEnumerator RawChars
{
get
@ -2914,6 +3156,13 @@ namespace System
return String.[Friend]CompareOrdinalHelper(val1.mPtr, val1.mLength, val2.mPtr, val2.mLength);
}
public int CompareTo(StringView strB, bool ignoreCase = false)
{
if (ignoreCase)
return String.[Friend]CompareOrdinalIgnoreCaseHelper(Ptr, Length, strB.Ptr, strB.Length);
return String.[Friend]CompareOrdinalHelper(Ptr, Length, strB.Ptr, strB.Length);
}
public bool Equals(StringView str)
{
if (mLength != str.[Friend]mLength)
@ -3037,9 +3286,9 @@ namespace System
return false;
}
public bool Contains(StringView stringView)
public bool Contains(StringView stringView, bool ignoreCase = false)
{
return IndexOf(stringView) != -1;
return IndexOf(stringView, ignoreCase) != -1;
}
public bool StartsWith(StringView b, StringComparison comparisonType = StringComparison.Ordinal)
@ -3130,6 +3379,92 @@ namespace System
TrimEnd();
}
public void TrimEnd(char32 trimChar) mut
{
let ptr = Ptr;
for (int i = mLength - 1; i >= 0; i--)
{
char8 c = ptr[i];
if (c >= (char8)0x80)
{
var (c32, idx, len) = GetChar32WithBacktrack(i);
if (c32 != trimChar)
{
if (i < mLength - 1)
{
mLength = i + 1;
}
return;
}
i = idx;
}
else if (c != (char32)trimChar)
{
if (i < mLength - 1)
{
mLength = i + 1;
}
return;
}
}
Clear();
}
public void TrimEnd(char8 trimChar) mut
{
TrimEnd((char32)trimChar);
}
public void TrimStart(char32 trimChar) mut
{
let ptr = Ptr;
for (int i = 0; i < mLength; i++)
{
char8 c = ptr[i];
if (c >= (char8)0x80)
{
var (c32, len) = GetChar32(i);
if (c32 != trimChar)
{
if (i > 0)
{
mPtr += i;
mLength -= i;
}
return;
}
i += len - 1;
}
else if (c != (char32)trimChar)
{
if (i > 0)
{
mPtr += i;
mLength -= i;
}
return;
}
}
Clear();
}
public void TrimStart(char8 trimChar) mut
{
TrimStart((char32)trimChar);
}
public void Trim(char32 trimChar) mut
{
TrimStart(trimChar);
TrimEnd(trimChar);
}
public void Trim(char8 trimChar) mut
{
TrimStart((.)trimChar);
TrimEnd((.)trimChar);
}
public bool StartsWith(char8 c)
{
if (mLength == 0)
@ -3137,6 +3472,15 @@ namespace System
return Ptr[0] == c;
}
public bool StartsWith(char32 c)
{
if (c < '\x80')
return StartsWith((char8)c);
if (mLength == 0)
return false;
return UTF8.Decode(Ptr, mLength).c == c;
}
public bool EndsWith(char8 c)
{
if (mLength == 0)
@ -3144,6 +3488,19 @@ namespace System
return Ptr[mLength - 1] == c;
}
public bool EndsWith(char32 c)
{
if (c < '\x80')
return EndsWith((char8)c);
if (mLength == 0)
return false;
char8* ptr = Ptr;
int idx = mLength - 1;
while ((idx > 0) && ((uint8)ptr[idx] & 0xC0 == 0x80))
idx--;
return UTF8.Decode(ptr + idx, mLength - idx).c == c;
}
public void QuoteString(String outString)
{
String.QuoteString(Ptr, Length, outString);
@ -3226,6 +3583,34 @@ namespace System
return StringSplitEnumerator(Ptr, Length, separators, count, options);
}
public String Intern()
{
using (String.[Friend]sMonitor.Enter())
{
bool needsLiteralPass = String.[Friend]sInterns.Count == 0;
String* internalLinkPtr = *((String**)(String.[Friend]sStringLiterals));
if (internalLinkPtr != String.[Friend]sPrevInternLinkPtr)
{
String.[Friend]sPrevInternLinkPtr = internalLinkPtr;
needsLiteralPass = true;
}
if (needsLiteralPass)
String.[Friend]CheckLiterals(String.[Friend]sStringLiterals);
String* entryPtr;
if (String.[Friend]sInterns.TryAddAlt(this, out entryPtr))
{
String result = new String(mLength + 1);
result.Append(this);
result.EnsureNullTerminator();
*entryPtr = result;
String.[Friend]sOwnedInterns.Add(result);
return result;
}
return *entryPtr;
}
}
public static operator StringView (String str)
{
StringView sv;

View file

@ -227,6 +227,26 @@ static
}
}
public static mixin DeleteContainerAndDisposeItems(var container)
{
if (container != null)
{
for (var value in container)
value.Dispose();
delete container;
}
}
public static mixin ClearAndDisposeItems(var container)
{
if (container != null)
{
for (var value in container)
value.Dispose();
container.Clear();
}
}
public static mixin DeleteAndNullify(var val)
{
delete val;

View file

@ -1,6 +1,7 @@
using System.Diagnostics;
namespace System.Text
{
[StaticInitPriority(100)]
abstract class Encoding
{
public enum DecodeError

View file

@ -1,7 +1,7 @@
using System.Diagnostics;
namespace System.Text
{
public class UTF16
public static class UTF16
{
public enum EncodeError
{
@ -140,10 +140,10 @@ namespace System.Text
public static int GetMaxEncodedLen(int utf8Len)
{
// Consider all incoming char8s are < \u80, each incoming char88 equals one outgoing char816 (utfLen * 1)
// For char8s from \u80 to \u7FF, then two incoming char88 equals one outgoing char816 (utfLen * 0.5)
// For char8s from \u800 to \u7FFF, then three incoming char88 equals one or two char816s (utfLen * 0.33) to (utfLen * 0.67)
// For char8s from \u1000 to \u10FFFF, then four incoming char88 equals two outgoing char816s (utfLen * 0.5)
// Consider all incoming chars are < \u80, each incoming char8 equals one outgoing char16 (utfLen * 1)
// For chars from \u80 to \u7FF, then two incoming char8 equals one outgoing char16 (utfLen * 0.5)
// For chars from \u800 to \u7FFF, then three incoming char8 equals one or two char16s (utfLen * 0.33) to (utfLen * 0.67)
// For chars from \u1000 to \u10FFFF, then four incoming char8 equals two outgoing char16s (utfLen * 0.5)
return utf8Len;
}
@ -211,7 +211,7 @@ namespace System.Text
if (c <= '\u{FFFF}')
{
#if BF_UTF_PEDANTIC
// Illegal UTF16 char8?
// Illegal UTF16 char?
Debug.Assert((c <= '\u{D7FF}') || (c >= '\u{E000}'));
#endif
EncodeChar((char16)c);

View file

@ -1,7 +1,7 @@
using System.Diagnostics;
namespace System.Text
{
class UTF8
static class UTF8
{
public const int8[256] sTrailingBytesForUTF8 =
.(

View file

@ -8,10 +8,11 @@ namespace System.Threading
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(Object obj);
[StaticInitPriority(100)]
public sealed class Thread
{
private int mInternalThread;
private int32 mPriority;
private ThreadPriority mPriority = .Normal;
public int32 mMaxStackSize;
private String mName ~ delete _;
private Delegate mDelegate;
@ -21,7 +22,7 @@ namespace System.Threading
bool mAutoDelete;
public static Thread sMainThread = new Thread() ~ delete _;
[StaticInitPriority(101)]
[StaticInitPriority(102)]
struct RuntimeThreadInit
{
static Object Thread_Alloc()
@ -67,6 +68,8 @@ namespace System.Threading
if (thread.mName != null)
thread.InformThreadNameChange(thread.mName);
if (thread.mPriority != .Normal)
thread.SetPriorityNative((.)thread.mPriority);
int32 stackStart = 0;
thread.SetStackStart((void*)&stackStart);
@ -219,8 +222,18 @@ namespace System.Threading
public ThreadPriority Priority
{
get { return (ThreadPriority)GetPriorityNative(); }
set { SetPriorityNative((int32)value); }
get
{
if (mInternalThread != 0)
return (ThreadPriority)GetPriorityNative();
return mPriority;
}
set
{
mPriority = value;
if (mInternalThread != 0)
SetPriorityNative((int32)value);
}
}
[CallingConvention(.Cdecl)]
private extern int32 GetPriorityNative();

View file

@ -253,7 +253,10 @@ namespace System {
if (rule != null)
rule = rule.Clone();
oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule);
m_oneYearLocalFromUtc = oneYearLocFromUtc;
if (Interlocked.CompareExchange(ref m_oneYearLocalFromUtc, null, oneYearLocFromUtc) != null) {
delete oneYearLocFromUtc;
oneYearLocFromUtc = m_oneYearLocalFromUtc;
}
}
return oneYearLocFromUtc;
}

View file

@ -20,13 +20,14 @@ namespace System
protected const BindingFlags cDefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
protected int32 mSize;
protected TypeId mTypeId;
protected TypeId mBoxedType;
protected TypeFlags mTypeFlags;
protected int32 mMemberDataOffset;
protected TypeCode mTypeCode;
protected uint8 mAlign;
protected int32 mSize;
protected TypeId mTypeId;
protected TypeId mBoxedType;
protected TypeFlags mTypeFlags;
protected int32 mMemberDataOffset;
protected TypeCode mTypeCode;
protected uint8 mAlign;
protected uint8 mAllocStackCountOverride;
public static TypeId TypeIdEnd
{
@ -683,13 +684,7 @@ namespace System
namespace System.Reflection
{
public struct TypeId : int32
{
public Type ToType()
{
return Type.[Friend]sTypes[(int32)this];
}
}
public struct TypeId : int32 {}
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
public class TypeInstance : Type
@ -724,6 +719,7 @@ namespace System.Reflection
public int32 mMethodIdx;
public int32 mVirtualIdx;
public int32 mCustomAttributesIdx;
public int32 mReturnCustomAttributesIdx;
}
public enum ParamFlags : int16
@ -740,6 +736,7 @@ namespace System.Reflection
public TypeId mType;
public ParamFlags mParamFlags;
public int32 mDefaultIdx;
public int32 mCustomAttributesIdx;
}
public struct InterfaceData
@ -1137,7 +1134,7 @@ namespace System.Reflection
public Type GetGenericArg(int argIdx)
{
return mResolvedTypeRefs[argIdx].ToType();
return Type.GetType(mResolvedTypeRefs[argIdx]);
}
public override void GetFullName(String strBuffer)
@ -1191,7 +1188,10 @@ namespace System.Reflection
let genericType = GetGenericArg(0);
let arraySize = [Friend]mInstSize - genericType.Size + genericType.Stride * count;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, 1);
int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount);
#else
void* mem = new [Align(16)] uint8[arraySize]* (?);
obj = Internal.UnsafeCastToObject(mem);

View file

@ -48,8 +48,8 @@ namespace System
public struct VTable
{
public function HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
public function HResult(COM_IUnknown* self) AddRef;
public function HResult(COM_IUnknown* self) Release;
public function uint32(COM_IUnknown* self) AddRef;
public function uint32(COM_IUnknown* self) Release;
}
public enum HResult : int32