aspclassic-core/AspClassic.Scripting/Runtime/SymbolDictionary.cs
Jelle Luteijn 484dbfc9d9 progress
2022-05-15 11:19:49 +02:00

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();
}
}
}
}
}