wasSharp

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 9  →  ?path2? @ 10
/Collections/Generic/CircularQueue.cs
@@ -0,0 +1,232 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections.Generic;
 
namespace wasSharp.Collections.Generic
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// A circular queue implementation based on linked lists.
/// </summary>
/// <typeparam name="T">the type of value to store</typeparam>
public class CircularQueue<T>
{
private readonly LinkedList<T> Store = new LinkedList<T>();
private LinkedListNode<T> CurrentNode;
 
private readonly object SyncRoot = new object();
 
public CircularQueue()
{
}
 
public CircularQueue(IEnumerable<T> items)
{
Enqueue(items);
}
 
public CircularQueue(CircularQueue<T> queue)
{
lock (SyncRoot)
{
lock (queue.SyncRoot)
{
foreach (var item in queue.Items)
{
Store.AddLast(item);
}
 
if (CurrentNode == null)
CurrentNode = Store.First;
}
}
}
 
public int Count
{
get
{
lock (SyncRoot)
{
return Store.Count;
}
}
}
 
private T GetNext
{
get
{
lock (SyncRoot)
{
if (CurrentNode == null)
return default(T);
 
var value = CurrentNode.Value;
 
switch (CurrentNode.Next != null)
{
case true:
CurrentNode = CurrentNode.Next;
break;
default:
CurrentNode = Store.First;
break;
}
 
return value;
}
}
}
 
public IEnumerable<T> Items
{
get
{
lock (SyncRoot)
{
if (CurrentNode == null)
yield break;
 
var node = CurrentNode;
do
{
yield return node.Value;
node = node.Next;
} while (node != null);
}
}
}
 
public void Enqueue(IEnumerable<T> items)
{
lock (SyncRoot)
{
foreach (var i in items)
Store.AddLast(i);
 
if (CurrentNode == null)
CurrentNode = Store.First;
}
}
 
public void Enqueue(T item)
{
lock (SyncRoot)
{
Store.AddLast(item);
 
if (CurrentNode == null)
CurrentNode = Store.First;
}
}
 
public T Dequeue()
{
lock (SyncRoot)
{
return GetNext;
}
}
 
public IEnumerable<T> Dequeue(int count = 1)
{
if (count <= 0)
yield break;
 
lock (SyncRoot)
{
if (CurrentNode == null)
yield break;
 
do
{
yield return GetNext;
} while (--count != 0);
}
}
 
public void Clear()
{
lock (SyncRoot)
{
Store.Clear();
 
CurrentNode = null;
}
}
 
public bool Contains(T item)
{
lock (SyncRoot)
{
return Store.Contains(item);
}
}
 
public void CopyTo(T[] array, int arrayIndex)
{
lock (SyncRoot)
{
Store.CopyTo(array, arrayIndex);
}
}
 
public bool Remove(T item)
{
lock (SyncRoot)
{
var node = Store.Find(item);
if (node == null)
return false;
if (CurrentNode.Equals(node))
{
switch (node.Next != null)
{
case true:
CurrentNode = node.Next;
break;
default:
CurrentNode = Store.First;
break;
}
}
Store.Remove(node);
return true;
}
}
 
public void RemoveAll(IEnumerable<T> items)
{
var itemSet = new HashSet<T>(items);
lock (SyncRoot)
{
var node = CurrentNode;
do
{
var next = node.Next;
if (itemSet.Contains(node.Value))
{
switch (next != null)
{
case true:
CurrentNode = next;
break;
default:
CurrentNode = Store.First;
break;
}
Store.Remove(node);
}
node = next;
} while (node != null);
}
}
}
}
/Collections/Generic/RangeCollection.cs
@@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections;
using System.Collections.Generic;
using System.Linq;
 
namespace wasSharp.Collections.Generic
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// A collection that maps ranges to values with O(1) complexity
/// lookups and O(n) insertions.
/// </summary>
/// <typeparam name="T">the type of value to store</typeparam>
public class RangeCollection<T> : IEnumerable
{
private readonly Dictionary<int, T> map;
 
public RangeCollection(int min, int max)
{
map = new Dictionary<int, T>(max - min);
}
 
public T this[int x]
{
get
{
T value;
return map.TryGetValue(x, out value) ? value : default(T);
}
}
 
public IEnumerator GetEnumerator()
{
return ((IEnumerable) map).GetEnumerator();
}
 
/// <summary>
/// Map a value to a range.
/// </summary>
/// <param name="Value">the value for the range</param>
/// <param name="min">the minimal range</param>
/// <param name="max">the maximal range</param>
public void Add(T Value, int min, int max)
{
foreach (var i in Enumerable.Range(min, max - min + 1))
{
map.Add(i, Value);
}
}
}
}
/Collections/Generic/SerializableDictionary.cs
@@ -0,0 +1,129 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
 
