Coverage Report

Created: 2024-02-25 06:25

/src/tor/src/lib/container/map.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2003-2004, Roger Dingledine
2
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3
 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4
/* See LICENSE for licensing information */
5
6
/**
7
 * \file map.c
8
 *
9
 * \brief Hash-table implementations of a string-to-void* map, and of
10
 * a digest-to-void* map.
11
 **/
12
13
#include "lib/container/map.h"
14
#include "lib/ctime/di_ops.h"
15
#include "lib/defs/digest_sizes.h"
16
#include "lib/string/util_string.h"
17
#include "lib/malloc/malloc.h"
18
19
#include "lib/log/util_bug.h"
20
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include "ext/ht.h"
25
26
/** Helper: Declare an entry type and a map type to implement a mapping using
27
 * ht.h.  The map type will be called <b>maptype</b>.  The key part of each
28
 * entry is declared using the C declaration <b>keydecl</b>.  All functions
29
 * and types associated with the map get prefixed with <b>prefix</b> */
30
#define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix)      \
31
  typedef struct prefix ## entry_t {                      \
32
    HT_ENTRY(prefix ## entry_t) node;                     \
33
    void *val;                                            \
34
    keydecl;                                              \
35
  } prefix ## entry_t;                                    \
36
  struct maptype {                                        \
37
    HT_HEAD(prefix ## impl, prefix ## entry_t) head;      \
38
  }
39
40
DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
41
DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
42
DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
43
44
/** Helper: compare strmap_entry_t objects by key value. */
45
static inline int
46
strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
47
8.64k
{
48
8.64k
  return !strcmp(a->key, b->key);
49
8.64k
}
50
51
/** Helper: return a hash value for a strmap_entry_t. */
52
static inline unsigned int
53
strmap_entry_hash(const strmap_entry_t *a)
54
8.60k
{
55
8.60k
  return (unsigned) siphash24g(a->key, strlen(a->key));
56
8.60k
}
57
58
/** Helper: compare digestmap_entry_t objects by key value. */
59
static inline int
60
digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
61
0
{
62
0
  return tor_memeq(a->key, b->key, DIGEST_LEN);
63
0
}
64
65
/** Helper: return a hash value for a digest_map_t. */
66
static inline unsigned int
67
digestmap_entry_hash(const digestmap_entry_t *a)
68
0
{
69
0
  return (unsigned) siphash24g(a->key, DIGEST_LEN);
70
0
}
71
72
/** Helper: compare digestmap_entry_t objects by key value. */
73
static inline int
74
digest256map_entries_eq(const digest256map_entry_t *a,
75
                        const digest256map_entry_t *b)
76
49
{
77
49
  return tor_memeq(a->key, b->key, DIGEST256_LEN);
78
49
}
79
80
/** Helper: return a hash value for a digest_map_t. */
81
static inline unsigned int
82
digest256map_entry_hash(const digest256map_entry_t *a)
83
104
{
84
104
  return (unsigned) siphash24g(a->key, DIGEST256_LEN);
85
104
}
86
87
HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
88
             strmap_entries_eq);
89
HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
90
             strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_);
91
92
HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
93
             digestmap_entries_eq);
94
HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
95
             digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_);
96
97
HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
98
             digest256map_entry_hash,
99
             digest256map_entries_eq);
100
HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
101
             digest256map_entry_hash,
102
             digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_);
103
104
#define strmap_entry_free(ent) \
105
0
  FREE_AND_NULL(strmap_entry_t, strmap_entry_free_, (ent))
106
#define digestmap_entry_free(ent) \
107
0
  FREE_AND_NULL(digestmap_entry_t, digestmap_entry_free_, (ent))
108
#define digest256map_entry_free(ent) \
109
51
  FREE_AND_NULL(digest256map_entry_t, digest256map_entry_free_, (ent))
