using System; using System.Collections; using System.Collections.Generic; using System.Threading; using AspClassic.Scripting.Utils; namespace AspClassic.Scripting.Runtime; internal sealed class SymbolDictionary : BaseSymbolDictionary, IDictionary, ICollection, IDictionary, ICollection>, IAttributesCollection, IEnumerable>, IEnumerable { private Dictionary _data = new Dictionary(); ICollection IDictionary.Keys { get { List list = new List(); lock (this) { foreach (SymbolId key in _data.Keys) { if (!(key == BaseSymbolDictionary.ObjectKeys)) { list.Add(SymbolTable.IdToString(key)); } } Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists != null) { list.AddRange(objectKeysDictionaryIfExists.Keys); return list; } return list; } } } ICollection IDictionary.Values { get { lock (this) { Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists == null) { return _data.Values; } List list = new List(); foreach (KeyValuePair datum in _data) { if (!(datum.Key == BaseSymbolDictionary.ObjectKeys)) { list.Add(datum.Value); } } foreach (object value in objectKeysDictionaryIfExists.Values) { list.Add(value); } return list; } } } public object this[object key] { get { string text = key as string; lock (this) { if (text != null) { if (_data.TryGetValue(SymbolTable.StringToId(text), out var value)) { return value; } } else { Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists != null) { return objectKeysDictionaryIfExists[key]; } } } throw new KeyNotFoundException($"'{key}'"); } set { string text = key as string; lock (this) { if (text != null) { _data[SymbolTable.StringToId(text)] = value; return; } Dictionary objectKeysDictionary = GetObjectKeysDictionary(); objectKeysDictionary[key] = value; } } } public int Count { get { lock (this) { int num = _data.Count; Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists != null) { num += objectKeysDictionaryIfExists.Count - 1; } return num; } } } public bool IsReadOnly => false; object IAttributesCollection.this[SymbolId name] { get { lock (this) { return _data[name]; } } set { lock (this) { _data[name] = value; } } } public IDictionary SymbolAttributes { get { lock (this) { if (GetObjectKeysDictionaryIfExists() == null) { return _data; } Dictionary dictionary = new Dictionary(); foreach (KeyValuePair datum in _data) { if (!(datum.Key == BaseSymbolDictionary.ObjectKeys)) { dictionary.Add(datum.Key, datum.Value); } } return dictionary; } } } public ICollection Keys => AsObjectKeyedDictionary().Keys; public bool IsFixedSize => false; ICollection IDictionary.Keys { get { List list = new List(); lock (this) { foreach (SymbolId key in _data.Keys) { if (!(key == BaseSymbolDictionary.ObjectKeys)) { list.Add(SymbolTable.IdToString(key)); } } Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists != null) { list.AddRange(objectKeysDictionaryIfExists.Keys); return list; } return list; } } } ICollection IDictionary.Values { get { List list = new List(); lock (this) { foreach (KeyValuePair datum in _data) { if (!(datum.Key == BaseSymbolDictionary.ObjectKeys)) { list.Add(datum.Value); } } Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists != null) { list.AddRange(objectKeysDictionaryIfExists.Values); return list; } return list; } } } object IDictionary.this[object key] { get { return AsObjectKeyedDictionary()[key]; } set { AsObjectKeyedDictionary()[key] = value; } } public bool IsSynchronized => true; public object SyncRoot => this; public SymbolDictionary() { } public SymbolDictionary(IAttributesCollection from) { lock (from) { foreach (KeyValuePair item in from) { AsObjectKeyedDictionary().Add(item.Key, item.Value); } } } private Dictionary GetObjectKeysDictionary() { Dictionary dictionary = GetObjectKeysDictionaryIfExists(); if (dictionary == null) { dictionary = new Dictionary(); _data.Add(BaseSymbolDictionary.ObjectKeys, dictionary); } return dictionary; } private Dictionary GetObjectKeysDictionaryIfExists() { if (_data.TryGetValue(BaseSymbolDictionary.ObjectKeys, out var value)) { return (Dictionary)value; } return null; } void IDictionary.Add(object key, object value) { string text = key as string; lock (this) { if (text != null) { _data.Add(SymbolTable.StringToId(text), value); return; } Dictionary objectKeysDictionary = GetObjectKeysDictionary(); objectKeysDictionary[key] = value; } } bool IDictionary.ContainsKey(object key) { string text = key as string; lock (this) { if (text != null) { if (!SymbolTable.StringHasId(text)) { return false; } return _data.ContainsKey(SymbolTable.StringToId(text)); } return GetObjectKeysDictionaryIfExists()?.ContainsKey(key) ?? false; } } bool IDictionary.Remove(object key) { string text = key as string; lock (this) { if (text != null) { return _data.Remove(SymbolTable.StringToId(text)); } return GetObjectKeysDictionaryIfExists()?.Remove(key) ?? false; } } bool IDictionary.TryGetValue(object key, out object value) { string text = key as string; lock (this) { if (text != null) { return _data.TryGetValue(SymbolTable.StringToId(text), out value); } value = null; return GetObjectKeysDictionaryIfExists()?.TryGetValue(key, out value) ?? false; } } public void Add(KeyValuePair item) { string text = item.Key as string; lock (this) { if (text != null) { _data.Add(SymbolTable.StringToId(text), item.Value); return; } Dictionary objectKeysDictionary = GetObjectKeysDictionary(); objectKeysDictionary[item.Key] = item.Value; } } public void Clear() { lock (this) { _data.Clear(); } } public bool Contains(KeyValuePair item) { if (AsObjectKeyedDictionary().TryGetValue(item.Key, out var value) && value == item.Value) { return true; } return false; } public void CopyTo(KeyValuePair[] array, int arrayIndex) { ContractUtils.RequiresNotNull(array, "array"); lock (this) { ContractUtils.RequiresArrayRange(array, arrayIndex, Count, "arrayIndex", "array"); foreach (KeyValuePair item in (IEnumerable>)this) { array[arrayIndex++] = item; } } } public bool Remove(KeyValuePair item) { lock (this) { if (item.Key is string text && AsObjectKeyedDictionary().TryGetValue(text, out var value) && value == item.Value) { _data.Remove(SymbolTable.StringToId(text)); return true; } } return false; } IEnumerator> IEnumerable>.GetEnumerator() { bool lockTaken = false; SymbolDictionary obj2 = default(SymbolDictionary); try { SymbolDictionary obj; obj2 = (obj = this); Monitor.Enter(obj, ref lockTaken); foreach (KeyValuePair o in _data) { KeyValuePair keyValuePair = o; if (!(keyValuePair.Key == BaseSymbolDictionary.ObjectKeys)) { KeyValuePair keyValuePair2 = o; string key = SymbolTable.IdToString(keyValuePair2.Key); KeyValuePair keyValuePair3 = o; yield return new KeyValuePair(key, keyValuePair3.Value); } } Dictionary objData = GetObjectKeysDictionaryIfExists(); if (objData == null) { yield break; } foreach (KeyValuePair item in objData) { yield return item; } } finally { if (lockTaken) { Monitor.Exit(obj2); } } } public IEnumerator GetEnumerator() { foreach (KeyValuePair o in _data) { KeyValuePair keyValuePair = o; if (!(keyValuePair.Key == BaseSymbolDictionary.ObjectKeys)) { KeyValuePair keyValuePair2 = o; yield return SymbolTable.IdToString(keyValuePair2.Key); } } IDictionary objData = GetObjectKeysDictionaryIfExists(); if (objData == null) { yield break; } foreach (object key in objData.Keys) { yield return key; } } public void Add(SymbolId name, object value) { lock (this) { _data.Add(name, value); } } public bool ContainsKey(SymbolId name) { lock (this) { return _data.ContainsKey(name); } } public bool Remove(SymbolId name) { lock (this) { return _data.Remove(name); } } public bool TryGetValue(SymbolId name, out object value) { lock (this) { return _data.TryGetValue(name, out value); } } public void AddObjectKey(object name, object value) { AsObjectKeyedDictionary().Add(name, value); } public bool ContainsObjectKey(object name) { return AsObjectKeyedDictionary().ContainsKey(name); } public bool RemoveObjectKey(object name) { return AsObjectKeyedDictionary().Remove(name); } public bool TryGetObjectValue(object name, out object value) { return AsObjectKeyedDictionary().TryGetValue(name, out value); } public IDictionary AsObjectKeyedDictionary() { return this; } void IDictionary.Add(object key, object value) { AsObjectKeyedDictionary().Add(key, value); } public bool Contains(object key) { lock (this) { return AsObjectKeyedDictionary().ContainsKey(key); } } IDictionaryEnumerator IDictionary.GetEnumerator() { Dictionary objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists(); if (objectKeysDictionaryIfExists == null) { return new TransformDictionaryEnumerator(_data); } List list = new List(); list.Add(new TransformDictionaryEnumerator(_data)); Dictionary.Enumerator enumerator = objectKeysDictionaryIfExists.GetEnumerator(); list.Add(enumerator); return new DictionaryUnionEnumerator(list); } void IDictionary.Remove(object key) { string text = key as string; lock (this) { if (text != null) { _data.Remove(SymbolTable.StringToId(text)); } else { GetObjectKeysDictionaryIfExists()?.Remove(key); } } } public void CopyTo(Array array, int index) { ContractUtils.RequiresNotNull(array, "array"); lock (this) { ContractUtils.RequiresListRange(array, index, Count, "index", "array"); IEnumerator enumerator = GetEnumerator(); try { while (enumerator.MoveNext()) { object current = enumerator.Current; array.SetValue(current, index++); } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } } } }