Coverage Report

Created: 2026-05-16 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/open62541_15/src_generated/mdnsd/xht.c
Line
Count
Source
1
#include "open62541/config.h"
2
/* Simple string->void* hashtable, very static and bare minimal, but efficient
3
 *
4
 * Copyright (c) 2003  Jeremie Miller <jer@jabber.org>
5
 * Copyright (c) 2016-2022  Joachim Wiberg <troglobit@gmail.com>
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *     * Redistributions of source code must retain the above copyright
11
 *       notice, this list of conditions and the following disclaimer.
12
 *     * Redistributions in binary form must reproduce the above copyright
13
 *       notice, this list of conditions and the following disclaimer in the
14
 *       documentation and/or other materials provided with the distribution.
15
 *     * Neither the name of the copyright holders nor the names of its
16
 *       contributors may be used to endorse or promote products derived from
17
 *       this software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#include "xht.h"
33
#include <string.h>
34
#include <stdlib.h>
35
36
typedef struct xhn {
37
  char flag;
38
  struct xhn *next;
39
  union {
40
    char *key;
41
    const char *ckey;
42
  } u;
43
  void *val;
44
} xhn_t;
45
46
struct xht {
47
  int prime;
48
  xhn_t *zen;
49
};
50
51
/* Generates a hash code for a string.
52
 * This function uses the ELF hashing algorithm as reprinted in 
53
 * Andrew Binstock, "Hashing Rehashed," Dr. Dobb's Journal, April 1996.
54
 */
