/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Apache License, Version 2.0. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Apache License, Version 2.0, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Apache License, Version 2.0. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespace Microsoft.Scripting.Utils { /// /// A hybrid dictionary which compares based upon object identity. /// class HybridReferenceDictionary where TKey : class { private KeyValuePair[] _keysAndValues; private Dictionary _dict; private int _count; private const int _arraySize = 10; public HybridReferenceDictionary() { } public HybridReferenceDictionary(int initialCapicity) { if (initialCapicity > _arraySize) { _dict = new Dictionary(initialCapicity); } else { _keysAndValues = new KeyValuePair[initialCapicity]; } } public bool TryGetValue(TKey key, out TValue value) { Debug.Assert(key != null); if (_dict != null) { return _dict.TryGetValue(key, out value); } else if (_keysAndValues != null) { for (int i = 0; i < _keysAndValues.Length; i++) { if (_keysAndValues[i].Key == key) { value = _keysAndValues[i].Value; return true; } } } value = default(TValue); return false; } public bool Remove(TKey key) { Debug.Assert(key != null); if (_dict != null) { return _dict.Remove(key); } else if (_keysAndValues != null) { for (int i = 0; i < _keysAndValues.Length; i++) { if (_keysAndValues[i].Key == key) { _keysAndValues[i] = new KeyValuePair(); _count--; return true; } } } return false; } public bool ContainsKey(TKey key) { Debug.Assert(key != null); if (_dict != null) { return _dict.ContainsKey(key); } else if (_keysAndValues != null) { for (int i = 0; i < _keysAndValues.Length; i++) { if (_keysAndValues[i].Key == key) { return true; } } } return false; } public int Count { get { if (_dict != null) { return _dict.Count; } return _count; } } public IEnumerator> GetEnumerator() { if (_dict != null) { return _dict.GetEnumerator(); } return GetEnumeratorWorker(); } private IEnumerator> GetEnumeratorWorker() { if (_keysAndValues != null) { for (int i = 0; i < _keysAndValues.Length; i++) { if (_keysAndValues[i].Key != null) { yield return _keysAndValues[i]; } } } } public TValue this[TKey key] { get { Debug.Assert(key != null); TValue res; if (TryGetValue(key, out res)) { return res; } throw new KeyNotFoundException(); } set { Debug.Assert(key != null); if (_dict != null) { _dict[key] = value; } else { int index; if (_keysAndValues != null) { index = -1; for (int i = 0; i < _keysAndValues.Length; i++) { if (_keysAndValues[i].Key == key) { _keysAndValues[i] = new KeyValuePair(key, value); return; } else if (_keysAndValues[i].Key == null) { index = i; } } } else { _keysAndValues = new KeyValuePair[_arraySize]; index = 0; } if (index != -1) { _count++; _keysAndValues[index] = new KeyValuePair(key, value); } else { _dict = new Dictionary(); for (int i = 0; i < _keysAndValues.Length; i++) { _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value; } _keysAndValues = null; _dict[key] = value; } } } } } }