1 /* Copyright (c) 2013, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 /* Define fp_pair_map_t structures */
9 struct fp_pair_map_entry_s
{
10 HT_ENTRY(fp_pair_map_entry_s
) node
;
15 struct fp_pair_map_s
{
16 HT_HEAD(fp_pair_map_impl
, fp_pair_map_entry_s
) head
;
20 * Hash function and equality checker for fp_pair_map_t
23 /** Compare fp_pair_entry_t objects by key value. */
25 fp_pair_map_entries_eq(const fp_pair_map_entry_t
*a
,
26 const fp_pair_map_entry_t
*b
)
28 return tor_memeq(&(a
->key
), &(b
->key
), sizeof(fp_pair_t
));
31 /** Return a hash value for an fp_pair_entry_t. */
32 static INLINE
unsigned int
33 fp_pair_map_entry_hash(const fp_pair_map_entry_t
*a
)
35 tor_assert(sizeof(a
->key
) == DIGEST_LEN
*2);
36 return (unsigned) siphash24g(&a
->key
, DIGEST_LEN
*2);
40 * Hash table functions for fp_pair_map_t
43 HT_PROTOTYPE(fp_pair_map_impl
, fp_pair_map_entry_s
, node
,
44 fp_pair_map_entry_hash
, fp_pair_map_entries_eq
)
45 HT_GENERATE(fp_pair_map_impl
, fp_pair_map_entry_s
, node
,
46 fp_pair_map_entry_hash
, fp_pair_map_entries_eq
,
47 0.6, tor_malloc
, tor_realloc
, tor_free
)
49 /** Constructor to create a new empty map from fp_pair_t to void *
55 fp_pair_map_t
*result
;
57 result
= tor_malloc(sizeof(fp_pair_map_t
));
58 HT_INIT(fp_pair_map_impl
, &result
->head
);
62 /** Set the current value for key to val; returns the previous
63 * value for key if one was set, or NULL if one was not.
67 fp_pair_map_set(fp_pair_map_t
*map
, const fp_pair_t
*key
, void *val
)
69 fp_pair_map_entry_t
*resolve
;
70 fp_pair_map_entry_t search
;
77 memcpy(&(search
.key
), key
, sizeof(*key
));
78 resolve
= HT_FIND(fp_pair_map_impl
, &(map
->head
), &search
);
80 oldval
= resolve
->val
;
83 resolve
= tor_malloc_zero(sizeof(fp_pair_map_entry_t
));
84 memcpy(&(resolve
->key
), key
, sizeof(*key
));
86 HT_INSERT(fp_pair_map_impl
, &(map
->head
), resolve
);
93 /** Set the current value for the key (first, second) to val; returns
94 * the previous value for key if one was set, or NULL if one was not.
98 fp_pair_map_set_by_digests(fp_pair_map_t
*map
,
99 const char *first
, const char *second
,
107 memcpy(k
.first
, first
, DIGEST_LEN
);
108 memcpy(k
.second
, second
, DIGEST_LEN
);
110 return fp_pair_map_set(map
, &k
, val
);
113 /** Return the current value associated with key, or NULL if no value is set.
117 fp_pair_map_get(const fp_pair_map_t
*map
, const fp_pair_t
*key
)
119 fp_pair_map_entry_t
*resolve
;
120 fp_pair_map_entry_t search
;
126 memcpy(&(search
.key
), key
, sizeof(*key
));
127 resolve
= HT_FIND(fp_pair_map_impl
, &(map
->head
), &search
);
128 if (resolve
) val
= resolve
->val
;
133 /** Return the current value associated the key (first, second), or
134 * NULL if no value is set.
138 fp_pair_map_get_by_digests(const fp_pair_map_t
*map
,
139 const char *first
, const char *second
)
146 memcpy(k
.first
, first
, DIGEST_LEN
);
147 memcpy(k
.second
, second
, DIGEST_LEN
);
149 return fp_pair_map_get(map
, &k
);
152 /** Remove the value currently associated with key from the map.
153 * Return the value if one was set, or NULL if there was no entry for
154 * key. The caller must free any storage associated with the
159 fp_pair_map_remove(fp_pair_map_t
*map
, const fp_pair_t
*key
)
161 fp_pair_map_entry_t
*resolve
;
162 fp_pair_map_entry_t search
;
168 memcpy(&(search
.key
), key
, sizeof(*key
));
169 resolve
= HT_REMOVE(fp_pair_map_impl
, &(map
->head
), &search
);
178 /** Remove all entries from map, and deallocate storage for those entries.
179 * If free_val is provided, it is invoked on every value in map.
183 fp_pair_map_free(fp_pair_map_t
*map
, void (*free_val
)(void*))
185 fp_pair_map_entry_t
**ent
, **next
, *this;
188 for (ent
= HT_START(fp_pair_map_impl
, &(map
->head
));
189 ent
!= NULL
; ent
= next
) {
191 next
= HT_NEXT_RMV(fp_pair_map_impl
, &(map
->head
), ent
);
192 if (free_val
) free_val(this->val
);
195 tor_assert(HT_EMPTY(&(map
->head
)));
196 HT_CLEAR(fp_pair_map_impl
, &(map
->head
));
201 /** Return true iff map has no entries.
205 fp_pair_map_isempty(const fp_pair_map_t
*map
)
209 return HT_EMPTY(&(map
->head
));
212 /** Return the number of items in map.
216 fp_pair_map_size(const fp_pair_map_t
*map
)
220 return HT_SIZE(&(map
->head
));
223 /** return an iterator pointing to the start of map.
227 fp_pair_map_iter_init(fp_pair_map_t
*map
)
231 return HT_START(fp_pair_map_impl
, &(map
->head
));
234 /** Advance iter a single step to the next entry of map, and return
239 fp_pair_map_iter_next(fp_pair_map_t
*map
, fp_pair_map_iter_t
*iter
)
244 return HT_NEXT(fp_pair_map_impl
, &(map
->head
), iter
);
247 /** Advance iter a single step to the next entry of map, removing the current
248 * entry, and return its new value.
252 fp_pair_map_iter_next_rmv(fp_pair_map_t
*map
, fp_pair_map_iter_t
*iter
)
254 fp_pair_map_entry_t
*rmv
;
261 iter
= HT_NEXT_RMV(fp_pair_map_impl
, &(map
->head
), iter
);
267 /** Set *key_out and *val_out to the current entry pointed to by iter.
271 fp_pair_map_iter_get(fp_pair_map_iter_t
*iter
,
272 fp_pair_t
*key_out
, void **val_out
)
277 if (key_out
) memcpy(key_out
, &((*iter
)->key
), sizeof(fp_pair_t
));
278 if (val_out
) *val_out
= (*iter
)->val
;
281 /** Return true iff iter has advanced past the last entry of its map.
285 fp_pair_map_iter_done(fp_pair_map_iter_t
*iter
)
287 return (iter
== NULL
);
290 /** Assert if anything has gone wrong with the internal
291 * representation of map.
295 fp_pair_map_assert_ok(const fp_pair_map_t
*map
)
297 tor_assert(!fp_pair_map_impl_HT_REP_IS_BAD_(&(map
->head
)));