using System; using System.Collections.Generic; using System.Text; namespace Apewer { /// 数组构建器。 public sealed class ArrayBuilder { private Type _type = typeof(T); private T[] _array; private int _capacity; private int _count; private int _step; /// 创建构建程序实例。 /// 每次扩容的增量,最小值:1,默认值:256。 /// public ArrayBuilder(int step = 256) { if (step < 1) throw new ArgumentOutOfRangeException(nameof(step)); _step = step; _capacity = step; _count = 0; _array = new T[step]; } private ArrayBuilder(ArrayBuilder old) { _step = old._step; _capacity = old._capacity; _count = old._count; _array = new T[_capacity]; if (_count > 0) Array.Copy(old._array, _array, _count); } /// 获取或设置指定位置的元素,索引器范围为 [0, Length)。 /// public T this[int index] { get { if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。"); return _array[index]; } set { if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。"); _array[index] = value; } } /// 源数组。 public T[] Origin { get => _array; } /// 缓冲区的容量。 public int Capacity { get => _capacity; } /// 当前的元素数量。 public int Length { get => _count; } /// 当前的元素数量。 public int Count { get => _count; } /// 指定元素在数组中的偏移位置。 public int IndexOf(T value) { var array = _array; var length = _count; if (length < 1) return -1; for (var i = 0; i < length; i++) { var item = array[i]; if (item == null) continue; if (item.Equals(value)) return i; } return -1; } /// 已包含指定的元素。 public bool Contains(T value) => IndexOf(value) > -1; /// 添加元素。 public void Add(T item) { if (_capacity - _count < 1) { _capacity += _step; var temp = new T[_capacity]; Array.Copy(_array, temp, _count); _array = temp; } _array[_count] = item; _count++; } /// 添加多个元素。 public void Add(params T[] items) { if (items == null) return; var length = items.Length; if (length < 1) return; if (_capacity - _count < length) { _capacity = _count + length; var temp = new T[_capacity]; Array.Copy(_array, temp, _count); _array = temp; } Array.Copy(items, 0, _array, _count, length); _count += length; } /// 添加多个元素。 public void Add(ICollection items) { if (items == null) return; var length = items.Count; if (length < 1) return; if (_capacity - _count < length) { _capacity = _count + length; var temp = new T[_capacity]; Array.Copy(_array, temp, _count); _array = temp; } items.CopyTo(_array, _count); _count += length; } /// 添加多个元素。 public void Add(IEnumerable items) { if (items == null) return; foreach (var item in items) Add(item); } /// 添加元素。 /// 要添加的元素数组。 /// buffer 的开始位置。 /// buffer 的元素数量。 /// /// public void Add(T[] buffer, int offset, int count) { if (buffer == null) throw new ArgumentNullException(nameof(buffer)); var length = buffer.Length; if (offset < 0 || offset >= length || count < 0) throw new ArgumentOutOfRangeException(); if (offset + count > length) throw new ArgumentOutOfRangeException(); if (_capacity - _count < length) { _capacity = _count + length; var temp = new T[_capacity]; Array.Copy(_array, temp, _count); _array = temp; } Array.Copy(buffer, offset, _array, _count, count); _count += count; } /// 清空所有元素。 public void Clear() { _capacity = 0; _count = 0; _array = new T[0]; } // 修剪数组,去除剩余空间。 void Trim() { if (_count == 0) { if (_capacity > 0) { _capacity = 0; _array = new T[0]; } return; } if (_count == _capacity) return; var array = new T[_count]; Array.Copy(_array, array, _count); _capacity = _count; } #region 模仿 JavaScript 数组方法。 /// 添加元素。 public void Push(T item) => Add(item); /// 取出最后一个元素。 public T Pop(Func @default = null) { if (_count > 0) { var offset = _count - 1; var value = _array[offset]; _array[offset] = default(T); _count -= 1; return value; } return @default == null ? default(T) : @default.Invoke(); } /// 取出第一个元素,当数组为空时使用指定方法返回默认值。 public T Shift(Func @default = null) { if (_count > 0) { var value = _array[0]; var temp = new T[_count]; if (_count > 1) Array.Copy(_array, 1, temp, 0, _count - 1); _array = temp; _count -= 1; return value; } return @default == null ? default(T) : @default.Invoke(); } /// 添加元素到数组最前端。 public void Unshift(T item) { var remains = _capacity - _count; var length = remains > 0 ? _capacity : (_capacity + _step); var temp = new T[length]; temp[0] = item; if (_count > 0) { Array.Copy(_array, 0, temp, 1, _count); _count++; } _capacity = length; _array = temp; } #endregion #region 导出、转换。 /// 导出字符串。 public override string ToString() => ToString(null); /// 导出字符串。 /// 分隔符。 public string ToString(string separator) { var sb = new StringBuilder(); var hasSeparator = !string.IsNullOrEmpty(separator); if (_type.IsValueType) { for (var i = 0; i < _count; i++) { if (i > 0 && hasSeparator) sb.Append(separator); sb.Append(_array[i].ToString()); } } else { var isString = _type == typeof(string); for (var i = 0; i < _count; i++) { if (_array[i] == null) continue; if (i > 0 && hasSeparator) sb.Append(separator); sb.Append(isString ? _array[i] as string : _array[i].ToString()); } } return sb.ToString(); } /// 导出到新数组。 /// 导出后清空元素。 public T[] Export(bool clear = false) { if (_count == 0) return new T[0]; if (_count == _capacity) return _array; var array = new T[_count]; Array.Copy(_array, array, _count); if (clear) _array = new T[0]; return array; } /// 克隆当前实例,生成新实例。 public ArrayBuilder Clone() => new ArrayBuilder(this); /// 使用 Export 方法实现从 ArrayBuilder<T> 到 T[] 的隐式转换。 public static implicit operator T[](ArrayBuilder instance) => instance == null ? null : instance.Export(); internal static string Text(ArrayBuilder ab) { if (ab == null) return ""; if (ab._count < 1) return ""; return new string(ab._array, 0, ab._count); } internal static string Text(ArrayBuilder ab, int start, int count) { if (start < 0) throw new ArgumentOutOfRangeException("startIndex", "起始位置不可小于 0。"); if (count < 0) throw new ArgumentOutOfRangeException("maxCount", "最大数量不可小于 0。"); if (ab == null || count < 1) return ""; if (start < 0) start = 0; var total = ab._count; if (start + count > total) count = total - start; if (count < 1) return ""; return new string(ab._array, start, count); } internal static string Join(ArrayBuilder ab, string separator) { if (ab == null) return ""; return Join(ab, separator, 0, ab._count); } internal static string Join(ArrayBuilder ab, string separator, int start, int count) { if (start < 0) throw new ArgumentOutOfRangeException("startIndex", "起始位置不可小于 0。"); if (count < 0) throw new ArgumentOutOfRangeException("maxCount", "最大数量不可小于 0。"); if (ab == null || count < 1) return ""; // 数组为空。 if (start < 0) start = 0; // 修正起始位置最小值。 var total = ab._count; // 数组中的元素总数。 if (start + count > total) count = total - start; // 最大数量。 if (count < 1) return ""; // 不取任何元素。 var end = start + count; // 结束位置。 var se = string.IsNullOrEmpty(separator); // 分隔符为空。 var sb = new StringBuilder(); for (var i = start; i < end; i++) { var item = ab._array[i]; if (i > start && !se) sb.Append(separator); if (item == null || item == "") continue; sb.Append(item); } return sb.ToString(); } #endregion } }