using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace StgSharp.Logic { [StructLayout(LayoutKind.Explicit, Size = 8)] internal struct LogSeperator { [FieldOffset(0)] public ulong all; [FieldOffset(0)] public long all_s; [FieldOffset(0)] public uint low; [FieldOffset(4)] public uint high; [FieldOffset(0)] public int low_s; [FieldOffset(4)] public int high_s; public LogSeperator(uint high, uint low) { this.high = high; this.low = low; } } /// /// A linear data structure with dynamic length. /// It contains a of , /// each is twice longer than the former one. /// /// public class DynamicArrayList { private List arrayIndexList; private LogSeperator indexpair; private int lastMain = 0; // main index to the last used element private int lastSub = 0; private int length; private int subLength = 1; // sub index to the last used element private Queue unusedMainIndex; private Queue unusedSubIndex; public DynamicArrayList() { arrayIndexList = [new T[1]]; length = 0; unusedMainIndex = new Queue(); unusedSubIndex = new Queue(); unusedMainIndex.Enqueue(0); unusedSubIndex.Enqueue(0); } /// /// Init a with a certain amount of elements prepared. /// /// Amount of elements to be prepared. public DynamicArrayList(int count) { arrayIndexList = new List(); length = count; unusedMainIndex = new(); unusedSubIndex = new(); SeprateIndex(count); int subcount = 1; for (int i = 0; i < indexpair.high_s; i++) { arrayIndexList.Add(new T[count]); for (int j = 0; j < subcount; j++) { unusedMainIndex.Enqueue(i); unusedSubIndex.Enqueue(j); } count >>= 1; } if (indexpair.low_s != 0) { arrayIndexList.Add(new T[1 >> indexpair.high_s]); for (int j = 0; j < indexpair.high_s; j++) { unusedMainIndex.Enqueue(indexpair.high_s); unusedSubIndex.Enqueue(j); } } } internal T this[long index] { get { indexpair.all_s = index; if ( indexpair.low_s > lastSub || indexpair.high_s > lastMain || indexpair.low_s < 0 || indexpair.high_s < 0) { throw new IndexOutOfRangeException(); } return arrayIndexList[indexpair.high_s][indexpair.low_s]; } set { indexpair.all_s = index; if ( indexpair.low_s > lastSub || indexpair.high_s > lastMain || indexpair.low_s < 0 || indexpair.high_s < 0) { throw new IndexOutOfRangeException(); } arrayIndexList[indexpair.high_s][indexpair.low_s] = value; } } public T this[int index] { get { if (index + 1 > length || index < 0) { throw new ArgumentOutOfRangeException("index"); } SeprateIndex(index); return arrayIndexList[indexpair.high_s][indexpair.low_s]; } set { if (index + 1 > length || index < 0) { throw new ArgumentOutOfRangeException("index"); } SeprateIndex(index); arrayIndexList[indexpair.high_s][indexpair.low_s] = value; } } public T this[uint index] { get { if (index + 1 > length || index < 0) { throw new ArgumentOutOfRangeException("index"); } SeprateIndex(index); return arrayIndexList[indexpair.high_s][indexpair.low_s]; } set { if (index + 1 > length || index < 0) { throw new ArgumentOutOfRangeException("index"); } SeprateIndex(index); arrayIndexList[indexpair.high_s][indexpair.low_s] = value; } } public int Count => length; /// /// Length of this /// public int Length { get { return length; } } public int Add(T item) { // this list is tite, all item is side by side if (unusedMainIndex.Count == 0) { // no extra space, a new sub array is needed if (lastSub + 1 == 1 << lastMain) { subLength <<= 1; arrayIndexList.Add(new T[subLength]); lastMain++; lastSub = 0; arrayIndexList[lastMain][0] = item; length++; return length - 1; } length++; lastSub++; arrayIndexList[lastMain][lastSub] = item; return length - 1; } length++; int main = unusedMainIndex.Dequeue(); int sub = unusedSubIndex.Dequeue(); arrayIndexList[main][sub] = item; return sub + (1 << main); } public void Clear() { arrayIndexList.Clear(); unusedMainIndex.Clear(); unusedSubIndex.Clear(); length = 0; } public bool Contains(T item) { foreach (T[] list in arrayIndexList) { foreach (T i in list) { if (i.Equals(item)) { return true; } } } return false; } public int IndexOf(T item) { int index = 1; foreach (T[] list in arrayIndexList) { int subindex = 0; foreach (T i in list) { if (i.Equals(item)) { return index + subindex - 1; } subindex++; } index <<= 1; } return -1; } public bool Remove(T item) { int index = 0; foreach (T[] list in arrayIndexList) { int subindex = 0; foreach (T i in list) { if (i.Equals(item)) { list[subindex] = default; if (subindex == lastSub && index == lastMain) { if (lastSub == 0) { lastMain = lastMain == 0 ? 0 : lastMain - 1; lastSub = arrayIndexList[lastMain].Length - 1; } else { lastSub--; } length--; return true; } unusedMainIndex.Enqueue(index); unusedSubIndex.Enqueue(subindex); return true; } subindex++; } index++; } return false; } public void RemoveAt(int index) { if (index > length || index < 0) { throw new ArgumentOutOfRangeException(nameof(index)); } SeprateIndex(index); arrayIndexList[indexpair.high_s][indexpair.low] = default; //the last element was removed. if (index + 1 == length) { //the last array can be disposed if (lastSub == 0) { arrayIndexList.RemoveAt(lastMain); lastMain--; lastSub = (length / 2) - 1; } length--; return; } unusedMainIndex.Enqueue(indexpair.high_s); unusedSubIndex.Enqueue(indexpair.low_s); } public void ShowStructure() { foreach (T[] l in arrayIndexList) { foreach (T item in l) { Console.Write($"{item}\t"); } Console.Write("\n\n"); } } private void SeprateIndex(uint ulongIndex) { indexpair.high = ulongIndex; int mainindex = 0; while (indexpair.high > 1) { indexpair.all >>= 1; mainindex++; } indexpair.high_s = mainindex; indexpair.low >>= (int)(32 - mainindex); } private void SeprateIndex(int longIndex) { indexpair.high_s = longIndex; int mainindex = 0; while (indexpair.high > 1) { indexpair.all >>= 1; mainindex++; } indexpair.high_s = mainindex; indexpair.low >>= (int)(32 - mainindex); } } }