You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ArrayListLib/Sources/ArrayList.twin
+85-41Lines changed: 85 additions & 41 deletions
Original file line number
Diff line number
Diff line change
@@ -7,22 +7,28 @@ Public Class ArrayList
7
7
Private pItems() As Variant
8
8
Private pIndex As Long
9
9
Private pVersion As Long
10
+
Private pBaseIndex As Long
11
+
12
+
Public Sub New(Optional ByVal Capacity As Long = 2, Optional ByVal BaseIndex As Long = 0)
13
+
ReDim pItems(0 To Capacity - 1)
14
+
pBaseIndex = BaseIndex
15
+
End Sub
10
16
11
17
[ DefaultMember ]
12
18
Public Property Get Item(ByVal Index As Long) As Variant Implements IArrayList.Item
13
-
If Index < 0 Or Index >= pIndex Then Err.Raise 9
14
-
Return pItems(Index)
19
+
If Index < pBaseIndex Or Index >= pIndex + pBaseIndex Then Err.Raise 9
20
+
Return pItems(Index - pBaseIndex)
15
21
End Property
16
22
17
23
Public Property Let Item(ByVal Index As Long, Value As Variant) Implements IArrayList.Item
18
-
If Index < 0 Or Index >= pIndex Then Err.Raise 9
19
-
pItems(Index) = Value
24
+
If Index < pBaseIndex Or Index >= pIndex + pBaseIndex Then Err.Raise 9
25
+
pItems(Index - pBaseIndex) = Value
20
26
pVersion += 1
21
27
End Property
22
28
23
29
Public Property Set Item(ByVal Index As Long, Value As Variant) Implements IArrayList.Item
24
-
If Index < 0 Or Index >= pIndex Then Err.Raise 9
25
-
Set pItems(Index) = Value
30
+
If Index < pBaseIndex Or Index >= pIndex + pBaseIndex Then Err.Raise 9
31
+
Set pItems(Index - pBaseIndex) = Value
26
32
pVersion += 1
27
33
End Property
28
34
@@ -35,6 +41,9 @@ Public Class ArrayList
35
41
pVersion += 1
36
42
End Property
37
43
44
+
Public Property Get BaseIndex() As Long Implements IArrayList.BaseIndex: Return pBaseIndex: End Property
45
+
46
+
Public Property Let BaseIndex(Value As Long) Implements IArrayList.BaseIndex: pBaseIndex = Value: pVersion += 1: End Property
38
47
[ Hidden ]
39
48
Public Property Get Version() As Long Implements IArrayList.Version: Return pVersion: End Property
40
49
@@ -53,7 +62,7 @@ Public Class ArrayList
53
62
[ Hidden ]
54
63
[ Description ("CAUTION: Limit usage only in For Each In .Items calls, do NOT assign the return value of .Items to another variable unless you know what you're doing.") ]
55
64
Public Function Items() As Variant() Implements IArrayList.Items
56
-
/* Returns a Variant Array pointing to the same memory as the internal array of this list
65
+
/* Returns a 0-based Variant Array pointing to the same memory as the internal array of this list
57
66
* without increasing the reference count of byref elements within the list.
58
67
* If you assign this array to a variable in your code, you must remove the reference
59
68
* before it goes out of scope to prevent double deallocation of byref values.
@@ -74,7 +83,7 @@ Public Class ArrayList
74
83
Public Function Add(Value As Variant) As Long Implements IArrayList.Add
75
84
If pIndex > UBound(pItems) Then GrowCapacity 1
76
85
If IsObject(Value) Then Set pItems(pIndex) = Value Else pItems(pIndex) = Value
77
-
Add = pIndex
86
+
Add = pIndex + pBaseIndex
78
87
pIndex += 1
79
88
pVersion += 1
80
89
End Function
@@ -89,7 +98,8 @@ Public Class ArrayList
89
98
90
99
[ Description ("Creates a shallow copy of this ArrayList.") ]
91
100
Public Function Clone() As Variant Implements IArrayList.Clone
[ Description ("When using this enumerator for more advanced usage other than regular For Each usage, Index is always 0-based regardless of the current BaseIndex value in this ArrayList.") ]
141
152
Public Function GetEnumerator(Optional ByVal Index As Long = 0, Optional ByVal GetCount As Variant, Optional ByVal GetStep As Long = 1, Optional ByRef ThisEnumerator As IEnumerator) As stdole.IUnknown Implements IArrayList.GetEnumerator
153
+
Static mEnumerator As Enumerator, mEnumeratorB As Enumerator, mVer As Long, mVerB As Long
142
154
If IsMissing(GetCount) Then GetCount = pIndex - Index
143
-
Return New Enumerator(pItems, Index, GetCount, GetStep, ThisEnumerator)
155
+
If GetCount > 0 Then
156
+
If mEnumerator Is Nothing Then
157
+
Set mEnumerator = New Enumerator(pItems, Index, GetCount, GetStep, ThisEnumerator)
158
+
mVer = pVersion
159
+
Else
160
+
If pVersion <> mVer Then
161
+
mEnumerator.Bind pItems, Index, GetCount, GetStep
162
+
mVer = pVersion
163
+
Else
164
+
If Not mEnumerator.IsAvailable Then
165
+
If mEnumeratorB Is Nothing Then
166
+
Set mEnumeratorB = New Enumerator(pItems, Index, GetCount, GetStep, ThisEnumerator)
[ Description ("Returns the index of a particular item. Returns -1 if the item isn't in the list.") ]
147
-
Public Function IndexOf(Value As Variant, Optional ByVal Index As Long = 0, Optional ByVal GetCount As Variant) As Long Implements IArrayList.IndexOf
183
+
Public Function IndexOf(Value As Variant, Optional ByVal Index As Variant, Optional ByVal GetCount As Variant) As Long Implements IArrayList.IndexOf
184
+
If IsMissing(Index) Then Index = pBaseIndex
185
+
Index = CLng(Index - pBaseIndex)
148
186
If IsMissing(GetCount) Then GetCount = pIndex - Index
149
187
If Index > pIndex Or GetCount < 0 Or Index > pIndex - GetCount Then Err.Raise 9
150
188
GetCount = Index + GetCount - 1
@@ -153,23 +191,24 @@ Public Class ArrayList
153
191
Select Case vt
154
192
Case vbNull
155
193
For i = Index To GetCount
156
-
If IsNull(pItems(i)) Then Return i
194
+
If IsNull(pItems(i)) Then Return i + pBaseIndex
157
195
Next i
158
196
Case vbObject
159
197
For i = Index To GetCount
160
-
If VarType(pItems(i)) = vt AndAlso ObjPtr(pItems(i)) = ObjPtr(Value) Then Return i
198
+
If VarType(pItems(i)) = vt AndAlso ObjPtr(pItems(i)) = ObjPtr(Value) Then Return i + pBaseIndex
161
199
Next i
162
200
Case Else
163
201
For i = Index To GetCount
164
-
If VarType(pItems(i)) = vt AndAlso pItems(i) = Value Then Return i
202
+
If VarType(pItems(i)) = vt AndAlso pItems(i) = Value Then Return i + pBaseIndex
165
203
Next i
166
204
End Select
167
205
Return -1
168
206
End Function
169
207
170
208
[ Description ("Returns the last index of a particular item. Returns -1 if the item isn't in the list.") ]
171
209
Public Function LastIndexOf(ByRef Value As Variant, Optional ByVal Index As Variant, Optional ByVal GetCount As Variant) As Long Implements IArrayList.LastIndexOf
172
-
If IsMissing(Index) Then Index = pIndex - 1
210
+
If IsMissing(Index) Then Index = pIndex + pBaseIndex - 1
211
+
Index = CLng(Index - pBaseIndex)
173
212
If IsMissing(GetCount) Then GetCount = Index + 1
174
213
If Index >= pIndex Or GetCount > Index + 1 Then Err.Raise 9
175
214
GetCount = Index - (GetCount - 1)
@@ -178,36 +217,37 @@ Public Class ArrayList
178
217
Select Case vt
179
218
Case vbNull
180
219
For i = Index To GetCount Step -1
181
-
If IsNull(pItems(i)) Then Return i
220
+
If IsNull(pItems(i)) Then Return i + pBaseIndex
182
221
Next i
183
222
Case vbObject
184
223
For i = Index To GetCount Step -1
185
-
If VarType(pItems(i)) = vt AndAlso ObjPtr(pItems(i)) = ObjPtr(Value) Then Return i
224
+
If VarType(pItems(i)) = vt AndAlso ObjPtr(pItems(i)) = ObjPtr(Value) Then Return i + pBaseIndex
186
225
Next i
187
226
Case Else
188
227
For i = Index To GetCount Step -1
189
-
If VarType(pItems(i)) = vt AndAlso pItems(i) = Value Then Return i
228
+
If VarType(pItems(i)) = vt AndAlso pItems(i) = Value Then Return i + pBaseIndex
190
229
Next i
191
230
End Select
192
231
Return -1
193
232
End Function
194
233
195
234
[ Description ("Inserts value into the list at position Index. Index must be non-negative and less than or equal to the number of elements in the list. If Index equals the number of items in the list, then value is appended to the end.") ]
196
235
Public Sub Insert(ByVal Index As Long, Value As Variant) Implements IArrayList.Insert
197
-
ReserveSpaceForInsert Index, 1
198
-
If IsObject(Value) Then Set pItems(Index) = Value Else pItems(Index) = Value
236
+
ReserveSpaceForInsert Index - pBaseIndex, 1
237
+
If IsObject(Value) Then Set pItems(Index - pBaseIndex) = Value Else pItems(Index - pBaseIndex) = Value
199
238
pIndex += 1
200
239
pVersion += 1
201
240
End Sub
202
241
203
242
[ Description ("Removes an item from the list.") ]
204
243
Public Sub Remove(Value As Variant) Implements IArrayList.Remove
205
244
Dim Index As Long = IndexOf(Value)
206
-
If Index >= 0 Then RemoveAt Index
245
+
If Index >= pBaseIndex Then RemoveAt Index
207
246
End Sub
208
247
209
248
[ Description ("Removes the item at Index position.") ]
210
249
Public Sub RemoveAt(ByVal Index As Long) Implements IArrayList.RemoveAt
250
+
Index = Index - pBaseIndex
211
251
If Index < 0 Or Index >= pIndex Then Err.Raise 9
212
252
pItems(Index) = Empty
213
253
If Index < pIndex - 1 Then VBA.vbaCopyBytes (pIndex - Index - 1) * VARIANT_SIZE, VarPtr(pItems(Index)), VarPtr(pItems(Index + 1))
@@ -218,6 +258,7 @@ Public Class ArrayList
218
258
219
259
Public Sub RemoveRange(ByVal Index As Long, ByVal GetCount As Long) Implements IArrayList.RemoveRange
220
260
Dim i As Long
261
+
Index = Index - pBaseIndex
221
262
If Index < 0 Or GetCount < 0 Or (pIndex - Index < GetCount) Then Err.Raise 9
222
263
For i = 0 To GetCount - 1
223
264
pItems(Index + i) = Empty
@@ -228,30 +269,33 @@ Public Class ArrayList
228
269
pVersion += 1
229
270
End Sub
230
271
231
-
Public Sub Reverse(Optional ByVal Index As Long = 0, Optional ByVal GetCount As Variant) Implements IArrayList.Reverse
272
+
Public Sub Reverse(Optional ByVal Index As Variant, Optional ByVal GetCount As Variant) Implements IArrayList.Reverse
273
+
If IsMissing(Index) Then Index = pBaseIndex
274
+
Index = CLng(Index) - pBaseIndex
232
275
If IsMissing(GetCount) Then GetCount = pIndex - Index
233
276
If Index < 0 Or GetCount < 0 Or (pIndex - Index < GetCount) Then Err.Raise 9
234
277
Dim i As Long, p0 As LongPtr = VarPtr(pItems(0)), iMax As Long = GetCount \ 2
Public Sub AddRange(Target As Variant) Implements IArrayList.AddRange
250
-
InsertRange pIndex, Target
293
+
InsertRange pIndex + pBaseIndex, Target
251
294
End Sub
252
295
253
296
Public Sub InsertRange(ByVal Index As Long, Target As Variant) Implements IArrayList.InsertRange
254
297
Dim v As Variant, GetCount As Long
298
+
Index -= pBaseIndex
255
299
Select Case VarType(Target)
256
300
Case vbArray + vbVariant
257
301
GetCount = (UBound(Target) - LBound(Target)) + 1
@@ -282,13 +326,14 @@ Public Class ArrayList
282
326
End Sub
283
327
284
328
Public Function GetRange(ByVal Index As Long, ByVal GetCount As Long) As IListRange Implements IArrayList.GetRange
285
-
If Index < 0 Or GetCount < 0 Or pIndex - Index < GetCount Then Err.Raise 9
329
+
If Index < pBaseIndex Or GetCount < 0 Or pIndex - (Index - pBaseIndex) < GetCount Then Err.Raise 9
286
330
Dim r As New ListRange
287
331
Set GetRange = r.Bind(Me, Index, GetCount)
288
332
End Function
289
333
290
334
Public Sub SetRange(ByVal Index As Long, Target As Variant) Implements IArrayList.SetRange
291
335
Dim v As Variant, GetCount As Long
336
+
Index -= pBaseIndex
292
337
Select Case VarType(Target)
293
338
Case vbArray + vbVariant
294
339
GetCount = (UBound(Target) - LBound(Target)) + 1
@@ -318,12 +363,14 @@ Public Class ArrayList
318
363
/* [ CompilerOptions ("+llvm,+optimize") ] */
319
364
[ ArrayBoundsChecks (False) ]
320
365
[ IntegerOverflowChecks (False) ]
321
-
Public Sub Sort(Optional ByVal Index As Long = 0, Optional ByVal GetCount As Variant, Optional Comparer As IComparer = Nothing) Implements IArrayList.Sort
366
+
Public Sub Sort(Optional ByVal Index As Variant, Optional ByVal GetCount As Variant, Optional Comparer As IComparer = Nothing) Implements IArrayList.Sort
367
+
If IsMissing(Index) Then Index = pBaseIndex
368
+
Index -= pBaseIndex
322
369
If IsMissing(GetCount) Then GetCount = pIndex - Index
323
370
If Comparer IsNot Nothing Then
324
-
QuickSort Index, Index + GetCount - 1, Comparer
371
+
QuickSort CLng(Index), Index + GetCount - 1, Comparer
325
372
Else
326
-
QuickSortV2 Index, Index + GetCount - 1
373
+
QuickSortV2 CLng(Index), Index + GetCount - 1
327
374
End If
328
375
pVersion += 1
329
376
End Sub
@@ -334,13 +381,14 @@ Public Class ArrayList
334
381
[ Description ("Searches a section of a sorted list. Returns the index of the given value in the list. If not found, returns a negative integer. Use the bitwise operator (Not) to get the index of the first element larger than this one, if any.") ]
335
382
Public Function BinarySearch(ByVal Index As Long, ByVal GetCount As Long, Value As Variant, Optional ByRef Comparer As IComparer = Nothing) As Long Implements IArrayList.BinarySearch
336
383
Dim lo As Long, hi As Long, i As Long
384
+
Index -= pBaseIndex
337
385
lo = Index
338
386
hi = Index + GetCount - 1
339
387
If Comparer IsNot Nothing Then
340
388
Do While (lo <= hi)
341
389
i = lo + ((hi - lo) \ 2)
342
390
Select Case Comparer.Compare(pItems(i), Value)
343
-
Case 0: Return i
391
+
Case 0: Return i + pBaseIndex
344
392
Case Is < 0: lo = i + 1
345
393
Case Else: hi = i - 1
346
394
End Select
@@ -349,37 +397,33 @@ Public Class ArrayList
349
397
Do While (lo <= hi)
350
398
i = lo + ((hi - lo) \ 2)
351
399
Select Case pItems(i)
352
-
Case Value: Return i
400
+
Case Value: Return i + pBaseIndex
353
401
Case Is < Value: lo = i + 1
354
402
Case Else: hi = i - 1
355
403
End Select
356
404
Loop
357
405
End If
358
-
Return Not lo
406
+
Return Not (lo + pBaseIndex)
359
407
End Function
360
408
361
409
#Region "HIDDEN METHODS IN MSCORLIB"
362
410
[ Hidden ]
363
411
Public Function IndexOf_2(ByRef Value As Variant, ByVal Index As Long, ByVal GetCount As Long) As Long: Return IndexOf(Value, Index, GetCount): End Function
364
412
[ Hidden ]
365
-
Public Function IndexOf_3(ByRef Value As Variant) As Long: Return IndexOf(Value, 0): End Function
413
+
Public Function IndexOf_3(ByRef Value As Variant) As Long: Return IndexOf(Value, pBaseIndex): End Function
366
414
[ Hidden ]
367
-
Public Sub Sort_2(ByRef Comparer As IComparer): Sort 0, , Comparer: End Sub
415
+
Public Sub Sort_2(ByRef Comparer As IComparer): Sort pBaseIndex, , Comparer: End Sub
368
416
[ Hidden ]
369
-
Public Function BinarySearch_2(ByRef Value As Variant) As Long: Return BinarySearch(0, pIndex, Value): End Function
417
+
Public Function BinarySearch_2(ByRef Value As Variant) As Long: Return BinarySearch(pBaseIndex, pIndex, Value): End Function
370
418
[ Hidden ]
371
-
Public Function BinarySearch_3(ByRef Value As Variant, ByRef Comparer As IComparer) As Long: Return BinarySearch(0, pIndex, Value, Comparer): End Function
419
+
Public Function BinarySearch_3(ByRef Value As Variant, ByRef Comparer As IComparer) As Long: Return BinarySearch(pBaseIndex, pIndex, Value, Comparer): End Function
372
420
[ Hidden ]
373
421
Public Function LastIndexOf_2(ByRef Value As Variant, ByVal Index As Long) As Long: Return LastIndexOf(Value, Index, Index + 1): End Function
374
422
[ Hidden ]
375
423
Public Function LastIndexOf_3(ByRef Value As Variant, ByVal Index As Long, ByVal GetCount As Long) As Long: Return LastIndexOf(Value, Index, GetCount): End Function
0 commit comments