Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
FastList.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Collections.ObjectModel;
7 using System.Diagnostics;
8 using System.Runtime.InteropServices;
9 using SiliconStudio.Core.Serialization.Serializers;
10 
11 namespace SiliconStudio.Core.Collections
12 {
13  /// <summary>
14  /// Similar to <see cref="List{T}"/>, with direct access to underlying array.
15  /// </summary>
16  /// <typeparam name="T">The type of elements in the list.</typeparam>
17  [DataSerializer(typeof(ListAllSerializer<,>), Mode = DataSerializerGenericMode.TypeAndGenericArguments)]
18  [DebuggerDisplay("Count = {Count}")]
19  public class FastList<T> : IList<T>, IReadOnlyList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
20  {
21  // Fields
22  private const int _defaultCapacity = 4;
23  private static readonly T[] _emptyArray;
24 
25  /// <summary>
26  /// Gets the items.
27  /// </summary>
28  public T[] Items { get; private set; }
29 
30  private int _size;
31 
32  // Methods
33  static FastList()
34  {
35  _emptyArray = new T[0];
36  }
37 
38  public FastList()
39  {
40  Items = _emptyArray;
41  }
42 
43  public FastList(IEnumerable<T> collection)
44  {
45  var is2 = collection as ICollection<T>;
46  if (is2 != null)
47  {
48  int count = is2.Count;
49  Items = new T[count];
50  is2.CopyTo(Items, 0);
51  _size = count;
52  }
53  else
54  {
55  _size = 0;
56  Items = new T[_defaultCapacity];
57  using (IEnumerator<T> enumerator = collection.GetEnumerator())
58  {
59  while (enumerator.MoveNext())
60  {
61  Add(enumerator.Current);
62  }
63  }
64  }
65  }
66 
67  public FastList(int capacity)
68  {
69  Items = new T[capacity];
70  }
71 
72  public int Capacity
73  {
74  get { return Items.Length; }
75  set
76  {
77  if (value != Items.Length)
78  {
79  if (value > 0)
80  {
81  var destinationArray = new T[value];
82  if (_size > 0)
83  {
84  Array.Copy(Items, 0, destinationArray, 0, _size);
85  }
86  Items = destinationArray;
87  }
88  else
89  {
90  Items = _emptyArray;
91  }
92  }
93  }
94  }
95 
96  #region IList<T> Members
97 
98  public void Add(T item)
99  {
100  if (_size == Items.Length)
101  {
102  EnsureCapacity(_size + 1);
103  }
104  Items[_size++] = item;
105  }
106 
107  public void IncreaseCapacity(int index)
108  {
109  EnsureCapacity(_size + index);
110  _size += index;
111  }
112 
113  public void Clear()
114  {
115  Clear(false);
116  }
117 
118  public bool Contains(T item)
119  {
120  if (item == null)
121  {
122  for (int j = 0; j < _size; j++)
123  {
124  if (Items[j] == null)
125  {
126  return true;
127  }
128  }
129  return false;
130  }
131  EqualityComparer<T> comparer = EqualityComparer<T>.Default;
132  for (int i = 0; i < _size; i++)
133  {
134  if (comparer.Equals(Items[i], item))
135  {
136  return true;
137  }
138  }
139  return false;
140  }
141 
142  public void CopyTo(T[] array, int arrayIndex)
143  {
144  Array.Copy(Items, 0, array, arrayIndex, _size);
145  }
146 
147  public int IndexOf(T item)
148  {
149  return Array.IndexOf(Items, item, 0, _size);
150  }
151 
152  public void Insert(int index, T item)
153  {
154  if (_size == Items.Length)
155  {
156  EnsureCapacity(_size + 1);
157  }
158  if (index < _size)
159  {
160  Array.Copy(Items, index, Items, index + 1, _size - index);
161  }
162  Items[index] = item;
163  _size++;
164  }
165 
166  public bool Remove(T item)
167  {
168  int index = IndexOf(item);
169  if (index >= 0)
170  {
171  RemoveAt(index);
172  return true;
173  }
174  return false;
175  }
176 
177  public void RemoveAt(int index)
178  {
179  _size--;
180  if (index < _size)
181  {
182  Array.Copy(Items, index + 1, Items, index, _size - index);
183  }
184  Items[_size] = default(T);
185  }
186 
187  IEnumerator<T> IEnumerable<T>.GetEnumerator()
188  {
189  return new Enumerator(this);
190  }
191 
192  IEnumerator IEnumerable.GetEnumerator()
193  {
194  return new Enumerator(this);
195  }
196 
197  public int Count
198  {
199  get { return _size; }
200  }
201 
202  public T this[int index]
203  {
204  get { return Items[index]; }
205  set
206  {
207  Items[index] = value;
208  }
209  }
210 
211  bool ICollection<T>.IsReadOnly
212  {
213  get { return false; }
214  }
215 
216  #endregion
217 
218  /// <summary>
219  /// Clears this list with a fast-clear option.
220  /// </summary>
221  /// <param name="fastClear">if set to <c>true</c> this method only resets the count elements but doesn't clear items referenced already stored in the list.</param>
222  public void Clear(bool fastClear)
223  {
224  if (!fastClear && _size > 0)
225  {
226  Array.Clear(Items, 0, _size);
227  }
228  _size = 0;
229  }
230 
231  public void AddRange(IEnumerable<T> collection)
232  {
233  InsertRange(_size, collection);
234  }
235 
236  public ReadOnlyCollection<T> AsReadOnly()
237  {
238  return new ReadOnlyCollection<T>(this);
239  }
240 
241  public int BinarySearch(T item)
242  {
243  return BinarySearch(0, Count, item, null);
244  }
245 
246  public int BinarySearch(T item, IComparer<T> comparer)
247  {
248  return BinarySearch(0, Count, item, comparer);
249  }
250 
251  public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
252  {
253  return Array.BinarySearch(Items, index, count, item, comparer);
254  }
255 
256  public void CopyTo(T[] array)
257  {
258  CopyTo(array, 0);
259  }
260 
261  public void CopyTo(int index, T[] array, int arrayIndex, int count)
262  {
263  Array.Copy(Items, index, array, arrayIndex, count);
264  }
265 
266  public void EnsureCapacity(int min)
267  {
268  if (Items.Length < min)
269  {
270  int num = (Items.Length == 0) ? _defaultCapacity : (Items.Length*2);
271  if (num < min)
272  {
273  num = min;
274  }
275  Capacity = num;
276  }
277  }
278 
279  public bool Exists(Predicate<T> match)
280  {
281  return (FindIndex(match) != -1);
282  }
283 
284  public T Find(Predicate<T> match)
285  {
286  for (int i = 0; i < _size; i++)
287  {
288  if (match(Items[i]))
289  {
290  return Items[i];
291  }
292  }
293  return default(T);
294  }
295 
296  public FastList<T> FindAll(Predicate<T> match)
297  {
298  var list = new FastList<T>();
299  for (int i = 0; i < _size; i++)
300  {
301  if (match(Items[i]))
302  {
303  list.Add(Items[i]);
304  }
305  }
306  return list;
307  }
308 
309  public int FindIndex(Predicate<T> match)
310  {
311  return FindIndex(0, _size, match);
312  }
313 
314  public int FindIndex(int startIndex, Predicate<T> match)
315  {
316  return FindIndex(startIndex, _size - startIndex, match);
317  }
318 
319  public int FindIndex(int startIndex, int count, Predicate<T> match)
320  {
321  int num = startIndex + count;
322  for (int i = startIndex; i < num; i++)
323  {
324  if (match(Items[i]))
325  {
326  return i;
327  }
328  }
329  return -1;
330  }
331 
332  public T FindLast(Predicate<T> match)
333  {
334  for (int i = _size - 1; i >= 0; i--)
335  {
336  if (match(Items[i]))
337  {
338  return Items[i];
339  }
340  }
341  return default(T);
342  }
343 
344  public int FindLastIndex(Predicate<T> match)
345  {
346  return FindLastIndex(_size - 1, _size, match);
347  }
348 
349  public int FindLastIndex(int startIndex, Predicate<T> match)
350  {
351  return FindLastIndex(startIndex, startIndex + 1, match);
352  }
353 
354  public int FindLastIndex(int startIndex, int count, Predicate<T> match)
355  {
356  int num = startIndex - count;
357  for (int i = startIndex; i > num; i--)
358  {
359  if (match(Items[i]))
360  {
361  return i;
362  }
363  }
364  return -1;
365  }
366 
367  public void ForEach(Action<T> action)
368  {
369  for (int i = 0; i < _size; i++)
370  {
371  action(Items[i]);
372  }
373  }
374 
375  public Enumerator GetEnumerator()
376  {
377  return new Enumerator(this);
378  }
379 
380  public FastList<T> GetRange(int index, int count)
381  {
382  var list = new FastList<T>(count);
383  Array.Copy(Items, index, list.Items, 0, count);
384  list._size = count;
385  return list;
386  }
387 
388  public int IndexOf(T item, int index)
389  {
390  return Array.IndexOf(Items, item, index, _size - index);
391  }
392 
393  public int IndexOf(T item, int index, int count)
394  {
395  return Array.IndexOf(Items, item, index, count);
396  }
397 
398  public void InsertRange(int index, IEnumerable<T> collection)
399  {
400  var is2 = collection as ICollection<T>;
401  if (is2 != null)
402  {
403  int count = is2.Count;
404  if (count > 0)
405  {
406  EnsureCapacity(_size + count);
407  if (index < _size)
408  {
409  Array.Copy(Items, index, Items, index + count, _size - index);
410  }
411  if (this == is2)
412  {
413  Array.Copy(Items, 0, Items, index, index);
414  Array.Copy(Items, (index + count), Items, (index*2), (_size - index));
415  }
416  else
417  {
418  is2.CopyTo(Items, index);
419  }
420  _size += count;
421  }
422  }
423  else
424  {
425  using (IEnumerator<T> enumerator = collection.GetEnumerator())
426  {
427  while (enumerator.MoveNext())
428  {
429  Insert(index++, enumerator.Current);
430  }
431  }
432  }
433  }
434 
435  private static bool IsCompatibleObject(object value)
436  {
437  return ((value is T) || ((value == null) && (default(T) == null)));
438  }
439 
440  public int LastIndexOf(T item)
441  {
442  if (_size == 0)
443  {
444  return -1;
445  }
446  return LastIndexOf(item, _size - 1, _size);
447  }
448 
449  public int LastIndexOf(T item, int index)
450  {
451  return LastIndexOf(item, index, index + 1);
452  }
453 
454  public int LastIndexOf(T item, int index, int count)
455  {
456  if (_size == 0)
457  {
458  return -1;
459  }
460  return Array.LastIndexOf(Items, item, index, count);
461  }
462 
463  public int RemoveAll(Predicate<T> match)
464  {
465  int index = 0;
466  while ((index < _size) && !match(Items[index]))
467  {
468  index++;
469  }
470  if (index >= _size)
471  {
472  return 0;
473  }
474  int num2 = index + 1;
475  while (num2 < _size)
476  {
477  while ((num2 < _size) && match(Items[num2]))
478  {
479  num2++;
480  }
481  if (num2 < _size)
482  {
483  Items[index++] = Items[num2++];
484  }
485  }
486  Array.Clear(Items, index, _size - index);
487  int num3 = _size - index;
488  _size = index;
489  return num3;
490  }
491 
492  public void RemoveRange(int index, int count)
493  {
494  if (count > 0)
495  {
496  _size -= count;
497  if (index < _size)
498  {
499  Array.Copy(Items, index + count, Items, index, _size - index);
500  }
501  Array.Clear(Items, _size, count);
502  }
503  }
504 
505  public void Reverse()
506  {
507  Reverse(0, Count);
508  }
509 
510  public void Reverse(int index, int count)
511  {
512  Array.Reverse(Items, index, count);
513  }
514 
515  public void Sort()
516  {
517  Sort(0, Count, null);
518  }
519 
520  public void Sort(IComparer<T> comparer)
521  {
522  Sort(0, Count, comparer);
523  }
524 
525  //public void Sort(Comparison<T> comparison)
526  //{
527  // if (this._size > 0)
528  // {
529  // IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
530  // Array.Sort<T>(this.Items, 0, this._size, comparer);
531  // }
532  //}
533 
534  public void Sort(int index, int count, IComparer<T> comparer)
535  {
536  Array.Sort(Items, index, count, comparer);
537  }
538 
539  public T[] ToArray()
540  {
541  var destinationArray = new T[_size];
542  Array.Copy(Items, 0, destinationArray, 0, _size);
543  return destinationArray;
544  }
545 
546  public void TrimExcess()
547  {
548  var num = (int) (Items.Length*0.9);
549  if (_size < num)
550  {
551  Capacity = _size;
552  }
553  }
554 
555  public bool TrueForAll(Predicate<T> match)
556  {
557  for (int i = 0; i < _size; i++)
558  {
559  if (!match(Items[i]))
560  {
561  return false;
562  }
563  }
564  return true;
565  }
566 
567  // Properties
568 
569  // Nested Types
570 
571  #region Nested type: Enumerator
572 
573  [StructLayout(LayoutKind.Sequential)]
574  public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
575  {
576  private readonly FastList<T> list;
577  private int index;
578  private T current;
579 
580  internal Enumerator(FastList<T> list)
581  {
582  this.list = list;
583  index = 0;
584  current = default(T);
585  }
586 
587  public void Dispose()
588  {
589  }
590 
591  public bool MoveNext()
592  {
593  FastList<T> list = this.list;
594  if (index < list._size)
595  {
596  current = list.Items[index];
597  index++;
598  return true;
599  }
600  return MoveNextRare();
601  }
602 
603  private bool MoveNextRare()
604  {
605  index = list._size + 1;
606  current = default(T);
607  return false;
608  }
609 
610  public T Current
611  {
612  get { return current; }
613  }
614 
615  object IEnumerator.Current
616  {
617  get { return Current; }
618  }
619 
620  void IEnumerator.Reset()
621  {
622  index = 0;
623  current = default(T);
624  }
625  }
626 
627  #endregion
628  }
629 }
int FindLastIndex(int startIndex, Predicate< T > match)
Definition: FastList.cs:349
int LastIndexOf(T item, int index, int count)
Definition: FastList.cs:454
void Sort(int index, int count, IComparer< T > comparer)
Definition: FastList.cs:534
void AddRange(IEnumerable< T > collection)
Definition: FastList.cs:231
DataSerializerGenericMode
Defines what generic parameters to pass to the serializer.
FastList< T > GetRange(int index, int count)
Definition: FastList.cs:380
void CopyTo(T[] array, int arrayIndex)
Definition: FastList.cs:142
bool Exists(Predicate< T > match)
Definition: FastList.cs:279
Similar to List{T}, with direct access to underlying array.
Definition: FastList.cs:19
int BinarySearch(T item, IComparer< T > comparer)
Definition: FastList.cs:246
FastList(IEnumerable< T > collection)
Definition: FastList.cs:43
bool TrueForAll(Predicate< T > match)
Definition: FastList.cs:555
_In_ size_t count
Definition: DirectXTexP.h:174
void Clear(bool fastClear)
Clears this list with a fast-clear option.
Definition: FastList.cs:222
int RemoveAll(Predicate< T > match)
Definition: FastList.cs:463
void Sort(IComparer< T > comparer)
Definition: FastList.cs:520
void Reverse(int index, int count)
Definition: FastList.cs:510
int IndexOf(T item, int index, int count)
Definition: FastList.cs:393
ReadOnlyCollection< T > AsReadOnly()
Definition: FastList.cs:236
int FindIndex(Predicate< T > match)
Definition: FastList.cs:309
void CopyTo(int index, T[] array, int arrayIndex, int count)
Definition: FastList.cs:261
int FindLastIndex(Predicate< T > match)
Definition: FastList.cs:344
void InsertRange(int index, IEnumerable< T > collection)
Definition: FastList.cs:398
int FindLastIndex(int startIndex, int count, Predicate< T > match)
Definition: FastList.cs:354
int FindIndex(int startIndex, int count, Predicate< T > match)
Definition: FastList.cs:319
FastList< T > FindAll(Predicate< T > match)
Definition: FastList.cs:296
int BinarySearch(int index, int count, T item, IComparer< T > comparer)
Definition: FastList.cs:251
void RemoveRange(int index, int count)
Definition: FastList.cs:492
int FindIndex(int startIndex, Predicate< T > match)
Definition: FastList.cs:314