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

Moving corlib files out of "System" directory into root

This commit is contained in:
Brian Fiete 2019-09-19 05:46:35 -07:00
parent 4cd58262e4
commit 7dbfd15292
179 changed files with 3 additions and 0 deletions

View file

@ -0,0 +1,118 @@
// 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.Diagnostics;
namespace System.Collections.Generic
{
public class BinaryHeap<T>
{
protected T[] mData ~ delete _;
protected int32 mSize = 0;
protected Comparison<T> mComparison ~ delete _;
public this(Comparison<T> comparison)
{
Constructor(4, comparison);
}
public this(int32 capacity, Comparison<T> comparison)
{
Constructor(capacity, comparison);
}
private void Constructor(int32 capacity, Comparison<T> comparison)
{
mData = new T[capacity];
mComparison = comparison;
}
public int32 Size
{
get
{
return mSize;
}
}
/// Add an item to the heap
public void Add(T item)
{
if (mSize == mData.Count)
Resize();
mData[mSize] = item;
HeapifyUp(mSize);
mSize++;
}
/// Get the item of the root
public T Peek()
{
return mData[0];
}
/// Extract the item of the root
public T Pop()
{
T item = mData[0];
mSize--;
mData[0] = mData[mSize];
HeapifyDown(0);
return item;
}
public void Clear()
{
mSize = 0;
}
private void Resize()
{
T[] resizedData = new T[mData.Count * 2];
Array.Copy(mData, 0, resizedData, 0, mData.Count);
delete mData;
mData = resizedData;
}
[Optimize]
private void HeapifyUp(int32 childIdx)
{
if (childIdx > 0)
{
int32 parentIdx = (childIdx - 1) / 2;
if (mComparison(mData[childIdx], mData[parentIdx]) > 0)
{
// swap parent and child
T t = mData[parentIdx];
mData[parentIdx] = mData[childIdx];
mData[childIdx] = t;
HeapifyUp(parentIdx);
}
}
}
[Optimize]
private void HeapifyDown(int32 parentIdx)
{
int32 leftChildIdx = 2 * parentIdx + 1;
int32 rightChildIdx = leftChildIdx + 1;
int32 largestChildIdx = parentIdx;
if (leftChildIdx < mSize && mComparison(mData[leftChildIdx], mData[largestChildIdx]) > 0)
{
largestChildIdx = leftChildIdx;
}
if (rightChildIdx < mSize && mComparison(mData[rightChildIdx], mData[largestChildIdx]) > 0)
{
largestChildIdx = rightChildIdx;
}
if (largestChildIdx != parentIdx)
{
T t = mData[parentIdx];
mData[parentIdx] = mData[largestChildIdx];
mData[largestChildIdx] = t;
HeapifyDown(largestChildIdx);
}
}
}
}

View file

