Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmcurl/lib/uint-hash.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
#include "curl_setup.h"
25
26
#include "uint-hash.h"
27
28
/* random patterns for API verification */
29
#ifdef DEBUGBUILD
30
#define CURL_UINT32_HASHINIT 0x7117e779
31
#endif
32
33
static uint32_t uint32_hash_hash(uint32_t id, uint32_t slots)
34
0
{
35
0
  return (id % slots);
36
0
}
37
38
struct uint_hash_entry {
39
  struct uint_hash_entry *next;
40
  void *value;
41
  uint32_t id;
42
};
43
44
void Curl_uint32_hash_init(struct uint_hash *h,
45
                           uint32_t slots,
46
                           Curl_uint32_hash_dtor *dtor)
47
0
{
48
0
  DEBUGASSERT(h);
49
0
  DEBUGASSERT(slots);
50
51
0
  h->table = NULL;
52
0
  h->dtor = dtor;
53
0
  h->size = 0;
54
0
  h->slots = slots;
55
#ifdef DEBUGBUILD
56
  h->init = CURL_UINT32_HASHINIT;
57
#endif
58
0
}
59
60
static struct uint_hash_entry *uint32_hash_mk_entry(uint32_t id, void *value)
61
0
{
62
0
  struct uint_hash_entry *e;
63
64
  /* allocate the struct for the hash entry */
65
0
  e = curlx_malloc(sizeof(*e));
66
0
  if(e) {
67
0
    e->id = id;
68
0
    e->next = NULL;
69
0
    e->value = value;
70
0
  }
71
0
  return e;
72
0
}
73
74
static void uint32_hash_entry_clear(struct uint_hash *h,
75
                                    struct uint_hash_entry *e)
76
0
{
77
0
  DEBUGASSERT(h);
78
0
  DEBUGASSERT(e);
79
0
  if(e->value) {
80
0
    if(h->dtor)
81
0
      h->dtor(e->id, e->value);
82
0
    e->value = NULL;
83
0
  }
84
0
}
85
86
static void uint32_hash_entry_destroy(struct uint_hash *h,
87
                                      struct uint_hash_entry *e)
88
0
{
89
0
  uint32_hash_entry_clear(h, e);
90
0
  curlx_free(e);
91
0
}
92
93
static void uint32_hash_entry_unlink(struct uint_hash *h,
94
                                     struct uint_hash_entry **he_anchor,
95
                                     struct uint_hash_entry *he)
96
0
{
97
0
  *he_anchor = he->next;
98
0
  --h->size;
99
0
}
100
101
static void uint32_hash_elem_link(struct uint_hash *h,
102
                                  struct uint_hash_entry **he_anchor,
103
                                  struct uint_hash_entry *he)
