1 module skia.List;
2 
3 import skia.Common;
4 import skia.Exceptions;
5 
6 import std.range;
7 import std.algorithm;
8 import std.container.array;
9 
10 /**
11  * see_also:
12  *  https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-5.0
13  */
14 
15 class List(T) : IList!T {
16 
17     private Array!(T) _array;
18 
19     this() { }
20 
21     this(int capacity) {
22         _array.reserve(capacity);
23     }
24 
25     this(Array!T array) {
26         this._array = array;
27     }
28 
29     this(T[] list) {
30         this._array = list.array;
31     }
32 
33     T front() {
34         return _array.front;
35     }
36 
37     T moveFront() {
38         // return _array.moveFront();
39         // TODO: Tasks pending completion -@Administrator at 2021-04-08T10:25:50+08:00
40         // 
41         throw new NotImplementedException();
42     }
43 
44     void popFront() { 
45         _array.removeBack;
46     }
47 
48     bool IsReadOnly()
49     {
50         return false;
51     }
52 
53     int Count() {
54         return cast(int)_array.length;
55     }
56 
57     bool empty() {
58         return _array.empty();
59     }
60 
61     int opApply(scope int delegate(T) dg) {
62         assert(dg !is null);
63 
64         int r = 0;
65         foreach (T item; _array) {
66             r = dg(item);
67             if (r != 0) {
68                 break;
69             }
70         }
71         return r;
72     }
73 
74     int opApply(scope int delegate(size_t, T) dg) {
75         assert(dg !is null);
76 
77         int r = 0;
78         for (int i = 0; i < _array.length; i++) {
79             r = dg(i, _array[i]);
80             if (r != 0) {
81                 break;
82             }
83         }
84         return r;
85 
86     }
87 
88     T opIndex(int index)
89     {
90         return _array[index];
91     }
92 
93     T opIndexAssign(T value, int index)
94     {
95         _array[index] = value;
96         return value;
97     }
98 
99     void Add(T item) {
100         _array.insertBack(item);
101     }
102 
103     void Insert(int index, T item) {
104         _array.insertBefore(_array[index .. index + 1], item);
105     }
106 
107     void Clear() {
108         _array.clear();
109     }
110 
111     bool Contains(T o) {
112         return _array[].canFind(o);
113     }
114 
115     bool Exists(T o) {
116         return _array[].canFind(o);
117     }
118 
119     void CopyTo(T[] array, int arrayIndex = 0)
120     {
121         assert(arrayIndex >= 0 && arrayIndex <= _array.length);
122 
123         if (array.length + arrayIndex < _array.length)
124         {
125             // _array = _array[0..arrayIndex] ~ array ~ _array[(array.length + arrayIndex)..$];
126             for(size_t i = 0; i < array.length; i++) {
127                 _array[arrayIndex + i + 1] = array[i];
128             }
129         }
130         else 
131         {
132             // _array = _array[0..arrayIndex] ~ array;
133             _array.removeBack(_array.length - arrayIndex - 1);
134             _array ~= Array!T(array);
135         }
136     }
137 
138     int IndexOf(T o) {
139         for (size_t i = 0; i < _array.length; i++) {
140             static if (is(T == class)) {
141                 if (_array[i] is o)
142                     return cast(int) i;
143             } else {
144                 if (_array[i] == o)
145                     return cast(int) i;
146             }
147         }
148 
149         return -1;
150     }
151 
152     int LastIndexOf(T item) {
153         for (size_t i = _array.length - 1; i >= 0; i--) {
154             if (_array[i] == item)
155                 return cast(int) i;
156         }
157 
158         return -1;
159     }
160 
161     bool Remove(T item) {
162         int index = IndexOf(item);
163         if (index < 0)
164             return false;
165         _array.linearRemove(_array[index .. index + 1]);
166         return true;
167     }
168 
169     T RemoveAt(int index) {
170         T oldValue = _array[index];
171         _array.linearRemove(_array[index .. index + 1]);
172         return oldValue;
173     }
174 
175     T FirstOrDefault(scope bool delegate(T) dg) {
176         if (dg is null) {
177             return _array.front();
178         }
179         foreach (T item; _array) {
180             if (dg(item)) {
181                 return item;
182             }
183         }
184         return T.init;
185     }
186 
187     List!T Where(scope bool delegate(T) dg) {
188         assert(dg !is null);
189         
190         List!(T) meets = new List!(T)();
191         auto subArray = _array[].filter!(dg).array;
192         foreach (T item; subArray) {
193             meets.Add(item);
194         }
195         return meets;
196     }
197 
198     T[] ToList() {
199         return _array.array;
200     }
201 }
202