@ -0,0 +1,996 @@
// 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_DICTIONARY
#endif
namespace System.Collections.Generic
{
using System;
using System.Collections;
using System.Diagnostics;
using System.Diagnostics.Contracts;
public class Dictionary<TKey, TValue> where TKey : IHashable //: IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback
{
private struct Entry
{
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 mNext; // Index of next entry, -1 if last
}
private int_cosize[] mBuckets ~ delete _;
private Entry[] mEntries ~ delete _;
private int_cosize mCount;
private int_cosize mFreeList;
private int_cosize mFreeCount;
#if VERSION_DICTIONARY
private int32 mVersion;
const String cVersionError = "Dictionary changed during enumeration";
#endif
public this(): this(0) { }
public this(int_cosize capacity)
{
//if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
if (capacity > 0) Initialize(capacity);
//TODO: this.comparer = comparer ?? EqualityComparer<TKey>.Default;
}
public int Count
{
get { return mCount - mFreeCount; }
}
public bool IsEmpty
{
get { return mCount - mFreeCount == 0; }
}
/*public KeyCollection Keys
{
get
{
//Contract.Ensures(Contract.Result<KeyCollection>() != null);
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}*/
/*ICollection<TKey> IDictionary<TKey, TValue>.Keys
{
get
{
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
{
get
{
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}*/
public ValueEnumerator Values
{
get
{
//Contract.Ensures(Contract.Result<ValueCollection>() != null);
return ValueEnumerator(this);
}
}
public KeyEnumerator Keys
{
get
{
//Contract.Ensures(Contract.Result<ValueCollection>() != null);
return KeyEnumerator(this);
}
}
/*ICollection<TValue> IDictionary<TKey, TValue>.Values
{
get
{
if (values == null) values = new ValueCollection(this);
return values;
}
}
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
{
get
{
if (values == null) values = new ValueCollection(this);
return values;
}
}*/
public ref TValue this[TKey key]
{
get
{
int_cosize i = (int_cosize)FindEntry(key);
if (i >= 0) return ref mEntries[i].mValue;
Runtime.FatalError("Key not found");
}
set
{
Insert(key, value, false);
}
}
public void Add(TKey key, TValue value)
{
Insert(key, value, true);
}
public bool TryAdd(TKey key, TValue value)
{
TKey* keyPtr;
TValue* valuePtr;
bool inserted = Insert(key, false, out keyPtr, out valuePtr);
if (!inserted)
return false;
*keyPtr = key;
*valuePtr = value;
return true;
}
public bool TryAdd(TKey key, out TKey* keyPtr, out TValue* valuePtr)
{
return Insert(key, false, out keyPtr, out valuePtr);
}
public enum AddResult
{
case Added(TKey* keyPtr, TValue* valuePtr);
case Exists(TKey* keyPtr, TValue* valuePtr);
}
public AddResult TryAdd(TKey key)
{
TKey* keyPtr;
TValue* valuePtr;
if (Insert(key, false, out keyPtr, out valuePtr))
return .Added(keyPtr, valuePtr);
return .Exists(keyPtr, valuePtr);
}
/*void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
{
Add(keyValuePair.Key, keyValuePair.Value);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
{
int i = FindEntry(keyValuePair.Key);
if (i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value))
{
return true;
}
return false;
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
{
int i = FindEntry(keyValuePair.Key);
if (i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value))
{
Remove(keyValuePair.Key);
return true;
}
return false;
}*/
public Result<TValue> GetValue(TKey key)
{
int_cosize i = (int_cosize)FindEntry(key);
if (i >= 0) return mEntries[i].mValue;
return .Err;
}
public void Clear()
{
if (mCount > 0)
{
for (int_cosize i = 0; i < mBuckets.Count; i++) mBuckets[i] = -1;
//for (int_cosize i = 0; i < mCount; i++)
//mEntries[i] = default(Entry);
//Array.Clear(entries, 0, count);
mFreeList = -1;
mCount = 0;
mFreeCount = 0;
#if VERSION_DICTIONARY
mVersion++;
#endif
}
}
public bool ContainsKey(TKey key)
{
return FindEntry(key) >= 0;
}
public bool ContainsValue(TValue value)
{
if (value == null)
{
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;
}*/
}
return false;
}
public Enumerator GetEnumerator()
{
return Enumerator(this, Enumerator.KeyValuePair);
}
private int FindEntry(TKey key)
{
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
for (int_cosize i = mBuckets[hashCode % mBuckets.Count]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
}
}
return -1;
}
private int FindEntryWith<TAltKey>(TAltKey key) where TAltKey : IOpEquals<TKey>, IHashable
{
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
for (int_cosize i = mBuckets[hashCode % mBuckets.Count]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key)) return i;
}
}
return -1;
}
private void Initialize(int capacity)
{
int_cosize size = GetPrimeish((int_cosize)capacity);
mBuckets = new int_cosize[size];
for (int_cosize i < (int_cosize)mBuckets.Count) mBuckets[i] = -1;
mEntries = new Entry[size];
mFreeList = -1;
}
private void Insert(TKey key, TValue value, bool add)
{
if (mBuckets == null) Initialize(0);
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize targetBucket = hashCode % (int_cosize)mBuckets.Count;
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
{
if (add)
{
Runtime.FatalError("Adding duplicate");
}
mEntries[i].mValue = value;
#if VERSION_DICTIONARY
mVersion++;
#endif
return;
}
}
int_cosize index;
if (mFreeCount > 0)
{
index = mFreeList;
mFreeList = mEntries[index].mNext;
mFreeCount--;
}
else
{
if (mCount == mEntries.Count)
{
Resize();
targetBucket = hashCode % (int_cosize)mBuckets.Count;
}
index = mCount;
mCount++;
}
mEntries[index].mHashCode = hashCode;
mEntries[index].mNext = mBuckets[targetBucket];
mEntries[index].mKey = key;
mEntries[index].mValue = value;
mBuckets[targetBucket] = index;
#if VERSION_DICTIONARY
mVersion++;
#endif
}
private bool Insert(TKey key, bool add, out TKey* keyPtr, out TValue* valuePtr)
{
if (mBuckets == null) Initialize(0);
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize targetBucket = hashCode % (int_cosize)mBuckets.Count;
for (int_cosize i = mBuckets[targetBucket]; i >= 0; i = mEntries[i].mNext)
{
if (mEntries[i].mHashCode == hashCode && (mEntries[i].mKey == key))
{
if (add)
{
Runtime.FatalError("Adding duplicate entry");
}
keyPtr = &mEntries[i].mKey;
valuePtr = &mEntries[i].mValue;
return false;
}
}
int_cosize index;
if (mFreeCount > 0)
{
index = mFreeList;
mFreeList = mEntries[index].mNext;
mFreeCount--;
}
else
{
if (mCount == mEntries.Count)
{
Resize();
targetBucket = hashCode % (int_cosize)mBuckets.Count;
}
index = mCount;
mCount++;
}
mEntries[index].mHashCode = hashCode;
mEntries[index].mNext = mBuckets[targetBucket];
mEntries[index].mKey = key;
mBuckets[targetBucket] = index;
#if VERSION_DICTIONARY
mVersion++;
#endif
keyPtr = &mEntries[index].mKey;
valuePtr = &mEntries[index].mValue;
return true;
}
// Close to prime but faster to compute
int_cosize GetPrimeish(int_cosize min)
{
// This is a minimal effort to help address-aligned data
return (min | 1);
}
int_cosize ExpandSize(int_cosize oldSize)
{
int_cosize newSize = 2 * oldSize;
return GetPrimeish(newSize);
}
private void Resize()
{
Resize(ExpandSize(mCount), false);
}
private void Resize(int newSize, bool forceNewHashCodes)
{
Contract.Assert(newSize >= mEntries.Count);
int_cosize[] newBuckets = new int_cosize[newSize];
for (int_cosize i = 0; i < newBuckets.Count; i++) newBuckets[i] = -1;
Entry[] newEntries = new Entry[newSize];
mEntries.CopyTo(newEntries, 0, 0, mCount);
if (forceNewHashCodes)
{
for (int_cosize i = 0; i < mCount; i++)
{
if (newEntries[i].mHashCode != -1)
{
newEntries[i].mHashCode = (int_cosize)newEntries[i].mKey.GetHashCode() & 0x7FFFFFFF;
}
}
}
for (int_cosize i = 0; i < mCount; i++)
{
if (newEntries[i].mHashCode >= 0)
{
int_cosize bucket = (int_cosize)(newEntries[i].mHashCode % newSize);
newEntries[i].mNext = newBuckets[bucket];
newBuckets[bucket] = i;
}
}
delete mBuckets;
delete mEntries;
mBuckets = newBuckets;
mEntries = newEntries;
}
public bool Remove(TKey key)
{
if (key == null)
{
ThrowUnimplemented();
//ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize bucket = hashCode % (int_cosize)mBuckets.Count;
int_cosize last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
{
if ((mEntries[i].mHashCode == hashCode) && (mEntries[i].mKey == key))
{
if (last < 0)
{
mBuckets[bucket] = mEntries[i].mNext;
}
else
{
mEntries[last].mNext = mEntries[i].mNext;
}
mEntries[i].mHashCode = -1;
mEntries[i].mNext = mFreeList;
#if BF_ENABLE_REALTIME_LEAK_CHECK
mEntries[i].mKey = default;
mEntries[i].mValue = default;
#endif
mFreeList = i;
mFreeCount++;
#if VERSION_DICTIONARY
mVersion++;
#endif
return true;
}
}
}
return false;
}
public Result<(TKey key, TValue value)> GetAndRemove(TKey key)
{
if (mBuckets != null)
{
int_cosize hashCode = (int_cosize)key.GetHashCode() & 0x7FFFFFFF;
int_cosize bucket = hashCode % (int_cosize)mBuckets.Count;
int_cosize last = -1;
for (int_cosize i = mBuckets[bucket]; i >= 0; last = i,i = mEntries[i].mNext)
{
if ((mEntries[i].mHashCode == hashCode) && (mEntries[i].mKey == key))
{
if (last < 0)
{
mBuckets[bucket] = mEntries[i].mNext;
}
else
{
mEntries[last].mNext = mEntries[i].mNext;
}
TKey entryKey = mEntries[i].mKey;
TValue result = mEntries[i].mValue;
mEntries[i].mHashCode = -1;
mEntries[i].mNext = mFreeList;
#if BF_ENABLE_REALTIME_LEAK_CHECK
mEntries[i].mKey = default(TKey);
mEntries[i].mValue = default(TValue);
#endif
mFreeList = i;
mFreeCount++;
#if VERSION_DICTIONARY
mVersion++;
#endif
return .Ok((entryKey, result));
}
}
}
return .Err;
}
public bool TryGetValue(TKey key, out TValue value)
{
int_cosize i = (int_cosize)FindEntry(key);
if (i >= 0)
{
value = mEntries[i].mValue;
return true;
}
value = default(TValue);
return false;
}
public bool TryGetValue(TKey key, out TKey matchKey, out TValue value)
{
int_cosize i = (int_cosize)FindEntry(key);
if (i >= 0)
{
matchKey = mEntries[i].mKey;
value = mEntries[i].mValue;
return true;
}
matchKey = default(TKey);
value = default(TValue);
return false;
}
public bool TryGetWith<TAltKey>(TAltKey key, out TKey matchKey, out TValue value) where TAltKey : IOpEquals<TKey>, IHashable
{
int_cosize i = (int_cosize)FindEntryWith(key);
if (i >= 0)
{
matchKey = mEntries[i].mKey;
value = mEntries[i].mValue;
return true;
}
matchKey = default(TKey);
value = default(TValue);
return false;
}
public TValue GetValueOrDefault(TKey key)
{
int_cosize i = (int_cosize)FindEntry(key);
if (i >= 0)
{
return mEntries[i].mValue;
}
return default(TValue);
}
private static bool IsCompatibleKey(Object key)
{
if (key == null)
{
ThrowUnimplemented();
//ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
return (key is TKey);
}
public struct Enumerator : IEnumerator<(TKey key, TValue value)>//, IDictionaryEnumerator
{
private Dictionary<TKey, TValue> mDictionary;
#if VERSION_DICTIONARY
private int_cosize mVersion;
#endif
private int_cosize mIndex;
private int_cosize mCurrentIndex;
//private KeyValuePair<TKey, TValue> current;
private int_cosize mGetEnumeratorRetType; // What should Enumerator.Current return?
internal const int_cosize DictEntry = 1;
internal const int_cosize KeyValuePair = 2;
internal this(Dictionary<TKey, TValue> dictionary, int_cosize getEnumeratorRetType)
{
mDictionary = dictionary;
#if VERSION_DICTIONARY
mVersion = dictionary.mVersion;
#endif
mIndex = 0;
mGetEnumeratorRetType = getEnumeratorRetType;
//current = KeyValuePair<TKey, TValue>();
//current = default(KeyValuePair<TKey, TValue>);
mCurrentIndex = -1;
}
#if VERSION_DICTIONARY
void CheckVersion()
{
if (mVersion != mDictionary.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public bool MoveNext() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
// dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
while ((uint)mIndex < (uint)mDictionary.mCount)
{
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
{
mCurrentIndex = mIndex;
//current = KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
mIndex++;
return true;
}
mIndex++;
}
mIndex = mDictionary.mCount + 1;
//current = default(KeyValuePair<TKey, TValue>);
mCurrentIndex = -1;
return false;
}
public ref TKey Key
{
get
{
return ref mDictionary.mEntries[mCurrentIndex].mKey;
}
}
public ref TValue Value
{
get
{
return ref mDictionary.mEntries[mCurrentIndex].mValue;
}
}
public (TKey key, TValue value) Current
{
get { return (mDictionary.mEntries[mCurrentIndex].mKey, mDictionary.mEntries[mCurrentIndex].mValue); }
}
public void Dispose()
{
}
public void SetValue(TValue value)
{
mDictionary.mEntries[mCurrentIndex].mValue = value;
}
public void Reset() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
mIndex = 0;
//current = default(KeyValuePair<TKey, TValue>);
mCurrentIndex = -1;
}
/*DictionaryEntry IDictionaryEnumerator.Entry
{
get
{
if (index == 0 || (index == dictionary.count + 1))
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return new DictionaryEntry(current.Key, current.Value);
}
}
object IDictionaryEnumerator.Key
{
get
{
if (index == 0 || (index == dictionary.count + 1))
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return current.Key;
}
}
object IDictionaryEnumerator.Value
{
get
{
if (index == 0 || (index == dictionary.count + 1))
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return current.Value;
}
}*/
public Result<(TKey key, TValue value)> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
public struct ValueEnumerator : IEnumerator<TValue>, IResettable
{
private Dictionary<TKey, TValue> mDictionary;
#if VERSION_DICTIONARY
private int_cosize mVersion;
#endif
private int_cosize mIndex;
private TValue mCurrent;
internal const int_cosize cDictEntry = 1;
internal const int_cosize cKeyValuePair = 2;
internal this(Dictionary<TKey, TValue> dictionary)
{
mDictionary = dictionary;
#if VERSION_DICTIONARY
mVersion = dictionary.mVersion;
#endif
mIndex = 0;
mCurrent = default;
}
public bool MoveNext() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
// dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
while ((uint)mIndex < (uint)mDictionary.mCount)
{
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
{
mCurrent = mDictionary.mEntries[mIndex].mValue;
mIndex++;
return true;
}
mIndex++;
}
mIndex = mDictionary.mCount + 1;
mCurrent = default;
return false;
}
public TValue Current
{
get { return mCurrent; }
}
public ref TKey Key
{
get
{
return ref mDictionary.mEntries[mIndex].mKey;
}
}
#if VERSION_DICTIONARY
void CheckVersion()
{
if (mVersion != mDictionary.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public void Dispose()
{
}
public void Reset() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
mIndex = 0;
mCurrent = default;
}
public Result<TValue> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
public struct RefValueEnumerator : IEnumerator<TValue>, IResettable
{
private Dictionary<TKey, TValue> mDictionary;
#if VERSION_DICTIONARY
private int_cosize mVersion;
#endif
private int_cosize mIndex;
private TValue* mCurrent;
internal const int_cosize DictEntry = 1;
internal const int_cosize KeyValuePair = 2;
internal this(Dictionary<TKey, TValue> dictionary)
{
mDictionary = dictionary;
#if VERSION_DICTIONARY
mVersion = dictionary.mVersion;
#endif
mIndex = 0;
mCurrent = null;
}
#if VERSION_DICTIONARY
void CheckVersion()
{
if (mVersion != mDictionary.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public bool MoveNext() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
// dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
while ((uint32)mIndex < (uint32)mDictionary.mCount)
{
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
{
mCurrent = &mDictionary.mEntries[mIndex].mValue;
mIndex++;
return true;
}
mIndex++;
}
mIndex = mDictionary.mCount + 1;
mCurrent = null;
return false;
}
public TValue Current
{
get { return *mCurrent; }
}
public ref TKey Key
{
get
{
return ref mDictionary.mEntries[mIndex - 1].mKey;
}
}
public void Dispose()
{
}
public void Reset() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
mIndex = 0;
mCurrent = null;
}
public Result<TValue> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
public struct KeyEnumerator : IEnumerator<TKey>, IResettable
{
private Dictionary<TKey, TValue> mDictionary;
# if VERSION_DICTIONARY
private int32 mVersion;
#endif
private int_cosize mIndex;
private TKey* mCurrent;
internal const int_cosize DictEntry = 1;
internal const int_cosize KeyValuePair = 2;
internal this(Dictionary<TKey, TValue> dictionary)
{
mDictionary = dictionary;
#if VERSION_DICTIONARY
mVersion = dictionary.mVersion;
#endif
mIndex = 0;
mCurrent = null;
}
#if VERSION_DICTIONARY
void CheckVersion()
{
if (mVersion != mDictionary.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public bool MoveNext() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
// dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
while ((uint32)mIndex < (uint32)mDictionary.mCount)
{
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
{
mCurrent = &mDictionary.mEntries[mIndex].mKey;
mIndex++;
return true;
}
mIndex++;
}
mIndex = mDictionary.mCount + 1;
mCurrent = null;
return false;
}
public TKey Current
{
get { return *mCurrent; }
}
public ref TValue Value
{
get
{
return ref mDictionary.mEntries[mIndex - 1].mValue;
}
}
public void Dispose()
{
}
public void Reset() mut
{
#if VERSION_DICTIONARY
CheckVersion();
#endif
mIndex = 0;
mCurrent = null;
}
public Result<TKey> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
namespace System.Collections.Generic
{
}

View file

@ -0,0 +1,11 @@
namespace System.Collections.Generic
{
using System;
public interface IEqualityComparer</*in*/ T>
{
bool Equals(T x, T y);
int GetHashCode(T obj);
}
}

View file

@ -0,0 +1,39 @@
namespace System.Collections.Generic
{
public struct KeyValuePair<TKey, TValue>
{
private TKey mKey;
private TValue mValue;
public this(TKey key, TValue value)
{
this.mKey = key;
this.mValue = value;
}
public TKey Key
{
get { return mKey; }
}
public TValue Value
{
get { return mValue; }
}
public override void ToString(String strOut)
{
strOut.Append('[');
if (Key != null)
{
Key.ToString(strOut);
}
strOut.Append(", ");
if (Value != null)
{
Value.ToString(strOut);
}
strOut.Append(']');
}
}
}

View file

@ -0,0 +1,778 @@
// 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()
{
}
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)
{
var items = mItems;
#if BF_ENABLE_REALTIME_LEAK_CHECK
mItems = null;
Interlocked.Fence();
#endif
Free(items);
}
}
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));
var oldItems = mItems;
mItems = newItems;
if (IsDynAlloc)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
// We need to avoid scanning a deleted mItems
Interlocked.Fence();
#endif
Free(oldItems);
}
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
{
Runtime.Assert((uint)index < (uint)mSize);
return ref mItems[index];
}
[Unchecked, Inline]
get
{
return ref mItems[index];
}
[Checked]
set
{
Runtime.Assert((uint)index < (uint)mSize);
mItems[index] = value;
#if VERSION_LIST
mVersion++;
#endif
}
[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 the GC 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 (mSize == AllocSize) EnsureCapacity(mSize + 1);
mItems[mSize++] = item;
#if VERSION_LIST
mVersion++;
#endif
}
/// Adds an item to the back of the list.
public void Add(Span<T> addSpan)
{
if (mSize == AllocSize) EnsureCapacity(mSize + addSpan.Length);
for (var val in ref addSpan)
mItems[mSize++] = val;
#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 i = 0; i < mSize; i++)
array[i + arrayIndex] = mItems[i];
}
public void CopyTo(int index, T[] array, int arrayIndex, int count)
{
// Delegate rest of error checking to Array.Copy.
for (int i = 0; i < count; i++)
array[i + arrayIndex] = mItems[i + index];
}
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 FindIndex(Predicate<T> match)
{
for (int_cosize i = 0; i < mSize; i++)
if (match(mItems[i]))
return i;
return -1;
}
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)
{
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 int RemoveAll(Predicate<T> match)
{
int_cosize freeIndex = 0; // the first free slot in items array
// Find the first item which needs to be removed.
while (freeIndex < mSize && !match(mItems[freeIndex])) freeIndex++;
if (freeIndex >= mSize) return 0;
int_cosize current = freeIndex + 1;
while (current < mSize)
{
// Find the first item which needs to be kept.
while (current < mSize && match(mItems[current])) current++;
if (current < mSize)
{
// copy item to the free slot.
mItems[freeIndex++] = mItems[current++];
}
}
int_cosize result = mSize - freeIndex;
mSize = freeIndex;
#if VERSION_LIST
mVersion++;
#endif
return result;
}
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;
}
/// Searches a section of the list for a given element using a binary search
/// algorithm. Elements of the list are compared to the search value using
/// the given IComparer interface. If comparer is null, elements of
/// the list are compared to the search value using the IComparable
/// interface, which in that case must be implemented by all elements of the
/// list and the given search value. This method assumes that the given
/// section of the list is already sorted; if this is not the case, the
/// result will be incorrect.
///
/// The method returns the index of the given value in the list. If the
/// list does not contain the given value, the method returns a negative
/// integer. The bitwise complement operator (~) can be applied to a
/// negative result to produce the index of the first element (if any) that
/// is larger than the given search value. This is also the index at which
/// the search value should be inserted into the list in order for the list
/// to remain sorted.
///
/// The method uses the Array.BinarySearch method to perform the
/// search.
///
/// @brief Searches a section of the list for a given element using a binary search algorithm.
public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
{
return (int_cosize)Array.BinarySearch(mItems, index, count, item, comparer);
}
public int_cosize BinarySearch(T item, IComparer<T> comparer)
{
//Contract.Ensures(Contract.Result<int>() <= Count);
return (int_cosize)BinarySearch(0, Count, item, comparer);
}
public static operator Span<T>(List<T> list)
{
return Span<T>(list.mItems, list.mSize);
}
protected override void GCMarkMembers()
{
if (mItems == null)
return;
let type = typeof(T);
if ((type.mTypeFlags & .WantsMark) == 0)
return;
for (int i < mSize)
{
GC.Mark_Unbound(mItems[i]);
}
}
public struct Enumerator : IRefEnumerator<T>, IResettable
{
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;
}
set
{
*mCurrent = value;
}
}
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;
}
}
}
extension List<T> where T : IOpComparable
{
public int_cosize BinarySearch(T item)
{
return (int_cosize)BinarySearch(0, Count, item, scope CompareWrapper<T>());
}
public void Sort()
{
Sort(scope (lhs, rhs) => lhs <=> rhs);
}
}
class ListWithAlloc<T> : List<T>
{
IRawAllocator mAlloc;
public this(IRawAllocator alloc)
{
mAlloc = alloc;
}
/*protected override void* Alloc(int size, int align)
{
return mAlloc.Alloc(size, align);
}
protected override void Free(void* ptr)
{
mAlloc.Free(ptr);
}*/
}
}