namespace wasSharp.Collections.Generic
{
/// <summary>
/// A serializable dictionary class.
/// </summary>
/// <typeparam name="TKey">the key</typeparam>
/// <typeparam name="TValue">the value</typeparam>
[XmlRoot("Dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
 
public SerializableDictionary(IEnumerable<KeyValuePair<TKey, TValue>> kvp)
{
foreach (var i in kvp)
{
Add(i.Key, i.Value);
}
}
 
public SerializableDictionary()
{
}
 
/// <summary>
/// Deep-clones the serializable dictionary.
/// </summary>
/// <returns>a deep clone of the original dictionary</returns>
public SerializableDictionary<TKey, TValue> Clone()
{
SerializableDictionary<TKey, TValue> clone;
try
{
using (var writer = new MemoryStream())
{
var serializer =
new XmlSerializer(
typeof(SerializableDictionary<TKey, TValue>));
serializer.Serialize(writer, this);
writer.Seek(0, SeekOrigin.Begin);
clone = (SerializableDictionary<TKey, TValue>)
new XmlSerializer(
typeof(SerializableDictionary<TKey, TValue>))
.Deserialize(writer);
}
}
/* cloning failed so return an empty dictionary */
catch (Exception)
{
clone = new SerializableDictionary<TKey, TValue>();
}
return clone;
}
 
public XmlSchema GetSchema()
{
return null;
}
 
public void ReadXml(XmlReader reader)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
 
var wasEmpty = reader.IsEmptyElement;
reader.Read();
 
if (wasEmpty)
return;
 
while (!reader.NodeType.Equals(XmlNodeType.EndElement))
{
reader.ReadStartElement("Item");
 
reader.ReadStartElement("Key");
var key = (TKey) keySerializer.Deserialize(reader);
reader.ReadEndElement();
 
reader.ReadStartElement("Value");
var value = (TValue) valueSerializer.Deserialize(reader);
reader.ReadEndElement();
 
Add(key, value);
 
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
 
public void WriteXml(XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
 
foreach (var key in Keys)
{
writer.WriteStartElement("Item");
 
writer.WriteStartElement("Key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
 
writer.WriteStartElement("Value");
var value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
 
writer.WriteEndElement();
}
}
 
#endregion
}
}
/Collections/Generic/SerializableSortedDictionary.cs
@@ -0,0 +1,129 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
 
namespace wasSharp.Collections.Generic
{
/// <summary>
/// A serializable sorted dictionary class.
/// </summary>
/// <typeparam name="TKey">the key</typeparam>
/// <typeparam name="TValue">the value</typeparam>
[XmlRoot("SortedDictionary")]
public class SerializableSortedDictionary<TKey, TValue>
: SortedDictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
 
public SerializableSortedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> kvp)
{
foreach (var i in kvp)
{
Add(i.Key, i.Value);
}
}
 
public SerializableSortedDictionary()
{
}
 
/// <summary>
/// Deep-clones the serializable dictionary.
/// </summary>
/// <returns>a deep clone of the original dictionary</returns>
public SerializableSortedDictionary<TKey, TValue> Clone()
{
SerializableSortedDictionary<TKey, TValue> clone;
try
{
using (var writer = new MemoryStream())
{
var serializer =
new XmlSerializer(
typeof(SerializableDictionary<TKey, TValue>));
serializer.Serialize(writer, this);
writer.Seek(0, SeekOrigin.Begin);
clone = (SerializableSortedDictionary<TKey, TValue>)
new XmlSerializer(
typeof(SerializableSortedDictionary<TKey, TValue>))
.Deserialize(writer);
}
}
/* cloning failed so return an empty dictionary */
catch (Exception)
{
clone = new SerializableSortedDictionary<TKey, TValue>();
}
return clone;
}
 
public XmlSchema GetSchema()
{
return null;
}
 
public void ReadXml(XmlReader reader)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
 
var wasEmpty = reader.IsEmptyElement;
reader.Read();
 
if (wasEmpty)
return;
 
while (!reader.NodeType.Equals(XmlNodeType.EndElement))
{
reader.ReadStartElement("Item");
 
reader.ReadStartElement("Key");
var key = (TKey) keySerializer.Deserialize(reader);
reader.ReadEndElement();
 
reader.ReadStartElement("Value");
var value = (TValue) valueSerializer.Deserialize(reader);
reader.ReadEndElement();
 
Add(key, value);
 
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
 
public void WriteXml(XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
 
foreach (var key in Keys)
{
writer.WriteStartElement("Item");
 
writer.WriteStartElement("Key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
 
writer.WriteStartElement("Value");
var value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
 
writer.WriteEndElement();
}
}
 
#endregion
}
}
/Collections/Specialized/ExtendedObservableCollection.cs
@@ -0,0 +1,43 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
 
namespace wasSharp.Collections.Specialized
{
/// <summary>
/// An observable collection allowing the add of a range of items.
/// </summary>
/// <typeparam name="T">the collection type</typeparam>
public class ExtendedObservableCollection<T> : ObservableCollection<T>
{
private bool _suppressNotification;
 
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
 
public void AddRange(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException(nameof(list));
 
_suppressNotification = true;
 
foreach (var item in list)
{
Add(item);
}
_suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
}
/Collections/Specialized/ObservableHashSet.cs
@@ -0,0 +1,136 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
 
namespace wasSharp.Collections.Specialized
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// An implementation of an observable HashSet.
/// </summary>
/// <typeparam name="T">the object type</typeparam>
public class ObservableHashSet<T> : ICollection<T>, INotifyCollectionChanged
{
private readonly HashSet<T> store = new HashSet<T>();
 
public ObservableHashSet(HashSet<T> set)
{
UnionWith(set);
}
 
public ObservableHashSet()
{
}
 
public ObservableHashSet(T item)
{
Add(item);
}
 
public ObservableHashSet(ObservableHashSet<T> other)
{
UnionWith(other);
}
 
public ObservableHashSet(IEnumerable<T> list)
{
UnionWith(list);
}
 
public bool IsVirgin { get; private set; } = true;
 
public IEnumerator<T> GetEnumerator()
{
return store.GetEnumerator();
}
 
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
 
public void Add(T item)
{
store.Add(item);
IsVirgin = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
 
public void Clear()
{
store.Clear();
if (!IsVirgin)
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
IsVirgin = false;
}
 
public bool Contains(T item)
{
return store.Contains(item);
}
 
public void CopyTo(T[] array, int arrayIndex)
{
store.CopyTo(array, arrayIndex);
}
 
public bool Remove(T item)
{
var removed = store.Remove(item);
IsVirgin = false;
if (removed)
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
return removed;
}
 
public int Count => store.Count;
 
public bool IsReadOnly => false;
 
public event NotifyCollectionChangedEventHandler CollectionChanged;
 
public void UnionWith(IEnumerable<T> list)
{
var added = new List<T>(list.Except(store));
store.UnionWith(added);
if (!IsVirgin && added.Any())
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added));
IsVirgin = false;
}
 
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
CollectionChanged?.Invoke(this, args);
}
 
public void ExceptWith(IEnumerable<T> list)
{
var removed = new List<T>(list.Intersect(store));
store.ExceptWith(removed);
if (!IsVirgin && removed.Any())
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,
removed));
IsVirgin = false;
}
 
public void RemoveWhere(Func<T, bool> func)
{
var removed = new List<T>(store.Where(func));
store.ExceptWith(removed);
if (!IsVirgin && removed.Any())
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,
removed));
IsVirgin = false;
}
}
}
/Collections/Utilities/Extensions.cs
@@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections.Generic;
using System.Linq;
 
