using System; using System.Collections; using System.Collections.Generic; namespace Cryville.Common.Buffers { /// /// An auto-resized array as a variable-length string used as a target that is modified frequently. /// public class TargetString : IEnumerable { public event Action OnUpdate; char[] _arr; bool _invalidated; /// /// Creates an instance of the class with a capacity of 16. /// public TargetString() : this(16) { } /// /// Creates an instance of the class. /// /// The initial capacity of the string. /// is less than or equal to 0. public TargetString(int capacity) { if (capacity <= 0) throw new ArgumentOutOfRangeException("capacity"); _arr = new char[capacity]; } /// /// Gets or sets one of the characters in the string. /// /// The zero-based index of the character. /// The character at the given index. /// is less than 0 or not less than . /// /// Set to a desired value before updating the characters. /// Call after all the characters are updated. /// public char this[int index] { get { if (index < 0 || index >= m_length) throw new ArgumentOutOfRangeException("index"); return _arr[index]; } set { if (index < 0 || index >= m_length) throw new ArgumentOutOfRangeException("index"); if (_arr[index] == value) return; _arr[index] = value; _invalidated = true; } } int m_length; /// /// The length of the string. /// /// The value specified for a set operation is less than 0. public int Length { get { return m_length; } set { if (Length < 0) throw new ArgumentOutOfRangeException("length"); if (m_length == value) return; if (_arr.Length < value) { var len = _arr.Length; while (len < value) len *= 2; var arr2 = new char[len]; Array.Copy(_arr, arr2, m_length); _arr = arr2; } m_length = value; _invalidated = true; } } /// /// Validates the string. /// public void Validate() { if (!_invalidated) return; _invalidated = false; var ev = OnUpdate; if (ev != null) ev.Invoke(); } internal char[] TrustedAsArray() { return _arr; } /// /// Returns an enumerator that iterates through the . /// /// A for the . public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } public struct Enumerator : IEnumerator { readonly TargetString _self; int _index; internal Enumerator(TargetString self) { _self = self; _index = -1; } public char Current { get { if (_index < 0) throw new InvalidOperationException(_index == -1 ? "Enum not started" : "Enum ended"); return _self[_index]; } } object IEnumerator.Current { get { return Current; } } public void Dispose() { _index = -2; } public bool MoveNext() { if (_index == -2) return false; _index++; if (_index >= _self.Length) { _index = -2; return false; } return true; } public void Reset() { _index = -1; } } } }