May be useful for someone, extended NativeHashMap container for replacing value by key.
Cause native Unity implementation not support that yet
May be someone posted this before on forum (really don’t remember, cause so many posts watched by me on forum from the beginning of ECS, and I can’t remember all if so, please link thread with that )
Implemented 2 variations - by indexer and by method call:
Indexer
public TValue this [TKey key]
{
get
{
TValue res;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (TryGetValue(key, out res))
return res;
else
throw new ArgumentException($"Key: {key} is not present in the NativeHashMap.");
#else
TryGetValue(key, out res);
return res;
#endif
}
set
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (!TryReplaceValue(key, value))
throw new ArgumentException($"Key: {key} is not present in the NativeHashMap.");
#else
TryReplaceValue(key, value)
#endif
}
}
TryReplaceValue
public bool TryReplaceValue(TKey key, TValue item)
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
#endif
return NativeHashMapBase<TKey, TValue>.TryReplaceValue(m_Buffer, key, item, false, m_AllocatorLabel);
}
public static unsafe bool TryReplaceValue(NativeHashMapData* data, TKey key, TValue item, bool isMultiHashMap,
Allocator allocation)
{
TValue tempItem;
NativeMultiHashMapIterator<TKey> tempIt;
if (isMultiHashMap)
return false;
return TryReplaceFirstValueAtomic(data, key, item, out tempIt);
}
public static unsafe bool TryReplaceFirstValueAtomic(NativeHashMapData* data, TKey key, TValue item,
out NativeMultiHashMapIterator<TKey> it)
{
it.key = key;
if (data->allocatedIndexLength <= 0)
{
it.EntryIndex = it.NextEntryIndex = -1;
return false;
}
// First find the slot based on the hash
int* buckets = (int*) data->buckets;
int bucket = key.GetHashCode() & data->bucketCapacityMask;
it.EntryIndex = it.NextEntryIndex = buckets[bucket];
return TryReplaceNextValueAtomic(data, item, ref it);
}
public static unsafe bool TryReplaceNextValueAtomic(NativeHashMapData* data, TValue item,
ref NativeMultiHashMapIterator<TKey> it)
{
int entryIdx = it.NextEntryIndex;
it.NextEntryIndex = -1;
it.EntryIndex = -1;
if (entryIdx < 0 || entryIdx >= data->keyCapacity)
return false;
int* nextPtrs = (int*) data->next;
while (!UnsafeUtility.ReadArrayElement<TKey>(data->keys, entryIdx).Equals(it.key))
{
entryIdx = nextPtrs[entryIdx];
if (entryIdx < 0 || entryIdx >= data->keyCapacity)
return false;
}
it.NextEntryIndex = nextPtrs[entryIdx];
it.EntryIndex = entryIdx;
// Write the value
UnsafeUtility.WriteArrayElement(data->keys, entryIdx, it.key);
UnsafeUtility.WriteArrayElement(data->values, entryIdx, item);
return true;
}
Maded on Collections version 0.0.9-preview.11.
For using just replace NativeHashMap.cs inside your ProjectFolder\Library\PackageCache\com.unity.collections@0.0.9-preview.11\Unity.Collections location.
4216720–374389–NativeHashMap.cs (44.5 KB)