Coverage Report

Created: 2026-09-14 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MapServer/src/maphash.c
Line
Count
Source
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
5
 * Purpose:  Implement hashTableObj class.
6
 * Author:   Sean Gillies, sgillies@frii.com
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a
12
 * copy of this software and associated documentation files (the "Software"),
13
 * to deal in the Software without restriction, including without limitation
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
 * and/or sell copies of the Software, and to permit persons to whom the
16
 * Software is furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies of this Software or works derived from this Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 * DEALINGS IN THE SOFTWARE.
28
 ****************************************************************************/
29
30
#include <ctype.h>
31
32
#include "mapserver.h"
33
#include "maphash.h"
34
35
297k
static unsigned hash(const char *key) {
36
297k
  unsigned hashval;
37
38
5.15M
  for (hashval = 0; *key != '\0'; key++)
39
4.85M
    hashval = tolower(*key) + 31 * hashval;
40
41
297k
  return (hashval % MS_HASHSIZE);
42
297k
}
43
44
0
hashTableObj *msCreateHashTable() {
45
0
  int i;
46
0
  hashTableObj *table;
47
48
0
  table = (hashTableObj *)msSmallMalloc(sizeof(hashTableObj));
49
0
  table->items =
50
0
      (struct hashObj **)msSmallMalloc(sizeof(struct hashObj *) * MS_HASHSIZE);
51
52
0
  for (i = 0; i < MS_HASHSIZE; i++)
53
0
    table->items[i] = NULL;
54
0
  table->numitems = 0;
55
56
0
  return table;
57
0
}
58
59
43.2k
int initHashTable(hashTableObj *table) {
60
43.2k
  int i;
61
62
43.2k
  table->items =
63
43.2k
      (struct hashObj **)malloc(sizeof(struct hashObj *) * MS_HASHSIZE);
64
43.2k
  MS_CHECK_ALLOC(table->items, sizeof(struct hashObj *) * MS_HASHSIZE,
65
43.2k
                 MS_FAILURE);
66
67
1.81M
  for (i = 0; i < MS_HASHSIZE; i++)
68
1.77M
    table->items[i] = NULL;
69
43.2k
  table->numitems = 0;
70
43.2k
  return MS_SUCCESS;
71
43.2k
}
72
73
0
void msFreeHashTable(hashTableObj *table) {
74
0
  if (table != NULL) {
75
0
    msFreeHashItems(table);
76
0
    free(table);
77
0
  }
78
0
}
79
80
0
int msHashIsEmpty(const hashTableObj *table) {
81
0
  if (table->numitems == 0)
82
0
    return MS_TRUE;
83
0
  else
84
0
    return MS_FALSE;
85
0
}
86
87
43.2k
void msFreeHashItems(hashTableObj *table) {
88
43.2k
  int i;
89
43.2k
  struct hashObj *tp = NULL;
90
43.2k
  struct hashObj *prev_tp = NULL;
91
92
43.2k
  if (table) {
93
43.2k
    if (table->items) {
94
1.81M
      for (i = 0; i < MS_HASHSIZE; i++) {
95
1.77M
        if (table->items[i] != NULL) {
96
81.6k
          for (tp = table->items[i]; tp != NULL;
97
40.8k
               prev_tp = tp, tp = tp->next, free(prev_tp)) {
98
40.8k
            msFree(tp->key);
99
40.8k
            msFree(tp->data);
100
40.8k
          }
101
40.7k
        }
102
1.77M
      }
103
43.2k
      free(table->items);
104
43.2k
      table->items = NULL;
105
43.2k
    } else {
106
0
      msSetError(MS_HASHERR, "No items allocated.", "msFreeHashItems()");
107
0
    }
108
43.2k
  } else {
109
0
    msSetError(MS_HASHERR, "Can't free NULL table", "msFreeHashItems()");
110
0
  }
111
43.2k
}
112
113
struct hashObj *msInsertHashTable(hashTableObj *table, const char *key,
114
40.9k
                                  const char *value) {
115
40.9k
  struct hashObj *tp;
116
40.9k
  unsigned hashval;
117
118
40.9k
  if (!table || !key || !value) {
119
0
    msSetError(MS_HASHERR, "Invalid hash table or key", "msInsertHashTable");
120
0
    return NULL;
121
0
  }
122
123
41.1k
  for (tp = table->items[hash(key)]; tp != NULL; tp = tp->next)
124
253
    if (strcasecmp(key, tp->key) == 0)
125
88
      break;
126
127
40.9k
  if (tp == NULL) { /* not found */
128
40.8k
    tp = (struct hashObj *)malloc(sizeof(*tp));
129
40.8k
    MS_CHECK_ALLOC(tp, sizeof(*tp), NULL);
130
40.8k
    tp->key = msStrdup(key);
131
40.8k
    hashval = hash(key);
132
40.8k
    tp->next = table->items[hashval];
133
40.8k
    table->items[hashval] = tp;
134
40.8k
    table->numitems++;
135
40.8k
  } else {
136
88
    free(tp->data);
137
88
  }
138
139
40.9k
  if ((tp->data = msStrdup(value)) == NULL)
140
0
    return NULL;
141
142
40.9k
  return tp;
143
40.9k
}
144
145
214k
const char *msLookupHashTable(const hashTableObj *table, const char *key) {
146
214k
  struct hashObj *tp;
147
148
214k
  if (!table || !key) {
149
0
    return (NULL);
150
0
  }
151
152
229k
  for (tp = table->items[hash(key)]; tp != NULL; tp = tp->next)
153
37.0k
    if (strcasecmp(key, tp->key) == 0)
154
22.1k
      return (tp->data);
155
156
192k
  return NULL;
157
214k
}
158
159
0
int msRemoveHashTable(hashTableObj *table, const char *key) {
160
0
  struct hashObj *tp;
161
0
  struct hashObj *prev_tp = NULL;
162
0
  int status = MS_FAILURE;
163
164
0
  if (!table || !key) {
165
0
    msSetError(MS_HASHERR, "No hash table", "msRemoveHashTable");
166
0
    return MS_FAILURE;
167
0
  }
168
169
0
  tp = table->items[hash(key)];
170
0
  if (!tp) {
171
0
    msSetError(MS_HASHERR, "No such hash entry", "msRemoveHashTable");
172
0
    return MS_FAILURE;
173
0
  }
174
175
0
  prev_tp = NULL;
176
0
  while (tp != NULL) {
177
0
    if (strcasecmp(key, tp->key) == 0) {
178
0
      status = MS_SUCCESS;
179
0
      if (prev_tp) {
180
0
        prev_tp->next = tp->next;
181
0
        msFree(tp->key);
182
0
        msFree(tp->data);
183
0
        free(tp);
184
0
        break;
185
0
      } else {
186
0
        table->items[hash(key)] = tp->next;
187
0
        msFree(tp->key);
188
0
        msFree(tp->data);
189
0
        free(tp);
190
0
        break;
191
0
      }
192
0
    }
193
0
    prev_tp = tp;
194
0
    tp = tp->next;
195
0
  }
196
197
0
  if (status == MS_SUCCESS)
198
0
    table->numitems--;
199
200
0
  return status;
201
0
}
202
203
1.08k
const char *msFirstKeyFromHashTable(const hashTableObj *table) {
204
1.08k
  int hash_index;
205
206
1.08k
  if (!table) {
207
0
    msSetError(MS_HASHERR, "No hash table", "msFirstKeyFromHashTable");
208
0
    return NULL;
209
0
  }
210
211
16.5k
  for (hash_index = 0; hash_index < MS_HASHSIZE; hash_index++) {
212
16.5k
    if (table->items[hash_index] != NULL)
213
1.07k
      return table->items[hash_index]->key;
214
16.5k
  }
215
216
4
  return NULL;
217
1.08k
}
218
219
const char *msNextKeyFromHashTable(const hashTableObj *table,
220
1.68k
                                   const char *lastKey) {
221
1.68k
  int hash_index;
222
1.68k
  struct hashObj *link;
223
224
1.68k
  if (!table) {
225
0
    msSetError(MS_HASHERR, "No hash table", "msNextKeyFromHashTable");
226
0
    return NULL;
227
0
  }
228
229
1.68k
  if (lastKey == NULL)
230
0
    return msFirstKeyFromHashTable(table);
231
232
1.68k
  hash_index = hash(lastKey);
233
1.68k
  for (link = table->items[hash_index];
234
1.80k
       link != NULL && strcasecmp(lastKey, link->key) != 0; link = link->next) {
235
118
  }
236
237
1.68k
  if (link != NULL && link->next != NULL)
238
91
    return link->next->key;
239
240
28.9k
  while (++hash_index < MS_HASHSIZE) {
241
27.8k
    if (table->items[hash_index] != NULL)
242
514
      return table->items[hash_index]->key;
243
27.8k
  }
244
245
1.07k
  return NULL;
246
1.59k
}