using System; using System.Collections.Generic; using System.Linq; using System.Text; using libxmltv.Interfaces; using System.Runtime.Serialization; using System.Collections; using System.Runtime.InteropServices; using System.Reflection; namespace libxmltv.Core { public class PropertyCollection : IPropertyCollection { private List items = new List(); public PropertyCollection() : this(new List()) { } public PropertyCollection(ICollection collection) { foreach (var t in collection) { items.Add(t); } } public int PropertyCount { get { return items.Count; } } public bool IsReadOnly { get { return (items as ICollection).IsReadOnly; } } public void AddProperty(T item) { items.Add(item); } public void ClearProperties() { items.Clear(); } public bool ContainsProperty(T item) { return items.Contains(item); } public void CopyPropertiesTo(T[] array, int arrayIndex) { items.CopyTo(array, arrayIndex); } public bool RemoveProperty(T item) { return items.Remove(item); } public IEnumerator GetEnumerator() { return items.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return items.GetEnumerator(); } } public class PropertyDictionary : PropertyDictionary { public PropertyDictionary() : base() { } public PropertyDictionary(IPropertyDictionary dictionary) : base(dictionary) { } public PropertyDictionary(IEqualityComparer comparer) : base(comparer) { } public PropertyDictionary(int capacity) :base(capacity) { } public PropertyDictionary(IPropertyDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) { } public PropertyDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { } protected PropertyDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } } public class PropertyDictionary : IPropertyDictionary { [StructLayout(LayoutKind.Sequential)] private struct Entry { public int hashCode; public int next; public TKey name; public TValue value; } private Entry[] entries { get{ List list = new List(); int index = 0; foreach (var t in properties) { Entry entry = new Entry(); entry.hashCode = this.properties.Comparer.GetHashCode(t.Key) & 0x7fffffff; entry.next = index + 1; entry.name = t.Key; entry.value = t.Value; list.Add(entry); index++; } return list.ToArray(); } } private int version { get { Type t = typeof(Dictionary); var field = t.GetField("version", BindingFlags.NonPublic | BindingFlags.Instance); var v = Convert.ToInt32(field.GetValue(properties)); return v; } } private Dictionary properties; public PropertyDictionary() { properties = new Dictionary(); } public PropertyDictionary(IPropertyDictionary dictionary) :this() { foreach (var d in dictionary) { properties.Add(d.Name, d.Value); } } public PropertyDictionary(IEqualityComparer comparer) { properties = new Dictionary(comparer); } public PropertyDictionary(int capacity) { properties = new Dictionary(capacity); } public PropertyDictionary(IPropertyDictionary dictionary, IEqualityComparer comparer) : this(comparer) { foreach (var d in dictionary) { properties.Add(d.Name, d.Value); } } public PropertyDictionary(int capacity, IEqualityComparer comparer) { properties = new Dictionary(capacity, comparer); } protected PropertyDictionary(SerializationInfo info, StreamingContext context) { } public IPropertyCollection PropertyKeys { get { return new PropertyCollection(properties.Keys); } } public IPropertyCollection PropertyValues { get { return new PropertyCollection(properties.Values); } } public TValue this[TKey key] { get { if (this.ContainsProperty(key)) { return properties[key]; } else { throw new KeyNotFoundException(string.Format("Property '{0}' does not exist.", key)); } } set { if (this.ContainsProperty(key)) { properties[key] = value; } else { throw new KeyNotFoundException(string.Format("Property '{0}' does not exist.", key)); } } } public void AddProperty(TKey key, TValue value) { if (properties.ContainsKey(key)) { this[key] = value; } else { properties.Add(key, value); } } public bool ContainsProperty(TKey key) { return properties.ContainsKey(key); } public bool RemoveProperty(TKey key) { return properties.Remove(key); } public bool TryGetPropertyValue(TKey key, out TValue value) { return properties.TryGetValue(key, out value); } public int PropertyCount { get { return properties.Count; } } public bool IsReadOnly { get { return (properties as ICollection).IsReadOnly; } } public void AddProperty(PropertyValuePair item) { AddProperty(item.Name, item.Value); } public void ClearProperties() { properties.Clear(); } public bool ContainsProperty(PropertyValuePair item) { return ContainsProperty(item.Name); } public void CopyPropertiesTo(PropertyValuePair[] array, int arrayIndex) { var list = properties.ToList().Cast>().ToList(); list.CopyTo(array, arrayIndex); } public bool RemoveProperty(PropertyValuePair item) { return RemoveProperty(item.Name); } IEnumerator> IEnumerable>.GetEnumerator() { return new PropertyDictionaryEnumerator(this, 2); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return properties.GetEnumerator(); } #region enumerator support public class PropertyDictionaryEnumerator: IEnumerator>, IDisposable { private PropertyDictionary dictionary; private int index; private PropertyValuePair current; private int getEnumeratorRetType; internal const int DictEntry = 1; internal const int KeyValuePair = 2; private int version; public PropertyDictionaryEnumerator(PropertyDictionary dictionary, int getEnumeratorRetType) { this.dictionary = dictionary; this.version = dictionary.version; this.index = 0; this.getEnumeratorRetType = getEnumeratorRetType; this.current = new PropertyValuePair(); } public PropertyValuePair Current { get { return this.current; } } public void Dispose() { } object IEnumerator.Current { get { if ((this.index == 0) || (this.index == (this.dictionary.Count() + 1))) { throw new InvalidOperationException("Operation can't happen"); } if (this.getEnumeratorRetType == 1) { return new DictionaryEntry(this.current.Name, this.current.Value); } return new PropertyValuePair(this.current.Name, this.current.Value); } } public bool MoveNext() { if (this.version != this.dictionary.version) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } while (this.index < this.dictionary.Count()) { if (this.dictionary.entries[this.index].hashCode >= 0) { this.current = new KeyValuePair(this.dictionary.entries[this.index].name, this.dictionary.entries[this.index].value); this.index++; return true; } this.index++; } this.index = this.dictionary.Count() + 1; this.current = new PropertyValuePair(); return false; } public void Reset() { if (this.version != this.dictionary.version) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); } this.index = 0; this.current = new KeyValuePair(); } } #endregion } }