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;
}
}
}
}