You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.7 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace Apewer
  5. {
  6. /// <summary>数组构建器。</summary>
  7. public sealed class ArrayBuilder<T>
  8. {
  9. private T[] _array;
  10. private int _capacity;
  11. private int _count;
  12. private int _step;
  13. /// <summary>创建构建程序实例。</summary>
  14. /// <param name="step">每次扩容的增量,最小值:1,默认值:256。</param>
  15. /// <exception cref="ArgumentNullException"></exception>
  16. public ArrayBuilder(int step = 256)
  17. {
  18. if (step < 1) throw new ArgumentOutOfRangeException(nameof(step));
  19. _step = step;
  20. _capacity = step;
  21. _count = 0;
  22. _array = new T[step];
  23. }
  24. private ArrayBuilder(ArrayBuilder<T> old)
  25. {
  26. _step = old._step;
  27. _capacity = old._capacity;
  28. _count = old._count;
  29. _array = new T[_capacity];
  30. if (_count > 0) Array.Copy(old._array, _array, _count);
  31. }
  32. /// <summary>获取或设置指定位置的元素,索引器范围为 [0, Length)。</summary>
  33. /// <exception cref="ArgumentOutOfRangeException"></exception>
  34. public T this[int index]
  35. {
  36. get
  37. {
  38. if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
  39. return _array[index];
  40. }
  41. set
  42. {
  43. if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
  44. _array[index] = value;
  45. }
  46. }
  47. /// <summary>缓冲区的容量。</summary>
  48. public int Capacity { get => _capacity; }
  49. /// <summary>当前的元素数量。</summary>
  50. public int Length { get => _count; }
  51. /// <summary>当前的元素数量。</summary>
  52. public int Count { get => _count; }
  53. /// <summary>指定元素在数组中的偏移位置。</summary>
  54. public int IndexOf(T value)
  55. {
  56. var array = _array;
  57. var length = _count;
  58. if (length < 1) return -1;
  59. for (var i = 0; i < length; i++)
  60. {
  61. var item = array[i];
  62. if (item == null) continue;
  63. if (item.Equals(value)) return i;
  64. }
  65. return -1;
  66. }
  67. /// <summary>已包含指定的元素。</summary>
  68. public bool Contains(T value) => IndexOf(value) > -1;
  69. /// <summary>添加元素。</summary>
  70. public void Add(T item)
  71. {
  72. if (_capacity - _count < 1)
  73. {
  74. _capacity += _step;
  75. var temp = new T[_capacity];
  76. Array.Copy(_array, temp, _count);
  77. _array = temp;
  78. }
  79. _array[_count] = item;
  80. _count++;
  81. }
  82. /// <summary>添加多个元素。</summary>
  83. public void Add(params T[] items)
  84. {
  85. if (items == null) return;
  86. var length = items.Length;
  87. if (length < 1) return;
  88. if (_capacity - _count < length)
  89. {
  90. _capacity = _count + length;
  91. var temp = new T[_capacity];
  92. Array.Copy(_array, temp, _count);
  93. _array = temp;
  94. }
  95. Array.Copy(items, _array, length);
  96. _count += length;
  97. }
  98. /// <summary>添加多个元素。</summary>
  99. public void Add(ICollection<T> items)
  100. {
  101. if (items == null) return;
  102. var length = items.Count;
  103. if (length < 1) return;
  104. if (_capacity - _count < length)
  105. {
  106. _capacity = _count + length;
  107. var temp = new T[_capacity];
  108. Array.Copy(_array, temp, _count);
  109. _array = temp;
  110. }
  111. items.CopyTo(_array, _count);
  112. _count += length;
  113. }
  114. /// <summary>添加多个元素。</summary>
  115. public void Add(IEnumerable<T> items)
  116. {
  117. if (items == null) return;
  118. foreach (var item in items) Add(item);
  119. }
  120. /// <summary>添加元素。</summary>
  121. /// <param name="buffer">要添加的元素数组。</param>
  122. /// <param name="offset">buffer 的开始位置。</param>
  123. /// <param name="count">buffer 的元素数量。</param>
  124. /// <exception cref="ArgumentNullException"></exception>
  125. /// <exception cref="ArgumentOutOfRangeException"></exception>
  126. public void Add(T[] buffer, int offset, int count)
  127. {
  128. if (buffer == null) throw new ArgumentNullException(nameof(buffer));
  129. var length = buffer.Length;
  130. if (offset < 0 || offset >= length || count < 0) throw new ArgumentOutOfRangeException();
  131. if (offset + count > length) throw new ArgumentOutOfRangeException();
  132. if (_capacity - _count < length)
  133. {
  134. _capacity = _count + length;
  135. var temp = new T[_capacity];
  136. Array.Copy(_array, temp, _count);
  137. _array = temp;
  138. }
  139. Array.Copy(buffer, offset, _array, _count, count);
  140. _count = _capacity;
  141. }
  142. /// <summary>清空所有元素。</summary>
  143. public void Clear()
  144. {
  145. _capacity = 0;
  146. _count = 0;
  147. _array = new T[0];
  148. }
  149. // 修剪数组,去除剩余空间。
  150. void Trim()
  151. {
  152. if (_count == 0)
  153. {
  154. if (_capacity > 0)
  155. {
  156. _capacity = 0;
  157. _array = new T[0];
  158. }
  159. return;
  160. }
  161. if (_count == _capacity) return;
  162. var array = new T[_count];
  163. Array.Copy(_array, array, _count);
  164. _capacity = _count;
  165. }
  166. /// <summary></summary>
  167. /// <param name="clear"></param>
  168. /// <returns></returns>
  169. public T[] Export(bool clear = false)
  170. {
  171. if (_count == 0) return new T[0];
  172. if (_count == _capacity) return _array;
  173. var array = new T[_count];
  174. Array.Copy(_array, array, _count);
  175. return array;
  176. }
  177. /// <summary>克隆当前实例,生成新实例。</summary>
  178. public ArrayBuilder<T> Clone() => new ArrayBuilder<T>(this);
  179. /// <summary>使用 Export 方法实现从 ArrayBuilder&lt;T&gt; 到 T[] 的隐式转换。</summary>
  180. public static implicit operator T[](ArrayBuilder<T> instance) => instance == null ? null : instance.Export();
  181. }
  182. }