#ifndef HT_H #define HT_H #include "pair.h" #include "util.h" enum { HT_INIT_CAP = 1 << 8 }; /* The algorithm here imitates the algorithm used by python's hash tables. The source code of the python dict object can be found in the following URL: */ /* We can use anything as the key, except that the type of the keys should satisfy the following conditions. - Hash-able: We must know how to produce the hash value of a key. - Comparable: We must know how to compare two keys, in order to know if two keys are "equal". */ /* type for a hash function */ typedef NUM (*hash_func_t) (CCR_MOD(void *)key); /* comparison function type */ typedef BOOL (*compare_func_t) (CCR_MOD(void *)keya, CCR_MOD(void *)keyb); /* FIXME: Hide this struct from the header file. */ /* WARNING: Don't use these fields directly. These fields are exposed in this header file simply because I want to use pointers to ht and do arithmetic on those pointers. But these fields might change anytime in the future, if I think of some new ideas, or something like that. */ struct ht_s { void **keys; void **values; NUM *indices; UNUM capability; /* REVIEW: What is the purpose of SIZE? */ /* ANSWER: For looping over keys / values. */ int size; hash_func_t hf; compare_func_t cf; }; typedef struct ht_s ht; /* On error return NULL */ ht *new_ht(UNUM size, int nargs, ...); /* This enum empowers the user the ability to control how to free the hash table. The destroy function always frees keys, values, and indices pointers. If the option contains the word "SELF", it means to also free the hash table pointer itself. Otherwise, it contains NO_SELF, and it means not to free the hash table pointer. If it contains the word "KEY" (respectively "VALUE"), then it means to also free the pointers stored in the keys (respectively values) array. How to free the pointers? If the option contains the word "FIRST", then it means to free the first pointer stored in the array corresponding to the word before "FIRST". And it frees each and every of the other word's pointers. To free both keys and values pointers in the same manner, i.e. free both of the first pointers or free each and every pointers, use the option containing "EVERY_FIRST" or "EVERY" respectively. */ enum HT_DESTROY_FLAG_e { DESTROY_NONE_NO_SELF, DESTROY_NONE_SELF, DESTROY_KEY_SELF, DESTROY_KEY_FIRST_SELF, DESTROY_KEY_NO_SELF, DESTROY_KEY_FIRST_NO_SELF, DESTROY_VALUE_SELF, DESTROY_VALUE_FIRST_SELF, DESTROY_VALUE_NO_SELF, DESTROY_VALUE_FIRST_NO_SELF, DESTROY_EVERY_SELF, DESTROY_EVERY_FIRST_SELF, DESTROY_EVERY_NO_SELF, DESTROY_EVERY_FIRST_NO_SELF, DESTROY_KEY_FIRST_VALUE_SELF, DESTROY_KEY_FIRST_VALUE_NO_SELF, DESTROY_KEY_VALUE_FIRST_SELF, DESTROY_KEY_VALUE_FIRST_NO_SELF }; typedef enum HT_DESTROY_FLAG_e HT_DESTROY_FLAG; void destroy_ht(ht * restrict htp, HT_DESTROY_FLAG flag); BOOL ht_insert(ht * const restrict htp, void *key, void *value); P_ATTR NUM ht_size(CCR_MOD(ht *) htp); P_ATTR void **ht_values(CCR_MOD(ht *) htp); P_ATTR void **ht_keys(CCR_MOD(ht *) htp); enum HT_DELETE_FLAG_e { DELETE_NONE, DELETE_KEY, DELETE_VALUE, DELETE_EVERY }; typedef enum HT_DELETE_FLAG_e HT_DELETE_FLAG; BOOL ht_delete(ht * const restrict htp, void *key, HT_DELETE_FLAG flag); void ht_reset(ht * const restrict htp, HT_DELETE_FLAG flag); P_ATTR void *ht_find(CCR_MOD(ht *) htp, void *key); /* Pairing hash tables */ /* On error return NULL */ ht *new_ht2(UNUM size); /* On error return NULL */ ht *new_ht3(UNUM size); ht *new_ht4(UNUM size); #define NEW_P2(P, X, Y, CLEAN) do { \ SAFE_MALLOC(pair2, P, 1, CLEAN); \ P->x = X; \ P->y = Y; \ } while (0) #define NEW_P3(P, X, Y, Z, CLEAN) do { \ SAFE_MALLOC(pair3, P, 1, CLEAN); \ P->x = X; \ P->y = Y; \ P->z = Z; \ } while (0) #define NEW_P4(P, X, Y, Z, W, CLEAN) do { \ SAFE_MALLOC(pair4, P, 1, CLEAN); \ P->x = X; \ P->y = Y; \ P->z = Z; \ P->u = W; \ } while (0) #endif