Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
public class Array<T> : List<T>
|
||||
{
|
||||
public Array(int size) : base(size)
|
||||
{
|
||||
_limit = size;
|
||||
}
|
||||
|
||||
public Array(params T[] args) : base(args)
|
||||
{
|
||||
_limit = args.Length;
|
||||
}
|
||||
|
||||
public Array(int size, T defaultFillValue) : this(size)
|
||||
{
|
||||
Fill(defaultFillValue);
|
||||
}
|
||||
|
||||
public void Fill(T value)
|
||||
{
|
||||
for (var i = 0; i < _limit; ++i)
|
||||
Add(value);
|
||||
}
|
||||
|
||||
public new void Add(T value)
|
||||
{
|
||||
if (base.Count >= _limit)
|
||||
throw new InternalBufferOverflowException("Attempted to read more array elements from packet " + base.Count + 1 + " than allowed " + _limit);
|
||||
|
||||
base.Add(value);
|
||||
}
|
||||
|
||||
public new T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return base[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index >= Count)
|
||||
{
|
||||
if (Count >= _limit)
|
||||
throw new InternalBufferOverflowException("Attempted to read more array elements from packet " + base.Count + 1 + " than allowed " + _limit);
|
||||
base.Insert(index, value);
|
||||
}
|
||||
else
|
||||
base[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetLimit() { return _limit; }
|
||||
|
||||
public static implicit operator T[] (Array<T> array)
|
||||
{
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
int _limit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace System.Collections
|
||||
{
|
||||
public class BitSet : ICollection, ICloneable
|
||||
{
|
||||
public BitSet(int length, bool defaultValue = false)
|
||||
{
|
||||
if (length < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("length");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
m_array = new uint[GetArrayLength(length, BitsPerInt32)];
|
||||
m_length = length;
|
||||
|
||||
uint fillValue = defaultValue ? 0xffffffff : 0;
|
||||
for (int i = 0; i < m_array.Length; i++)
|
||||
{
|
||||
m_array[i] = fillValue;
|
||||
}
|
||||
|
||||
_version = 0;
|
||||
}
|
||||
|
||||
public BitSet(uint[] values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
throw new ArgumentNullException("values");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
// this value is chosen to prevent overflow when computing m_length
|
||||
if (values.Length > UInt32.MaxValue / BitsPerInt32)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
m_array = new uint[values.Length];
|
||||
m_length = values.Length * BitsPerInt32;
|
||||
|
||||
Array.Copy(values, m_array, values.Length);
|
||||
|
||||
_version = 0;
|
||||
}
|
||||
|
||||
public BitSet(BitSet bits)
|
||||
{
|
||||
if (bits == null)
|
||||
{
|
||||
throw new ArgumentNullException("bits");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
int arrayLength = GetArrayLength(bits.m_length, BitsPerInt32);
|
||||
m_array = new uint[arrayLength];
|
||||
m_length = bits.m_length;
|
||||
|
||||
Array.Copy(bits.m_array, m_array, arrayLength);
|
||||
|
||||
_version = bits._version;
|
||||
}
|
||||
|
||||
public bool this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get(index);
|
||||
}
|
||||
set
|
||||
{
|
||||
Set(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Get(int index)
|
||||
{
|
||||
if (index < 0 || index >= Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
return (Convert.ToInt64(m_array[index / 32]) & (1 << (index % 32))) != 0;
|
||||
}
|
||||
|
||||
public void Set(int index, bool value)
|
||||
{
|
||||
if (index < 0 || index >= Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
if (value)
|
||||
{
|
||||
m_array[index / 32] |= (1u << (index % 32));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_array[index / 32] &= ~(1u << (index % 32));
|
||||
}
|
||||
|
||||
_version++;
|
||||
}
|
||||
|
||||
public void SetAll(bool value)
|
||||
{
|
||||
uint fillValue = value ? 0xffffffff : 0u;
|
||||
int ints = GetArrayLength(m_length, BitsPerInt32);
|
||||
for (int i = 0; i < ints; i++)
|
||||
{
|
||||
m_array[i] = fillValue;
|
||||
}
|
||||
|
||||
_version++;
|
||||
}
|
||||
|
||||
public BitSet And(BitSet value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (Length != value.Length)
|
||||
throw new ArgumentException();
|
||||
Contract.EndContractBlock();
|
||||
|
||||
int ints = GetArrayLength(m_length, BitsPerInt32);
|
||||
for (int i = 0; i < ints; i++)
|
||||
{
|
||||
m_array[i] &= value.m_array[i];
|
||||
}
|
||||
|
||||
_version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BitSet Or(BitSet value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (Length != value.Length)
|
||||
throw new ArgumentException();
|
||||
Contract.EndContractBlock();
|
||||
|
||||
int ints = GetArrayLength(m_length, BitsPerInt32);
|
||||
for (int i = 0; i < ints; i++)
|
||||
{
|
||||
m_array[i] |= value.m_array[i];
|
||||
}
|
||||
|
||||
_version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BitSet Xor(BitSet value)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (Length != value.Length)
|
||||
throw new ArgumentException();
|
||||
Contract.EndContractBlock();
|
||||
|
||||
int ints = GetArrayLength(m_length, BitsPerInt32);
|
||||
for (int i = 0; i < ints; i++)
|
||||
{
|
||||
m_array[i] ^= value.m_array[i];
|
||||
}
|
||||
|
||||
_version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BitSet Not()
|
||||
{
|
||||
int ints = GetArrayLength(m_length, BitsPerInt32);
|
||||
for (int i = 0; i < ints; i++)
|
||||
{
|
||||
m_array[i] = ~m_array[i];
|
||||
}
|
||||
|
||||
_version++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<int>() >= 0);
|
||||
return m_length;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value");
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
int newints = GetArrayLength(value, BitsPerInt32);
|
||||
if (newints > m_array.Length || newints + _ShrinkThreshold < m_array.Length)
|
||||
{
|
||||
// grow or shrink (if wasting more than _ShrinkThreshold ints)
|
||||
uint[] newarray = new uint[newints];
|
||||
Array.Copy(m_array, newarray, newints > m_array.Length ? m_array.Length : newints);
|
||||
m_array = newarray;
|
||||
}
|
||||
|
||||
if (value > m_length)
|
||||
{
|
||||
// clear high bit values in the last int
|
||||
int last = GetArrayLength(m_length, BitsPerInt32) - 1;
|
||||
int bits = m_length % 32;
|
||||
if (bits > 0)
|
||||
{
|
||||
m_array[last] &= (1u << bits) - 1;
|
||||
}
|
||||
|
||||
// clear remaining int values
|
||||
Array.Clear(m_array, last + 1, newints - last - 1);
|
||||
}
|
||||
|
||||
m_length = value;
|
||||
_version++;
|
||||
}
|
||||
}
|
||||
|
||||
// ICollection implementation
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
if (index < 0)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
|
||||
if (array.Rank != 1)
|
||||
throw new ArgumentException();
|
||||
|
||||
Contract.EndContractBlock();
|
||||
|
||||
if (array is uint[])
|
||||
{
|
||||
Array.Copy(m_array, 0, array, index, GetArrayLength(m_length, BitsPerInt32));
|
||||
}
|
||||
else if (array is byte[])
|
||||
{
|
||||
int arrayLength = GetArrayLength(m_length, BitsPerByte);
|
||||
if ((array.Length - index) < arrayLength)
|
||||
throw new ArgumentException();
|
||||
|
||||
byte[] b = (byte[])array;
|
||||
for (int i = 0; i < arrayLength; i++)
|
||||
b[index + i] = (byte)((m_array[i / 4] >> ((i % 4) * 8)) & 0x000000FF); // Shift to bring the required byte to LSB, then mask
|
||||
}
|
||||
else if (array is bool[])
|
||||
{
|
||||
if (array.Length - index < m_length)
|
||||
throw new ArgumentException();
|
||||
|
||||
bool[] b = (bool[])array;
|
||||
for (int i = 0; i < m_length; i++)
|
||||
b[index + i] = ((m_array[i / 32] >> (i % 32)) & 0x00000001) != 0;
|
||||
}
|
||||
else
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<int>() >= 0);
|
||||
|
||||
return (int)m_length;
|
||||
}
|
||||
}
|
||||
|
||||
public Object Clone()
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Object>() != null);
|
||||
Contract.Ensures(((BitArray)Contract.Result<Object>()).Length == this.Length);
|
||||
|
||||
BitSet bitArray = new BitSet(m_array);
|
||||
bitArray._version = _version;
|
||||
bitArray.m_length = m_length;
|
||||
return bitArray;
|
||||
}
|
||||
|
||||
public Object SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_syncRoot == null)
|
||||
{
|
||||
System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
|
||||
}
|
||||
return _syncRoot;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSynchronized
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return new BitArrayEnumeratorSimple(this);
|
||||
}
|
||||
|
||||
// XPerY=n means that n Xs can be stored in 1 Y.
|
||||
private const int BitsPerInt32 = 32;
|
||||
private const int BytesPerInt32 = 4;
|
||||
private const int BitsPerByte = 8;
|
||||
|
||||
private static int GetArrayLength(int n, int div)
|
||||
{
|
||||
Contract.Assert(div > 0, "GetArrayLength: div arg must be greater than 0");
|
||||
return n > 0 ? (((n - 1) / div) + 1) : 0;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class BitArrayEnumeratorSimple : IEnumerator, ICloneable
|
||||
{
|
||||
private BitSet bitarray;
|
||||
private int index;
|
||||
private int version;
|
||||
private bool currentElement;
|
||||
|
||||
internal BitArrayEnumeratorSimple(BitSet bitarray)
|
||||
{
|
||||
this.bitarray = bitarray;
|
||||
this.index = -1;
|
||||
version = bitarray._version;
|
||||
}
|
||||
|
||||
public Object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
public virtual bool MoveNext()
|
||||
{
|
||||
//if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
|
||||
if (index < (bitarray.Count - 1))
|
||||
{
|
||||
index++;
|
||||
currentElement = bitarray.Get(index);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
index = bitarray.Count;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual Object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index == -1)
|
||||
throw new InvalidOperationException();
|
||||
if (index >= bitarray.Count)
|
||||
throw new InvalidOperationException();
|
||||
return currentElement;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
//if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
|
||||
index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private uint[] m_array;
|
||||
private int m_length;
|
||||
private int _version;
|
||||
[NonSerialized]
|
||||
private Object _syncRoot;
|
||||
|
||||
private const int _ShrinkThreshold = 256;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
public interface IMultiMap<TKey, TValue>
|
||||
{
|
||||
void AddRange(TKey key, IEnumerable<TValue> valueList);
|
||||
List<TValue> this[TKey key] { get; set;}
|
||||
bool Remove(TKey key, TValue value);
|
||||
void Add(TKey key, TValue value);
|
||||
bool ContainsKey(TKey key);
|
||||
|
||||
ICollection<TKey> Keys {get;}
|
||||
bool Remove(TKey key);
|
||||
ICollection<TValue> Values{get;}
|
||||
|
||||
void Add(KeyValuePair<TKey, TValue> item);
|
||||
void Clear();
|
||||
bool Contains(TKey key, TValue item);
|
||||
void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex);
|
||||
int Count {get;}
|
||||
bool Remove(KeyValuePair<TKey, TValue> item);
|
||||
|
||||
List<TValue> LookupByKey(TKey key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Framework.Collections
|
||||
{
|
||||
public class LinkedListElement
|
||||
{
|
||||
internal LinkedListElement iNext;
|
||||
internal LinkedListElement iPrev;
|
||||
|
||||
public LinkedListElement()
|
||||
{
|
||||
iNext = iPrev = null;
|
||||
}
|
||||
|
||||
~LinkedListElement() { delink(); }
|
||||
|
||||
bool hasNext() { return (iNext != null && iNext.iNext != null); }
|
||||
bool hasPrev() { return (iPrev != null && iPrev.iPrev != null); }
|
||||
public bool isInList() { return (iNext != null && iPrev != null); }
|
||||
|
||||
public LinkedListElement GetNextElement() { return hasNext() ? iNext : null; }
|
||||
public LinkedListElement GetPrevElement() { return hasPrev() ? iPrev : null; }
|
||||
|
||||
public void delink()
|
||||
{
|
||||
if (!isInList())
|
||||
return;
|
||||
|
||||
iNext.iPrev = iPrev;
|
||||
iPrev.iNext = iNext;
|
||||
iNext = null;
|
||||
iPrev = null;
|
||||
}
|
||||
|
||||
public void insertBefore(LinkedListElement pElem)
|
||||
{
|
||||
pElem.iNext = this;
|
||||
pElem.iPrev = iPrev;
|
||||
iPrev.iNext = pElem;
|
||||
iPrev = pElem;
|
||||
}
|
||||
|
||||
public void insertAfter(LinkedListElement pElem)
|
||||
{
|
||||
pElem.iPrev = this;
|
||||
pElem.iNext = iNext;
|
||||
iNext.iPrev = pElem;
|
||||
iNext = pElem;
|
||||
}
|
||||
}
|
||||
|
||||
public class LinkedListHead
|
||||
{
|
||||
LinkedListElement iFirst = new LinkedListElement();
|
||||
LinkedListElement iLast = new LinkedListElement();
|
||||
uint iSize;
|
||||
|
||||
public LinkedListHead()
|
||||
{
|
||||
iSize = 0;
|
||||
// create empty list
|
||||
|
||||
iFirst.iNext = iLast;
|
||||
iLast.iPrev = iFirst;
|
||||
}
|
||||
|
||||
public bool isEmpty() { return (!iFirst.iNext.isInList()); }
|
||||
|
||||
public LinkedListElement GetFirstElement() { return (isEmpty() ? null : iFirst.iNext); }
|
||||
public LinkedListElement GetLastElement() { return (isEmpty() ? null : iLast.iPrev); }
|
||||
|
||||
public void insertFirst(LinkedListElement pElem)
|
||||
{
|
||||
iFirst.insertAfter(pElem);
|
||||
}
|
||||
|
||||
public void insertLast(LinkedListElement pElem)
|
||||
{
|
||||
iLast.insertBefore(pElem);
|
||||
}
|
||||
|
||||
public uint getSize()
|
||||
{
|
||||
if (iSize == 0)
|
||||
{
|
||||
uint result = 0;
|
||||
LinkedListElement e = GetFirstElement();
|
||||
while (e != null)
|
||||
{
|
||||
++result;
|
||||
e = e.GetNextElement();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return iSize;
|
||||
}
|
||||
|
||||
public void incSize() { ++iSize; }
|
||||
public void decSize() { --iSize; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
public sealed class MultiMap<TKey, TValue> : IMultiMap<TKey, TValue>, IDictionary<TKey, TValue>
|
||||
{
|
||||
public MultiMap() { }
|
||||
|
||||
public MultiMap(IEnumerable<KeyValuePair<TKey, TValue>> initialData)
|
||||
{
|
||||
foreach (var item in initialData)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
_interalStorage.Add(key, new List<TValue>());
|
||||
|
||||
_interalStorage[key].Add(value);
|
||||
}
|
||||
|
||||
public void AddRange(TKey key, IEnumerable<TValue> valueList)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
{
|
||||
_interalStorage.Add(key, new List<TValue>());
|
||||
}
|
||||
foreach (TValue value in valueList)
|
||||
{
|
||||
_interalStorage[key].Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(item.Key))
|
||||
{
|
||||
_interalStorage.Add(item.Key, new List<TValue>());
|
||||
}
|
||||
_interalStorage[item.Key].Add(item.Value);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return _interalStorage.Remove(key);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (!ContainsKey(item.Key))
|
||||
return false;
|
||||
|
||||
bool val = _interalStorage[item.Key].Remove(item.Value);
|
||||
|
||||
if (!val)
|
||||
return false;
|
||||
|
||||
if (_interalStorage[item.Key].Empty())
|
||||
_interalStorage.Remove(item.Key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(TKey key, TValue value)
|
||||
{
|
||||
if (!ContainsKey(key))
|
||||
return false;
|
||||
|
||||
bool val = _interalStorage[key].Remove(value);
|
||||
|
||||
if (!val)
|
||||
return false;
|
||||
|
||||
if (_interalStorage[key].Empty())
|
||||
_interalStorage.Remove(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _interalStorage.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
List<TValue> valueList;
|
||||
if (_interalStorage.TryGetValue(item.Key, out valueList))
|
||||
return valueList.Contains(item.Value);
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Contains(TKey key, TValue item)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key)) return false;
|
||||
return _interalStorage[key].Contains(item);
|
||||
}
|
||||
|
||||
public List<TValue> LookupByKey(TKey key)
|
||||
{
|
||||
if (_interalStorage.ContainsKey(key))
|
||||
return _interalStorage[key].ToList();
|
||||
|
||||
return new List<TValue>();
|
||||
}
|
||||
|
||||
public List<TValue> LookupByKey(object key)
|
||||
{
|
||||
TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey));
|
||||
if (_interalStorage.ContainsKey(newkey))
|
||||
return _interalStorage[newkey].ToList();
|
||||
|
||||
return new List<TValue>();
|
||||
}
|
||||
|
||||
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
{
|
||||
value = default(TValue);
|
||||
return false;
|
||||
}
|
||||
value = _interalStorage[key].Last();
|
||||
return true;
|
||||
}
|
||||
|
||||
TValue IDictionary<TKey, TValue>.this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _interalStorage[key].LastOrDefault();
|
||||
}
|
||||
set
|
||||
{
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TValue> this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
return new List<TValue>();
|
||||
return _interalStorage[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
_interalStorage.Add(key, value);
|
||||
else
|
||||
_interalStorage[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return _interalStorage.Keys; }
|
||||
}
|
||||
|
||||
public ICollection<TValue> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
List<TValue> retVal = new List<TValue>();
|
||||
foreach (var item in _interalStorage)
|
||||
{
|
||||
retVal.AddRange(item.Value);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public List<KeyValuePair<TKey, TValue>> KeyValueList
|
||||
{
|
||||
get
|
||||
{
|
||||
List<KeyValuePair<TKey, TValue>> retVal = new List<KeyValuePair<TKey, TValue>>();
|
||||
foreach (var pair in _interalStorage)
|
||||
{
|
||||
foreach (var value in pair.Value)
|
||||
retVal.Add(new KeyValuePair<TKey, TValue>(pair.Key, value));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_interalStorage.Clear();
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
if (arrayIndex < 0)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "argument 'arrayIndex' cannot be negative");
|
||||
|
||||
if (arrayIndex >= array.Length || Count > array.Length - arrayIndex)
|
||||
array = new KeyValuePair<TKey, TValue>[Count];
|
||||
|
||||
int index = arrayIndex;
|
||||
foreach (KeyValuePair<TKey, TValue> pair in this)
|
||||
array[index++] = new KeyValuePair<TKey, TValue>(pair.Key, pair.Value);
|
||||
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var item in _interalStorage)
|
||||
{
|
||||
count += item.Value.Count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
int ICollection<KeyValuePair<TKey, TValue>>.Count
|
||||
{
|
||||
get { return _interalStorage.Count; }
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return new MultiMapEnumerator<TKey, TValue>(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return new MultiMapEnumerator<TKey, TValue>(this);
|
||||
}
|
||||
|
||||
private Dictionary<TKey, List<TValue>> _interalStorage = new Dictionary<TKey, List<TValue>>();
|
||||
}
|
||||
|
||||
public sealed class SortedMultiMap<TKey, TValue> : IMultiMap<TKey, TValue>, IDictionary<TKey, TValue>
|
||||
{
|
||||
public SortedMultiMap() { }
|
||||
|
||||
public SortedMultiMap(IEnumerable<KeyValuePair<TKey, TValue>> initialData)
|
||||
{
|
||||
foreach (var item in initialData)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
_interalStorage.Add(key, new List<TValue>());
|
||||
|
||||
_interalStorage[key].Add(value);
|
||||
}
|
||||
|
||||
public void AddRange(TKey key, IEnumerable<TValue> valueList)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
{
|
||||
_interalStorage.Add(key, new List<TValue>());
|
||||
}
|
||||
foreach (TValue value in valueList)
|
||||
{
|
||||
_interalStorage[key].Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(item.Key))
|
||||
{
|
||||
_interalStorage.Add(item.Key, new List<TValue>());
|
||||
}
|
||||
_interalStorage[item.Key].Add(item.Value);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return _interalStorage.Remove(key);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (!ContainsKey(item.Key))
|
||||
return false;
|
||||
|
||||
bool val = _interalStorage[item.Key].Remove(item.Value);
|
||||
|
||||
if (!val)
|
||||
return false;
|
||||
|
||||
if (_interalStorage[item.Key].Empty())
|
||||
_interalStorage.Remove(item.Key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(TKey key, TValue value)
|
||||
{
|
||||
if (!ContainsKey(key))
|
||||
return false;
|
||||
|
||||
bool val = _interalStorage[key].Remove(value);
|
||||
|
||||
if (!val)
|
||||
return false;
|
||||
|
||||
if (_interalStorage[key].Empty())
|
||||
_interalStorage.Remove(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _interalStorage.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
List<TValue> valueList;
|
||||
if (_interalStorage.TryGetValue(item.Key, out valueList))
|
||||
return valueList.Contains(item.Value);
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Contains(TKey key, TValue item)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key)) return false;
|
||||
return _interalStorage[key].Contains(item);
|
||||
}
|
||||
|
||||
public List<TValue> LookupByKey(TKey key)
|
||||
{
|
||||
if (_interalStorage.ContainsKey(key))
|
||||
return _interalStorage[key].ToList();
|
||||
|
||||
return new List<TValue>();
|
||||
}
|
||||
|
||||
public List<TValue> LookupByKey(object key)
|
||||
{
|
||||
TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey));
|
||||
if (_interalStorage.ContainsKey(newkey))
|
||||
return _interalStorage[newkey].ToList();
|
||||
|
||||
return new List<TValue>();
|
||||
}
|
||||
|
||||
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
{
|
||||
value = default(TValue);
|
||||
return false;
|
||||
}
|
||||
value = _interalStorage[key].Last();
|
||||
return true;
|
||||
}
|
||||
|
||||
TValue IDictionary<TKey, TValue>.this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _interalStorage[key].LastOrDefault();
|
||||
}
|
||||
set
|
||||
{
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TValue> this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
return new List<TValue>();
|
||||
return _interalStorage[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!_interalStorage.ContainsKey(key))
|
||||
_interalStorage.Add(key, value);
|
||||
else _interalStorage[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return _interalStorage.Keys; }
|
||||
}
|
||||
|
||||
public ICollection<TValue> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
List<TValue> retVal = new List<TValue>();
|
||||
foreach (var item in _interalStorage)
|
||||
{
|
||||
retVal.AddRange(item.Value);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public List<KeyValuePair<TKey, TValue>> KeyValueList
|
||||
{
|
||||
get
|
||||
{
|
||||
List<KeyValuePair<TKey, TValue>> retVal = new List<KeyValuePair<TKey, TValue>>();
|
||||
foreach (var pair in _interalStorage)
|
||||
{
|
||||
foreach (var value in pair.Value)
|
||||
retVal.Add(new KeyValuePair<TKey, TValue>(pair.Key, value));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_interalStorage.Clear();
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
if (arrayIndex < 0)
|
||||
throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "argument 'arrayIndex' cannot be negative");
|
||||
|
||||
if (arrayIndex >= array.Length || Count > array.Length - arrayIndex)
|
||||
array = new KeyValuePair<TKey, TValue>[Count];
|
||||
|
||||
int index = arrayIndex;
|
||||
foreach (KeyValuePair<TKey, TValue> pair in this)
|
||||
array[index++] = new KeyValuePair<TKey, TValue>(pair.Key, pair.Value);
|
||||
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var item in _interalStorage)
|
||||
{
|
||||
count += item.Value.Count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
int ICollection<KeyValuePair<TKey, TValue>>.Count
|
||||
{
|
||||
get { return _interalStorage.Count; }
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return new SortedMultiMapEnumerator<TKey, TValue>(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return new SortedMultiMapEnumerator<TKey, TValue>(this);
|
||||
}
|
||||
|
||||
private SortedDictionary<TKey, List<TValue>> _interalStorage = new SortedDictionary<TKey, List<TValue>>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
public class MultiMapEnumerator<TKey, TValue> : IEnumerator<KeyValuePair<TKey, TValue>>
|
||||
{
|
||||
MultiMap<TKey, TValue> _map;
|
||||
IEnumerator<TKey> _keyEnumerator;
|
||||
IEnumerator<TValue> _valueEnumerator;
|
||||
|
||||
public MultiMapEnumerator(MultiMap<TKey, TValue> map)
|
||||
{
|
||||
_map = map;
|
||||
Reset();
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValuePair<TKey, TValue> Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return new KeyValuePair<TKey, TValue>(_keyEnumerator.Current, _valueEnumerator.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_keyEnumerator = null;
|
||||
_valueEnumerator = null;
|
||||
_map = null;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!_valueEnumerator.MoveNext())
|
||||
{
|
||||
if (!_keyEnumerator.MoveNext())
|
||||
return false;
|
||||
_valueEnumerator = _map[_keyEnumerator.Current].GetEnumerator();
|
||||
_valueEnumerator.MoveNext();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_keyEnumerator = _map.Keys.GetEnumerator();
|
||||
_valueEnumerator = new List<TValue>().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public class SortedMultiMapEnumerator<TKey, TValue> : IEnumerator<KeyValuePair<TKey, TValue>>
|
||||
{
|
||||
SortedMultiMap<TKey, TValue> _map;
|
||||
IEnumerator<TKey> _keyEnumerator;
|
||||
IEnumerator<TValue> _valueEnumerator;
|
||||
|
||||
public SortedMultiMapEnumerator(SortedMultiMap<TKey, TValue> map)
|
||||
{
|
||||
_map = map;
|
||||
Reset();
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValuePair<TKey, TValue> Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return new KeyValuePair<TKey, TValue>(_keyEnumerator.Current, _valueEnumerator.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_keyEnumerator = null;
|
||||
_valueEnumerator = null;
|
||||
_map = null;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!_valueEnumerator.MoveNext())
|
||||
{
|
||||
if (!_keyEnumerator.MoveNext())
|
||||
return false;
|
||||
_valueEnumerator = _map[_keyEnumerator.Current].GetEnumerator();
|
||||
_valueEnumerator.MoveNext();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_keyEnumerator = _map.Keys.GetEnumerator();
|
||||
_valueEnumerator = new List<TValue>().GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Framework.Collections
|
||||
{
|
||||
public class StringArray
|
||||
{
|
||||
public StringArray(int size)
|
||||
{
|
||||
_str = new string[size];
|
||||
|
||||
for (var i = 0; i < size; ++i)
|
||||
_str[i] = "";
|
||||
}
|
||||
|
||||
public StringArray(string str, params string[] separator)
|
||||
{
|
||||
_str = str.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public StringArray(string str, params char[] separator)
|
||||
{
|
||||
_str = str.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public string this[int index]
|
||||
{
|
||||
get { return _str[index]; }
|
||||
set { _str[index] = value; }
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return _str.GetEnumerator();
|
||||
}
|
||||
|
||||
public int Length { get { return _str.Length; } }
|
||||
|
||||
string[] _str;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user