110
111
static inline void
112
strmap_entry_free_(strmap_entry_t *ent)
113
0
{
114
0
  tor_free(ent->key);
115
0
  tor_free(ent);
116
0
}
117
static inline void
118
digestmap_entry_free_(digestmap_entry_t *ent)
119
0
{
120
0
  tor_free(ent);
121
0
}
122
static inline void
123
digest256map_entry_free_(digest256map_entry_t *ent)
124
51
{
125
51
  tor_free(ent);
126
51
}
127
128
static inline void
129
strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
130
8.60k
{
131
8.60k
  ent->key = (char*)key;
132
8.60k
}
133
static inline void
134
digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
135
0
{
136
0
  memcpy(ent->key, key, DIGEST_LEN);
137
0
}
138
static inline void
139
digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
140
104
{
141
104
  memcpy(ent->key, key, DIGEST256_LEN);
142
104
}
143
static inline void
144
strmap_assign_key(strmap_entry_t *ent, const char *key)
145
2.17k
{
146
2.17k
  ent->key = tor_strdup(key);
147
2.17k
}
148
static inline void
149
digestmap_assign_key(digestmap_entry_t *ent, const char *key)
150
0
{
151
0
  memcpy(ent->key, key, DIGEST_LEN);
152
0
}
153
static inline void
154
digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
155
51
{
156
51
  memcpy(ent->key, key, DIGEST256_LEN);
157
51
}
158
159
/**
160
 * Macro: implement all the functions for a map that are declared in
161
 * map.h by the DECLARE_MAP_FNS() macro.  You must additionally define a
162
 * prefix_entry_free_() function to free entries (and their keys), a
163
 * prefix_assign_tmp_key() function to temporarily set a stack-allocated
164
 * entry to hold a key, and a prefix_assign_key() function to set a
165
 * heap-allocated entry to hold a key.
166
 */
167
#define IMPLEMENT_MAP_FNS(maptype, keytype, prefix)                     \
168
  /** Create and return a new empty map. */                             \