104
0
{
105
0
  he->next = *he_anchor;
106
0
  *he_anchor = he;
107
0
  ++h->size;
108
0
}
109
110
0
#define CURL_UINT32_HASH_SLOT(h, id) h->table[uint32_hash_hash(id, h->slots)]
111
0
#define CURL_UINT32_HASH_SLOT_ADDR(h, id) &CURL_UINT32_HASH_SLOT(h, id)
112
113
bool Curl_uint32_hash_set(struct uint_hash *h, uint32_t id, void *value)
114
0
{
115
0
  struct uint_hash_entry *he, **slot;
116
117
0
  DEBUGASSERT(h);
118
0
  DEBUGASSERT(h->slots);
119
0
  DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
120
0
  if(!h->table) {
121
0
    h->table = curlx_calloc(h->slots, sizeof(*he));
122
0
    if(!h->table)
123
0
      return FALSE; /* OOM */
124
0
  }
125
126
0
  slot = CURL_UINT32_HASH_SLOT_ADDR(h, id);
127
0
  for(he = *slot; he; he = he->next) {
128
0
    if(he->id == id) {
129
      /* existing key entry, overwrite by clearing old pointer */
130
0
      uint32_hash_entry_clear(h, he);
131
0
      he->value = value;
132
0
      return TRUE;
133
0
    }
134
0
  }
135
136
0
  he = uint32_hash_mk_entry(id, value);
137
0
  if(!he)
138
0
    return FALSE; /* OOM */
139
140
0
  uint32_hash_elem_link(h, slot, he);
141
0
  return TRUE;
142
0
}
143
144
bool Curl_uint32_hash_remove(struct uint_hash *h, uint32_t id)
145
0
{
146
0
  DEBUGASSERT(h);
147
0
  DEBUGASSERT(h->slots);
148
0
  DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
149
0
  if(h->table) {
150
0
    struct uint_hash_entry *he, **he_anchor;
151
152
0
    he_anchor = CURL_UINT32_HASH_SLOT_ADDR(h, id);
153
0
    while(*he_anchor) {
154
0
      he = *he_anchor;
155
0
      if(id == he->id) {
156
0
        uint32_hash_entry_unlink(h, he_anchor, he);
157
0
        uint32_hash_entry_destroy(h, he);
158
0
        return TRUE;
159
0
      }
160
0
      he_anchor = &he->next;
161
0
    }
162
0
  }
163
0
  return FALSE;
164
0
}
165
166
void *Curl_uint32_hash_get(struct uint_hash *h, uint32_t id)
167
0
{
168
0
  DEBUGASSERT(h);
169
0
  DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
170
0
  if(h->table) {
171
0
    struct uint_hash_entry *he;
172
0
    DEBUGASSERT(h->slots);
173
0
    he = CURL_UINT32_HASH_SLOT(h, id);
174
0
    while(he) {
175
0
      if(id == he->id) {
176
0
        return he->value;
177
0
      }
178
0
      he = he->next;
179
0
    }
180
0
  }
181
0
  return NULL;
182
0
}
183
184
static void uint_hash_clear(struct uint_hash *h)
185
0
{
186
0
  if(h && h->table) {
187
0
    struct uint_hash_entry *he, **he_anchor;
188
0
    size_t i;
189
0
    DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
190
0
    for(i = 0; i < h->slots; ++i) {
191
0
      he_anchor = &h->table[i];
192
0
      while(*he_anchor) {
193
0
        he = *he_anchor;
194
0
        uint32_hash_entry_unlink(h, he_anchor, he);
195
0
        uint32_hash_entry_destroy(h, he);
196
0
      }
197
0
    }
198
0
  }
199
0
}
200
201
#ifdef UNITTESTS
202
UNITTEST void Curl_uint32_hash_clear(struct uint_hash *h)
203
{
204
  uint_hash_clear(h);
205
}
206
#endif
207
208
void Curl_uint32_hash_destroy(struct uint_hash *h)
209
0
{
210
0
  DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
211
0
  if(h->table) {
212
0
    uint_hash_clear(h);
213
0
    Curl_safefree(h->table);
214
0
  }
215
0
  DEBUGASSERT(h->size == 0);
216
0
  h->slots = 0;
217
0
}
218
219
uint32_t Curl_uint32_hash_count(struct uint_hash *h)
220
0
{
221
0
  DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
222
0
  return h->size;
223
0
}
224
225
void Curl_uint32_hash_visit(struct uint_hash *h,
226
                            Curl_uint32_hash_visit_cb *cb,
227
                            void *user_data)
228
0
{
229
0
  if(h && h->table && cb) {
230
0
    struct uint_hash_entry *he;
231
0
    size_t i;
232
0
    DEBUGASSERT(h->init == CURL_UINT32_HASHINIT);
233
0
    for(i = 0; i < h->slots; ++i) {
234
0
      for(he = h->table[i]; he; he = he->next) {
235
0
        if(!cb(he->id, he->value, user_data))
236
0
          return;
237
0
      }
238
0
    }
239
0
  }
240
0
}