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 { [Serializable] internal 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 { ICollection collection = (items as ICollection); if (collection == null) { throw new InvalidCastException(string.Format("Unable to cast: '{0}' to '{1}'", items.GetType().Name, typeof(ICollection).Name)); } return collection.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 override string ToString() { return string.Format("Property Count: {0}", PropertyCount); } } [Serializable] internal class PropertyDictionary : PropertyDictionary, IPropertyDictionary { 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) { } } [Serializable] internal class PropertyDictionary : IPropertyDictionary { [StructLayout(LayoutKind.Sequential)] private struct Entry { public int hashCode; public int next; public TKey name; public TValue value; public override string ToString() { return new PropertyValuePair(name, value).ToString(); } } 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(this.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 { IDictionary collection = (properties as IDictionary); if (collection == null) { throw new InvalidCastException(string.Format("Unable to cast: '{0}' to '{1}'", properties.GetType().Name, typeof(IDictionary).Name)); } return collection.IsReadOnly; } } public void AddProperty(IPropertyValuePair item) { AddProperty(item.Name, item.Value); } public void ClearProperties() { properties.Clear(); } public bool ContainsProperty(IPropertyValuePair item) { return ContainsProperty(item.Name); } public void CopyPropertiesTo(IPropertyValuePair[] array, int arrayIndex) { var list = properties.ToList().Cast>().ToList(); list.CopyTo(array, arrayIndex); } public bool RemoveProperty(IPropertyValuePair item) { return RemoveProperty(item.Name); } public IEnumerator> GetEnumerator() { //return new PropertyDictionaryEnumerator(this, 2); List> list = new List>(); foreach (var k in properties) { list.Add(new PropertyValuePair(k.Key, k.Value)); } return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return properties.GetEnumerator(); } public override string ToString() { return string.Format("Property Count: {0}", PropertyCount); } #region enumerator support //public class PropertyDictionaryEnumerator : IEnumerator>, IDisposable //{ // private PropertyDictionary dictionary; // private int index; // private IPropertyValuePair 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 IPropertyValuePair 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 =(IPropertyValuePair)(PropertyValuePair)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 = (IPropertyValuePair)(PropertyValuePair)new KeyValuePair(); // } //} #endregion } }