169
  MOCK_IMPL(maptype *,                                                  \
170
  prefix##_new,(void))                                                  \
171
515
  {                                                                     \
172
515
    maptype *result;                                                    \
173
515
    result = tor_malloc(sizeof(maptype));                               \
174
515
    HT_INIT(prefix##_impl, &result->head);                              \
175
515
    return result;                                                      \
176
515
  }                                                                     \
strmap_new__real
Line
Count
Source
171
21
  {                                                                     \
172
21
    maptype *result;                                                    \
173
21
    result = tor_malloc(sizeof(maptype));                               \
174
21
    HT_INIT(prefix##_impl, &result->head);                              \
175
21
    return result;                                                      \
176
21
  }                                                                     \
Unexecuted instantiation: digestmap_new__real
digest256map_new__real
Line
Count
Source
171
494
  {                                                                     \
172
494
    maptype *result;                                                    \
173
494
    result = tor_malloc(sizeof(maptype));                               \
174
494
    HT_INIT(prefix##_impl, &result->head);                              \
175
494
    return result;                                                      \
176
494
  }                                                                     \
177
                                                                        \
178
  /** Return the item from <b>map</b> whose key matches <b>key</b>, or  \
179
   * NULL if no such value exists. */                                   \
180
  void *                                                                \
181
  prefix##_get(const maptype *map, const keytype key)                   \
182
6.47k
  {                                                                     \
183
6.47k
    prefix ##_entry_t *resolve;                                         \
184
6.47k
    prefix ##_entry_t search;                                           \
185
6.47k
    tor_assert(map);                                                    \
186
6.47k
    tor_assert(key);                                                    \
187
6.47k
    prefix ##_assign_tmp_key(&search, key);                             \
188
6.47k
    resolve = HT_FIND(prefix ##_impl, &map->head, &search);             \
189
6.47k
    if (resolve) {                                                      \
190
4.02k
      return resolve->val;                                              \
191
4.02k
    } else {                                                            \
192
2.45k
      return NULL;                                                      \
193
2.45k
    }                                                                   \
194
6.47k
  }                                                                     \
strmap_get
Line
Count
Source
182
6.42k
  {                                                                     \
183
6.42k
    prefix ##_entry_t *resolve;                                         \
184
6.42k
    prefix ##_entry_t search;                                           \
185
6.42k
    tor_assert(map);                                                    \
186
6.42k
    tor_assert(key);                                                    \
187
6.42k
    prefix ##_assign_tmp_key(&search, key);                             \
188
6.42k
    resolve = HT_FIND(prefix ##_impl, &map->head, &search);             \
189
6.42k
    if (resolve) {                                                      \
190
4.02k
      return resolve->val;                                              \
191
4.02k
    } else {                                                            \
192
2.40k
      return NULL;                                                      \
193
2.40k
    }                                                                   \
194
6.42k
  }                                                                     \
Unexecuted instantiation: digestmap_get
digest256map_get
Line
Count
Source
182
53
  {                                                                     \
183
53
    prefix ##_entry_t *resolve;                                         \
184
53
    prefix ##_entry_t search;                                           \
185
53
    tor_assert(map);                                                    \
186
53
    tor_assert(key);                                                    \
187
53
    prefix ##_assign_tmp_key(&search, key);                             \
188
53
    resolve = HT_FIND(prefix ##_impl, &map->head, &search);             \
189
53
    if (resolve) {                                                      \
190
2
      return resolve->val;                                              \
191
51
    } else {                                                            \
192
51
      return NULL;                                                      \
193
51
    }                                                                   \
194
53
  }                                                                     \
195
                                                                        \
196
  /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>;      \
197
   * return the previous value, or NULL if no such value existed. */     \
198
  void *                                                                \
199
  prefix##_set(maptype *map, const keytype key, void *val)              \
200
2.22k
  {                                                                     \
201
2.22k
    prefix##_entry_t search;                                            \
202
2.22k
    void *oldval;                                                       \
203
2.22k
    tor_assert(map);                                                    \
204
2.22k
    tor_assert(key);                                                    \
205
2.22k
    tor_assert(val);                                                    \
206
2.22k
    prefix##_assign_tmp_key(&search, key);                              \
207
2.22k
    /* We a lot of our time in this function, so the code below is */   \
208
2.22k
    /* meant to optimize the check/alloc/set cycle by avoiding the two */\
209
2.22k
    /* trips to the hash table that we would do in the unoptimized */   \
210
2.22k
    /* version of this code. (Each of HT_INSERT and HT_FIND calls */     \
211
2.22k
    /* HT_SET_HASH and HT_FIND_P.) */                                   \
212
2.22k
    HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash,        \
213
2.22k
                       &(map->head),                                    \
214
2.22k
                       prefix##_entry_t, &search, ptr,                  \
215
2.22k
                       {                                                \
216
2.22k
                         /* we found an entry. */                       \
217
2.22k
                         oldval = (*ptr)->val;                          \
218
2.22k
                         (*ptr)->val = val;                             \
219
2.22k
                         return oldval;                                 \
220
2.22k
                       },                                               \
221
2.22k
                       {                                                \
222
2.22k
                         /* We didn't find the entry. */                \
223
2.22k
                         prefix##_entry_t *newent =                     \
224
2.22k
                           tor_malloc_zero(sizeof(prefix##_entry_t));   \
225
2.22k
                         prefix##_assign_key(newent, key);              \
226
2.22k
                         newent->val = val;                             \
227
2.22k
                         HT_FOI_INSERT_(node, &(map->head),             \
228
2.22k
                            &search, newent, ptr);                      \
229
2.22k
                         return NULL;                                   \
230
2.22k
    });                                                                 \
231
0
  }                                                                     \
strmap_set
Line
Count
Source
200
2.17k
  {                                                                     \
201
2.17k
    prefix##_entry_t search;                                            \
202
2.17k
    void *oldval;                                                       \
203
2.17k
    tor_assert(map);                                                    \
204
2.17k
    tor_assert(key);                                                    \
205
2.17k
    tor_assert(val);                                                    \
206
2.17k
    prefix##_assign_tmp_key(&search, key);                              \
207
2.17k
    /* We a lot of our time in this function, so the code below is */   \
208
2.17k
    /* meant to optimize the check/alloc/set cycle by avoiding the two */\
209
2.17k
    /* trips to the hash table that we would do in the unoptimized */   \
210
2.17k
    /* version of this code. (Each of HT_INSERT and HT_FIND calls */     \
211
2.17k
    /* HT_SET_HASH and HT_FIND_P.) */                                   \
212
2.17k
    HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash,        \
213
2.17k
                       &(map->head),                                    \
214
2.17k
                       prefix##_entry_t, &search, ptr,                  \
215
2.17k
                       {                                                \
216
2.17k
                         /* we found an entry. */                       \
217
2.17k
                         oldval = (*ptr)->val;                          \
218
2.17k
                         (*ptr)->val = val;                             \
219
2.17k
                         return oldval;                                 \
220
2.17k
                       },                                               \
221
2.17k
                       {                                                \
222
2.17k
                         /* We didn't find the entry. */                \
223
2.17k
                         prefix##_entry_t *newent =                     \
224
2.17k
                           tor_malloc_zero(sizeof(prefix##_entry_t));   \
225
2.17k
                         prefix##_assign_key(newent, key);              \
226
2.17k
                         newent->val = val;                             \
227
2.17k
                         HT_FOI_INSERT_(node, &(map->head),             \
228
2.17k
                            &search, newent, ptr);                      \
229
2.17k
                         return NULL;                                   \
230
2.17k
    });                                                                 \
231
0
  }                                                                     \
Unexecuted instantiation: digestmap_set
digest256map_set
Line
Count
Source
200
51
  {                                                                     \
201
51
    prefix##_entry_t search;                                            \
202
51
    void *oldval;                                                       \
203
51
    tor_assert(map);                                                    \
204
51
    tor_assert(key);                                                    \
205
51
    tor_assert(val);                                                    \
206
51
    prefix##_assign_tmp_key(&search, key);                              \
207
51
    /* We a lot of our time in this function, so the code below is */   \
208
51
    /* meant to optimize the check/alloc/set cycle by avoiding the two */\
209
51
    /* trips to the hash table that we would do in the unoptimized */   \
210
51
    /* version of this code. (Each of HT_INSERT and HT_FIND calls */     \
211
51
    /* HT_SET_HASH and HT_FIND_P.) */                                   \
212
51
    HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash,        \
213
51
                       &(map->head),                                    \
214
51
                       prefix##_entry_t, &search, ptr,                  \
215
51
                       {                                                \
216
51
                         /* we found an entry. */                       \
217
51
                         oldval = (*ptr)->val;                          \
218
51
                         (*ptr)->val = val;                             \
219
51
                         return oldval;                                 \
220
51
                       },                                               \
221
51
                       {                                                \
222
51
                         /* We didn't find the entry. */                \
223
51
                         prefix##_entry_t *newent =                     \
224
51
                           tor_malloc_zero(sizeof(prefix##_entry_t));   \
225
51
                         prefix##_assign_key(newent, key);              \
226
51
                         newent->val = val;                             \
227
51
                         HT_FOI_INSERT_(node, &(map->head),             \
228
51
                            &search, newent, ptr);                      \
229
51
                         return NULL;                                   \
230
51
    });                                                                 \
231
0
  }                                                                     \
232
                                                                        \
233
  /** Remove the value currently associated with <b>key</b> from the map. \
234
   * Return the value if one was set, or NULL if there was no entry for \
235
   * <b>key</b>.                                                        \
236
   *                                                                    \
237
   * Note: you must free any storage associated with the returned value. \
238
   */                                                                   \
239
  void *                                                                \
240
  prefix##_remove(maptype *map, const keytype key)                      \
241
0
  {                                                                     \
242
0
    prefix##_entry_t *resolve;                                          \
243
0
    prefix##_entry_t search;                                            \
244
0
    void *oldval;                                                       \
245
0
    tor_assert(map);                                                    \
246
0
    tor_assert(key);                                                    \
247
0
    prefix##_assign_tmp_key(&search, key);                              \
248
0
    resolve = HT_REMOVE(prefix##_impl, &map->head, &search);            \
249
0
    if (resolve) {                                                      \
250
0
      oldval = resolve->val;                                            \
251
0
      prefix##_entry_free(resolve);                                     \
252
0
      return oldval;                                                    \
253
0
    } else {                                                            \
254
0
      return NULL;                                                      \
255
0
    }                                                                   \
256
0
  }                                                                     \
Unexecuted instantiation: strmap_remove
Unexecuted instantiation: digestmap_remove
Unexecuted instantiation: digest256map_remove
257
                                                                        \
258
  /** Return the number of elements in <b>map</b>. */                   \
259
  int                                                                   \
260
  prefix##_size(const maptype *map)                                     \
261
6.19k
  {                                                                     \
262
6.19k
    return HT_SIZE(&map->head);                                         \
263
6.19k
  }                                                                     \
strmap_size
Line
Count
Source
261
6.19k
  {                                                                     \
262
6.19k
    return HT_SIZE(&map->head);                                         \
263
6.19k
  }                                                                     \
Unexecuted instantiation: digestmap_size
Unexecuted instantiation: digest256map_size
264
                                                                        \
265
  /** Return true iff <b>map</b> has no entries. */                     \
266
  int                                                                   \
267
  prefix##_isempty(const maptype *map)                                  \
268
0
  {                                                                     \
269
0
    return HT_EMPTY(&map->head);                                        \
270
0
  }                                                                     \
Unexecuted instantiation: strmap_isempty
Unexecuted instantiation: digestmap_isempty
Unexecuted instantiation: digest256map_isempty
271
                                                                        \
272
  /** Assert that <b>map</b> is not corrupt. */                         \
273
  void                                                                  \
274
  prefix##_assert_ok(const maptype *map)                                \
275
0
  {                                                                     \
276
0
    tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head));              \
277
0
  }                                                                     \
Unexecuted instantiation: strmap_assert_ok
Unexecuted instantiation: digestmap_assert_ok
Unexecuted instantiation: digest256map_assert_ok
278
                                                                        \
279
  /** Remove all entries from <b>map</b>, and deallocate storage for    \
280
   * those entries.  If free_val is provided, invoked it every value in \
281
   * <b>map</b>. */                                                     \
282
  MOCK_IMPL(void,                                                       \
283
  prefix##_free_, (maptype *map, void (*free_val)(void*)))              \
284
8.03k
  {                                                                     \
285
8.03k
    prefix##_entry_t **ent, **next, *this;                              \
286
8.03k
    if (!map)                                                           \
287
8.03k
      return;                                                           \
288
8.03k
    for (ent = HT_START(prefix##_impl, &map->head); ent != NULL;        \
289
494
         ent = next) {                                                  \
290
51
      this = *ent;                                                      \
291
51
      next = HT_NEXT_RMV(prefix##_impl, &map->head, ent);               \
292
51
      if (free_val)                                                     \
293
51
        free_val(this->val);                                            \
294
51
      prefix##_entry_free(this);                                        \
295
51
    }                                                                   \
296
494
    tor_assert(HT_EMPTY(&map->head));                                   \
297
494
    HT_CLEAR(prefix##_impl, &map->head);                                \
298
494
    tor_free(map);                                                      \
299
494
  }                                                                     \
Unexecuted instantiation: strmap_free___real
digestmap_free___real
Line
Count
Source
284
7.53k
  {                                                                     \
285
7.53k
    prefix##_entry_t **ent, **next, *this;                              \
286
7.53k
    if (!map)                                                           \
287
7.53k
      return;                                                           \
288
7.53k
    for (ent = HT_START(prefix##_impl, &map->head); ent != NULL;        \
289
0
         ent = next) {                                                  \
290
0
      this = *ent;                                                      \
291
0
      next = HT_NEXT_RMV(prefix##_impl, &map->head, ent);               \
292
0
      if (free_val)                                                     \
293
0
        free_val(this->val);                                            \
294
0
      prefix##_entry_free(this);                                        \
295
0
    }                                                                   \
296
0
    tor_assert(HT_EMPTY(&map->head));                                   \
297
0
    HT_CLEAR(prefix##_impl, &map->head);                                \
298
0
    tor_free(map);                                                      \
299
0
  }                                                                     \
digest256map_free___real
Line
Count
Source
284
494
  {                                                                     \
285
494
    prefix##_entry_t **ent, **next, *this;                              \
286
494
    if (!map)                                                           \
287
494
      return;                                                           \
288
545
    for (ent = HT_START(prefix##_impl, &map->head); ent != NULL;        \
289
494
         ent = next) {                                                  \
290
51
      this = *ent;                                                      \
291
51
      next = HT_NEXT_RMV(prefix##_impl, &map->head, ent);               \
292
51
      if (free_val)                                                     \
293
51
        free_val(this->val);                                            \
294
51
      prefix##_entry_free(this);                                        \
295
51
    }                                                                   \
296
494
    tor_assert(HT_EMPTY(&map->head));                                   \
297
494
    HT_CLEAR(prefix##_impl, &map->head);                                \
298
494
    tor_free(map);                                                      \
299
494
  }                                                                     \
300
                                                                        \
301
  /** return an <b>iterator</b> pointer to the front of a map.          \
302
   *                                                                    \
303
   * Iterator example:                                                  \
304
   *                                                                    \
305
   * \code                                                              \
306
   * // uppercase values in "map", removing empty values.               \
307
   *                                                                    \
308
   * strmap_iter_t *iter;                                               \
309
   * const char *key;                                                   \
310
   * void *val;                                                         \
311
   * char *cp;                                                          \
312
   *                                                                    \
313
   * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) {    \
314
   *    strmap_iter_get(iter, &key, &val);                              \
315
   *    cp = (char*)val;                                                \
316
   *    if (!*cp) {                                                     \
317
   *       iter = strmap_iter_next_rmv(map,iter);                       \
318
   *       free(val);                                                   \
319
   *    } else {                                                        \
320
   *       for (;*cp;cp++) *cp = TOR_TOUPPER(*cp);                      \
321
   */                                                                   \
322
  prefix##_iter_t *                                                     \
323
  prefix##_iter_init(maptype *map)                                      \
324
0
  {                                                                     \
325
0
    tor_assert(map);                                                    \
326
0
    return HT_START(prefix##_impl, &map->head);                         \
327
0
  }                                                                     \
Unexecuted instantiation: strmap_iter_init
Unexecuted instantiation: digestmap_iter_init
Unexecuted instantiation: digest256map_iter_init
328
                                                                        \
329
  /** Advance <b>iter</b> a single step to the next entry, and return   \
330
   * its new value. */                                                  \
331
  prefix##_iter_t *                                                     \
332
  prefix##_iter_next(maptype *map, prefix##_iter_t *iter)               \
333
0
  {                                                                     \
334
0
    tor_assert(map);                                                    \
335
0
    tor_assert(iter);                                                   \
336
0
    return HT_NEXT(prefix##_impl, &map->head, iter);                    \
337
0
  }                                                                     \
Unexecuted instantiation: strmap_iter_next
Unexecuted instantiation: digestmap_iter_next
Unexecuted instantiation: digest256map_iter_next
338
  /** Advance <b>iter</b> a single step to the next entry, removing the \
339
   * current entry, and return its new value. */                        \
340
  prefix##_iter_t *                                                     \
341
  prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter)           \
342
0
  {                                                                     \
343
0
    prefix##_entry_t *rmv;                                              \
344
0
    tor_assert(map);                                                    \
345
0
    tor_assert(iter);                                                   \
346
0
    tor_assert(*iter);                                                  \
347
0
    rmv = *iter;                                                        \
348
0
    iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter);                \
349
0
    prefix##_entry_free(rmv);                                           \
350
0
    return iter;                                                        \
351
0
  }                                                                     \
Unexecuted instantiation: strmap_iter_next_rmv
Unexecuted instantiation: digestmap_iter_next_rmv
Unexecuted instantiation: digest256map_iter_next_rmv
352
  /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed    \
353
   * to by iter. */                                                     \
354
  void                                                                  \
355
  prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp,         \
356
                    void **valp)                                        \
357
0
  {                                                                     \
358
0
    tor_assert(iter);                                                   \
359
0
    tor_assert(*iter);                                                  \
360
0
    tor_assert(keyp);                                                   \
361
0
    tor_assert(valp);                                                   \
362
0
    *keyp = (*iter)->key;                                               \
363
0
    *valp = (*iter)->val;                                               \
364
0
  }                                                                     \
Unexecuted instantiation: strmap_iter_get
Unexecuted instantiation: digestmap_iter_get
Unexecuted instantiation: digest256map_iter_get
365
  /** Return true iff <b>iter</b> has advanced past the last entry of   \
366
   * <b>map</b>. */                                                     \
367
  int                                                                   \
368
  prefix##_iter_done(prefix##_iter_t *iter)                             \
369
0
  {                                                                     \
370
0
    return iter == NULL;                                                \
371
0
  }
Unexecuted instantiation: strmap_iter_done
Unexecuted instantiation: digestmap_iter_done
Unexecuted instantiation: digest256map_iter_done
372
373
IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
374
IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
375
IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
376
377
/** Same as strmap_set, but first converts <b>key</b> to lowercase. */
378
void *
379
strmap_set_lc(strmap_t *map, const char *key, void *val)
380
0
{
381
  /* We could be a little faster by using strcasecmp instead, and a separate
382
   * type, but I don't think it matters. */
383
0
  void *v;
384
0
  char *lc_key = tor_strdup(key);
385
0
  tor_strlower(lc_key);
386
0
  v = strmap_set(map,lc_key,val);
387
0
  tor_free(lc_key);
388
0
  return v;
389
0
}
390
391
/** Same as strmap_get, but first converts <b>key</b> to lowercase. */
392
void *
393
strmap_get_lc(const strmap_t *map, const char *key)
394
227
{
395
227
  void *v;
396
227
  char *lc_key = tor_strdup(key);
397
227
  tor_strlower(lc_key);
398
227
  v = strmap_get(map,lc_key);
399
227
  tor_free(lc_key);
400
227
  return v;
401
227
}
402
403
/** Same as strmap_remove, but first converts <b>key</b> to lowercase */
404
void *
405
strmap_remove_lc(strmap_t *map, const char *key)
406
0
{
407
0
  void *v;
408
0
  char *lc_key = tor_strdup(key);
409
0
  tor_strlower(lc_key);
410
0
  v = strmap_remove(map,lc_key);
411
0
  tor_free(lc_key);
412
0
  return v;
413
0
}