using System; using System.Collections; using System.Text; namespace Be.Windows.Forms { internal class DataMap : ICollection, IEnumerable { readonly object _syncRoot = new object(); internal int _count; internal DataBlock _firstBlock; internal int _version; public DataMap() { } public DataMap(IEnumerable collection) { if (collection == null) { throw new ArgumentNullException("collection"); } foreach (DataBlock item in collection) { AddLast(item); } } public DataBlock FirstBlock { get { return _firstBlock; } } public void AddAfter(DataBlock block, DataBlock newBlock) { AddAfterInternal(block, newBlock); } public void AddBefore(DataBlock block, DataBlock newBlock) { AddBeforeInternal(block, newBlock); } public void AddFirst(DataBlock block) { if (_firstBlock == null) { AddBlockToEmptyMap(block); } else { AddBeforeInternal(_firstBlock, block); } } public void AddLast(DataBlock block) { if (_firstBlock == null) { AddBlockToEmptyMap(block); } else { AddAfterInternal(GetLastBlock(), block); } } public void Remove(DataBlock block) { RemoveInternal(block); } public void RemoveFirst() { if (_firstBlock == null) { throw new InvalidOperationException("The collection is empty."); } RemoveInternal(_firstBlock); } public void RemoveLast() { if (_firstBlock == null) { throw new InvalidOperationException("The collection is empty."); } RemoveInternal(GetLastBlock()); } public DataBlock Replace(DataBlock block, DataBlock newBlock) { AddAfterInternal(block, newBlock); RemoveInternal(block); return newBlock; } public void Clear() { DataBlock block = FirstBlock; while (block != null) { DataBlock nextBlock = block.NextBlock; InvalidateBlock(block); block = nextBlock; } _firstBlock = null; _count = 0; _version++; } void AddAfterInternal(DataBlock block, DataBlock newBlock) { newBlock._previousBlock = block; newBlock._nextBlock = block._nextBlock; newBlock._map = this; if (block._nextBlock != null) { block._nextBlock._previousBlock = newBlock; } block._nextBlock = newBlock; this._version++; this._count++; } void AddBeforeInternal(DataBlock block, DataBlock newBlock) { newBlock._nextBlock = block; newBlock._previousBlock = block._previousBlock; newBlock._map = this; if (block._previousBlock != null) { block._previousBlock._nextBlock = newBlock; } block._previousBlock = newBlock; if (_firstBlock == block) { _firstBlock = newBlock; } this._version++; this._count++; } void RemoveInternal(DataBlock block) { DataBlock previousBlock = block._previousBlock; DataBlock nextBlock = block._nextBlock; if (previousBlock != null) { previousBlock._nextBlock = nextBlock; } if (nextBlock != null) { nextBlock._previousBlock = previousBlock; } if (_firstBlock == block) { _firstBlock = nextBlock; } InvalidateBlock(block); _count--; _version++; } DataBlock GetLastBlock() { DataBlock lastBlock = null; for (DataBlock block = FirstBlock; block != null; block = block.NextBlock) { lastBlock = block; } return lastBlock; } void InvalidateBlock(DataBlock block) { block._map = null; block._nextBlock = null; block._previousBlock = null; } void AddBlockToEmptyMap(DataBlock block) { block._map = this; block._nextBlock = null; block._previousBlock = null; _firstBlock = block; _version++; _count++; } #region ICollection Members public void CopyTo(Array array, int index) { DataBlock[] blockArray = array as DataBlock[]; for (DataBlock block = FirstBlock; block != null; block = block.NextBlock) { blockArray[index++] = block; } } public int Count { get { return _count; } } public bool IsSynchronized { get { return false; } } public object SyncRoot { get { return _syncRoot; } } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { return new Enumerator(this); } #endregion #region Enumerator Nested Type internal class Enumerator : IEnumerator, IDisposable { DataMap _map; DataBlock _current; int _index; int _version; internal Enumerator(DataMap map) { _map = map; _version = map._version; _current = null; _index = -1; } object IEnumerator.Current { get { if (_index < 0 || _index > _map.Count) { throw new InvalidOperationException("Enumerator is positioned before the first element or after the last element of the collection."); } return _current; } } public bool MoveNext() { if (this._version != _map._version) { throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); } if (_index >= _map.Count) { return false; } if (++_index == 0) { _current = _map.FirstBlock; } else { _current = _current.NextBlock; } return (_index < _map.Count); } void IEnumerator.Reset() { if (this._version != this._map._version) { throw new InvalidOperationException("Collection was modified after the enumerator was instantiated."); } this._index = -1; this._current = null; } public void Dispose() { } } #endregion } }