Added NightAlert project for travel kit
This commit is contained in:
630
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/AvlNode.cs
vendored
Normal file
630
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/AvlNode.cs
vendored
Normal file
@@ -0,0 +1,630 @@
|
||||
//
|
||||
// AvlNode.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
class AvlNode<T>
|
||||
{
|
||||
public static readonly AvlNode<T> Empty = new NullNode();
|
||||
|
||||
sealed class NullNode : AvlNode<T>
|
||||
{
|
||||
public override bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override AvlNode<T> NewOrMutate(T newValue, AvlNode<T> newLeft, AvlNode<T> newRight)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override AvlNode<T> ToMutable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public T Value;
|
||||
AvlNode<T> left;
|
||||
AvlNode<T> right;
|
||||
int _count;
|
||||
int _depth;
|
||||
|
||||
public virtual bool IsEmpty { get { return false; } }
|
||||
|
||||
public AvlNode<T> Left { get { return left; } }
|
||||
|
||||
public AvlNode<T> Right { get { return right; } }
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
}
|
||||
|
||||
int Balance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return left._depth - right._depth;
|
||||
}
|
||||
}
|
||||
|
||||
int Depth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _depth;
|
||||
}
|
||||
}
|
||||
|
||||
public AvlNode()
|
||||
{
|
||||
right = Empty;
|
||||
left = Empty;
|
||||
}
|
||||
|
||||
public AvlNode(T val) : this(val, Empty, Empty)
|
||||
{
|
||||
}
|
||||
|
||||
AvlNode(T val, AvlNode<T> lt, AvlNode<T> gt)
|
||||
{
|
||||
Value = val;
|
||||
left = lt;
|
||||
right = gt;
|
||||
_count = 1 + left._count + right._count;
|
||||
_depth = 1 + Math.Max(left._depth, right._depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the subtree with the min value at the root, or Empty if Empty
|
||||
/// </summary>
|
||||
AvlNode<T> Min
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsEmpty)
|
||||
return Empty;
|
||||
var dict = this;
|
||||
var next = dict.left;
|
||||
while (next != Empty)
|
||||
{
|
||||
dict = next;
|
||||
next = dict.left;
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix the root balance if LTDict and GTDict have good balance
|
||||
/// Used to keep the depth less than 1.44 log_2 N (AVL tree)
|
||||
/// </summary>
|
||||
AvlNode<T> FixRootBalance()
|
||||
{
|
||||
int bal = Balance;
|
||||
if (Math.Abs(bal) < 2)
|
||||
return this;
|
||||
|
||||
if (bal == 2)
|
||||
{
|
||||
if (left.Balance == 1 || left.Balance == 0)
|
||||
{
|
||||
//Easy case:
|
||||
return this.RotateToGT();
|
||||
}
|
||||
if (left.Balance == -1)
|
||||
{
|
||||
//Rotate LTDict:
|
||||
var newlt = ToMutableIfNecessary(left).RotateToLT();
|
||||
var newroot = NewOrMutate(Value, newlt, right);
|
||||
return newroot.RotateToGT();
|
||||
}
|
||||
throw new Exception(String.Format("LTDict too unbalanced: {0}", left.Balance));
|
||||
}
|
||||
if (bal == -2)
|
||||
{
|
||||
if (right.Balance == -1 || right.Balance == 0)
|
||||
{
|
||||
//Easy case:
|
||||
return this.RotateToLT();
|
||||
}
|
||||
if (right.Balance == 1)
|
||||
{
|
||||
//Rotate GTDict:
|
||||
var newgt = ToMutableIfNecessary(right).RotateToGT();
|
||||
var newroot = NewOrMutate(Value, left, newgt);
|
||||
return newroot.RotateToLT();
|
||||
}
|
||||
throw new Exception(String.Format("LTDict too unbalanced: {0}", left.Balance));
|
||||
}
|
||||
//In this case we can show: |bal| > 2
|
||||
//if( Math.Abs(bal) > 2 ) {
|
||||
throw new Exception(String.Format("Tree too out of balance: {0}", Balance));
|
||||
}
|
||||
|
||||
public AvlNode<T> SearchNode(T value, Comparison<T> comparer)
|
||||
{
|
||||
var dict = this;
|
||||
while (dict != Empty)
|
||||
{
|
||||
int comp = comparer(dict.Value, value);
|
||||
if (comp < 0)
|
||||
{
|
||||
dict = dict.right;
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
dict = dict.left;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Awesome:
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
return Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new tree with the key-value pair inserted
|
||||
/// If the key is already present, it replaces the value
|
||||
/// This operation is O(Log N) where N is the number of keys
|
||||
/// </summary>
|
||||
public AvlNode<T> InsertIntoNew(int index, T val)
|
||||
{
|
||||
if (IsEmpty)
|
||||
return new AvlNode<T>(val);
|
||||
|
||||
AvlNode<T> newlt = left;
|
||||
AvlNode<T> newgt = right;
|
||||
|
||||
if (index <= left._count)
|
||||
{
|
||||
newlt = ToMutableIfNecessary(left).InsertIntoNew(index, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
newgt = ToMutableIfNecessary(right).InsertIntoNew(index - left._count - 1, val);
|
||||
}
|
||||
|
||||
var newroot = NewOrMutate(Value, newlt, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new tree with the key-value pair inserted
|
||||
/// If the key is already present, it replaces the value
|
||||
/// This operation is O(Log N) where N is the number of keys
|
||||
/// </summary>
|
||||
public AvlNode<T> InsertIntoNew(T val, Comparison<T> comparer)
|
||||
{
|
||||
if (IsEmpty)
|
||||
return new AvlNode<T>(val);
|
||||
|
||||
AvlNode<T> newlt = left;
|
||||
AvlNode<T> newgt = right;
|
||||
|
||||
int comp = comparer(Value, val);
|
||||
T newv = Value;
|
||||
if (comp < 0)
|
||||
{
|
||||
//Let the GTDict put it in:
|
||||
newgt = ToMutableIfNecessary(right).InsertIntoNew(val, comparer);
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
//Let the LTDict put it in:
|
||||
newlt = ToMutableIfNecessary(left).InsertIntoNew(val, comparer);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Replace the current value:
|
||||
newv = val;
|
||||
}
|
||||
var newroot = NewOrMutate(newv, newlt, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
|
||||
public AvlNode<T> SetItem(int index, T val)
|
||||
{
|
||||
AvlNode<T> newlt = left;
|
||||
AvlNode<T> newgt = right;
|
||||
|
||||
if (index < left._count)
|
||||
{
|
||||
newlt = ToMutableIfNecessary(left).SetItem(index, val);
|
||||
}
|
||||
else if (index > left._count)
|
||||
{
|
||||
newgt = ToMutableIfNecessary(right).SetItem(index - left._count - 1, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NewOrMutate(val, newlt, newgt);
|
||||
}
|
||||
return NewOrMutate(Value, newlt, newgt);
|
||||
}
|
||||
|
||||
public AvlNode<T> GetNodeAt(int index)
|
||||
{
|
||||
if (index < left._count)
|
||||
return left.GetNodeAt(index);
|
||||
if (index > left._count)
|
||||
return right.GetNodeAt(index - left._count - 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to remove the key, and return the resulting Dict
|
||||
/// if the key is not found, old_node is Empty, else old_node is the Dict
|
||||
/// with matching Key
|
||||
/// </summary>
|
||||
public AvlNode<T> RemoveFromNew(int index, out bool found)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
found = false;
|
||||
return Empty;
|
||||
}
|
||||
|
||||
if (index < left._count)
|
||||
{
|
||||
var newlt = ToMutableIfNecessary(left).RemoveFromNew(index, out found);
|
||||
if (!found)
|
||||
{
|
||||
//Not found, so nothing changed
|
||||
return this;
|
||||
}
|
||||
var newroot = NewOrMutate(Value, newlt, right);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
|
||||
if (index > left._count)
|
||||
{
|
||||
var newgt = ToMutableIfNecessary(right).RemoveFromNew(index - left._count - 1, out found);
|
||||
if (!found)
|
||||
{
|
||||
//Not found, so nothing changed
|
||||
return this;
|
||||
}
|
||||
var newroot = NewOrMutate(Value, left, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
|
||||
//found it
|
||||
found = true;
|
||||
return RemoveRoot();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to remove the key, and return the resulting Dict
|
||||
/// if the key is not found, old_node is Empty, else old_node is the Dict
|
||||
/// with matching Key
|
||||
/// </summary>
|
||||
public AvlNode<T> RemoveFromNew(T val, Comparison<T> comparer, out bool found)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
found = false;
|
||||
return Empty;
|
||||
}
|
||||
int comp = comparer(Value, val);
|
||||
if (comp < 0)
|
||||
{
|
||||
var newgt = ToMutableIfNecessary(right).RemoveFromNew(val, comparer, out found);
|
||||
if (!found)
|
||||
{
|
||||
//Not found, so nothing changed
|
||||
return this;
|
||||
}
|
||||
var newroot = NewOrMutate(Value, left, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
if (comp > 0)
|
||||
{
|
||||
var newlt = ToMutableIfNecessary(left).RemoveFromNew(val, comparer, out found);
|
||||
if (!found)
|
||||
{
|
||||
//Not found, so nothing changed
|
||||
return this;
|
||||
}
|
||||
var newroot = NewOrMutate(Value, newlt, right);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
//found it
|
||||
found = true;
|
||||
return RemoveRoot();
|
||||
}
|
||||
|
||||
AvlNode<T> RemoveMax(out AvlNode<T> max)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
max = Empty;
|
||||
return Empty;
|
||||
}
|
||||
if (right.IsEmpty)
|
||||
{
|
||||
//We are the max:
|
||||
max = this;
|
||||
return left;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Go down:
|
||||
var newgt = ToMutableIfNecessary(right).RemoveMax(out max);
|
||||
var newroot = NewOrMutate(Value, left, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
}
|
||||
|
||||
AvlNode<T> RemoveMin(out AvlNode<T> min)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
min = Empty;
|
||||
return Empty;
|
||||
}
|
||||
if (left.IsEmpty)
|
||||
{
|
||||
//We are the minimum:
|
||||
min = this;
|
||||
return right;
|
||||
}
|
||||
//Go down:
|
||||
var newlt = ToMutableIfNecessary(left).RemoveMin(out min);
|
||||
var newroot = NewOrMutate(Value, newlt, right);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a new dict with the root key-value pair removed
|
||||
/// </summary>
|
||||
AvlNode<T> RemoveRoot()
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
if (left.IsEmpty)
|
||||
{
|
||||
return right;
|
||||
}
|
||||
if (right.IsEmpty)
|
||||
{
|
||||
return left;
|
||||
}
|
||||
//Neither are empty:
|
||||
if (left._count < right._count)
|
||||
{
|
||||
//LTDict has fewer, so promote from GTDict to minimize depth
|
||||
AvlNode<T> min;
|
||||
var newgt = ToMutableIfNecessary(right).RemoveMin(out min);
|
||||
var newroot = NewOrMutate(min.Value, left, newgt);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
else
|
||||
{
|
||||
AvlNode<T> max;
|
||||
var newlt = ToMutableIfNecessary(left).RemoveMax(out max);
|
||||
var newroot = NewOrMutate(max.Value, newlt, right);
|
||||
return newroot.FixRootBalance();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the Root into the GTDict and promote LTDict node up
|
||||
/// If LTDict is empty, this operation returns this
|
||||
/// </summary>
|
||||
AvlNode<T> RotateToGT()
|
||||
{
|
||||
if (left.IsEmpty || IsEmpty)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
var newLeft = ToMutableIfNecessary(left);
|
||||
var lL = newLeft.left;
|
||||
var lR = newLeft.right;
|
||||
var newRight = NewOrMutate(Value, lR, right);
|
||||
return newLeft.NewOrMutate(newLeft.Value, lL, newRight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the Root into the LTDict and promote GTDict node up
|
||||
/// If GTDict is empty, this operation returns this
|
||||
/// </summary>
|
||||
AvlNode<T> RotateToLT()
|
||||
{
|
||||
if (right.IsEmpty || IsEmpty)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
var newRight = ToMutableIfNecessary(right);
|
||||
var rL = newRight.left;
|
||||
var rR = newRight.right;
|
||||
var newLeft = NewOrMutate(Value, left, rL);
|
||||
return newRight.NewOrMutate(newRight.Value, newLeft, rR);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate from largest to smallest key
|
||||
/// </summary>
|
||||
public IEnumerator<T> GetEnumerator(bool reverse)
|
||||
{
|
||||
var to_visit = new Stack<AvlNode<T>>();
|
||||
to_visit.Push(this);
|
||||
while (to_visit.Count > 0)
|
||||
{
|
||||
var this_d = to_visit.Pop();
|
||||
continue_without_pop:
|
||||
if (this_d.IsEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (reverse)
|
||||
{
|
||||
if (this_d.right.IsEmpty)
|
||||
{
|
||||
//This is the next biggest value in the Dict:
|
||||
yield return this_d.Value;
|
||||
this_d = this_d.left;
|
||||
goto continue_without_pop;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Break it up
|
||||
to_visit.Push(this_d.left);
|
||||
to_visit.Push(new AvlNode<T>(this_d.Value));
|
||||
this_d = this_d.right;
|
||||
goto continue_without_pop;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this_d.left.IsEmpty)
|
||||
{
|
||||
//This is the next biggest value in the Dict:
|
||||
yield return this_d.Value;
|
||||
this_d = this_d.right;
|
||||
goto continue_without_pop;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Break it up
|
||||
if (!this_d.right.IsEmpty)
|
||||
to_visit.Push(this_d.right);
|
||||
to_visit.Push(new AvlNode<T>(this_d.Value));
|
||||
this_d = this_d.left;
|
||||
goto continue_without_pop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> Enumerate(int index, int count, bool reverse)
|
||||
{
|
||||
// TODO!
|
||||
int i;
|
||||
var e = GetEnumerator(reverse);
|
||||
if (!reverse)
|
||||
{
|
||||
i = 0;
|
||||
while (e.MoveNext ())
|
||||
{
|
||||
if (index <= i)
|
||||
yield return e.Current;
|
||||
i++;
|
||||
if (i >= index + count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = Count - 1;
|
||||
while (e.MoveNext ())
|
||||
{
|
||||
if (i <= index)
|
||||
yield return e.Current;
|
||||
i--;
|
||||
if (i <= index - count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual AvlNode<T> ToImmutable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual AvlNode<T> NewOrMutate(T newValue, AvlNode<T> newLeft, AvlNode<T> newRight)
|
||||
{
|
||||
return new AvlNode<T>(newValue, newLeft, newRight);
|
||||
}
|
||||
|
||||
public virtual AvlNode<T> ToMutable()
|
||||
{
|
||||
//throw new NotImplementedException ();
|
||||
return new MutableAvlNode(Value, left, right);
|
||||
}
|
||||
|
||||
public virtual AvlNode<T> ToMutableIfNecessary(AvlNode<T> node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public virtual bool IsMutable { get { return false; } }
|
||||
|
||||
sealed class MutableAvlNode : AvlNode<T>
|
||||
{
|
||||
public MutableAvlNode(T val, AvlNode<T> lt, AvlNode<T> gt) : base (val, lt, gt)
|
||||
{
|
||||
}
|
||||
|
||||
public override AvlNode<T> ToImmutable()
|
||||
{
|
||||
return new AvlNode<T>(Value, left.ToImmutable(), right.ToImmutable());
|
||||
}
|
||||
|
||||
public override AvlNode<T> NewOrMutate(T newValue, AvlNode<T> newLeft, AvlNode<T> newRight)
|
||||
{
|
||||
Value = newValue;
|
||||
left = newLeft;
|
||||
right = newRight;
|
||||
_count = 1 + left._count + right._count;
|
||||
_depth = 1 + Math.Max(left._depth, right._depth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override AvlNode<T> ToMutable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public override AvlNode<T> ToMutableIfNecessary(AvlNode<T> node)
|
||||
{
|
||||
return node.ToMutable();
|
||||
}
|
||||
|
||||
public override bool IsMutable { get { return true; } }
|
||||
}
|
||||
}
|
||||
}
|
||||
56
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableDictionary.cs
vendored
Normal file
56
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableDictionary.cs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// ImmutableDictionary.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public interface IImmutableDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
|
||||
{
|
||||
IEqualityComparer<TValue> ValueComparer
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> Add(TKey key, TValue value);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> AddRange(IEnumerable<KeyValuePair<TKey, TValue>> pairs);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> Clear();
|
||||
|
||||
bool Contains(KeyValuePair<TKey, TValue> pair);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> Remove(TKey key);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> RemoveRange(IEnumerable<TKey> keys);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> SetItem(TKey key, TValue value);
|
||||
|
||||
IImmutableDictionary<TKey, TValue> SetItems(IEnumerable<KeyValuePair<TKey, TValue>> items);
|
||||
}
|
||||
}
|
||||
|
||||
70
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableList.cs
vendored
Normal file
70
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableList.cs
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// IImmutableList.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public interface IImmutableList<T> : IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
|
||||
{
|
||||
IEqualityComparer<T> ValueComparer
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IImmutableList<T> Add(T value);
|
||||
|
||||
IImmutableList<T> AddRange(IEnumerable<T> items);
|
||||
|
||||
IImmutableList<T> Clear();
|
||||
|
||||
bool Contains(T value);
|
||||
|
||||
int IndexOf(T value);
|
||||
|
||||
IImmutableList<T> Insert(int index, T element);
|
||||
|
||||
IImmutableList<T> InsertRange(int index, IEnumerable<T> items);
|
||||
|
||||
IImmutableList<T> Remove(T value);
|
||||
|
||||
IImmutableList<T> RemoveAll(Predicate<T> match);
|
||||
|
||||
IImmutableList<T> RemoveAt(int index);
|
||||
|
||||
IImmutableList<T> RemoveRange(int index, int count);
|
||||
|
||||
IImmutableList<T> RemoveRange(IEnumerable<T> items);
|
||||
|
||||
IImmutableList<T> Replace(T oldValue, T newValue);
|
||||
|
||||
IImmutableList<T> SetItem(int index, T value);
|
||||
|
||||
IImmutableList<T> WithComparer(IEqualityComparer<T> equalityComparer);
|
||||
}
|
||||
}
|
||||
47
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableQueue.cs
vendored
Normal file
47
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableQueue.cs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// IImmutableQueue.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public interface IImmutableQueue<T> : IEnumerable<T>, IEnumerable
|
||||
{
|
||||
bool IsEmpty
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IImmutableQueue<T> Clear();
|
||||
|
||||
IImmutableQueue<T> Dequeue();
|
||||
|
||||
IImmutableQueue<T> Enqueue(T value);
|
||||
|
||||
T Peek();
|
||||
}
|
||||
}
|
||||
62
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableSet.cs
vendored
Normal file
62
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableSet.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// IImmutableSet.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public interface IImmutableSet<T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
|
||||
{
|
||||
IImmutableSet<T> Add(T value);
|
||||
|
||||
IImmutableSet<T> Clear();
|
||||
|
||||
bool Contains(T value);
|
||||
|
||||
IImmutableSet<T> Except(IEnumerable<T> other);
|
||||
|
||||
IImmutableSet<T> Intersect(IEnumerable<T> other);
|
||||
|
||||
bool IsProperSubsetOf(IEnumerable<T> other);
|
||||
|
||||
bool IsProperSupersetOf(IEnumerable<T> other);
|
||||
|
||||
bool IsSubsetOf(IEnumerable<T> other);
|
||||
|
||||
bool IsSupersetOf(IEnumerable<T> other);
|
||||
|
||||
bool Overlaps(IEnumerable<T> other);
|
||||
|
||||
IImmutableSet<T> Remove(T value);
|
||||
|
||||
bool SetEquals(IEnumerable<T> other);
|
||||
|
||||
IImmutableSet<T> SymmetricExcept(IEnumerable<T> other);
|
||||
|
||||
IImmutableSet<T> Union(IEnumerable<T> other);
|
||||
}
|
||||
}
|
||||
47
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableStack.cs
vendored
Normal file
47
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/IImmutableStack.cs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// IImmutableStack.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public interface IImmutableStack<T> : IEnumerable<T>, IEnumerable
|
||||
{
|
||||
bool IsEmpty
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IImmutableStack<T> Clear();
|
||||
|
||||
T Peek();
|
||||
|
||||
IImmutableStack<T> Pop();
|
||||
|
||||
IImmutableStack<T> Push(T value);
|
||||
}
|
||||
}
|
||||
604
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableDictionary.cs
vendored
Normal file
604
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableDictionary.cs
vendored
Normal file
@@ -0,0 +1,604 @@
|
||||
//
|
||||
// ImmutableDictionary.cs
|
||||
//
|
||||
// Contains code from ACIS P2P Library (https://github.com/ptony82/brunet)
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
/** Read-only immutable data structure for IComparable Keys
|
||||
* Implemented as a readonly binary AVL tree, so most operations
|
||||
* have 1.44 Log C complexity where C is the count.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/AVL_tree
|
||||
|
||||
* To modify, use the InsertIntoNew and RemoveFromNew methods
|
||||
* which return a new instance with minimal changes (about Log C),
|
||||
* so this is an efficient way to make changes without having
|
||||
* to copy the entire data structure.
|
||||
*
|
||||
* Clearly this is a thread-safe class (because it is read-only),
|
||||
* but note: if the K or V types are not immutable, you could have
|
||||
* a problem: someone could modify the object without changing the
|
||||
* dictionary and not only would the Dictionary be incorrectly ordered
|
||||
* you could have race conditions. It is required that you only use
|
||||
* immutable key types in the dictionary, and only thread-safe if
|
||||
* both the keys and values are immutable.
|
||||
*/
|
||||
public class ImmutableDictionary<TKey, TValue> : IImmutableDictionary<TKey, TValue> where TKey : System.IComparable<TKey>
|
||||
{
|
||||
internal static readonly ImmutableDictionary<TKey, TValue> Empty = new ImmutableDictionary<TKey, TValue>();
|
||||
AvlNode<KeyValuePair<TKey, TValue>> root = AvlNode<KeyValuePair<TKey, TValue>>.Empty;
|
||||
readonly IEqualityComparer<TKey> keyComparer;
|
||||
readonly IEqualityComparer<TValue> valueComparer;
|
||||
|
||||
internal ImmutableDictionary()
|
||||
{
|
||||
}
|
||||
|
||||
internal ImmutableDictionary(AvlNode<KeyValuePair<TKey, TValue>> root, IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer)
|
||||
{
|
||||
this.root = root;
|
||||
this.keyComparer = keyComparer;
|
||||
this.valueComparer = valueComparer;
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> WithComparers(IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer)
|
||||
{
|
||||
return new ImmutableDictionary<TKey, TValue>(root, keyComparer, valueComparer);
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> WithComparers(IEqualityComparer<TKey> keyComparer)
|
||||
{
|
||||
return WithComparers(keyComparer, valueComparer);
|
||||
}
|
||||
#region IImmutableDictionary implementation
|
||||
public ImmutableDictionary<TKey, TValue> Add(TKey key, TValue value)
|
||||
{
|
||||
var pair = new KeyValuePair<TKey, TValue>(key, value);
|
||||
return new ImmutableDictionary<TKey, TValue>(root.InsertIntoNew(pair, CompareKV), keyComparer, valueComparer);
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.Add(TKey key, TValue value)
|
||||
{
|
||||
return Add(key, value);
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> AddRange(IEnumerable<KeyValuePair<TKey, TValue>> pairs)
|
||||
{
|
||||
var result = this;
|
||||
foreach (var kv in pairs)
|
||||
result = result.Add(kv.Key, kv.Value);
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.AddRange(IEnumerable<KeyValuePair<TKey, TValue>> pairs)
|
||||
{
|
||||
return AddRange(pairs);
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> Clear()
|
||||
{
|
||||
return Empty;
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.Clear()
|
||||
{
|
||||
return Clear();
|
||||
}
|
||||
|
||||
static int CompareKV(KeyValuePair<TKey, TValue> left, KeyValuePair<TKey, TValue> right)
|
||||
{
|
||||
return left.Key.CompareTo(right.Key);
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> kv)
|
||||
{
|
||||
var node = root.SearchNode(kv, CompareKV);
|
||||
return !node.IsEmpty && valueComparer.Equals(node.Value.Value, kv.Value);
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> Remove(TKey key)
|
||||
{
|
||||
bool found;
|
||||
var pair = new KeyValuePair<TKey,TValue>(key, default (TValue));
|
||||
return new ImmutableDictionary<TKey, TValue>(root.RemoveFromNew(pair, CompareKV, out found), keyComparer, valueComparer);
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.Remove(TKey key)
|
||||
{
|
||||
return Remove(key);
|
||||
}
|
||||
|
||||
public IImmutableDictionary<TKey, TValue> RemoveRange(IEnumerable<TKey> keys)
|
||||
{
|
||||
IImmutableDictionary<TKey, TValue> result = this;
|
||||
foreach (var key in keys)
|
||||
{
|
||||
result = result.Remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.RemoveRange(IEnumerable<TKey> keys)
|
||||
{
|
||||
return RemoveRange(keys);
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> SetItem(TKey key, TValue value)
|
||||
{
|
||||
var result = this;
|
||||
if (result.ContainsKey(key))
|
||||
result = result.Remove(key);
|
||||
return result.Add(key, value);
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.SetItem(TKey key, TValue value)
|
||||
{
|
||||
return SetItem(key, value);
|
||||
}
|
||||
|
||||
public IImmutableDictionary<TKey, TValue> SetItems(IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
var result = this;
|
||||
foreach (var kv in items)
|
||||
{
|
||||
result = result.SetItem(kv.Key, kv.Value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableDictionary<TKey, TValue> IImmutableDictionary<TKey, TValue>.SetItems(IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
return SetItems(items);
|
||||
}
|
||||
|
||||
public IEqualityComparer<TKey> KeyComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return keyComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public IEqualityComparer<TValue> ValueComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return valueComparer;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region IReadOnlyDictionary implementation
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return !root.SearchNode(new KeyValuePair<TKey, TValue>(key, default(TValue)), CompareKV).IsEmpty;
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
var node = root.SearchNode(new KeyValuePair<TKey, TValue>(key, default(TValue)), CompareKV);
|
||||
if (node.IsEmpty)
|
||||
{
|
||||
value = default (TValue);
|
||||
return false;
|
||||
}
|
||||
value = node.Value.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public TValue this [TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
TValue value;
|
||||
if (TryGetValue(key, out value))
|
||||
return value;
|
||||
throw new KeyNotFoundException(String.Format("Key: {0}", key));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TKey> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var kv in this)
|
||||
{
|
||||
yield return kv.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var kv in this)
|
||||
{
|
||||
yield return kv.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region IEnumerable implementation
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
var to_visit = new Stack<AvlNode<KeyValuePair<TKey,TValue>>>();
|
||||
to_visit.Push(root);
|
||||
while (to_visit.Count > 0)
|
||||
{
|
||||
var this_d = to_visit.Pop();
|
||||
if (this_d.IsEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (this_d.Left.IsEmpty)
|
||||
{
|
||||
//This is the next smallest value in the Dict:
|
||||
yield return this_d.Value;
|
||||
to_visit.Push(this_d.Right);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Break it up
|
||||
to_visit.Push(this_d.Right);
|
||||
to_visit.Push(new AvlNode<KeyValuePair<TKey, TValue>>(this_d.Value));
|
||||
to_visit.Push(this_d.Left);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region IEnumerable implementation
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
#region IReadOnlyCollection implementation
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Count;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
public Builder ToBuilder()
|
||||
{
|
||||
return new Builder(root, keyComparer, valueComparer);
|
||||
}
|
||||
|
||||
public sealed class Builder : IDictionary<TKey, TValue>
|
||||
{
|
||||
AvlNode<KeyValuePair<TKey, TValue>> root;
|
||||
IEqualityComparer<TKey> keyComparer;
|
||||
|
||||
public IEqualityComparer<TKey> KeyComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return keyComparer;
|
||||
}
|
||||
set
|
||||
{
|
||||
keyComparer = value;
|
||||
}
|
||||
}
|
||||
|
||||
IEqualityComparer<TValue> valueComparer;
|
||||
|
||||
public IEqualityComparer<TValue> ValueComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return valueComparer;
|
||||
}
|
||||
set
|
||||
{
|
||||
valueComparer = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal Builder(AvlNode<KeyValuePair<TKey, TValue>> root, IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer)
|
||||
{
|
||||
this.root = root.ToMutable();
|
||||
this.keyComparer = keyComparer;
|
||||
this.valueComparer = valueComparer;
|
||||
}
|
||||
|
||||
public ImmutableDictionary<TKey, TValue> ToImmutable()
|
||||
{
|
||||
return new ImmutableDictionary<TKey, TValue>(root, keyComparer, valueComparer);
|
||||
}
|
||||
#region IDictionary implementation
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
Add(new KeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return !root.SearchNode(new KeyValuePair<TKey, TValue>(key, default (TValue)), CompareKV).IsEmpty;
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
bool found;
|
||||
root = root.RemoveFromNew(new KeyValuePair<TKey, TValue>(key, default (TValue)), CompareKV, out found);
|
||||
return found;
|
||||
}
|
||||
|
||||
public void SetItem(TKey key, TValue value)
|
||||
{
|
||||
if (ContainsKey(key))
|
||||
Remove(key);
|
||||
Add(key, value);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
var node = root.SearchNode(new KeyValuePair<TKey, TValue>(key, default(TValue)), CompareKV);
|
||||
if (node.IsEmpty)
|
||||
{
|
||||
value = default (TValue);
|
||||
return false;
|
||||
}
|
||||
value = node.Value.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public TValue this [TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
TValue value;
|
||||
if (TryGetValue(key, out value))
|
||||
return value;
|
||||
throw new KeyNotFoundException(String.Format("Key: {0}", key));
|
||||
}
|
||||
set
|
||||
{
|
||||
if (ContainsKey(key))
|
||||
Remove(key);
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
ICollection<TKey> IDictionary<TKey, TValue>.Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TKey> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var kv in this)
|
||||
{
|
||||
yield return kv.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICollection<TValue> IDictionary<TKey, TValue>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
return Values.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var kv in this)
|
||||
{
|
||||
yield return kv.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region ICollection implementation
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
root = root.InsertIntoNew(item, CompareKV);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
root = new AvlNode<KeyValuePair<TKey, TValue>>().ToMutable();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
TValue value;
|
||||
if (!TryGetValue(item.Key, out value))
|
||||
return false;
|
||||
return valueComparer.Equals(value, item.Value);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
if (arrayIndex < 0 || arrayIndex + Count > array.Length)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
foreach (var pair in this)
|
||||
{
|
||||
array[arrayIndex++] = pair;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (!Contains(item))
|
||||
return false;
|
||||
Remove(item.Key);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region IEnumerable implementation
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return root.GetEnumerator(false);
|
||||
}
|
||||
#endregion
|
||||
#region IEnumerable implementation
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImmutableDictionary
|
||||
{
|
||||
public static bool Contains<TKey, TValue>(this IImmutableDictionary<TKey, TValue> dictionary, TKey key, TValue value)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
return dictionary.Contains(new KeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>() where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return ImmutableDictionary<TKey, TValue>.Empty;
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>(IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer, IEnumerable<KeyValuePair<TKey, TValue>> items) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return Create<TKey, TValue>(keyComparer, valueComparer).AddRange(items);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>(IEqualityComparer<TKey> keyComparer, IEnumerable<KeyValuePair<TKey, TValue>> items) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return Create<TKey, TValue>(keyComparer).AddRange(items);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>(IEnumerable<KeyValuePair<TKey, TValue>> items) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return Create<TKey, TValue>().AddRange(items);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>(IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return Create<TKey, TValue>().WithComparers(keyComparer, valueComparer);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> Create<TKey, TValue>(IEqualityComparer<TKey> keyComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return Create<TKey, TValue>().WithComparers(keyComparer);
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return dictionary.GetValueOrDefault<TKey, TValue>(key, default (TValue));
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
TValue result;
|
||||
if (dictionary.TryGetValue(key, out result))
|
||||
return result;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return dictionary.GetValueOrDefault<TKey, TValue>(key, default (TValue));
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
TValue result;
|
||||
if (dictionary.TryGetValue(key, out result))
|
||||
return result;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source, IEqualityComparer<TKey> keyComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return source.ToImmutableDictionary(keyComparer, null);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return source.ToImmutableDictionary(null, null);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source, IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
return Create<TKey, TValue>(keyComparer, valueComparer).AddRange(source);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector, IEqualityComparer<TKey> keyComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return source.ToImmutableDictionary(keySelector, elementSelector, keyComparer, null);
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector, IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
return Create<TKey, TValue>(keyComparer, valueComparer).AddRange(source.Select(x => new KeyValuePair<TKey, TValue>(keySelector(x), elementSelector(x))));
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector) where TKey : System.IComparable<TKey>
|
||||
{
|
||||
return source.ToImmutableDictionary(keySelector, elementSelector, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
730
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableList.cs
vendored
Normal file
730
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableList.cs
vendored
Normal file
@@ -0,0 +1,730 @@
|
||||
//
|
||||
// ImmutableList.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public class ImmutableList<T> : IImmutableList<T>, IList<T>, IList
|
||||
{
|
||||
public static readonly ImmutableList<T> Empty = new ImmutableList<T>();
|
||||
readonly AvlNode<T> root = AvlNode<T>.Empty;
|
||||
readonly IEqualityComparer<T> valueComparer;
|
||||
|
||||
internal ImmutableList()
|
||||
{
|
||||
this.valueComparer = EqualityComparer<T>.Default;
|
||||
}
|
||||
|
||||
internal ImmutableList(AvlNode<T> root, IEqualityComparer<T> equalityComparer)
|
||||
{
|
||||
this.root = root;
|
||||
this.valueComparer = equalityComparer;
|
||||
}
|
||||
|
||||
public void CopyTo(int index, T[] array, int arrayIndex, int count)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
if (arrayIndex < 0 || arrayIndex + count > array.Length)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
if (count < 0 || index + count > Count)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
foreach (var item in root.Enumerate (index, count, false))
|
||||
{
|
||||
array[arrayIndex++] = item;
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
if (arrayIndex < 0 || arrayIndex + Count > array.Length)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
CopyTo(0, array, 0, Count);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
CopyTo(array, 0);
|
||||
}
|
||||
|
||||
public bool Exists(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return this.Any(i => match(i));
|
||||
}
|
||||
|
||||
public T Find(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return this.FirstOrDefault(i => match(i));
|
||||
}
|
||||
|
||||
public ImmutableList<T> FindAll(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
var builder = Clear().ToBuilder();
|
||||
foreach (var item in this)
|
||||
{
|
||||
if (match(item))
|
||||
builder.Add(item);
|
||||
}
|
||||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
public int FindIndex(int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
if (startIndex < 0 || startIndex >= Count)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (count < 0 || startIndex + count > Count)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
|
||||
int i = startIndex;
|
||||
foreach (var item in root.Enumerate (startIndex, count, false))
|
||||
{
|
||||
if (match(item))
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int FindIndex(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return FindIndex(0, Count, match);
|
||||
}
|
||||
|
||||
public int FindIndex(int startIndex, Predicate<T> match)
|
||||
{
|
||||
if (startIndex < 0 || startIndex >= Count)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return FindIndex(startIndex, Count - startIndex, match);
|
||||
}
|
||||
|
||||
public T FindLast(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return this.LastOrDefault(i => match(i));
|
||||
}
|
||||
|
||||
public int FindLastIndex(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return FindLastIndex(Count - 1, Count, match);
|
||||
}
|
||||
|
||||
public int FindLastIndex(int startIndex, Predicate<T> match)
|
||||
{
|
||||
if (startIndex < 0 || startIndex >= Count)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
return FindLastIndex(startIndex, startIndex + 1, match);
|
||||
}
|
||||
|
||||
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
|
||||
{
|
||||
if (startIndex < 0 || startIndex >= Count)
|
||||
throw new ArgumentOutOfRangeException("startIndex");
|
||||
if (count > Count || startIndex - count + 1 < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
|
||||
int index = startIndex;
|
||||
foreach (var item in root.Enumerate (startIndex, count, true))
|
||||
{
|
||||
if (match(item))
|
||||
return index;
|
||||
index--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void ForEach(Action<T> action)
|
||||
{
|
||||
if (action == null)
|
||||
throw new ArgumentNullException("action");
|
||||
foreach (var item in this)
|
||||
{
|
||||
action(item);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableList<T> GetRange(int index, int count)
|
||||
{
|
||||
return ImmutableList.Create(valueComparer, root.Enumerate(index, count, false));
|
||||
}
|
||||
|
||||
public int IndexOf(T value)
|
||||
{
|
||||
return IndexOf(value, 0, Count);
|
||||
}
|
||||
|
||||
public int IndexOf(T value, int index)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
return IndexOf(value, 0, Count - index);
|
||||
}
|
||||
|
||||
public int IndexOf(T value, int index, int count)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
if (count < 0 || index + count > Count)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
return FindIndex(index, count, i => valueComparer.Equals(value, i));
|
||||
}
|
||||
|
||||
public int LastIndexOf(T item, int index)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
return LastIndexOf(item, index, index + 1);
|
||||
}
|
||||
|
||||
public int LastIndexOf(T item)
|
||||
{
|
||||
return LastIndexOf(item, Count - 1, Count);
|
||||
}
|
||||
|
||||
public int LastIndexOf(T item, int index, int count)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
if (count > Count || index - count + 1 < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
return FindLastIndex(index, count, i => valueComparer.Equals(item, i));
|
||||
}
|
||||
#region IList implementation
|
||||
|
||||
int IList.Add(object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void IList.Clear()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
bool IList.Contains(object value)
|
||||
{
|
||||
return Contains((T)value);
|
||||
}
|
||||
|
||||
int IList.IndexOf(object value)
|
||||
{
|
||||
return IndexOf((T)value);
|
||||
}
|
||||
|
||||
void IList.Insert(int index, object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void IList.Remove(object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void IList.RemoveAt(int index)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
bool IList.IsFixedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
object IList.this [int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
bool IList.IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICollection implementation
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
foreach (var item in this)
|
||||
array.SetValue(item, index++);
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
object ICollection.SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IList<T> implementation
|
||||
T IList<T>.this [int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
void IList<T>.Insert(int index, T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void IList<T>.RemoveAt(int index)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICollection<T> implementation
|
||||
|
||||
void ICollection<T>.Add(T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void ICollection<T>.Clear()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
bool ICollection<T>.Remove(T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
bool ICollection<T>.IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IImmutableList<T> implementation
|
||||
|
||||
public ImmutableList<T> Add(T value)
|
||||
{
|
||||
return Insert(Count, value);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.Add(T value)
|
||||
{
|
||||
return Add(value);
|
||||
}
|
||||
|
||||
public ImmutableList<T> AddRange(IEnumerable<T> items)
|
||||
{
|
||||
return InsertRange(Count, items);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.AddRange(IEnumerable<T> items)
|
||||
{
|
||||
return AddRange(items);
|
||||
}
|
||||
|
||||
public ImmutableList<T> Clear()
|
||||
{
|
||||
return Empty.WithComparer(valueComparer);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.Clear()
|
||||
{
|
||||
return Clear();
|
||||
}
|
||||
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return IndexOf(value) != -1;
|
||||
}
|
||||
|
||||
public ImmutableList<T> Insert(int index, T element)
|
||||
{
|
||||
if (index > Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
return new ImmutableList<T>(root.InsertIntoNew(index, element), valueComparer);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.Insert(int index, T element)
|
||||
{
|
||||
return Insert(index, element);
|
||||
}
|
||||
|
||||
public ImmutableList<T> InsertRange(int index, IEnumerable<T> items)
|
||||
{
|
||||
var result = this;
|
||||
foreach (var item in items)
|
||||
{
|
||||
result = result.Insert(index++, item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.InsertRange(int index, IEnumerable<T> items)
|
||||
{
|
||||
return InsertRange(index, items);
|
||||
}
|
||||
|
||||
public ImmutableList<T> Remove(T value)
|
||||
{
|
||||
int loc = IndexOf(value);
|
||||
if (loc != -1)
|
||||
return RemoveAt(loc);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.Remove(T value)
|
||||
{
|
||||
return Remove(value);
|
||||
}
|
||||
|
||||
public ImmutableList<T> RemoveAll(Predicate<T> match)
|
||||
{
|
||||
if (match == null)
|
||||
throw new ArgumentNullException("match");
|
||||
var result = this;
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
if (match(result[i]))
|
||||
{
|
||||
result = result.RemoveAt(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.RemoveAll(Predicate<T> match)
|
||||
{
|
||||
return RemoveAll(match);
|
||||
}
|
||||
|
||||
public ImmutableList<T> RemoveAt(int index)
|
||||
{
|
||||
bool found;
|
||||
return new ImmutableList<T>(root.RemoveFromNew(index, out found), valueComparer);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.RemoveAt(int index)
|
||||
{
|
||||
return RemoveAt(index);
|
||||
}
|
||||
|
||||
void CheckRange(int idx, int count)
|
||||
{
|
||||
if (idx < 0)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
if ((uint)idx + (uint)count > (uint)this.Count)
|
||||
throw new ArgumentException("index and count exceed length of list");
|
||||
}
|
||||
|
||||
public ImmutableList<T> RemoveRange(int index, int count)
|
||||
{
|
||||
CheckRange(index, count);
|
||||
var result = this;
|
||||
while (count-- > 0)
|
||||
{
|
||||
result = result.RemoveAt(index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.RemoveRange(int index, int count)
|
||||
{
|
||||
return RemoveRange(index, count);
|
||||
}
|
||||
|
||||
public ImmutableList<T> RemoveRange(IEnumerable<T> items)
|
||||
{
|
||||
var result = this;
|
||||
foreach (var item in items)
|
||||
{
|
||||
result = result.Remove(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.RemoveRange(IEnumerable<T> items)
|
||||
{
|
||||
return RemoveRange(items);
|
||||
}
|
||||
|
||||
public ImmutableList<T> Replace(T oldValue, T newValue)
|
||||
{
|
||||
var idx = IndexOf(oldValue);
|
||||
if (idx < 0)
|
||||
return this;
|
||||
return SetItem(idx, newValue);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.Replace(T oldValue, T newValue)
|
||||
{
|
||||
return Replace(oldValue, newValue);
|
||||
}
|
||||
|
||||
public ImmutableList<T> SetItem(int index, T value)
|
||||
{
|
||||
if (index > Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
return new ImmutableList<T>(root.SetItem(index, value), valueComparer);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.SetItem(int index, T value)
|
||||
{
|
||||
return SetItem(index, value);
|
||||
}
|
||||
|
||||
public ImmutableList<T> WithComparer(IEqualityComparer<T> equalityComparer)
|
||||
{
|
||||
return new ImmutableList<T>(root, equalityComparer);
|
||||
}
|
||||
|
||||
IImmutableList<T> IImmutableList<T>.WithComparer(IEqualityComparer<T> equalityComparer)
|
||||
{
|
||||
return WithComparer(equalityComparer);
|
||||
}
|
||||
|
||||
public IEqualityComparer<T> ValueComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return valueComparer;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<T> implementation
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return root.GetEnumerator(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IReadOnlyList<T> implementation
|
||||
|
||||
public T this [int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index >= Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
return root.GetNodeAt(index).Value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IReadOnlyCollection implementation
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Count;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Builder
|
||||
public Builder ToBuilder()
|
||||
{
|
||||
return new Builder(root, valueComparer);
|
||||
}
|
||||
|
||||
public class Builder
|
||||
{
|
||||
AvlNode<T> root;
|
||||
readonly IEqualityComparer<T> valueComparer;
|
||||
|
||||
internal Builder(AvlNode<T> immutableRoot, IEqualityComparer<T> comparer)
|
||||
{
|
||||
root = immutableRoot.ToMutable();
|
||||
valueComparer = comparer;
|
||||
}
|
||||
|
||||
public ImmutableList<T> ToImmutable()
|
||||
{
|
||||
return new ImmutableList<T>(root.ToImmutable(), valueComparer);
|
||||
}
|
||||
|
||||
public void Add(T value)
|
||||
{
|
||||
Insert(Count, value);
|
||||
}
|
||||
|
||||
public void Insert(int index, T element)
|
||||
{
|
||||
if (index > Count)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
root = root.InsertIntoNew(index, element);
|
||||
Debug.Assert(root.IsMutable);
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ImmutableList
|
||||
{
|
||||
public static ImmutableList<T> Create<T>()
|
||||
{
|
||||
return ImmutableList<T>.Empty;
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(IEqualityComparer<T> equalityComparer, params T[] items)
|
||||
{
|
||||
return ImmutableList<T>.Empty.WithComparer(equalityComparer).AddRange(items);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(params T[] items)
|
||||
{
|
||||
return Create(EqualityComparer<T>.Default, items);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(IEqualityComparer<T> equalityComparer, IEnumerable<T> items)
|
||||
{
|
||||
return Create(equalityComparer, items.ToArray());
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(IEnumerable<T> items)
|
||||
{
|
||||
return Create(items.ToArray());
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(IEqualityComparer<T> equalityComparer, T item)
|
||||
{
|
||||
return ImmutableList<T>.Empty.WithComparer(equalityComparer).Add(item);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(T item)
|
||||
{
|
||||
return Create(EqualityComparer<T>.Default, item);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> Create<T>(IEqualityComparer<T> equalityComparer)
|
||||
{
|
||||
return Create<T>().WithComparer(equalityComparer);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> ToImmutableList<T>(this IEnumerable<T> source)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
return Create<T>().AddRange(source);
|
||||
}
|
||||
|
||||
public static ImmutableList<T> ToImmutableList<T>(this IEnumerable<T> source, IEqualityComparer<T> equalityComparer)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
return Create<T>().WithComparer(equalityComparer).AddRange(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
246
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableQueue.cs
vendored
Normal file
246
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableQueue.cs
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
//
|
||||
// ImmutableQueue.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public class ImmutableQueue<T> : IImmutableQueue<T>
|
||||
{
|
||||
readonly ImmutableStack<T> frontStack;
|
||||
readonly ImmutableStack<T> backStack;
|
||||
|
||||
internal ImmutableQueue()
|
||||
{
|
||||
frontStack = backStack = ImmutableStack<T>.Empty;
|
||||
}
|
||||
|
||||
ImmutableQueue(ImmutableStack<T> frontStack, ImmutableStack<T> backStack)
|
||||
{
|
||||
if (frontStack == null)
|
||||
throw new ArgumentNullException("frontStack");
|
||||
if (backStack == null)
|
||||
throw new ArgumentNullException("backStack");
|
||||
|
||||
this.frontStack = frontStack;
|
||||
this.backStack = backStack;
|
||||
}
|
||||
#region IImmutableQueue implementation
|
||||
internal static readonly ImmutableQueue<T> Empty = new ImmutableQueue<T>(ImmutableStack<T>.Empty, ImmutableStack<T>.Empty);
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return frontStack.IsEmpty && backStack.IsEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableQueue<T> Clear()
|
||||
{
|
||||
return Empty;
|
||||
}
|
||||
|
||||
IImmutableQueue<T> IImmutableQueue<T>.Clear()
|
||||
{
|
||||
return Empty;
|
||||
}
|
||||
|
||||
public ImmutableQueue<T> Dequeue()
|
||||
{
|
||||
if (IsEmpty)
|
||||
throw new InvalidOperationException("Queue is empty.");
|
||||
var stack = frontStack.Pop();
|
||||
if (!stack.IsEmpty)
|
||||
return new ImmutableQueue<T>(stack, backStack);
|
||||
return new ImmutableQueue<T>(Reverse(backStack), ImmutableStack<T>.Empty);
|
||||
}
|
||||
|
||||
public ImmutableQueue<T> Dequeue(out T value)
|
||||
{
|
||||
value = Peek();
|
||||
return Dequeue();
|
||||
}
|
||||
|
||||
IImmutableQueue<T> IImmutableQueue<T>.Dequeue()
|
||||
{
|
||||
return Dequeue();
|
||||
}
|
||||
|
||||
static ImmutableStack<T> Reverse(IImmutableStack<T> stack)
|
||||
{
|
||||
var result = ImmutableStack<T>.Empty;
|
||||
var cur = stack;
|
||||
while (!cur.IsEmpty)
|
||||
{
|
||||
result = result.Push(cur.Peek());
|
||||
cur = cur.Pop();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ImmutableQueue<T> Enqueue(T value)
|
||||
{
|
||||
if (IsEmpty)
|
||||
return new ImmutableQueue<T>(ImmutableStack<T>.Empty.Push(value), ImmutableStack<T>.Empty);
|
||||
|
||||
return new ImmutableQueue<T>(frontStack, backStack.Push(value));
|
||||
}
|
||||
|
||||
IImmutableQueue<T> IImmutableQueue<T>.Enqueue(T value)
|
||||
{
|
||||
return Enqueue(value);
|
||||
}
|
||||
|
||||
public T Peek()
|
||||
{
|
||||
if (IsEmpty)
|
||||
throw new InvalidOperationException("Queue is empty.");
|
||||
return frontStack.Peek();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
struct Enumerator : IEnumerator<T>
|
||||
{
|
||||
readonly ImmutableQueue<T> start;
|
||||
IImmutableStack<T> frontStack;
|
||||
IImmutableStack<T> backStack;
|
||||
|
||||
public Enumerator(ImmutableQueue<T> stack)
|
||||
{
|
||||
this.start = stack;
|
||||
this.frontStack = null;
|
||||
this.backStack = null;
|
||||
}
|
||||
#region IEnumerator implementation
|
||||
|
||||
bool IEnumerator.MoveNext()
|
||||
{
|
||||
if (frontStack == null)
|
||||
{
|
||||
frontStack = start.frontStack;
|
||||
backStack = Reverse (start.backStack);
|
||||
}
|
||||
else if (!frontStack.IsEmpty)
|
||||
{
|
||||
frontStack = frontStack.Pop();
|
||||
}
|
||||
else if (!backStack.IsEmpty)
|
||||
{
|
||||
backStack = backStack.Pop();
|
||||
}
|
||||
return !(frontStack.IsEmpty && backStack.IsEmpty);
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
frontStack = null;
|
||||
backStack = null;
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get { return Current; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerator implementation
|
||||
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (frontStack == null)
|
||||
return default(T);
|
||||
if (frontStack.IsEmpty && backStack.IsEmpty)
|
||||
throw new InvalidOperationException();
|
||||
return !frontStack.IsEmpty ? frontStack.Peek() : backStack.Peek();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ImmutableQueue
|
||||
{
|
||||
public static ImmutableQueue<T> Create<T>()
|
||||
{
|
||||
return ImmutableQueue<T>.Empty;
|
||||
}
|
||||
|
||||
public static ImmutableQueue<T> Create<T>(T item)
|
||||
{
|
||||
return Create<T>().Enqueue(item);
|
||||
}
|
||||
|
||||
public static ImmutableQueue<T> Create<T>(IEnumerable<T> items)
|
||||
{
|
||||
var result = ImmutableQueue<T>.Empty;
|
||||
foreach (var item in items)
|
||||
result = result.Enqueue(item);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ImmutableQueue<T> Create<T>(params T[] items)
|
||||
{
|
||||
return Create((IEnumerable<T>)items);
|
||||
}
|
||||
|
||||
public static IImmutableQueue<T> Dequeue<T>(this IImmutableQueue<T> queue, out T value)
|
||||
{
|
||||
if (queue == null)
|
||||
throw new ArgumentNullException("queue");
|
||||
value = queue.Peek();
|
||||
return queue.Dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
206
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableStack.cs
vendored
Normal file
206
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/ImmutableStack.cs
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// ImmutableStack.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Quobject.Collections.Immutable
|
||||
{
|
||||
public class ImmutableStack<T> : IImmutableStack<T>
|
||||
{
|
||||
readonly T head;
|
||||
readonly ImmutableStack<T> tail;
|
||||
|
||||
internal ImmutableStack()
|
||||
{
|
||||
}
|
||||
|
||||
ImmutableStack(T head, ImmutableStack<T> tail)
|
||||
{
|
||||
this.head = head;
|
||||
this.tail = tail;
|
||||
}
|
||||
#region IImmutableStack implementation
|
||||
internal static readonly ImmutableStack<T> Empty = new ImmutableStack<T>();
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return tail == null; }
|
||||
}
|
||||
|
||||
public ImmutableStack<T> Clear()
|
||||
{
|
||||
return Empty;
|
||||
}
|
||||
|
||||
IImmutableStack<T> IImmutableStack<T>.Clear()
|
||||
{
|
||||
return Empty;
|
||||
}
|
||||
|
||||
public T Peek()
|
||||
{
|
||||
if (IsEmpty)
|
||||
throw new InvalidOperationException("Stack is empty.");
|
||||
return head;
|
||||
}
|
||||
|
||||
public ImmutableStack<T> Pop()
|
||||
{
|
||||
if (IsEmpty)
|
||||
throw new InvalidOperationException("Stack is empty.");
|
||||
return tail;
|
||||
}
|
||||
|
||||
public ImmutableStack<T> Pop(out T value)
|
||||
{
|
||||
value = Peek();
|
||||
return Pop();
|
||||
}
|
||||
|
||||
IImmutableStack<T> IImmutableStack<T>.Pop()
|
||||
{
|
||||
return Pop();
|
||||
}
|
||||
|
||||
public ImmutableStack<T> Push(T value)
|
||||
{
|
||||
return new ImmutableStack<T>(value, this);
|
||||
}
|
||||
|
||||
IImmutableStack<T> IImmutableStack<T>.Push(T value)
|
||||
{
|
||||
return Push(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<T> implementation
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
struct Enumerator : IEnumerator<T>
|
||||
{
|
||||
readonly ImmutableStack<T> start;
|
||||
IImmutableStack<T> current;
|
||||
|
||||
public Enumerator(ImmutableStack<T> stack)
|
||||
{
|
||||
this.start = stack;
|
||||
this.current = null;
|
||||
}
|
||||
#region IEnumerator implementation
|
||||
|
||||
bool IEnumerator.MoveNext()
|
||||
{
|
||||
if (current == null)
|
||||
{
|
||||
current = this.start;
|
||||
}
|
||||
else if (!current.IsEmpty)
|
||||
{
|
||||
current = current.Pop();
|
||||
}
|
||||
|
||||
return !current.IsEmpty;
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get { return this.Current; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable implementation
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerator implementation
|
||||
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return current != null ? current.Peek() : default(T);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ImmutableStack
|
||||
{
|
||||
public static ImmutableStack<T> Create<T>()
|
||||
{
|
||||
return ImmutableStack<T>.Empty;
|
||||
}
|
||||
|
||||
public static ImmutableStack<T> Create<T>(T item)
|
||||
{
|
||||
return Create<T>().Push(item);
|
||||
}
|
||||
|
||||
public static ImmutableStack<T> Create<T>(IEnumerable<T> items)
|
||||
{
|
||||
var result = ImmutableStack<T>.Empty;
|
||||
foreach (var item in items)
|
||||
result = result.Push(item);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ImmutableStack<T> Create<T>(params T[] items)
|
||||
{
|
||||
return Create((IEnumerable<T>)items);
|
||||
}
|
||||
|
||||
public static IImmutableStack<T> Pop<T>(this IImmutableStack<T> stack, out T value)
|
||||
{
|
||||
if (stack == null)
|
||||
throw new ArgumentNullException("stack");
|
||||
value = stack.Peek();
|
||||
return stack.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
51
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/Properties/AssemblyInfo.cs
vendored
Normal file
51
ThirdParty/EngineIoClientDotNet/Src/Quobject.Collections.Immutable/Properties/AssemblyInfo.cs
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// AssemblyInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System.Reflection;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Quobject.Collections.Immutable")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("Xamarin Inc. (http://xamarin.com)")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>10.0.0</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{024A2111-4B19-44D7-917E-8514CF632469}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Quobject.Collections.Immutable</RootNamespace>
|
||||
<AssemblyName>Quobject.Collections.Immutable</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AvlNode.cs" />
|
||||
<Compile Include="IImmutableDictionary.cs" />
|
||||
<Compile Include="IImmutableList.cs" />
|
||||
<Compile Include="IImmutableQueue.cs" />
|
||||
<Compile Include="IImmutableSet.cs" />
|
||||
<Compile Include="IImmutableStack.cs" />
|
||||
<Compile Include="ImmutableDictionary.cs" />
|
||||
<Compile Include="ImmutableList.cs" />
|
||||
<Compile Include="ImmutableQueue.cs" />
|
||||
<Compile Include="ImmutableStack.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
Reference in New Issue
Block a user