This source file includes following definitions.
- _zip_hash_new
- _free_list
- _zip_hash_free
- _hash_string
- _zip_hash_add
- _zip_hash_delete
- _zip_hash_lookup
- _zip_hash_revert
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include "zipint.h"
37
38 struct zip_hash_entry {
39 const zip_uint8_t *name;
40 zip_int64_t orig_index;
41 zip_int64_t current_index;
42 struct zip_hash_entry *next;
43 };
44 typedef struct zip_hash_entry zip_hash_entry_t;
45
46 struct zip_hash {
47 zip_uint16_t table_size;
48 zip_hash_entry_t **table;
49 };
50
51 zip_hash_t *
52 _zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
53 {
54 zip_hash_t *hash;
55
56 if (table_size == 0) {
57 zip_error_set(error, ZIP_ER_INTERNAL, 0);
58 return NULL;
59 }
60
61 if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
62 zip_error_set(error, ZIP_ER_MEMORY, 0);
63 return NULL;
64 }
65 hash->table_size = table_size;
66 if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
67 free(hash);
68 zip_error_set(error, ZIP_ER_MEMORY, 0);
69 return NULL;
70 }
71
72 return hash;
73 }
74
75 static void
76 _free_list(zip_hash_entry_t *entry)
77 {
78 zip_hash_entry_t *next;
79 do {
80 next = entry->next;
81 free(entry);
82 entry = next;
83 } while (entry != NULL);
84 }
85
86 void
87 _zip_hash_free(zip_hash_t *hash)
88 {
89 zip_uint16_t i;
90
91 if (hash == NULL) {
92 return;
93 }
94
95 for (i=0; i<hash->table_size; i++) {
96 if (hash->table[i] != NULL) {
97 _free_list(hash->table[i]);
98 }
99 }
100 free(hash->table);
101 free(hash);
102 }
103
104 static zip_uint16_t
105 _hash_string(const zip_uint8_t *name, zip_uint16_t size)
106 {
107 #define HASH_MULTIPLIER 33
108 zip_uint16_t value = 5381;
109
110 if (name == NULL)
111 return 0;
112
113 while (*name != 0) {
114 value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
115 name++;
116 }
117
118 return value;
119 }
120
121
122 bool
123 _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
124 {
125 zip_uint16_t hash_value;
126 zip_hash_entry_t *entry;
127
128 if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
129 zip_error_set(error, ZIP_ER_INVAL, 0);
130 return false;
131 }
132
133 hash_value = _hash_string(name, hash->table_size);
134 for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
135 if (strcmp((const char *)name, (const char *)entry->name) == 0) {
136 if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
137 zip_error_set(error, ZIP_ER_EXISTS, 0);
138 return false;
139 }
140 else {
141 break;
142 }
143 }
144 }
145
146 if (entry == NULL) {
147 if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
148 zip_error_set(error, ZIP_ER_MEMORY, 0);
149 return false;
150 }
151 entry->name = name;
152 entry->next = hash->table[hash_value];
153 hash->table[hash_value] = entry;
154 entry->orig_index = -1;
155 }
156
157 if (flags & ZIP_FL_UNCHANGED) {
158 entry->orig_index = (zip_int64_t)index;
159 }
160 entry->current_index = (zip_int64_t)index;
161
162 return true;
163 }
164
165
166 bool
167 _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
168 {
169 zip_uint16_t hash_value;
170 zip_hash_entry_t *entry, *previous;
171
172 if (hash == NULL || name == NULL) {
173 zip_error_set(error, ZIP_ER_INVAL, 0);
174 return false;
175 }
176
177 hash_value = _hash_string(name, hash->table_size);
178 previous = NULL;
179 entry = hash->table[hash_value];
180 while (entry) {
181 if (strcmp((const char *)name, (const char *)entry->name) == 0) {
182 if (entry->orig_index == -1) {
183 if (previous) {
184 previous->next = entry->next;
185 }
186 else {
187 hash->table[hash_value] = entry->next;
188 }
189 free(entry);
190 }
191 else {
192 entry->current_index = -1;
193 }
194 return true;
195 }
196 previous = entry;
197 entry = entry->next;
198 };
199
200 zip_error_set(error, ZIP_ER_NOENT, 0);
201 return false;
202 }
203
204
205 zip_int64_t
206 _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
207 {
208 zip_uint16_t hash_value;
209 zip_hash_entry_t *entry;
210
211 if (hash == NULL || name == NULL) {
212 zip_error_set(error, ZIP_ER_INVAL, 0);
213 return -1;
214 }
215
216 hash_value = _hash_string(name, hash->table_size);
217 for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
218 if (strcmp((const char *)name, (const char *)entry->name) == 0) {
219 if (flags & ZIP_FL_UNCHANGED) {
220 if (entry->orig_index != -1) {
221 return entry->orig_index;
222 }
223 }
224 else {
225 if (entry->current_index != -1) {
226 return entry->current_index;
227 }
228 }
229 break;
230 }
231 }
232
233 zip_error_set(error, ZIP_ER_NOENT, 0);
234 return -1;
235 }
236
237 void
238 _zip_hash_revert(zip_hash_t *hash)
239 {
240 zip_uint16_t i;
241 zip_hash_entry_t *entry, *previous;
242
243 for (i = 0; i < hash->table_size; i++) {
244 previous = NULL;
245 entry = hash->table[i];
246 while (entry) {
247 if (entry->orig_index == -1) {
248 zip_hash_entry_t *p;
249 if (previous) {
250 previous->next = entry->next;
251 }
252 else {
253 hash->table[i] = entry->next;
254 }
255 p = entry;
256 entry = entry->next;
257
258 free(p);
259 }
260 else {
261 entry->current_index = entry->orig_index;
262 previous = entry;
263 entry = entry->next;
264 }
265 }
266 }
267 }