提交导表相关功能

This commit is contained in:
2025-09-27 17:53:39 +08:00
parent f899a55769
commit c1a3df2192
79 changed files with 4365 additions and 1 deletions

View File

@@ -0,0 +1,17 @@
namespace NBConfigBuilder;
/// <summary>
/// 实现了这个接口代表支持对象池
/// </summary>
public interface IPool
{
/// <summary>
/// 是否从池里创建的
/// </summary>
bool IsPool();
/// <summary>
/// 设置是否从池里创建的
/// </summary>
/// <param name="isPool"></param>
void SetIsPool(bool isPool);
}

View File

@@ -0,0 +1,25 @@
namespace NBConfigBuilder;
public partial class IntDictionaryConfig
{
public Dictionary<int, int> Dic;
public int this[int key] => GetValue(key);
public bool TryGetValue(int key, out int value)
{
value = default;
if (!Dic.ContainsKey(key))
{
return false;
}
value = Dic[key];
return true;
}
private int GetValue(int key)
{
return Dic.TryGetValue(key, out var value) ? value : 0;
}
}

View File

@@ -0,0 +1,77 @@
using System.Buffers;
namespace NBConfigBuilder;
public enum MemoryStreamBufferSource
{
None = 0,
Pack = 1,
UnPack = 2,
}
public sealed class MemoryStreamBuffer : MemoryStream, IBufferWriter<byte>
{
public MemoryStreamBufferSource MemoryStreamBufferSource;
public MemoryStreamBuffer()
{
}
public MemoryStreamBuffer(MemoryStreamBufferSource memoryStreamBufferSource, int capacity) : base(capacity)
{
MemoryStreamBufferSource = memoryStreamBufferSource;
}
public MemoryStreamBuffer(byte[] buffer) : base(buffer)
{
}
public void Advance(int count)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), count, "The value of 'count' cannot be negative.");
}
var newLength = Position + count;
if (newLength != Length)
{
SetLength(newLength);
}
Position = newLength;
}
public Memory<byte> GetMemory(int sizeHint = 0)
{
if (sizeHint < 0)
{
throw new ArgumentOutOfRangeException(nameof(sizeHint), sizeHint,
"The value of 'count' cannot be negative.");
}
if (Length - Position <= sizeHint)
{
SetLength(Position + sizeHint);
}
return new Memory<byte>(GetBuffer(), (int)Position, (int)(Length - Position));
}
public Span<byte> GetSpan(int sizeHint = 0)
{
if (sizeHint < 0)
{
throw new ArgumentOutOfRangeException(nameof(sizeHint), sizeHint,
"The value of 'count' cannot be negative.");
}
if (Length - Position <= sizeHint)
{
SetLength(Position + sizeHint);
}
return new Span<byte>(GetBuffer(), (int)Position, (int)(Length - Position));
}
}

View File

