网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
9.0 KiB

#if FAT
using System;
using System.Collections.Generic;
using System.Linq;
using LinqInternal.Collections.Specialized;
using LinqInternal.Collections.ThreadSafe;
using LinqInternal.Core;
namespace LinqInternal.Collections
{
[Serializable]
[System.Diagnostics.DebuggerNonUserCode]
internal class ProgressiveLookup<TKey, T> : ILookup<TKey, T>
{
private readonly IDictionary<TKey, IGrouping<TKey, T>> _cache;
private readonly IEqualityComparer<T> _itemComparer;
private readonly IEqualityComparer<TKey> _keyComparer;
private readonly ProgressiveSet<TKey> _keysReadonly;
private readonly Progressor<IGrouping<TKey, T>> _progressor;
public ProgressiveLookup(IEnumerable<IGrouping<TKey, T>> wrapped)
: this(wrapped, new NullAwareDictionary<TKey, IGrouping<TKey, T>>(), null, null)
{
// Empty
}
public ProgressiveLookup(IEnumerable<IGrouping<TKey, T>> wrapped, IEqualityComparer<TKey> keyComparer)
: this(wrapped, new NullAwareDictionary<TKey, IGrouping<TKey, T>>(keyComparer), keyComparer, null)
{
// Empty
}
protected ProgressiveLookup(IEnumerable<IGrouping<TKey, T>> wrapped, IDictionary<TKey, IGrouping<TKey, T>> cache, IEqualityComparer<TKey> keyComparer, IEqualityComparer<T> itemComparer)
{
if (cache == null)
{
throw new ArgumentNullException("cache");
}
_cache = cache;
_progressor = new Progressor<IGrouping<TKey, T>>(wrapped);
_progressor.SubscribeAction(obj => _cache.Add(new KeyValuePair<TKey, IGrouping<TKey, T>>(obj.Key, obj)));
_keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;
_itemComparer = itemComparer ?? EqualityComparer<T>.Default;
_keysReadonly = new ProgressiveSet<TKey>(Progressor<TKey>.CreateConverted(Progressor, input => input.Key), keyComparer);
}
protected ProgressiveLookup(Progressor<IGrouping<TKey, T>> wrapped, IDictionary<TKey, IGrouping<TKey, T>> cache, IEqualityComparer<TKey> keyComparer, IEqualityComparer<T> itemComparer)
{
if (cache == null)
{
throw new ArgumentNullException("cache");
}
_cache = cache;
_progressor = new Progressor<IGrouping<TKey, T>>(wrapped);
_progressor.SubscribeAction(obj => _cache.Add(new KeyValuePair<TKey, IGrouping<TKey, T>>(obj.Key, obj)));
_keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;
_itemComparer = itemComparer ?? EqualityComparer<T>.Default;
_keysReadonly = new ProgressiveSet<TKey>(Progressor<TKey>.CreateConverted(Progressor, input => input.Key), keyComparer);
}
protected ProgressiveLookup(TryTake<IGrouping<TKey, T>> tryTake, IDictionary<TKey, IGrouping<TKey, T>> cache, IEqualityComparer<TKey> keyComparer, IEqualityComparer<T> itemComparer)
{
if (cache == null)
{
throw new ArgumentNullException("cache");
}
_cache = cache;
_progressor = new Progressor<IGrouping<TKey, T>>(tryTake, false); // false because the underlaying structure may change
_progressor.SubscribeAction(obj => _cache.Add(new KeyValuePair<TKey, IGrouping<TKey, T>>(obj.Key, obj)));
_keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;
_itemComparer = itemComparer ?? EqualityComparer<T>.Default;
_keysReadonly = new ProgressiveSet<TKey>(Progressor<TKey>.CreateConverted(Progressor, input => input.Key), keyComparer);
}
public int Count
{
get
{
_progressor.AsEnumerable().Consume();
return _cache.Count;
}
}
public bool EndOfEnumeration
{
get { return _progressor.IsClosed; }
}
public IReadOnlyCollection<TKey> Keys
{
get { return _keysReadonly; }
}
protected IEqualityComparer<T> ItemComparer
{
get { return _itemComparer; }
}
protected IEqualityComparer<TKey> KeyComparer
{
get { return _keyComparer; }
}
protected Progressor<IGrouping<TKey, T>> Progressor
{
get { return _progressor; }
}
public IEnumerable<T> this[TKey key]
{
get
{
IGrouping<TKey, T> grouping;
if (TryGetValue(key, out grouping))
{
return grouping;
}
else
{
return ArrayReservoir<T>.EmptyArray;
}
}
}
public static ProgressiveLookup<TKey, T> Create(IEnumerable<T> source, Func<T, TKey> keySelector)
{
return new ProgressiveLookup<TKey, T>(source.GroupProgressiveBy(keySelector));
}
public static ProgressiveLookup<TKey, T> Create(IEnumerable<T> source, Func<T, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
{
return new ProgressiveLookup<TKey, T>(source.GroupProgressiveBy(keySelector, keyComparer), keyComparer);
}
public static ProgressiveLookup<TKey, T> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, T> elementSelector, IEqualityComparer<TKey> keyComparer)
{
return new ProgressiveLookup<TKey, T>(source.GroupProgressiveBy(keySelector, elementSelector, keyComparer), keyComparer);
}
public static ProgressiveLookup<TKey, T> Create(IEnumerable<KeyValuePair<TKey, T>> source)
{
return new ProgressiveLookup<TKey, T>(source.GroupProgressiveBy(item => item.Key, item => item.Value));
}
public static ProgressiveLookup<TKey, T> Create(IEnumerable<KeyValuePair<TKey, T>> source, IEqualityComparer<TKey> keyComparer)
{
return new ProgressiveLookup<TKey, T>(source.GroupProgressiveBy(item => item.Key, item => item.Value, keyComparer), keyComparer);
}
public bool Contains(TKey key)
{
if (_cache.ContainsKey(key))
{
return true;
}
else
{
IGrouping<TKey, T> item;
while (_progressor.TryTake(out item))
{
if (_keyComparer.Equals(key, item.Key))
{
return true;
}
}
return false;
}
}
public void CopyTo(KeyValuePair<TKey, IGrouping<TKey, T>>[] array)
{
_progressor.AsEnumerable().Consume();
_cache.CopyTo(array, 0);
}
public void CopyTo(KeyValuePair<TKey, IGrouping<TKey, T>>[] array, int arrayIndex)
{
_progressor.AsEnumerable().Consume();
_cache.CopyTo(array, arrayIndex);
}
public void CopyTo(KeyValuePair<TKey, IGrouping<TKey, T>>[] array, int arrayIndex, int countLimit)
{
Extensions.CanCopyTo(array, arrayIndex, countLimit);
_progressor.While(() => _cache.Count < countLimit).Consume();
_cache.CopyTo(array, arrayIndex, countLimit);
}
public void CopyTo(IGrouping<TKey, T>[] array, int arrayIndex)
{
_progressor.AsEnumerable().Consume();
_cache.Values.CopyTo(array, arrayIndex);
}
public void CopyTo(IGrouping<TKey, T>[] array)
{
_progressor.AsEnumerable().Consume();
_cache.Values.CopyTo(array, 0);
}
public void CopyTo(IGrouping<TKey, T>[] array, int arrayIndex, int countLimit)
{
Extensions.CanCopyTo(array, arrayIndex, countLimit);
_progressor.While(() => _cache.Count < countLimit).Consume();
_cache.Values.CopyTo(array, arrayIndex, countLimit);
}
public IEnumerator<IGrouping<TKey, T>> GetEnumerator()
{
foreach (var item in _cache)
{
yield return item.Value;
}
{
IGrouping<TKey, T> item;
while (_progressor.TryTake(out item))
{
yield return item;
}
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool TryGetValue(TKey key, out IGrouping<TKey, T> value)
{
if (_cache.TryGetValue(key, out value))
{
return true;
}
IGrouping<TKey, T> item;
while (_progressor.TryTake(out item))
{
if (_keyComparer.Equals(key, item.Key))
{
value = item;
return true;
}
}
return false;
}
}
}
#endif