namespace wasSharp.Collections.Utilities
{
public static class Extensions
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns true of an enumerable contains more than one element.
/// </summary>
/// <typeparam name="T">the type of the enumeration</typeparam>
/// <param name="e">the enumeration</param>
/// <returns>true if enumeration contains more than one element</returns>
/// <remarks>O(2) worst case</remarks>
public static bool Some<T>(this IEnumerable<T> e)
{
var i = 0;
using (var iter = e.GetEnumerator())
{
while (iter.MoveNext())
{
if (++i > 1)
return true;
}
return false;
}
}
 
/// <summary>
/// Compares two dictionaries for equality.
/// </summary>
/// <typeparam name="TKey">key type</typeparam>
/// <typeparam name="TValue">value type</typeparam>
/// <param name="dictionary">dictionary to compare</param>
/// <param name="otherDictionary">dictionary to compare to</param>
/// <returns>true if the dictionaries contain the same elements</returns>
public static bool ContentEquals<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
IDictionary<TKey, TValue> otherDictionary)
{
return
(dictionary ?? new Dictionary<TKey, TValue>()).Count.Equals(
(otherDictionary ?? new Dictionary<TKey, TValue>()).Count) &&
(otherDictionary ?? new Dictionary<TKey, TValue>())
.OrderBy(kvp => kvp.Key)
.SequenceEqual((dictionary ?? new Dictionary<TKey, TValue>())
.OrderBy(kvp => kvp.Key));
}
}
}