Move some classes to Cryville.Common.
This commit is contained in:
@@ -1,65 +0,0 @@
|
|||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// A resource pool that allows reusing instances of arrays of type <typeparamref name="T" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The item type of the arrays in the pool.</typeparam>
|
|
||||||
public class ArrayPool<T> {
|
|
||||||
private class Bucket : ObjectPool<T[]> {
|
|
||||||
readonly int _size;
|
|
||||||
public Bucket(int size, int capacity) : base(capacity) {
|
|
||||||
_size = size;
|
|
||||||
}
|
|
||||||
protected override T[] Construct() {
|
|
||||||
return new T[_size];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly Bucket[] _buckets;
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="ArrayPool{T}" /> class with the default maximum list size and bucket capacity.
|
|
||||||
/// </summary>
|
|
||||||
public ArrayPool() : this(0x40000000, 256) { }
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="ArrayPool{T}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="maxSize">The maximum size of the arrays in the pool.</param>
|
|
||||||
/// <param name="capacityPerBucket">The capacity of each bucket. The pool groups arrays of similar sizes into buckets for faster access.</param>
|
|
||||||
public ArrayPool(int maxSize, int capacityPerBucket) {
|
|
||||||
if (maxSize < 16) maxSize = 16;
|
|
||||||
int num = GetID(maxSize) + 1;
|
|
||||||
_buckets = new Bucket[num];
|
|
||||||
for (int i = 0; i < num; i++) {
|
|
||||||
_buckets[i] = new Bucket(GetSize(i), capacityPerBucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Rents an array that is at least the specified size from the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="size">The minimum size of the array.</param>
|
|
||||||
/// <returns>An array of type <see cref="T" /> that is at least the specified size.</returns>
|
|
||||||
public T[] Rent(int size) {
|
|
||||||
int len2 = size;
|
|
||||||
if (len2 < 16) len2 = 16;
|
|
||||||
var arr = _buckets[GetID(len2)].Rent();
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a rented array to the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="arr">The array to return.</param>
|
|
||||||
public void Return(T[] arr) {
|
|
||||||
int len2 = arr.Length;
|
|
||||||
if (len2 < 16) len2 = 16;
|
|
||||||
_buckets[GetID(len2)].Return(arr);
|
|
||||||
}
|
|
||||||
static int GetID(int size) {
|
|
||||||
size -= 1;
|
|
||||||
size >>= 4;
|
|
||||||
int num = 0;
|
|
||||||
for (; size != 0; size >>= 1) num++;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
static int GetSize(int id) {
|
|
||||||
return 0x10 << id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: df66519fa93e1b94ea5bb1702cc91b3f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// A set of resource pools categorized by a category type.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TCategory">The category type.</typeparam>
|
|
||||||
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
|
|
||||||
public abstract class CategorizedPool<TCategory, TObject> where TObject : class {
|
|
||||||
/// <summary>
|
|
||||||
/// The set of underlying pools.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>The <see cref="Rent(TCategory)" /> and <see cref="Return(TCategory, TObject)" /> method select an underlying pool directly from this set with the category as the key. When overridden, this set must be available since construction.</para>
|
|
||||||
/// </remarks>
|
|
||||||
protected abstract IReadOnlyDictionary<TCategory, ObjectPool<TObject>> Buckets { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// The count of objects rented from the set of pools.
|
|
||||||
/// </summary>
|
|
||||||
public int RentedCount { get; private set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Rents an object from the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="category">The category.</param>
|
|
||||||
/// <returns>The rented object.</returns>
|
|
||||||
public TObject Rent(TCategory category) {
|
|
||||||
var obj = Buckets[category].Rent();
|
|
||||||
RentedCount++;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a rented object to the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="category">The category.</param>
|
|
||||||
/// <param name="obj">The object to return.</param>
|
|
||||||
public void Return(TCategory category, TObject obj) {
|
|
||||||
Buckets[category].Return(obj);
|
|
||||||
--RentedCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// A utility to access a categorized pool, representing a single unit that uses a shared categorized pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TCategory">The category type.</typeparam>
|
|
||||||
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
|
|
||||||
public class CategorizedPoolAccessor<TCategory, TObject> where TObject : class {
|
|
||||||
readonly CategorizedPool<TCategory, TObject> _pool;
|
|
||||||
static readonly SimpleObjectPool<Dictionary<TObject, TCategory>> _dictPool
|
|
||||||
= new SimpleObjectPool<Dictionary<TObject, TCategory>>(1024);
|
|
||||||
Dictionary<TObject, TCategory> _rented;
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="CategorizedPoolAccessor{TCategory, TObject}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pool">The categorized pool.</param>
|
|
||||||
public CategorizedPoolAccessor(CategorizedPool<TCategory, TObject> pool) {
|
|
||||||
_pool = pool;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Rents an object from the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="category">The category.</param>
|
|
||||||
/// <returns>The rented object.</returns>
|
|
||||||
public TObject Rent(TCategory category) {
|
|
||||||
var obj = _pool.Rent(category);
|
|
||||||
if (_rented == null) _rented = _dictPool.Rent();
|
|
||||||
_rented.Add(obj, category);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a rented object to the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to return.</param>
|
|
||||||
public void Return(TObject obj) {
|
|
||||||
_pool.Return(_rented[obj], obj);
|
|
||||||
_rented.Remove(obj);
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns all objects rented by this accessor to the pool.
|
|
||||||
/// </summary>
|
|
||||||
public void ReturnAll() {
|
|
||||||
if (_rented == null) return;
|
|
||||||
foreach (var obj in _rented) {
|
|
||||||
_pool.Return(obj.Value, obj.Key);
|
|
||||||
}
|
|
||||||
_rented.Clear();
|
|
||||||
_dictPool.Return(_rented);
|
|
||||||
_rented = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ec18f22479042d747b88c093aa90c5c0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// A resource pool that allows reusing instances of lists of type <typeparamref name="T" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The item type of the lists in the pool.</typeparam>
|
|
||||||
public class ListPool<T> {
|
|
||||||
private class Bucket : ObjectPool<List<T>> {
|
|
||||||
readonly int _size;
|
|
||||||
public Bucket(int size, int capacity) : base(capacity) {
|
|
||||||
_size = size;
|
|
||||||
}
|
|
||||||
protected override List<T> Construct() {
|
|
||||||
return new List<T>(_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly Bucket[] _buckets;
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="ListPool{T}" /> class with the default maximum list size and bucket capacity.
|
|
||||||
/// </summary>
|
|
||||||
public ListPool() : this(0x40000000, 256) { }
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="ListPool{T}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="maxSize">The maximum size of the lists in the pool.</param>
|
|
||||||
/// <param name="capacityPerBucket">The capacity of each bucket. The pool groups lists of similar sizes into buckets for faster access.</param>
|
|
||||||
public ListPool(int maxSize, int capacityPerBucket) {
|
|
||||||
if (maxSize < 16) maxSize = 16;
|
|
||||||
int num = GetID(maxSize) + 1;
|
|
||||||
_buckets = new Bucket[num];
|
|
||||||
for (int i = 0; i < num; i++) {
|
|
||||||
_buckets[i] = new Bucket(GetSize(i), capacityPerBucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Rents a list of the specified size from the pool. The size of the list must not be changed when it is rented.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="size">The size of the list.</param>
|
|
||||||
/// <returns>A <see cref="List{T}" /> of the specified size.</returns>
|
|
||||||
public List<T> Rent(int size) {
|
|
||||||
int len2 = size;
|
|
||||||
if (len2 < 16) len2 = 16;
|
|
||||||
var list = _buckets[GetID(len2)].Rent();
|
|
||||||
if (list.Count < size)
|
|
||||||
for (int i = list.Count; i < size; i++) list.Add(default(T));
|
|
||||||
else if (list.Count > size)
|
|
||||||
list.RemoveRange(size, list.Count - size);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a rented list to the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="list">The list to return.</param>
|
|
||||||
public void Return(List<T> list) {
|
|
||||||
int len2 = list.Capacity;
|
|
||||||
if (len2 < 16) len2 = 16;
|
|
||||||
_buckets[GetID(len2)].Return(list);
|
|
||||||
}
|
|
||||||
static int GetID(int size) {
|
|
||||||
size -= 1;
|
|
||||||
size >>= 4;
|
|
||||||
int num = 0;
|
|
||||||
for (; size != 0; size >>= 1) num++;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
static int GetSize(int id) {
|
|
||||||
return 0x10 << id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2b7b45ff20c33ac47b476371673b037c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// A resource pool that allows reusing instances of type <typeparamref name="T" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of the objects in the pool.</typeparam>
|
|
||||||
public abstract class ObjectPool<T> where T : class {
|
|
||||||
int _index;
|
|
||||||
readonly T[] _objs;
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="ObjectPool{T}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The capacity of the pool.</param>
|
|
||||||
public ObjectPool(int capacity) {
|
|
||||||
_objs = new T[capacity];
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// The count of objects rented from the pool.
|
|
||||||
/// </summary>
|
|
||||||
public int RentedCount { get { return _index; } }
|
|
||||||
/// <summary>
|
|
||||||
/// Rents a object from the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The rented object.</returns>
|
|
||||||
public T Rent() {
|
|
||||||
T obj = null;
|
|
||||||
if (_index < _objs.Length) {
|
|
||||||
obj = _objs[_index];
|
|
||||||
_objs[_index++] = null;
|
|
||||||
}
|
|
||||||
if (obj == null) obj = Construct();
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a rented object to the pool.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to return.</param>
|
|
||||||
public void Return(T obj) {
|
|
||||||
if (_index > 0) {
|
|
||||||
Reset(obj);
|
|
||||||
_objs[--_index] = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new instance of type <typeparamref name="T" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The new instance.</returns>
|
|
||||||
protected abstract T Construct();
|
|
||||||
/// <summary>
|
|
||||||
/// Resets an object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object.</param>
|
|
||||||
protected virtual void Reset(T obj) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2745c44c3cc32be4ab3a43888c14b9a1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// A resource pool that allows reusing instances of type <typeparamref name="T" />, which has a parameterless constructor.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of the objects in the pool.</typeparam>
|
|
||||||
public class SimpleObjectPool<T> : ObjectPool<T> where T : class, new() {
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="SimpleObjectPool{T}" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The capacity of the pool.</param>
|
|
||||||
public SimpleObjectPool(int capacity) : base(capacity) { }
|
|
||||||
protected override T Construct() {
|
|
||||||
return new T();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b8cd439340f088d4eb83711a5bc6384d
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Buffers {
|
|
||||||
/// <summary>
|
|
||||||
/// An auto-resized <see cref="char" /> array as a variable-length string used as a target that is modified frequently.
|
|
||||||
/// </summary>
|
|
||||||
public class TargetString : IEnumerable<char> {
|
|
||||||
public event Action OnUpdate;
|
|
||||||
char[] _arr;
|
|
||||||
bool _invalidated;
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="TargetString" /> class with a capacity of 16.
|
|
||||||
/// </summary>
|
|
||||||
public TargetString() : this(16) { }
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="TargetString" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The initial capacity of the string.</param>
|
|
||||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity" /> is less than or equal to 0.</exception>
|
|
||||||
public TargetString(int capacity) {
|
|
||||||
if (capacity <= 0) throw new ArgumentOutOfRangeException("capacity");
|
|
||||||
_arr = new char[capacity];
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets one of the characters in the string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The zero-based index of the character.</param>
|
|
||||||
/// <returns>The character at the given index.</returns>
|
|
||||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> is less than 0 or not less than <see cref="Length" />.</exception>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Set <see cref="Length" /> to a desired value before updating the characters.</para>
|
|
||||||
/// <para>Call <see cref=" Validate" /> after all the characters are updated.</para>
|
|
||||||
/// </remarks>
|
|
||||||
public char this[int index] {
|
|
||||||
get {
|
|
||||||
if (index < 0 || index >= m_length)
|
|
||||||
throw new ArgumentOutOfRangeException("index");
|
|
||||||
return _arr[index];
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if (index < 0 || index >= m_length)
|
|
||||||
throw new ArgumentOutOfRangeException("index");
|
|
||||||
if (_arr[index] == value) return;
|
|
||||||
_arr[index] = value;
|
|
||||||
_invalidated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int m_length;
|
|
||||||
/// <summary>
|
|
||||||
/// The length of the string.
|
|
||||||
/// </summary>
|
|
||||||
/// <exception cref="ArgumentOutOfRangeException">The value specified for a set operation is less than 0.</exception>
|
|
||||||
public int Length {
|
|
||||||
get {
|
|
||||||
return m_length;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if (Length < 0) throw new ArgumentOutOfRangeException("length");
|
|
||||||
if (m_length == value) return;
|
|
||||||
if (_arr.Length < value) {
|
|
||||||
var len = _arr.Length;
|
|
||||||
while (len < value) len *= 2;
|
|
||||||
var arr2 = new char[len];
|
|
||||||
Array.Copy(_arr, arr2, m_length);
|
|
||||||
_arr = arr2;
|
|
||||||
}
|
|
||||||
m_length = value;
|
|
||||||
_invalidated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Validates the string.
|
|
||||||
/// </summary>
|
|
||||||
public void Validate() {
|
|
||||||
if (!_invalidated) return;
|
|
||||||
_invalidated = false;
|
|
||||||
var ev = OnUpdate;
|
|
||||||
if (ev != null) ev.Invoke();
|
|
||||||
}
|
|
||||||
internal char[] TrustedAsArray() { return _arr; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns an enumerator that iterates through the <see cref="TargetString" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A <see cref="Enumerator" /> for the <see cref="TargetString" />.</returns>
|
|
||||||
public Enumerator GetEnumerator() {
|
|
||||||
return new Enumerator(this);
|
|
||||||
}
|
|
||||||
IEnumerator<char> IEnumerable<char>.GetEnumerator() {
|
|
||||||
return new Enumerator(this);
|
|
||||||
}
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() {
|
|
||||||
return new Enumerator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Enumerator : IEnumerator<char> {
|
|
||||||
readonly TargetString _self;
|
|
||||||
int _index;
|
|
||||||
internal Enumerator(TargetString self) {
|
|
||||||
_self = self;
|
|
||||||
_index = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public char Current {
|
|
||||||
get {
|
|
||||||
if (_index < 0)
|
|
||||||
throw new InvalidOperationException(_index == -1 ? "Enum not started" : "Enum ended");
|
|
||||||
return _self[_index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object IEnumerator.Current { get { return Current; } }
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
_index = -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MoveNext() {
|
|
||||||
if (_index == -2) return false;
|
|
||||||
_index++;
|
|
||||||
if (_index >= _self.Length) {
|
|
||||||
_index = -2;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset() {
|
|
||||||
_index = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f0fc34ac257793d4883a9cfcdb6941b9
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections.Generic {
|
|
||||||
public interface IPairList<TKey, TValue> : IList<KeyValuePair<TKey, TValue>> {
|
|
||||||
void Add(TKey key, TValue value);
|
|
||||||
void Insert(int index, TKey key, TValue value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 73fb17b484b343242bcce27c15ed7d44
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections.Generic {
|
|
||||||
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView<,>))]
|
|
||||||
public struct PairCollection<TKey, TValue> : IDisposable {
|
|
||||||
public void Dispose() { }
|
|
||||||
readonly IPairList<TKey, TValue> _pairList;
|
|
||||||
readonly IDictionary<TKey, TValue> _dictionary;
|
|
||||||
public PairCollection(object collection) : this() {
|
|
||||||
var type = collection.GetType();
|
|
||||||
if (typeof(IPairList<TKey, TValue>).IsAssignableFrom(type)) _pairList = (IPairList<TKey, TValue>)collection;
|
|
||||||
else if (typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type)) _dictionary = (IDictionary<TKey, TValue>)collection;
|
|
||||||
else throw new ArgumentException("Parameter is not a pair collection");
|
|
||||||
}
|
|
||||||
public int Count {
|
|
||||||
get {
|
|
||||||
if (_pairList != null) return _pairList.Count;
|
|
||||||
else return _dictionary.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Add(TKey key, TValue value) {
|
|
||||||
if (_pairList != null) _pairList.Add(key, value);
|
|
||||||
else _dictionary.Add(key, value);
|
|
||||||
}
|
|
||||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) {
|
|
||||||
if (_pairList != null) _pairList.CopyTo(array, index);
|
|
||||||
else _dictionary.CopyTo(array, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsPairCollection(Type type) {
|
|
||||||
return typeof(IPairList<TKey, TValue>).IsAssignableFrom(type) || typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal class PairCollectionDebugView<TKey, TValue> {
|
|
||||||
readonly PairCollection<TKey, TValue> _self;
|
|
||||||
public PairCollectionDebugView(PairCollection<TKey, TValue> self) {
|
|
||||||
_self = self;
|
|
||||||
}
|
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
|
||||||
public KeyValuePair<TKey, TValue>[] Items {
|
|
||||||
get {
|
|
||||||
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
|
|
||||||
_self.CopyTo(array, 0);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2517e8f040bd36f46948e5fafaf5335c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections.Generic {
|
|
||||||
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView<,>))]
|
|
||||||
public class PairList<TKey, TValue> : List<KeyValuePair<TKey, TValue>>, IPairList<TKey, TValue>, IPairList {
|
|
||||||
public void Add(TKey key, TValue value) {
|
|
||||||
Add(new KeyValuePair<TKey, TValue>(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(object key, object value) {
|
|
||||||
try {
|
|
||||||
Add((TKey)key, (TValue)value);
|
|
||||||
}
|
|
||||||
catch (InvalidCastException) {
|
|
||||||
throw new ArgumentException("Wrong key type or value type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Insert(int index, TKey key, TValue value) {
|
|
||||||
Insert(index, new KeyValuePair<TKey, TValue>(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Insert(int index, object key, object value) {
|
|
||||||
try {
|
|
||||||
Insert(index, (TKey)key, (TValue)value);
|
|
||||||
}
|
|
||||||
catch (InvalidCastException) {
|
|
||||||
throw new ArgumentException("Wrong key type or value type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal class PairListDebugView<TKey, TValue> {
|
|
||||||
readonly PairList<TKey, TValue> _self;
|
|
||||||
public PairListDebugView(PairList<TKey, TValue> self) {
|
|
||||||
_self = self;
|
|
||||||
}
|
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
|
||||||
public KeyValuePair<TKey, TValue>[] Items {
|
|
||||||
get {
|
|
||||||
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
|
|
||||||
_self.CopyTo(array, 0);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d9ed5ea8b7b1a934287e7ec5971166c0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics.Contracts;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.ConstrainedExecution;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections {
|
|
||||||
internal static class HashHelpers {
|
|
||||||
#if FEATURE_RANDOMIZED_STRING_HASHING
|
|
||||||
public const int HashCollisionThreshold = 100;
|
|
||||||
public static bool s_UseRandomizedStringHashing = String.UseRandomizedHashing();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Table of prime numbers to use as hash table sizes.
|
|
||||||
// A typical resize algorithm would pick the smallest prime number in this array
|
|
||||||
// that is larger than twice the previous capacity.
|
|
||||||
// Suppose our Hashtable currently has capacity x and enough elements are added
|
|
||||||
// such that a resize needs to occur. Resizing first computes 2x then finds the
|
|
||||||
// first prime in the table greater than 2x, i.e. if primes are ordered
|
|
||||||
// p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
|
|
||||||
// Doubling is important for preserving the asymptotic complexity of the
|
|
||||||
// hashtable operations such as add. Having a prime guarantees that double
|
|
||||||
// hashing does not lead to infinite loops. IE, your hash function will be
|
|
||||||
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
|
|
||||||
public static readonly int[] primes = {
|
|
||||||
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
|
|
||||||
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
|
|
||||||
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
|
|
||||||
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
|
|
||||||
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
|
|
||||||
|
|
||||||
// Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
|
|
||||||
// object until OnDeserialization is called.
|
|
||||||
private static ConditionalWeakTable<object, SerializationInfo> s_SerializationInfoTable;
|
|
||||||
|
|
||||||
internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable {
|
|
||||||
get {
|
|
||||||
if (s_SerializationInfoTable == null) {
|
|
||||||
ConditionalWeakTable<object, SerializationInfo> newTable = new ConditionalWeakTable<object, SerializationInfo>();
|
|
||||||
Interlocked.CompareExchange(ref s_SerializationInfoTable, newTable, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_SerializationInfoTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
||||||
public static bool IsPrime(int candidate) {
|
|
||||||
if ((candidate & 1) != 0) {
|
|
||||||
int limit = (int)System.Math.Sqrt (candidate);
|
|
||||||
for (int divisor = 3; divisor <= limit; divisor += 2) {
|
|
||||||
if ((candidate % divisor) == 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return (candidate == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal const Int32 HashPrime = 101;
|
|
||||||
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
||||||
public static int GetPrime(int min) {
|
|
||||||
if (min < 0)
|
|
||||||
throw new ArgumentException("Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.");
|
|
||||||
Contract.EndContractBlock();
|
|
||||||
|
|
||||||
for (int i = 0; i < primes.Length; i++) {
|
|
||||||
int prime = primes[i];
|
|
||||||
if (prime >= min) return prime;
|
|
||||||
}
|
|
||||||
|
|
||||||
//outside of our predefined table.
|
|
||||||
//compute the hard way.
|
|
||||||
for (int i = (min | 1); i < Int32.MaxValue; i += 2) {
|
|
||||||
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetMinPrime() {
|
|
||||||
return primes[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns size of hashtable to grow to.
|
|
||||||
public static int ExpandPrime(int oldSize) {
|
|
||||||
int newSize = 2 * oldSize;
|
|
||||||
|
|
||||||
// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
|
|
||||||
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
|
|
||||||
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) {
|
|
||||||
Contract.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
|
|
||||||
return MaxPrimeArrayLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPrime(newSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This is the maximum prime smaller than Array.MaxArrayLength
|
|
||||||
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e7fe2c6f3299681448c1a546cce4dc65
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections {
|
|
||||||
public interface IPairList : IList {
|
|
||||||
void Add(object key, object value);
|
|
||||||
void Insert(int index, object key, object value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 046617672d437de4ab7e644a55defd3b
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections {
|
|
||||||
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView))]
|
|
||||||
public struct PairCollection : IDisposable {
|
|
||||||
public void Dispose() { }
|
|
||||||
readonly IPairList _pairList;
|
|
||||||
readonly IDictionary _dictionary;
|
|
||||||
public PairCollection(object collection) : this() {
|
|
||||||
var type = collection.GetType();
|
|
||||||
if (typeof(IPairList).IsAssignableFrom(type)) _pairList = (IPairList)collection;
|
|
||||||
else if (typeof(IDictionary).IsAssignableFrom(type)) _dictionary = (IDictionary)collection;
|
|
||||||
else throw new ArgumentException("Parameter is not a pair collection");
|
|
||||||
}
|
|
||||||
public int Count {
|
|
||||||
get {
|
|
||||||
if (_pairList != null) return _pairList.Count;
|
|
||||||
else return _dictionary.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Add(object key, object value) {
|
|
||||||
if (_pairList != null) _pairList.Add(key, value);
|
|
||||||
else _dictionary.Add(key, value);
|
|
||||||
}
|
|
||||||
public void CopyTo(KeyValuePair<object, object>[] array, int index) {
|
|
||||||
if (_pairList != null) _pairList.CopyTo(array, index);
|
|
||||||
else _dictionary.CopyTo(array, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsPairCollection(Type type) {
|
|
||||||
return typeof(IPairList).IsAssignableFrom(type) || typeof(IDictionary).IsAssignableFrom(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal class PairCollectionDebugView {
|
|
||||||
readonly PairCollection _self;
|
|
||||||
public PairCollectionDebugView(PairCollection self) {
|
|
||||||
_self = self;
|
|
||||||
}
|
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
|
||||||
public KeyValuePair<object, object>[] Items {
|
|
||||||
get {
|
|
||||||
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
|
|
||||||
_self.CopyTo(array, 0);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1f87dfb8f6a1f5640b6deae741cd715c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Collections {
|
|
||||||
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView))]
|
|
||||||
public class PairList : List<KeyValuePair<object, object>>, IPairList {
|
|
||||||
public void Add(object key, object value) {
|
|
||||||
Add(new KeyValuePair<object, object>(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Insert(int index, object key, object value) {
|
|
||||||
Insert(index, new KeyValuePair<object, object>(key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal class PairListDebugView {
|
|
||||||
readonly PairList _self;
|
|
||||||
public PairListDebugView(PairList self) {
|
|
||||||
_self = self;
|
|
||||||
}
|
|
||||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
|
||||||
public KeyValuePair<object, object>[] Items {
|
|
||||||
get {
|
|
||||||
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
|
|
||||||
_self.CopyTo(array, 0);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57fc9f037c1fda5449e2a365a835c82c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 634536d804abc784394d4ac028a77879
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -4,12 +4,12 @@ namespace Cryville.Common {
|
|||||||
public struct Identifier : IEquatable<Identifier> {
|
public struct Identifier : IEquatable<Identifier> {
|
||||||
public static Identifier Empty = new Identifier(0);
|
public static Identifier Empty = new Identifier(0);
|
||||||
public int Key { get; private set; }
|
public int Key { get; private set; }
|
||||||
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
|
public object Name { get { return IdentifierManager.Shared.Retrieve(Key); } }
|
||||||
public Identifier(int key) {
|
public Identifier(int key) {
|
||||||
Key = key;
|
Key = key;
|
||||||
}
|
}
|
||||||
public Identifier(object name) {
|
public Identifier(object name) {
|
||||||
Key = IdentifierManager.SharedInstance.Request(name);
|
Key = IdentifierManager.Shared.Request(name);
|
||||||
}
|
}
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
if (obj == null || !(obj is Identifier)) return false;
|
if (obj == null || !(obj is Identifier)) return false;
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Common {
|
|
||||||
/// <summary>
|
|
||||||
/// A manager that assigns each given identifiers a unique integer ID.
|
|
||||||
/// </summary>
|
|
||||||
public class IdentifierManager {
|
|
||||||
/// <summary>
|
|
||||||
/// A shared instance of the <see cref="IdentifierManager" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public static IdentifierManager SharedInstance = new IdentifierManager();
|
|
||||||
|
|
||||||
readonly Dictionary<object, int> _idents = new Dictionary<object, int>();
|
|
||||||
readonly List<object> _ids = new List<object>();
|
|
||||||
|
|
||||||
readonly object _syncRoot = new object();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an instance of the <see cref="IdentifierManager" /> class.
|
|
||||||
/// </summary>
|
|
||||||
public IdentifierManager() {
|
|
||||||
Request(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Requests an integer ID for an identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ident">The identifier.</param>
|
|
||||||
/// <returns>The integer ID.</returns>
|
|
||||||
public int Request(object ident) {
|
|
||||||
lock (_syncRoot) {
|
|
||||||
int id;
|
|
||||||
if (!_idents.TryGetValue(ident, out id)) {
|
|
||||||
_idents.Add(ident, id = _idents.Count);
|
|
||||||
_ids.Add(ident);
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the identifier assigned with an integer ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The integer ID.</param>
|
|
||||||
/// <returns>The identifier.</returns>
|
|
||||||
public object Retrieve(int id) {
|
|
||||||
lock (_syncRoot) {
|
|
||||||
return _ids[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user