// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System; using System.Collections.Generic; using Unity.Collections; namespace MagicaCloth { /// /// NativeMultiHashMapの機能拡張版 /// /// /// public class ExNativeMultiHashMap where TKey : struct, IEquatable where TValue : struct { /// /// ネイティブハッシュマップ /// NativeMultiHashMap nativeMultiHashMap; /// /// ネイティブリストの配列数 /// ※ジョブでエラーが出ないように事前に確保しておく /// int nativeLength; /// /// 使用キーの記録 /// Dictionary useKeyDict = new Dictionary(); //========================================================================================= public ExNativeMultiHashMap() { nativeMultiHashMap = new NativeMultiHashMap(1, Allocator.Persistent); nativeLength = NativeCount; } public void Dispose() { if (nativeMultiHashMap.IsCreated) { nativeMultiHashMap.Dispose(); } nativeLength = 0; } private int NativeCount { get { return nativeMultiHashMap.Count(); } } //========================================================================================= public bool IsCreated { get { return nativeMultiHashMap.IsCreated; } } /// /// データ追加 /// /// /// public void Add(TKey key, TValue value) { nativeMultiHashMap.Add(key, value); if (useKeyDict.ContainsKey(key)) useKeyDict[key] = useKeyDict[key] + 1; else useKeyDict[key] = 1; nativeLength = NativeCount; } /// /// データ削除 /// データ削除にはコストがかかるので注意! /// そして何故かこの関数は削除するごとに重くなる性質があるらしい(何故?) /// /// /// public void Remove(TKey key, TValue value) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { if (data.Equals(value)) { // 削除 nativeMultiHashMap.Remove(iterator); var cnt = useKeyDict[key] - 1; if (cnt == 0) useKeyDict.Remove(key); break; } } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } nativeLength = NativeCount; } /// /// 条件判定削除 /// 何故か削除はこちらで一括でやったほうが早い! /// /// trueを返せば削除 public void Remove(Func func) { List removeKey = new List(); foreach (TKey key in useKeyDict.Keys) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { // 削除判定 if (func(key, data)) { // 削除 nativeMultiHashMap.Remove(iterator); var cnt = useKeyDict[key] - 1; if (cnt == 0) removeKey.Add(key); } } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } } foreach (var key in removeKey) useKeyDict.Remove(key); nativeLength = NativeCount; } /// /// データ置き換え /// /// trueを返せば置換 /// 引数にデータを受け取り、修正したデータを返し置換する public void Replace(Func func, Func datafunc) { foreach (var key in useKeyDict.Keys) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { // 置換判定 if (func(key, data)) { // 置き換え nativeMultiHashMap.SetValue(datafunc(data), iterator); return; } } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } } nativeLength = NativeCount; } /// /// データに対してアクションを実行 /// /// public void Process(Action act) { foreach (var key in useKeyDict.Keys) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { act(key, data); } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } } } /// /// キーのデータに対してアクションを実行 /// /// /// public void Process(TKey key, Action act) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { act(data); } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } } /// /// データが存在するか判定する /// /// /// /// public bool Contains(TKey key, TValue value) { TValue data; NativeMultiHashMapIterator iterator; if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator)) { do { if (data.Equals(value)) { return true; } } while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator)); } return false; } /// /// キーが存在するか判定する /// /// /// public bool Contains(TKey key) { return useKeyDict.ContainsKey(key); } /// /// キーの削除 /// /// public void Remove(TKey key) { nativeMultiHashMap.Remove(key); useKeyDict.Remove(key); nativeLength = NativeCount; } /// /// 実際に利用されている要素数を返す /// public int Count { get { //return nativeMultiHashMap.Length; return nativeLength; } } /// /// データ削除 /// public void Clear() { nativeMultiHashMap.Clear(); nativeLength = 0; useKeyDict.Clear(); } /// /// 内部のNativeMultiHashMapを取得する /// /// public NativeMultiHashMap Map { get { return nativeMultiHashMap; } } } }