/** * DotGNU.Net.NameObjectCollectionBase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Gleb Novodran * Modifications: Michael Moore (mtmoore@uga.edu) */ using System; using System.Collections; using System.Runtime.Serialization; namespace System.Web { [Serializable] public abstract class NameObjectCollectionBase : ICollection, IEnumerable, ISerializable, IDeserializationCallback { private Hashtable m_ItemsContainer; /** Extends Hashtable based Items container to support storing null-key pairs */ private _Item m_NullKeyItem; private ArrayList m_ItemsArray; private IHashCodeProvider m_hashprovider; private IComparer m_comparer; private int m_defCapacity; private bool m_readonly; internal IComparer Comparer { get {return m_comparer;} } internal IHashCodeProvider HashCodeProvider { get {return m_hashprovider;} } internal protected /*?*/ class _Item { public string key; public object value; public _Item(string key, object value) { this.key = key; this.value = value; } } /** Implements IEnumerable interface for KeysCollection */ [Serializable] internal protected class KeysEnumerator : IEnumerator { private NameObjectCollectionBase m_collection; private int m_position; internal KeysEnumerator(NameObjectCollectionBase collection) { m_collection = collection; Reset(); } public object Current { get{ if ((m_position0); // throw new Exception("Not implemented yet"); } protected void BaseRemove( string name ) { int cnt = 0; String key; if (this.IsReadOnly) throw new NotSupportedException("Collection is read-only"); if (name!=null) { m_ItemsContainer.Remove(name); } else { m_NullKeyItem = null; } cnt = m_ItemsArray.Count; for (int i=0 ; i< cnt; ){ key=BaseGetKey(i); // TODO: consider case-sensivity if (String.Compare(key,name)==0){ m_ItemsArray.RemoveAt(i); cnt--; } else i++; } // throw new Exception("Not implemented yet"); } /** This function implemented the way Microsoft implemented it - item is removed from hashtable and array without considering the case when there are two items with the same key but different values in array. E.g. if hashtable is [("Key1","value1")] and array contains [("Key1","value1")("Key1","value2")] then after RemoveAt(1) the collection will be in following state: hashtable:[] array: [("Key1","value1")] It's ok only then the key is uniquely assosiated with the value To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added */ protected void BaseRemoveAt( int index ) { if (this.IsReadOnly) throw new NotSupportedException("Collection is read-only"); string key = BaseGetKey(index); if (key!=null){ // TODO: see LAME description above m_ItemsContainer.Remove(key); } else m_NullKeyItem = null; m_ItemsArray.RemoveAt(index); // throw new Exception("Not implemented yet"); } /** Sets the value of the entry at the specified index of the NameObjectCollectionBase instance */ protected void BaseSet( int index, object value ) { if (this.IsReadOnly) throw new NotSupportedException("Collection is read-only"); _Item item = (_Item)m_ItemsArray[index]; item.value = value; //throw new Exception("Not implemented yet"); } /** Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance */ protected void BaseSet( string name, object value ) { if (this.IsReadOnly) throw new NotSupportedException("Collection is read-only"); _Item item = FindFirstMatchedItem(name); if (item!=null) item.value=value; else BaseAdd(name, value); //throw new Exception("Not implemented yet"); } private _Item FindFirstMatchedItem(string name) { if (name!=null) return (_Item)m_ItemsContainer[name]; else { //TODO: consider null key case return m_NullKeyItem; //throw new Exception("Not implemented yet"); } } } }