17db96d56Sopenharmony_ci#ifndef Py_INTERNAL_HASHTABLE_H 27db96d56Sopenharmony_ci#define Py_INTERNAL_HASHTABLE_H 37db96d56Sopenharmony_ci#ifdef __cplusplus 47db96d56Sopenharmony_ciextern "C" { 57db96d56Sopenharmony_ci#endif 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE 87db96d56Sopenharmony_ci# error "this header requires Py_BUILD_CORE define" 97db96d56Sopenharmony_ci#endif 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci/* Single linked list */ 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_citypedef struct _Py_slist_item_s { 147db96d56Sopenharmony_ci struct _Py_slist_item_s *next; 157db96d56Sopenharmony_ci} _Py_slist_item_t; 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_citypedef struct { 187db96d56Sopenharmony_ci _Py_slist_item_t *head; 197db96d56Sopenharmony_ci} _Py_slist_t; 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#define _Py_SLIST_ITEM_NEXT(ITEM) (((_Py_slist_item_t *)ITEM)->next) 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci#define _Py_SLIST_HEAD(SLIST) (((_Py_slist_t *)SLIST)->head) 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ci/* _Py_hashtable: table entry */ 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_citypedef struct { 297db96d56Sopenharmony_ci /* used by _Py_hashtable_t.buckets to link entries */ 307db96d56Sopenharmony_ci _Py_slist_item_t _Py_slist_item; 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci Py_uhash_t key_hash; 337db96d56Sopenharmony_ci void *key; 347db96d56Sopenharmony_ci void *value; 357db96d56Sopenharmony_ci} _Py_hashtable_entry_t; 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci/* _Py_hashtable: prototypes */ 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci/* Forward declaration */ 417db96d56Sopenharmony_cistruct _Py_hashtable_t; 427db96d56Sopenharmony_citypedef struct _Py_hashtable_t _Py_hashtable_t; 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_citypedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key); 457db96d56Sopenharmony_citypedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2); 467db96d56Sopenharmony_citypedef void (*_Py_hashtable_destroy_func) (void *key); 477db96d56Sopenharmony_citypedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht, 487db96d56Sopenharmony_ci const void *key); 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_citypedef struct { 517db96d56Sopenharmony_ci // Allocate a memory block 527db96d56Sopenharmony_ci void* (*malloc) (size_t size); 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci // Release a memory block 557db96d56Sopenharmony_ci void (*free) (void *ptr); 567db96d56Sopenharmony_ci} _Py_hashtable_allocator_t; 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci/* _Py_hashtable: table */ 607db96d56Sopenharmony_cistruct _Py_hashtable_t { 617db96d56Sopenharmony_ci size_t nentries; // Total number of entries in the table 627db96d56Sopenharmony_ci size_t nbuckets; 637db96d56Sopenharmony_ci _Py_slist_t *buckets; 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci _Py_hashtable_get_entry_func get_entry_func; 667db96d56Sopenharmony_ci _Py_hashtable_hash_func hash_func; 677db96d56Sopenharmony_ci _Py_hashtable_compare_func compare_func; 687db96d56Sopenharmony_ci _Py_hashtable_destroy_func key_destroy_func; 697db96d56Sopenharmony_ci _Py_hashtable_destroy_func value_destroy_func; 707db96d56Sopenharmony_ci _Py_hashtable_allocator_t alloc; 717db96d56Sopenharmony_ci}; 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci/* Hash a pointer (void*) */ 747db96d56Sopenharmony_ciPyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key); 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci/* Comparison using memcmp() */ 777db96d56Sopenharmony_ciPyAPI_FUNC(int) _Py_hashtable_compare_direct( 787db96d56Sopenharmony_ci const void *key1, 797db96d56Sopenharmony_ci const void *key2); 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ciPyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new( 827db96d56Sopenharmony_ci _Py_hashtable_hash_func hash_func, 837db96d56Sopenharmony_ci _Py_hashtable_compare_func compare_func); 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ciPyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full( 867db96d56Sopenharmony_ci _Py_hashtable_hash_func hash_func, 877db96d56Sopenharmony_ci _Py_hashtable_compare_func compare_func, 887db96d56Sopenharmony_ci _Py_hashtable_destroy_func key_destroy_func, 897db96d56Sopenharmony_ci _Py_hashtable_destroy_func value_destroy_func, 907db96d56Sopenharmony_ci _Py_hashtable_allocator_t *allocator); 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ciPyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht); 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ciPyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht); 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_citypedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht, 977db96d56Sopenharmony_ci const void *key, const void *value, 987db96d56Sopenharmony_ci void *user_data); 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci/* Call func() on each entry of the hashtable. 1017db96d56Sopenharmony_ci Iteration stops if func() result is non-zero, in this case it's the result 1027db96d56Sopenharmony_ci of the call. Otherwise, the function returns 0. */ 1037db96d56Sopenharmony_ciPyAPI_FUNC(int) _Py_hashtable_foreach( 1047db96d56Sopenharmony_ci _Py_hashtable_t *ht, 1057db96d56Sopenharmony_ci _Py_hashtable_foreach_func func, 1067db96d56Sopenharmony_ci void *user_data); 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ciPyAPI_FUNC(size_t) _Py_hashtable_size(const _Py_hashtable_t *ht); 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci/* Add a new entry to the hash. The key must not be present in the hash table. 1117db96d56Sopenharmony_ci Return 0 on success, -1 on memory error. */ 1127db96d56Sopenharmony_ciPyAPI_FUNC(int) _Py_hashtable_set( 1137db96d56Sopenharmony_ci _Py_hashtable_t *ht, 1147db96d56Sopenharmony_ci const void *key, 1157db96d56Sopenharmony_ci void *value); 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci/* Get an entry. 1197db96d56Sopenharmony_ci Return NULL if the key does not exist. */ 1207db96d56Sopenharmony_cistatic inline _Py_hashtable_entry_t * 1217db96d56Sopenharmony_ci_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key) 1227db96d56Sopenharmony_ci{ 1237db96d56Sopenharmony_ci return ht->get_entry_func(ht, key); 1247db96d56Sopenharmony_ci} 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci/* Get value from an entry. 1287db96d56Sopenharmony_ci Return NULL if the entry is not found. 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ci Use _Py_hashtable_get_entry() to distinguish entry value equal to NULL 1317db96d56Sopenharmony_ci and entry not found. */ 1327db96d56Sopenharmony_ciPyAPI_FUNC(void*) _Py_hashtable_get(_Py_hashtable_t *ht, const void *key); 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci/* Remove a key and its associated value without calling key and value destroy 1367db96d56Sopenharmony_ci functions. 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci Return the removed value if the key was found. 1397db96d56Sopenharmony_ci Return NULL if the key was not found. */ 1407db96d56Sopenharmony_ciPyAPI_FUNC(void*) _Py_hashtable_steal( 1417db96d56Sopenharmony_ci _Py_hashtable_t *ht, 1427db96d56Sopenharmony_ci const void *key); 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci#ifdef __cplusplus 1467db96d56Sopenharmony_ci} 1477db96d56Sopenharmony_ci#endif 1487db96d56Sopenharmony_ci#endif /* !Py_INTERNAL_HASHTABLE_H */ 149