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