View file

@ -0,0 +1,350 @@
// 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_QUEUE
#endif
namespace System.Collections.Generic
{
using System;
using System.Diagnostics;
/// A simple Queue of generic items. Internally it is implemented as a
/// circular buffer, so Enqueue can be O(n). Dequeue is O(1).
public class Queue<T> : IEnumerable<T> //, System.Collections.ICollection, IReadOnlyCollection<T>
{
private T[] mArray;
private int_cosize mHead; // First valid element in the queue
private int_cosize mTail; // Last valid element in the queue
private int_cosize mSize; // Number of elements.
#if VERSION_QUEUE
private int32 mVersion;
const String cVersionError = "Queue changed during enumeration";
#endif
private Object mSyncRoot;
private const int32 cMinimumGrow = 4;
private const int32 cShrinkThreshold = 32;
private const int32 cGrowFactor = 200; // double each time
private const int32 cDefaultCapacity = 4;
static T[] sEmptyArray = new T[0] ~ delete _;
/// Creates a queue with room for capacity objects. The default initial
/// capacity and grow factor are used.
public this()
{
mArray = sEmptyArray;
}
/// Creates a queue with room for capacity objects. The default grow factor
/// is used.
public this(int capacity)
{
Debug.Assert(capacity >= 0);
mArray = new T[capacity];
mHead = 0;
mTail = 0;
mSize = 0;
}
// Fills a Queue with the elements of an ICollection. Uses the enumerator
// to get each of the elements.
//
/// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue3"]/*' />
/*public void Set<T>(T collection) where T : IEnumerable<T>
{
if (collection == null)
//ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Runtime.FatalError();
_array = new T[_DefaultCapacity];
_size = 0;
_version = 0;
using (var en = collection.GetEnumerator())
{
while (en.MoveNext())
{
Enqueue(en.Current);
}
}
}*/
public int Count
{
get { return mSize; }
}
/// Removes all items from the queue.
public void Clear()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
if (mHead < mTail)
Array.Clear(mArray, mHead, mSize);
else
{
Array.Clear(mArray, mHead, mArray.Count - mHead);
Array.Clear(mArray, 0, mTail);
}
#endif
mHead = 0;
mTail = 0;
mSize = 0;
#if VERSION_QUEUE
mVersion++;
#endif
}
/// CopyTo copies a collection into an Array, starting at a particular
/// index into the array.
public void CopyTo(T[] array, int arrayIndex)
{
Debug.Assert((uint)arrayIndex <= (uint)array.Count);
int arrayLen = array.Count;
Debug.Assert(arrayLen >= mSize);
int numToCopy = (arrayLen - arrayIndex < mSize) ? (arrayLen - arrayIndex) : mSize;
if (numToCopy == 0) return;
int firstPart = (mArray.Count - mHead < numToCopy) ? mArray.Count - mHead : numToCopy;
Array.Copy(mArray, mHead, array, arrayIndex, firstPart);
numToCopy -= firstPart;
if (numToCopy > 0)
{
Array.Copy(mArray, 0, array, arrayIndex + mArray.Count - mHead, numToCopy);
}
}
/// Adds item to the tail of the queue.
public void Enqueue(T item)
{
if (mSize == mArray.Count)
{
int newcapacity = (int)((int64)mArray.Count * (int64)cGrowFactor / 100);
if (newcapacity < mArray.Count + cMinimumGrow)
{
newcapacity = mArray.Count + cMinimumGrow;
}
SetCapacity(newcapacity);
}
mArray[mTail] = item;
mTail = (mTail + 1) % (int_cosize)mArray.Count;
mSize++;
#if VERSION_QUEUE
mVersion++;
#endif
}
/// GetEnumerator returns an IEnumerator over this Queue. This
/// Enumerator will support removing.
public Enumerator GetEnumerator()
{
return Enumerator(this);
}
/// Removes the object at the head of the queue and returns it. If the queue
/// is empty, this method simply returns null.
public T Dequeue()
{
if (mSize == 0)
//ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
Runtime.FatalError();
T removed = mArray[mHead];
mArray[mHead] = default(T);
mHead = (mHead + 1) % (int_cosize)mArray.Count;
mSize--;
#if VERSION_QUEUE
mVersion++;
#endif
return removed;
}
/// Returns the object at the head of the queue. The object remains in the
/// queue. If the queue is empty, this method throws an
/// InvalidOperationException.
public T Peek()
{
Debug.Assert(mSize != 0);
return mArray[mHead];
}
/// Returns true if the queue contains at least one object equal to item.
/// Equality is determined using item.Equals().
public bool Contains(T item)
{
int index = mHead;
int count = mSize;
while (count-- > 0)
{
if (((Object)item) == null)
{
if (((Object)mArray[index]) == null)
return true;
}
else if (mArray[index] != null && mArray[index] == item)
{
return true;
}
index = (index + 1) % mArray.Count;
}
return false;
}
internal T GetElement(int i)
{
return mArray[(mHead + i) % mArray.Count];
}
/// Iterates over the objects in the queue, returning an array of the
/// objects in the Queue, or an empty array if the queue is empty.
/// The order of elements in the array is first in to last in, the same
/// order produced by successive calls to Dequeue.
public T[] ToArray()
{
T[] arr = new T[mSize];
if (mSize == 0)
return arr;
if (mHead < mTail)
{
Array.Copy(mArray, mHead, arr, 0, mSize);
}else
{
Array.Copy(mArray, mHead, arr, 0, mArray.Count - mHead);
Array.Copy(mArray, 0, arr, mArray.Count - mHead, mTail);
}
return arr;
}
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
// must be >= _size.
private void SetCapacity(int capacity)
{
T[] newarray = new T[capacity];
if (mSize > 0)
{
if (mHead < mTail)
{
Array.Copy(mArray, mHead, newarray, 0, mSize);
}else
{
Array.Copy(mArray, mHead, newarray, 0, mArray.Count - mHead);
Array.Copy(mArray, 0, newarray, mArray.Count - mHead, mTail);
}
}
mArray = newarray;
mHead = 0;
mTail = (mSize == capacity) ? 0 : mSize;
#if VERSION_QUEUE
mVersion++;
#endif
}
public void TrimExcess()
{
int32 threshold = (int32)(((double)mArray.Count) * 0.9);
if (mSize < threshold)
{
SetCapacity(mSize);
}
}
/// Implements an enumerator for a Queue. The enumerator uses the
/// internal version number of the list to ensure that no modifications are
/// made to the list while an enumeration is in progress.
public struct Enumerator : IEnumerator<T>
{
private Queue<T> mQueue;
private int32 mIndex; // -1 = not started, -2 = ended/disposed
#if VERSION_QUEUE
private int32 mVersion;
#endif
private T mCurrentElement;
internal this(Queue<T> q)
{
mQueue = q;
#if VERSION_QUEUE
mVersion = mQueue.mVersion;
#endif
mIndex = -1;
mCurrentElement = default(T);
}
#if VERSION_QUEUE
void CheckVersion()
{
if (mVersion != mQueue.mVersion)
Runtime.FatalError(cVersionError);
}
#endif
public void Dispose() mut
{
mIndex = -2;
mCurrentElement = default(T);
}
public bool MoveNext() mut
{
#if VERSION_QUEUE
CheckVersion();
#endif
if (mIndex == -2)
return false;
mIndex++;
if (mIndex == mQueue.mSize)
{
mIndex = -2;
mCurrentElement = default(T);
return false;
}
mCurrentElement = mQueue.GetElement(mIndex);
return true;
}
public T Current
{
get
{
if (mIndex < 0)
{
if (mIndex == -1)
Runtime.FatalError("Enumeration not started");
else
Runtime.FatalError("Enumeration ended");
}
return mCurrentElement;
}
}
public void Reset() mut
{
#if VERSION_QUEUE
CheckVersion();
#endif
mIndex = -1;
mCurrentElement = default;
}
public Result<T> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
}

View file

@ -0,0 +1,326 @@
// 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 InsertionSortZ(int lo, int hi)
{
int i, j;
T t;
T2 ti = ?;
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;
}
}
private void InsertionSort(int lo, int hi)
{
int i, j;
T t;
T2 ti = ?;
for (i = lo; i < hi; i++)
{
j = i;
t = keys[i + 1];
if (items != null)
ti = items[i + 1];
while (j >= lo && comparer(t, keys[j]) < 0)
{
keys[j + 1] = keys[j];
if(items != null)
items[j + 1] = items[j];
j--;
}
keys[j + 1] = t;
if (items != null)
items[j + 1] = ti;
}
}
}
}

View file

@ -0,0 +1,24 @@
using System;
namespace System.Collections.Generic
{
interface IEnumerator<T>
{
Result<T> GetNext() mut;
}
interface IResettable
{
void Reset() mut;
}
interface IRefEnumerator<T> : IEnumerator<T>
{
Result<T*> GetNextRef() mut;
}
concrete interface IEnumerable<T>
{
concrete IEnumerator<T> GetEnumerator();
}
}