Coverage Report

Created: 2025-11-11 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/deps/mdnsd/libmdnsd/xht.c
Line
Count
Source
1
#include "xht.h"
2
#include <string.h>
3
#include <stdlib.h>
4
5
typedef struct xhn {
6
  char flag;
7
  struct xhn *next;
8
  char *key;
9
  void *val;
10
} xhn_t;
11
12
struct xht {
13
  int prime;
14
  xhn_t *zen;
15
};
16
17
/* Generates a hash code for a string.
18
 * This function uses the ELF hashing algorithm as reprinted in 
19
 * Andrew Binstock, "Hashing Rehashed," Dr. Dobb's Journal, April 1996.
20
 */
21
static int _xhter(const char *s)
22
0
{
23
  /* ELF hash uses unsigned chars and unsigned arithmetic for portability */
24
0
  const unsigned char *name = (const unsigned char *)s;
25
0
  unsigned long int h = 0;
26
27
0
  while (*name) {   /* do some fancy bitwanking on the string */
28
0
    unsigned long int g;
29
0
    h = (h << 4) + (unsigned long int)(*name++);
30
0
    if ((g = (h & 0xF0000000UL)) != 0)
31
0
      h ^= (g >> 24);
32
0
    h &= ~g;
33
34
0
  }
35
36
0
  return (int)h;
37
0
}
38
39
40
static xhn_t *_xht_node_find(xhn_t *n, const char *key)
41
0
{
42
0
  for (; n != 0; n = n->next)
43
0
    if (n->key != 0 && strcmp(key, n->key) == 0)
44
0
      return n;
45
0
  return 0;
46
0
}
47
48
49
xht_t *xht_new(int prime)
50
0
{
51
0
  xht_t *xnew;
52
53
0
  xnew = (xht_t *)MDNSD_malloc(sizeof(struct xht));
54
0
  xnew->prime = prime;
55
0
  xnew->zen = (xhn_t *)MDNSD_calloc(1, (sizeof(struct xhn) * (size_t)prime));  /* array of xhn_t size of prime */
56
57
0
  return xnew;
58
0
}
59
60
/* does the set work, used by xht_set and xht_store */
61
static xhn_t *_xht_set(xht_t *h, char *key, void *val, char flag)
62
0
{
63
0
  int i;
64
0
  xhn_t *n;
65
66
  /* get our index for this key */
67
0
  i = _xhter(key) % h->prime;
68
69
  /* check for existing key first, or find an empty one */
70
0
  if ((n = _xht_node_find(&h->zen[i], key)) == 0) {
71
0
    for (n = &h->zen[i]; n != 0; n = n->next) {
72
0
      if (n->val == 0)
73
0
        break;
74
0
    }
75
0
  }
76
77
  /* if none, make a new one, link into this index */
78
0
  if (n == NULL) {
79
0
    if (h->zen != NULL) {
80
0
      n = (xhn_t *)MDNSD_malloc(sizeof(struct xhn));
81
0
      n->next = NULL;
82
0
      n->next = h->zen[i].next;
83
0
      h->zen[i].next = n;
84
0
    }
85
0
  } else if (n->flag) {
86
    /* When flag is set, we manage their mem and free em first */
87
0
    MDNSD_free((void *)n->key);
88
0
    MDNSD_free(n->val);
89
0
  }
90
91
0
  if (n != NULL) {
92
0
    n->flag = flag;
93
0
    n->key = key;
94
0
    n->val = val;
95
0
  } else {
96
0
    MDNSD_free(key);
97
0
    MDNSD_free(val);
98
0
  }
99
100
0
  return n;
101
0
}
102
103
void xht_set(xht_t *h, char *key, void *val)
104
0
{
105
0
  if (h == 0 || key == 0)
106
0
    return;
107
0
  _xht_set(h, key, val, 0);
108
0
}
109
110
void xht_store(xht_t *h, char *key, int klen, void *val, int vlen)
111
0
{
112
0
  char *ckey, *cval;
113
114
0
  if (h == 0 || key == 0 || klen == 0)
115
0
    return;
116
117
0
  ckey = (char *)MDNSD_malloc((size_t)klen + 1);
118
0
  memcpy(ckey, key, (size_t)klen);
119
0
  ckey[klen] = '\0';
120
0
  cval = (char *)MDNSD_malloc((size_t)vlen + 1);
121
0
  memcpy(cval, val, (size_t)vlen);
122
0
  cval[vlen] = '\0';  /* convenience, in case it was a string too */
123
0
  _xht_set(h, ckey, cval, 1);
124
0
}
125
126
127
void *xht_get(xht_t *h, char *key)
128
0
{
129
0
  xhn_t *n;
130
131
0
  if (h == 0 || key == 0 || (n = _xht_node_find(&h->zen[_xhter(key) % h->prime], key)) == 0)
132
0
    return 0;
133
134
0
  return n->val;
135
0
}
136
137
138
void xht_free(xht_t *h)
139
0
{
140
0
  int i;
141
0
  xhn_t *n, *f;
142
143
0
  if (h == 0)
144
0
    return;
145
146
0
  for (i = 0; i < h->prime; i++) {
147
0
    if ((n = (&h->zen[i])) == NULL)
148
0
      continue;
149
0
    if (n->flag) {
150
0
      MDNSD_free((void *)n->key);
151
0
      MDNSD_free(n->val);
152
0
    }
153
0
    for (n = (&h->zen[i])->next; n != 0;) {
154
0
      f = n->next;
155
0
      if (n->flag) {
156
0
        MDNSD_free((void *)n->key);
157
0
        MDNSD_free(n->val);
158
0
      }
159
0
      MDNSD_free(n);
160
0
      n = f;
161
0
    }
162
0
  }
163
164
0
  MDNSD_free(h->zen);
165
0
  MDNSD_free(h);
166
0
}
167
168
void xht_walk(xht_t *h, xht_walker w, void *arg)
169
0
{
170
0
  int i;
171
0
  xhn_t *n;
172
173
0
  if (h == 0 || w == 0)
174
0
    return;
175
176
0
  for (i = 0; i < h->prime; i++) {
177
0
    for (n = &h->zen[i]; n != 0; n = n->next) {
178
0
      if (n->key != 0 && n->val != 0)
179
0
        (*w)(h, n->key, n->val, arg);
180
0
    }
181
0
  }
182
0
}