575 lines
12 KiB
C#
575 lines
12 KiB
C#
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<object, object>, ICollection<KeyValuePair<object, object>>, IAttributesCollection, IEnumerable<KeyValuePair<object, object>>, IEnumerable
|
|
{
|
|
private Dictionary<SymbolId, object> _data = new Dictionary<SymbolId, object>();
|
|
|
|
ICollection<object> IDictionary<object, object>.Keys
|
|
{
|
|
get
|
|
{
|
|
List<object> list = new List<object>();
|
|
lock (this)
|
|
{
|
|
foreach (SymbolId key in _data.Keys)
|
|
{
|
|
if (!(key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
list.Add(SymbolTable.IdToString(key));
|
|
}
|
|
}
|
|
Dictionary<object, object> objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists();
|
|
if (objectKeysDictionaryIfExists != null)
|
|
{
|
|
list.AddRange(objectKeysDictionaryIfExists.Keys);
|
|
return list;
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
}
|
|
|
|
ICollection<object> IDictionary<object, object>.Values
|
|
{
|
|
get
|
|
{
|
|
lock (this)
|
|
{
|
|
Dictionary<object, object> objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists();
|
|
if (objectKeysDictionaryIfExists == null)
|
|
{
|
|
return _data.Values;
|
|
}
|
|
List<object> list = new List<object>();
|
|
foreach (KeyValuePair<SymbolId, object> 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<object, object> 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<object, object> objectKeysDictionary = GetObjectKeysDictionary();
|
|
objectKeysDictionary[key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
lock (this)
|
|
{
|
|
int num = _data.Count;
|
|
Dictionary<object, object> 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<SymbolId, object> SymbolAttributes
|
|
{
|
|
get
|
|
{
|
|
lock (this)
|
|
{
|
|
if (GetObjectKeysDictionaryIfExists() == null)
|
|
{
|
|
return _data;
|
|
}
|
|
Dictionary<SymbolId, object> dictionary = new Dictionary<SymbolId, object>();
|
|
foreach (KeyValuePair<SymbolId, object> datum in _data)
|
|
{
|
|
if (!(datum.Key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
dictionary.Add(datum.Key, datum.Value);
|
|
}
|
|
}
|
|
return dictionary;
|
|
}
|
|
}
|
|
}
|
|
|
|
public ICollection<object> Keys => AsObjectKeyedDictionary().Keys;
|
|
|
|
public bool IsFixedSize => false;
|
|
|
|
ICollection IDictionary.Keys
|
|
{
|
|
get
|
|
{
|
|
List<object> list = new List<object>();
|
|
lock (this)
|
|
{
|
|
foreach (SymbolId key in _data.Keys)
|
|
{
|
|
if (!(key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
list.Add(SymbolTable.IdToString(key));
|
|
}
|
|
}
|
|
Dictionary<object, object> objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists();
|
|
if (objectKeysDictionaryIfExists != null)
|
|
{
|
|
list.AddRange(objectKeysDictionaryIfExists.Keys);
|
|
return list;
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
}
|
|
|
|
ICollection IDictionary.Values
|
|
{
|
|
get
|
|
{
|
|
List<object> list = new List<object>();
|
|
lock (this)
|
|
{
|
|
foreach (KeyValuePair<SymbolId, object> datum in _data)
|
|
{
|
|
if (!(datum.Key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
list.Add(datum.Value);
|
|
}
|
|
}
|
|
Dictionary<object, object> 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<object, object> item in from)
|
|
{
|
|
AsObjectKeyedDictionary().Add(item.Key, item.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
private Dictionary<object, object> GetObjectKeysDictionary()
|
|
{
|
|
Dictionary<object, object> dictionary = GetObjectKeysDictionaryIfExists();
|
|
if (dictionary == null)
|
|
{
|
|
dictionary = new Dictionary<object, object>();
|
|
_data.Add(BaseSymbolDictionary.ObjectKeys, dictionary);
|
|
}
|
|
return dictionary;
|
|
}
|
|
|
|
private Dictionary<object, object> GetObjectKeysDictionaryIfExists()
|
|
{
|
|
if (_data.TryGetValue(BaseSymbolDictionary.ObjectKeys, out var value))
|
|
{
|
|
return (Dictionary<object, object>)value;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void IDictionary<object, object>.Add(object key, object value)
|
|
{
|
|
string text = key as string;
|
|
lock (this)
|
|
{
|
|
if (text != null)
|
|
{
|
|
_data.Add(SymbolTable.StringToId(text), value);
|
|
return;
|
|
}
|
|
Dictionary<object, object> objectKeysDictionary = GetObjectKeysDictionary();
|
|
objectKeysDictionary[key] = value;
|
|
}
|
|
}
|
|
|
|
bool IDictionary<object, object>.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<object, object>.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<object, object>.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<object, object> item)
|
|
{
|
|
string text = item.Key as string;
|
|
lock (this)
|
|
{
|
|
if (text != null)
|
|
{
|
|
_data.Add(SymbolTable.StringToId(text), item.Value);
|
|
return;
|
|
}
|
|
Dictionary<object, object> objectKeysDictionary = GetObjectKeysDictionary();
|
|
objectKeysDictionary[item.Key] = item.Value;
|
|
}
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
lock (this)
|
|
{
|
|
_data.Clear();
|
|
}
|
|
}
|
|
|
|
public bool Contains(KeyValuePair<object, object> item)
|
|
{
|
|
if (AsObjectKeyedDictionary().TryGetValue(item.Key, out var value) && value == item.Value)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
|
|
{
|
|
ContractUtils.RequiresNotNull(array, "array");
|
|
lock (this)
|
|
{
|
|
ContractUtils.RequiresArrayRange(array, arrayIndex, Count, "arrayIndex", "array");
|
|
foreach (KeyValuePair<object, object> item in (IEnumerable<KeyValuePair<object, object>>)this)
|
|
{
|
|
array[arrayIndex++] = item;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool Remove(KeyValuePair<object, object> 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<KeyValuePair<object, object>> IEnumerable<KeyValuePair<object, object>>.GetEnumerator()
|
|
{
|
|
bool lockTaken = false;
|
|
SymbolDictionary obj2 = default(SymbolDictionary);
|
|
try
|
|
{
|
|
SymbolDictionary obj;
|
|
obj2 = (obj = this);
|
|
Monitor.Enter(obj, ref lockTaken);
|
|
foreach (KeyValuePair<SymbolId, object> o in _data)
|
|
{
|
|
KeyValuePair<SymbolId, object> keyValuePair = o;
|
|
if (!(keyValuePair.Key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
KeyValuePair<SymbolId, object> keyValuePair2 = o;
|
|
string key = SymbolTable.IdToString(keyValuePair2.Key);
|
|
KeyValuePair<SymbolId, object> keyValuePair3 = o;
|
|
yield return new KeyValuePair<object, object>(key, keyValuePair3.Value);
|
|
}
|
|
}
|
|
Dictionary<object, object> objData = GetObjectKeysDictionaryIfExists();
|
|
if (objData == null)
|
|
{
|
|
yield break;
|
|
}
|
|
foreach (KeyValuePair<object, object> item in objData)
|
|
{
|
|
yield return item;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (lockTaken)
|
|
{
|
|
Monitor.Exit(obj2);
|
|
}
|
|
}
|
|
}
|
|
|
|
public IEnumerator GetEnumerator()
|
|
{
|
|
foreach (KeyValuePair<SymbolId, object> o in _data)
|
|
{
|
|
KeyValuePair<SymbolId, object> keyValuePair = o;
|
|
if (!(keyValuePair.Key == BaseSymbolDictionary.ObjectKeys))
|
|
{
|
|
KeyValuePair<SymbolId, object> keyValuePair2 = o;
|
|
yield return SymbolTable.IdToString(keyValuePair2.Key);
|
|
}
|
|
}
|
|
IDictionary<object, object> 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<object, object> 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<object, object> objectKeysDictionaryIfExists = GetObjectKeysDictionaryIfExists();
|
|
if (objectKeysDictionaryIfExists == null)
|
|
{
|
|
return new TransformDictionaryEnumerator(_data);
|
|
}
|
|
List<IDictionaryEnumerator> list = new List<IDictionaryEnumerator>();
|
|
list.Add(new TransformDictionaryEnumerator(_data));
|
|
Dictionary<object, object>.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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|