public static UnsafeHashSet *Allocate(int capacity, int valStride, bool fixedSize = false) { var entryStride = sizeof(UnsafeHashCollection.Entry); // round capacity up to next prime capacity = UnsafeHashCollection.GetNextPrime(capacity); // this has to be true Assert.Check(entryStride == 16); var valAlignment = Native.GetAlignment(valStride); // the alignment for entry/key/val, we can't have less than ENTRY_ALIGNMENT // bytes alignment because entries are 16 bytes with 1 x pointer + 2 x 4 byte integers var alignment = Math.Max(UnsafeHashCollection.Entry.ALIGNMENT, valAlignment); // calculate strides for all elements valStride = Native.RoundToAlignment(valStride, alignment); entryStride = Native.RoundToAlignment(sizeof(UnsafeHashCollection.Entry), alignment); // dictionary ptr UnsafeHashSet *set; if (fixedSize) { var sizeOfHeader = Native.RoundToAlignment(sizeof(UnsafeHashSet), alignment); var sizeOfBucketsBuffer = Native.RoundToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment); var sizeofEntriesBuffer = (entryStride + valStride) * capacity; // allocate memory var ptr = Native.MallocAndClear(sizeOfHeader + sizeOfBucketsBuffer + sizeofEntriesBuffer, alignment); // start of memory is the dict itself set = (UnsafeHashSet *)ptr; // buckets are offset by header size set->_collection.Buckets = (UnsafeHashCollection.Entry * *)((byte *)ptr + sizeOfHeader); // initialize fixed buffer UnsafeBuffer.InitFixed(&set->_collection.Entries, (byte *)ptr + (sizeOfHeader + sizeOfBucketsBuffer), capacity, entryStride + valStride); } else { // allocate dict, buckets and entries buffer separately set = Native.MallocAndClear <UnsafeHashSet>(); set->_collection.Buckets = (UnsafeHashCollection.Entry * *)Native.MallocAndClear(sizeof(UnsafeHashCollection.Entry * *) * capacity, sizeof(UnsafeHashCollection.Entry * *)); // init dynamic buffer UnsafeBuffer.InitDynamic(&set->_collection.Entries, capacity, entryStride + valStride); } set->_collection.FreeCount = 0; set->_collection.UsedCount = 0; set->_collection.KeyOffset = entryStride; return(set); }
public static void Free(UnsafeHashMap *set) { if (set->_collection.Entries.Dynamic) { UnsafeHashCollection.Free(&set->_collection); } AllocHelper.Free(set); }
public static void Free(UnsafeHashMap *set) { if (set->_collection.Entries.Dynamic == 1) { UnsafeHashCollection.Free(&set->_collection); } Native.Free(set); }
public static void Or <T>(UnsafeHashSet *set, UnsafeHashSet *other) where T : unmanaged, IEquatable <T> { for (int i = other->_collection.UsedCount - 1; i >= 0; --i) { var entry = UnsafeHashCollection.GetEntry(&other->_collection, i); if (entry->State == UnsafeHashCollection.EntryState.Used) { // always add to this collection Add <T>(set, *(T *)((byte *)entry + other->_collection.KeyOffset)); } } }
public static void *GetPtr <K>(UnsafeHashMap *map, K key) where K : unmanaged, IEquatable <K> { var entry = UnsafeHashCollection.Find(&map->_collection, key, key.GetHashCode()); if (entry == null) { throw new KeyNotFoundException(key.ToString()); } return(GetValue(map, entry)); }
public static void Set <K>(UnsafeHashMap *map, K key, void *value, int size) where K : unmanaged, IEquatable <K> { var hash = key.GetHashCode(); var entry = UnsafeHashCollection.Find(&map->_collection, key, hash); if (entry == null) // insert new entry for key { entry = UnsafeHashCollection.Insert(&map->_collection, key, hash); } // assign value to entry UnsafeUtility.MemCpy(GetValue(map, entry), value, size); }
public static bool Add <T>(UnsafeHashSet *set, T key) where T : unmanaged, IEquatable <T> { var hash = key.GetHashCode(); var entry = UnsafeHashCollection.Find <T>(&set->_collection, key, hash); if (entry == null) { UnsafeHashCollection.Insert <T>(&set->_collection, key, hash); return(true); } return(false); }
public bool Next() { while (++_index < Collection->UsedCount) { var entry = UnsafeHashCollection.GetEntry(Collection, _index); if (entry->State == EntryState.Used) { Current = entry; return(true); } } Current = null; return(false); }
public static void Set <K, V>(UnsafeHashMap *map, K key, V value) where K : unmanaged, IEquatable <K> where V : unmanaged { var hash = key.GetHashCode(); var entry = UnsafeHashCollection.Find(&map->_collection, key, hash); if (entry == null) // insert new entry for key { entry = UnsafeHashCollection.Insert(&map->_collection, key, hash); } // assign value to entry *(V *)GetValue(map, entry) = value; }
public static bool TryGetValuePtr <K, V>(UnsafeHashMap *map, K key, out V *val) where K : unmanaged, IEquatable <K> where V : unmanaged { var entry = UnsafeHashCollection.Find <K>(&map->_collection, key, key.GetHashCode()); if (entry != null) { val = (V *)GetValue(map, entry); return(true); } val = null; return(false); }
public static void And <T>(UnsafeHashSet *set, UnsafeHashSet *other) where T : unmanaged, IEquatable <T> { for (int i = set->_collection.UsedCount - 1; i >= 0; --i) { var entry = UnsafeHashCollection.GetEntry(&set->_collection, i); if (entry->State == UnsafeHashCollection.EntryState.Used) { var key = *(T *)((byte *)entry + set->_collection.KeyOffset); var keyHash = key.GetHashCode(); // if we don't find this in other collection, remove it (And) if (UnsafeHashCollection.Find <T>(&other->_collection, key, keyHash) == null) { UnsafeHashCollection.Remove <T>(&set->_collection, key, keyHash); } } } }
public static void Add <K, V>(UnsafeHashMap *map, K key, V value) where K : unmanaged, IEquatable <K> where V : unmanaged { var hash = key.GetHashCode(); var entry = UnsafeHashCollection.Find <K>(&map->_collection, key, hash); if (entry == null) { // insert new entry for key entry = UnsafeHashCollection.Insert <K>(&map->_collection, key, hash); // assign value to entry *(V *)GetValue(map, entry) = value; } else { throw new InvalidOperationException(); } }
public static UnsafeHashMap *Allocate(int capacity, int keyStride, int valStride, bool fixedSize = false) { var entryStride = sizeof(UnsafeHashCollection.Entry); // round capacity up to next prime capacity = UnsafeHashCollection.GetNextPrime(capacity); // this has to be true Assert.Check(entryStride == 16); var keyAlignment = AllocHelper.GetAlignmentForArrayElement(keyStride); var valAlignment = AllocHelper.GetAlignmentForArrayElement(valStride); // the alignment for entry/key/val, we can't have less than ENTRY_ALIGNMENT // bytes alignment because entries are 8 bytes with 2 x 32 bit integers var alignment = Math.Max(UnsafeHashCollection.Entry.ALIGNMENT, Math.Max(keyAlignment, valAlignment)); // calculate strides for all elements keyStride = AllocHelper.RoundUpToAlignment(keyStride, alignment); valStride = AllocHelper.RoundUpToAlignment(valStride, alignment); entryStride = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashCollection.Entry), alignment); // map ptr UnsafeHashMap *map; if (fixedSize) { var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashMap), alignment); var sizeOfBucketsBuffer = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment); var sizeofEntriesBuffer = (entryStride + keyStride + valStride) * capacity; // allocate memory var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeOfBucketsBuffer + sizeofEntriesBuffer, alignment); // start of memory is the dict itself map = (UnsafeHashMap *)ptr; // buckets are offset by header size map->_collection.Buckets = (UnsafeHashCollection.Entry * *)((byte *)ptr + sizeOfHeader); // initialize fixed buffer UnsafeBuffer.InitFixed(&map->_collection.Entries, (byte *)ptr + (sizeOfHeader + sizeOfBucketsBuffer), capacity, entryStride + keyStride + valStride); } else { // allocate dict, buckets and entries buffer separately map = AllocHelper.MallocAndClear <UnsafeHashMap>(); map->_collection.Buckets = (UnsafeHashCollection.Entry * *)AllocHelper.MallocAndClear(sizeof(UnsafeHashCollection.Entry * *) * capacity, sizeof(UnsafeHashCollection.Entry * *)); // init dynamic buffer UnsafeBuffer.InitDynamic(&map->_collection.Entries, capacity, entryStride + keyStride + valStride); } // header init map->_collection.FreeCount = 0; map->_collection.UsedCount = 0; map->_collection.KeyOffset = entryStride; map->_valueOffset = entryStride + keyStride; return(map); }
public static bool Remove <K>(UnsafeHashMap *map, K key) where K : unmanaged, IEquatable <K> { return(UnsafeHashCollection.Remove <K>(&map->_collection, key, key.GetHashCode())); }
public static bool ContainsKey <K>(UnsafeHashMap *map, K key) where K : unmanaged, IEquatable <K> { return(UnsafeHashCollection.Find <K>(&map->_collection, key, key.GetHashCode()) != null); }
public static bool Contains <T>(UnsafeHashSet *set, T key) where T : unmanaged, IEquatable <T> { return(UnsafeHashCollection.Find <T>(&set->_collection, key, key.GetHashCode()) != null); }
public static bool Remove <T>(UnsafeHashSet *set, T key) where T : unmanaged, IEquatable <T> { return(UnsafeHashCollection.Remove <T>(&set->_collection, key, key.GetHashCode())); }
public static void Clear(UnsafeHashMap *set) { UnsafeHashCollection.Clear(&set->_collection); }