Coverage Report

Created: 2026-03-04 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libplist/src/hashtable.c
Line
Count
Source
1
/*
2
 * hashtable.c
3
 * really simple hash table implementation
4
 *
5
 * Copyright (c) 2011-2016 Nikias Bassen, All Rights Reserved.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
 */
21
#include "hashtable.h"
22
23
hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func, free_func_t free_func)
24
324
{
25
324
  hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t));
26
324
  int i;
27
1.32M
  for (i = 0; i < 4096; i++) {
28
1.32M
    ht->entries[i] = NULL;
29
1.32M
  }
30
324
  ht->count = 0;
31
324
  ht->hash_func = hash_func;
32
324
  ht->compare_func = compare_func;
33
324
  ht->free_func = free_func;
34
324
  return ht;
35
324
}
36
37
void hash_table_destroy(hashtable_t *ht)
38
24.2k
{
39
24.2k
  if (!ht) return;
40
41
324
  int i = 0;
42
1.32M
  for (i = 0; i < 4096; i++) {
43
1.32M
    if (ht->entries[i]) {
44
79.9k
      hashentry_t* e = ht->entries[i];
45
161k
      while (e) {
46
81.9k
        if (ht->free_func) {
47
0
          ht->free_func(e->value);
48
0
        }
49
81.9k
        hashentry_t* old = e;
50
81.9k
        e = e->next;
51
81.9k
        free(old);
52
81.9k
      }
53
79.9k
    }
54
1.32M
  }
55
324
  free(ht);
56
324
}
57
58
void hash_table_insert(hashtable_t* ht, void *key, void *value)
59
82.6k
{
60
82.6k
  if (!ht || !key) return;
61
62
82.6k
  unsigned int hash = ht->hash_func(key);
63
64
82.6k
  int idx0 = hash & 0xFFF;
65
66
  // get the idx0 list
67
82.6k
  hashentry_t* e = ht->entries[idx0];
68
85.0k
  while (e) {
69
3.16k
    if (ht->compare_func(e->key, key)) {
70
      // element already present. replace value.
71
677
      e->value = value;
72
677
      return;
73
677
    }
74
2.48k
    e = e->next;
75
2.48k
  }
76
77
  // if we get here, the element is not yet in the list.
78
79
  // make a new entry.
80
81.9k
  hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t));
81
81.9k
  entry->key = key;
82
81.9k
  entry->value = value;
83
81.9k
  if (!ht->entries[idx0]) {
84
    // first entry
85
79.9k
    entry->next = NULL;
86
79.9k
  } else {
87
    // add to list
88
1.93k
    entry->next = ht->entries[idx0];
89
1.93k
  }
90
81.9k
  ht->entries[idx0] = entry;
91
81.9k
  ht->count++;
92
81.9k
}
93
94
void* hash_table_lookup(hashtable_t* ht, void *key)
95
1.28k
{
96
1.28k
  if (!ht || !key) return NULL;
97
1.28k
  unsigned int hash = ht->hash_func(key);
98
99
1.28k
  int idx0 = hash & 0xFFF;
100
101
1.28k
  hashentry_t* e = ht->entries[idx0];
102
1.73k
  while (e) {
103
1.12k
    if (ht->compare_func(e->key, key)) {
104
677
      return e->value;
105
677
    }
106
450
    e = e->next;
107
450
  }
108
607
  return NULL;
109
1.28k
}
110
111
void hash_table_remove(hashtable_t* ht, void *key)
112
0
{
113
0
  if (!ht || !key) return;
114
115
0
  unsigned int hash = ht->hash_func(key);
116
117
0
  int idx0 = hash & 0xFFF;
118
119
  // get the idx0 list
120
0
  hashentry_t* e = ht->entries[idx0];
121
0
  hashentry_t* last = e;
122
0
  while (e) {
123
0
    if (ht->compare_func(e->key, key)) {
124
      // found element, remove it from the list
125
0
      hashentry_t* old = e;
126
0
      if (e == ht->entries[idx0]) {
127
0
        ht->entries[idx0] = e->next;
128
0
      } else {
129
0
        last->next = e->next;
130
0
      }
131
0
      if (ht->free_func) {
132
0
        ht->free_func(old->value);
133
0
      }
134
0
      free(old);
135
0
      return;
136
0
    }
137
0
    last = e;
138
0
    e = e->next;
139
0
  }
140
0
}