55
static int _xhter(const char *s)
56
16.2k
{
57
  /* ELF hash uses unsigned chars and unsigned arithmetic for portability */
58
16.2k
  const unsigned char *name = (const unsigned char *)s;
59
16.2k
  unsigned long h = 0, g;
60
61
301k
  while (*name) {   /* do some fancy bitwanking on the string */
62
285k
    h = (h << 4) + (unsigned long)(*name++);
63
285k
    if ((g = (h & 0xF0000000UL)) != 0)
64
198k
      h ^= (g >> 24);
65
285k
    h &= ~g;
66
67
285k
  }
68
69
16.2k
  return (int)h;
70
16.2k
}
71
72
73
static xhn_t *_xht_node_find(xhn_t *n, const char *key)
74
16.2k
{
75
58.4k
  for (; n != 0; n = n->next)
76
47.6k
    if (n->u.ckey && strcmp(key, n->u.ckey) == 0)
77
5.47k
      return n;
78
10.7k
  return 0;
79
16.2k
}
80
81
82
xht_t *xht_new(int prime)
83
1.23k
{
84
1.23k
  xht_t *xnew;
85
86
1.23k
  xnew = malloc(sizeof(struct xht));
87
1.23k
  if (!xnew)
88
0
    return NULL;
89
90
1.23k
  xnew->prime = prime;
91
1.23k
  xnew->zen = calloc(1, sizeof(struct xhn) * prime);  /* array of xhn_t size of prime */
92
1.23k
  if (!xnew->zen) {
93
0
    free(xnew);
94
0
    return NULL;
95
0
  }
96
97
1.23k
  return xnew;
98
1.23k
}
99
100
/* does the set work, used by xht_set and xht_store */
101
static xhn_t *_xht_set(xht_t *h, const char *key, void *val, char flag)
102
16.2k
{
103
16.2k
  int i;
104
16.2k
  xhn_t *n;
105
106
  /* get our index for this key */
107
16.2k
  i = _xhter(key) % h->prime;
108
109
  /* check for existing key first, or find an empty one */
110
16.2k
  n = _xht_node_find(&h->zen[i], key);
111
16.2k
  if (n == NULL) {
112
41.2k
    for (n = &h->zen[i]; n != 0; n = n->next) {
113
34.2k
      if (n->val == NULL)
114
3.76k
        break;
115
34.2k
    }
116
10.7k
  }
117
118
  /* if none, make a new_ one, link into this index */
119
16.2k
  if (n == NULL) {
120
6.99k
    n = calloc(1, sizeof(struct xhn));
121
6.99k
    if (n == NULL)
122
0
      return NULL;
123
124
6.99k
    n->next = h->zen[i].next;
125
6.99k
    h->zen[i].next = n;
126
6.99k
  }
127
128
  /* When flag is set, we manage their mem and free em first */
129
16.2k
  if (n->flag) {
130
5.47k
    free(n->u.key);
131
5.47k
    free(n->val);
132
5.47k
  }
133
134
16.2k
  n->flag = flag;
135
16.2k
  n->u.ckey = key;
136
16.2k
  n->val = val;
137
138
16.2k
  return n;
139
16.2k
}
140
141
void xht_set(xht_t *h, const char *key, void *val)
142
1.07k
{
143
1.07k
  if (h == NULL || h->zen == NULL || key == NULL)
144
0
    return;
145
1.07k
  _xht_set(h, key, val, 0);
146
1.07k
}
147
148
void xht_store(xht_t *h, const char *key, int klen, void *val, int vlen)
149
30.4k
{
150
30.4k
  char *ckey, *cval;
151
152
30.4k
  if (h == NULL || h->zen == NULL || key == NULL || klen == 0 || val == NULL)
153
15.2k
    return;
154
155
15.1k
  ckey = malloc(klen + 1);
156
15.1k
  if (!ckey)
157
0
    return;
158
159
15.1k
  memcpy(ckey, key, klen);
160
15.1k
  ckey[klen] = '\0';
161
162
15.1k
  cval = malloc(vlen + 1);
163
15.1k
  if (!cval) {
164
0
    free(ckey);
165
0
    return;
166
0
  }
167
168
15.1k
  memcpy(cval, val, vlen);
169
15.1k
  cval[vlen] = '\0';  /* convenience, in case it was a string too */
170
15.1k
  _xht_set(h, ckey, cval, 1);
171
15.1k
}
172
173
174
void *xht_get(xht_t *h, const char *key)
175
0
{
176
0
  xhn_t *n;
177
178
0
  if (h == NULL || h->zen == NULL || key == NULL)
179
0
    return NULL;
180
181
0
  n = _xht_node_find(&h->zen[_xhter(key) % h->prime], key);
182
0
  if (n == NULL)
183
0
    return NULL;
184
185
0
  return n->val;
186
0
}
187
188
189
void xht_free(xht_t *h)
190
1.23k
{
191
1.23k
  int i;
192
193
1.23k
  if (h == NULL)
194
0
    return;
195
196
23.1k
  for (i = 0; i < h->prime; i++) {
197
21.8k
    xhn_t *n = &h->zen[i];
198
199
21.8k
    if (n->flag) {
200
2.69k
      free(n->u.key);
201
2.69k
      n->u.key = NULL;
202
2.69k
      free(n->val);
203
2.69k
      n->val = NULL;
204
2.69k
    }
205
206
28.8k
    for (n = (&h->zen[i])->next; n != 0;) {
207
6.99k
      xhn_t *f = n->next;
208
209
6.99k
      n->next = NULL;
210
6.99k
      if (n->flag) {
211
6.99k
        free(n->u.key);
212
6.99k
        n->u.key = NULL;
213
6.99k
        free(n->val);
214
6.99k
        n->val = NULL;
215
6.99k
      }
216
6.99k
      free(n);
217
6.99k
      n = f;
218
6.99k
    }
219
21.8k
  }
220
221
1.23k
  free(h->zen);
222
1.23k
  h->zen = NULL;
223
1.23k
  free(h);
224
1.23k
}
225
226
void xht_walk(xht_t *h, xht_walker w, void *arg)
227
2.36k
{
228
2.36k
  int i;
229
2.36k
  xhn_t *n;
230
231
2.36k
  if (h == NULL || h->zen == NULL || w == NULL)
232
0
    return;
233
234
43.9k
  for (i = 0; i < h->prime; i++) {
235
97.1k
    for (n = &h->zen[i]; n != 0; n = n->next) {
236
55.5k
      if (n->u.ckey != 0 && n->val != 0)
237
21.5k
        (*w)(h, n->u.ckey, n->val, arg);
238
55.5k
    }
239
41.5k
  }
240
2.36k
}