@@ -0,0 +1,217 @@
namespace NBConfigBuilder;
/// <summary>
/// 可回收的、一对多关系的列表池。
/// </summary>
/// <typeparam name="TKey">键的类型。</typeparam>
/// <typeparam name="TValue">值的类型。</typeparam>
public class OneToManyListPool<TKey, TValue> : OneToManyList<TKey, TValue>, IDisposable, IPool where TKey : notnull
{
private bool _isPool;
private bool _isDispose;
/// <summary>
/// 创建一个 <see cref="OneToManyListPool{TKey, TValue}"/> 一对多关系的列表池的实例。
/// </summary>
/// <returns>创建的实例。</returns>
public static OneToManyListPool<TKey, TValue> Create()
{
var list = Pool<OneToManyListPool<TKey, TValue>>.Rent();
list._isDispose = false;
list._isPool = true;
return list;
}
/// <summary>
/// 释放当前对象所占用的资源,并将对象回收到对象池中。
/// </summary>
public void Dispose()
{
if (_isDispose)
{
return;
}
_isDispose = true;
Clear();
Pool<OneToManyListPool<TKey, TValue>>.Return(this);
}
/// <summary>
/// 获取一个值,该值指示当前实例是否为对象池中的实例。
/// </summary>
/// <returns></returns>
public bool IsPool()
{
return _isPool;
}
/// <summary>
/// 设置一个值,该值指示当前实例是否为对象池中的实例。
/// </summary>
/// <param name="isPool"></param>
public void SetIsPool(bool isPool)
{
_isPool = isPool;
}
}
/// <summary>
/// 一对多关系的列表字典。
/// </summary>
/// <typeparam name="TKey">键的类型。</typeparam>
/// <typeparam name="TValue">值的类型。</typeparam>
public class OneToManyList<TKey, TValue> : Dictionary<TKey, List<TValue>> where TKey : notnull
{
private readonly int _recyclingLimit = 120;
private static readonly List<TValue> Empty = new List<TValue>();
private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
/// <summary>
/// 初始化一个新的 <see cref="OneToManyList{TKey, TValue}"/> 实例。
/// </summary>
public OneToManyList()
{
}
/// <summary>
/// 设置最大缓存数量
/// </summary>
/// <param name="recyclingLimit">
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
/// 2:设置成0不控制数量全部缓存
/// </param>
public OneToManyList(int recyclingLimit)
{
_recyclingLimit = recyclingLimit;
}
/// <summary>
/// 判断给定的键和值是否存在于列表中。
/// </summary>
/// <param name="key">要搜索的键。</param>
/// <param name="value">要搜索的值。</param>
/// <returns>如果存在则为 <see langword="true"/>,否则为 <see langword="false"/>。</returns>
public bool Contains(TKey key, TValue value)
{
TryGetValue(key, out var list);
return list != null && list.Contains(value);
}
/// <summary>
/// 向列表中添加指定键和值。
/// </summary>
/// <param name="key">要添加值的键。</param>
/// <param name="value">要添加的值。</param>
public void Add(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
list = Fetch();
list.Add(value);
Add(key, list);
return;
}
list.Add(value);
}
/// <summary>
/// 获取指定键对应的列表中的第一个值。
/// </summary>
/// <param name="key">要获取值的键。</param>
/// <returns>键对应的列表中的第一个值。</returns>
public TValue First(TKey key)
{
return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
}
/// <summary>
/// 从列表中移除指定键和值。
/// </summary>
/// <param name="key">要移除值的键。</param>
/// <param name="value">要移除的值。</param>
/// <returns>如果成功移除则为 <see langword="true"/>,否则为 <see langword="false"/>。</returns>
public bool RemoveValue(TKey key, TValue value)
{
if (!TryGetValue(key, out var list))
{
return true;
}
var isRemove = list.Remove(value);
if (list.Count == 0)
{
isRemove = RemoveByKey(key);
}
return isRemove;
}
/// <summary>
/// 从列表中移除指定键及其关联的所有值。
/// </summary>
/// <param name="key">要移除的键。</param>
/// <returns>如果成功移除则为 <see langword="true"/>,否则为 <see langword="false"/>。</returns>
public bool RemoveByKey(TKey key)
{
if (!TryGetValue(key, out var list))
{
return false;
}
Remove(key);
Recycle(list);
return true;
}
/// <summary>
/// 获取指定键关联的所有值的列表。
/// </summary>
/// <param name="key">要获取值的键。</param>
/// <returns>键关联的所有值的列表。</returns>
public List<TValue> GetValues(TKey key)
{
if (TryGetValue(key, out List<TValue> list))
{
return list;
}
return Empty;
}
/// <summary>
/// 清除字典中的所有键值对,并回收相关的值集合。
/// </summary>
public new void Clear()
{
foreach (var keyValuePair in this) Recycle(keyValuePair.Value);
base.Clear();
}
/// <summary>
/// 从空闲值集合队列中获取一个值集合,如果队列为空则创建一个新的值集合。
/// </summary>
/// <returns>从队列中获取的值集合。</returns>
private List<TValue> Fetch()
{
return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
}
/// <summary>
/// 回收一个不再使用的值集合到空闲值集合队列中。
/// </summary>
/// <param name="list">要回收的值集合。</param>
private void Recycle(List<TValue> list)
{
list.Clear();
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
_queue.Enqueue(list);
}
}

View File

@@ -0,0 +1,72 @@
namespace NBConfigBuilder;
/// <summary>
/// 静态的对象池系统,不支持多线程。
/// </summary>
/// <typeparam name="T"></typeparam>
public static class Pool<T> where T : IPool, new()
{
private static readonly Queue<T> PoolQueue = new Queue<T>();
/// <summary>
/// 池子里可用的数量
/// </summary>
public static int Count => PoolQueue.Count;
/// <summary>
/// 租借
/// </summary>
/// <returns></returns>
public static T Rent()
{
return PoolQueue.Count == 0 ? new T() : PoolQueue.Dequeue();
}
/// <summary>
/// 租借
/// </summary>
/// <param name="generator">如果池子里没有,会先执行这个委托。</param>
/// <returns></returns>
public static T Rent(Func<T> generator)
{
return PoolQueue.Count == 0 ? generator() : PoolQueue.Dequeue();
}
/// <summary>
/// 返还
/// </summary>
/// <param name="t"></param>
public static void Return(T t)
{
if (t == null)
{
return;
}
PoolQueue.Enqueue(t);
}
/// <summary>
/// 返还
/// </summary>
/// <param name="t">返还的东西</param>
/// <param name="reset">返还后执行的委托</param>
public static void Return(T t, Action<T> reset)
{
if (t == null)
{
return;
}
reset(t);
PoolQueue.Enqueue(t);
}
/// <summary>
/// 清空池子
/// </summary>
public static void Clear()
{
PoolQueue.Clear();
}
}

View File

@@ -0,0 +1,20 @@
using System.ComponentModel;
namespace Fantasy.Serialize;
public abstract class ASerialize : ISupportInitialize, IDisposable
{
public virtual void Dispose()
{
}
public virtual void BeginInit()
{
}
public virtual void EndInit()
{
}
public virtual void AfterDeserialization() => EndInit();
}

View File

@@ -0,0 +1,25 @@
namespace NBConfigBuilder;
public sealed partial class StringDictionaryConfig
{
public Dictionary<int, string> Dic;
public string this[int key] => GetValue(key);
public bool TryGetValue(int key, out string value)
{
value = default;
if (!Dic.ContainsKey(key))
{
return false;
}
value = Dic[key];
return true;
}
private string GetValue(int key)
{
return Dic.TryGetValue(key, out var value) ? value : null;
}
}