hashtable.h

Go to the documentation of this file.
00001 
00055 #ifndef STRUCT_HASHTABLE_H
00056 #define STRUCT_HASHTABLE_H
00057 
00058 #include <cfg/compiler.h>
00059 #include <cfg/macros.h>
00060 #include <cfg/debug.h>
00061 
00066 #define CONFIG_HT_OPTIONAL_INTERNAL_KEY      1
00067 
00069 #define INTERNAL_KEY_MAX_LENGTH     15
00070 
00075 typedef const void *(*hook_get_key)(const void *data, uint8_t *key_length);
00076 
00077 
00088 struct HashTable
00089 {
00090     const void **mem;            
00091     uint16_t max_elts_log2;      
00092     struct {
00093         bool key_internal : 1;   
00094     } flags;
00095     union {
00096         hook_get_key hook;       
00097         uint8_t *mem;            
00098     } key_data;
00099 };
00100 
00101 
00103 typedef struct
00104 {
00105     const void** pos;
00106     const void** end;
00107 } HashIterator;
00108 
00109 
00121 #define DECLARE_HASHTABLE(name, size, hook_gk) \
00122     static const void* name##_nodes[1 << UINT32_LOG2(size)]; \
00123     struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, hook_gk }
00124 
00126 #define DECLARE_HASHTABLE_STATIC(name, size, hook_gk) \
00127     static const void* name##_nodes[1 << UINT32_LOG2(size)]; \
00128     static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, { hook_gk } }
00129 
00130 #if CONFIG_HT_OPTIONAL_INTERNAL_KEY
00131 
00136     #define DECLARE_HASHTABLE_INTERNALKEY(name, size) \
00137         static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \
00138         static const void* name##_nodes[1 << UINT32_LOG2(size)]; \
00139         struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys }
00140 
00142     #define DECLARE_HASHTABLE_INTERNALKEY_STATIC(name, size) \
00143         static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \
00144         static const void* name##_nodes[1 << UINT32_LOG2(size)]; \
00145         static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys }
00146 #endif
00147 
00157 void ht_init(struct HashTable* ht);
00158 
00176 bool ht_insert(struct HashTable* ht, const void* data);
00177 
00197 bool ht_insert_with_key(struct HashTable* ht, const void* key, uint8_t key_length, const void* data);
00198 
00207 const void* ht_find(struct HashTable* ht, const void* key, uint8_t key_length);
00208 
00210 #define ht_insert_str(ht, key, data)         ht_insert_with_key(ht, key, strlen(key), data)
00211 
00213 #define ht_find_str(ht, key)                 ht_find(ht, key, strlen(key))
00214 
00216 INLINE HashIterator ht_iter_begin(struct HashTable* ht)
00217 {
00218     HashIterator h;
00219 
00220     h.pos = &ht->mem[0];
00221     h.end = &ht->mem[1 << ht->max_elts_log2];
00222 
00223     while (h.pos != h.end && !*h.pos)
00224         ++h.pos;
00225 
00226     return h;
00227 }
00228 
00236 INLINE HashIterator ht_iter_end(struct HashTable* ht)
00237 {
00238     HashIterator h;
00239 
00240     h.pos = h.end = &ht->mem[1 << ht->max_elts_log2];
00241 
00242     return h;
00243 }
00244 
00246 INLINE bool ht_iter_cmp(HashIterator it1, HashIterator it2)
00247 {
00248     ASSERT(it1.end == it2.end);
00249     return it1.pos == it2.pos;
00250 }
00251 
00253 INLINE const void* ht_iter_get(HashIterator iter)
00254 { return *iter.pos; }
00255 
00262 INLINE HashIterator ht_iter_next(HashIterator h)
00263 {
00264     ++h.pos;
00265     while (h.pos != h.end && !(*h.pos))
00266         ++h.pos;
00267 
00268     return h;
00269 }
00270 
00271 #endif /* STRUCT_HASHTABLE_H */