diff options
Diffstat (limited to 'src/Common/src/System/Collections/Generic/LowLevelStack.cs')
-rw-r--r-- | src/Common/src/System/Collections/Generic/LowLevelStack.cs | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/Common/src/System/Collections/Generic/LowLevelStack.cs b/src/Common/src/System/Collections/Generic/LowLevelStack.cs new file mode 100644 index 000000000..b193036a2 --- /dev/null +++ b/src/Common/src/System/Collections/Generic/LowLevelStack.cs @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** Private version of Stack<T> for internal System.Private.CoreLib use. This +** permits sharing more source between BCL and System.Private.CoreLib (as well as the +** fact that Stack<T> is just a useful class in general.) +** +** This does not strive to implement the full api surface area +** (but any portion it does implement should match the real Stack<T>'s +** behavior.) +** +===========================================================*/ + +namespace System.Collections.Generic +{ + // Implements a variable-size Stack that uses an array of objects to store the + // elements. A Stack has a capacity, which is the allocated length + // of the internal array. As elements are added to a Stack, the capacity + // of the Stack is automatically increased as required by reallocating the + // internal array. + // + /// <summary> + /// LowLevelStack with no interface implementation to minimize both code and data size + /// Data size is smaller because there will be minimal virtual function table. + /// Code size is smaller because only functions called will be in the binary. + /// </summary> + internal class LowLevelStack<T> + { + protected T[] _items; + protected int _size; + protected int _version; + + private static readonly T[] s_emptyArray = new T[0]; + + public LowLevelStack() + { + _items = s_emptyArray; + } + + public LowLevelStack(int capacity) + { + if (capacity < 0) + throw new ArgumentOutOfRangeException(nameof(capacity)); + + if (capacity == 0) + _items = s_emptyArray; + else + { + _size = capacity; + _items = new T[capacity]; + } + } + + public LowLevelStack(IEnumerable<T> collection) + { + if (collection == null) + throw new ArgumentNullException(nameof(collection)); + + ICollection<T> c = collection as ICollection<T>; + if (c != null) + { + int count = c.Count; + if (count == 0) + { + _items = s_emptyArray; + } + else + { + _items = new T[count]; + c.CopyTo(_items, 0); + _size = count; + } + } + else + { + _size = 0; + _items = s_emptyArray; + + using (IEnumerator<T> en = collection.GetEnumerator()) + { + while (en.MoveNext()) + { + Push(en.Current); + } + } + } + } + + public int Count + { + get + { + return _items.Length; + } + } + + public void Push(T item) + { + _size = _size + 1; + Array.Resize(ref _items, _size); + _items[_size - 1] = item; + _version++; + } + + public T Pop() + { + ThrowIfEmptyStack(); + + _size = _size - 1; + T item = _items[_size]; + Array.Resize(ref _items, _size); + _version++; + return item; + } + + public bool TryPop(out T result) + { + if (_size == 0) + { + result = default; + return false; + } + + _size = _size - 1; + result = _items[_size]; + Array.Resize(ref _items, _size); + _version++; + + return true; + } + + public T Peek() + { + ThrowIfEmptyStack(); + return _items[_size - 1]; + } + + public bool TryPeek(out T result) + { + if (_size == 0) + { + result = default; + return false; + } + + result = _items[_size - 1]; + _version++; + return true; + } + + private void ThrowIfEmptyStack() + { + if (_size == 0) + throw new InvalidOperationException(); + } + } +} |