File: | t/helper/test-hashmap.c |
Location: | line 85, column 11 |
Description: | Result of 'malloc' is converted to a pointer of type 'unsigned int', which is incompatible with sizeof operand type 'int' |
1 | #include "git-compat-util.h" |
2 | #include "hashmap.h" |
3 | |
4 | struct test_entry |
5 | { |
6 | struct hashmap_entry ent; |
7 | /* key and value as two \0-terminated strings */ |
8 | char key[FLEX_ARRAY]; |
9 | }; |
10 | |
11 | static const char *get_value(const struct test_entry *e) |
12 | { |
13 | return e->key + strlen(e->key) + 1; |
14 | } |
15 | |
16 | static int test_entry_cmp(const struct test_entry *e1, |
17 | const struct test_entry *e2, const char* key) |
18 | { |
19 | return strcmp(e1->key, key ? key : e2->key); |
20 | } |
21 | |
22 | static int test_entry_cmp_icase(const struct test_entry *e1, |
23 | const struct test_entry *e2, const char* key) |
24 | { |
25 | return strcasecmp(e1->key, key ? key : e2->key); |
26 | } |
27 | |
28 | static struct test_entry *alloc_test_entry(int hash, char *key, int klen, |
29 | char *value, int vlen) |
30 | { |
31 | struct test_entry *entry = malloc(sizeof(struct test_entry) + klen |
32 | + vlen + 2); |
33 | hashmap_entry_init(entry, hash); |
34 | memcpy(entry->key, key, klen + 1)__builtin___memcpy_chk (entry->key, key, klen + 1, __builtin_object_size (entry->key, 0)); |
35 | memcpy(entry->key + klen + 1, value, vlen + 1)__builtin___memcpy_chk (entry->key + klen + 1, value, vlen + 1, __builtin_object_size (entry->key + klen + 1, 0)); |
36 | return entry; |
37 | } |
38 | |
39 | #define HASH_METHOD_FNV0 0 |
40 | #define HASH_METHOD_I1 1 |
41 | #define HASH_METHOD_IDIV102 2 |
42 | #define HASH_METHOD_03 3 |
43 | #define HASH_METHOD_X24 4 |
44 | #define TEST_SPARSE8 8 |
45 | #define TEST_ADD16 16 |
46 | #define TEST_SIZE100000 100000 |
47 | |
48 | static unsigned int hash(unsigned int method, unsigned int i, const char *key) |
49 | { |
50 | unsigned int hash = 0; |
51 | switch (method & 3) |
52 | { |
53 | case HASH_METHOD_FNV0: |
54 | hash = strhash(key); |
55 | break; |
56 | case HASH_METHOD_I1: |
57 | hash = i; |
58 | break; |
59 | case HASH_METHOD_IDIV102: |
60 | hash = i / 10; |
61 | break; |
62 | case HASH_METHOD_03: |
63 | hash = 0; |
64 | break; |
65 | } |
66 | |
67 | if (method & HASH_METHOD_X24) |
68 | hash = 2 * hash; |
69 | return hash; |
70 | } |
71 | |
72 | /* |
73 | * Test performance of hashmap.[ch] |
74 | * Usage: time echo "perfhashmap method rounds" | test-hashmap |
75 | */ |
76 | static void perf_hashmap(unsigned int method, unsigned int rounds) |
77 | { |
78 | struct hashmap map; |
79 | char buf[16]; |
80 | struct test_entry **entries; |
81 | unsigned int *hashes; |
82 | unsigned int i, j; |
83 | |
84 | entries = malloc(TEST_SIZE100000 * sizeof(struct test_entry *)); |
85 | hashes = malloc(TEST_SIZE100000 * sizeof(int)); |
Result of 'malloc' is converted to a pointer of type 'unsigned int', which is incompatible with sizeof operand type 'int' | |
86 | for (i = 0; i < TEST_SIZE100000; i++) { |
87 | snprintf(buf, sizeof(buf), "%i", i)__builtin___snprintf_chk (buf, sizeof(buf), 0, __builtin_object_size (buf, 2 > 1 ? 1 : 0), "%i", i); |
88 | entries[i] = alloc_test_entry(0, buf, strlen(buf), "", 0); |
89 | hashes[i] = hash(method, i, entries[i]->key); |
90 | } |
91 | |
92 | if (method & TEST_ADD16) { |
93 | /* test adding to the map */ |
94 | for (j = 0; j < rounds; j++) { |
95 | hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0); |
96 | |
97 | /* add entries */ |
98 | for (i = 0; i < TEST_SIZE100000; i++) { |
99 | hashmap_entry_init(entries[i], hashes[i]); |
100 | hashmap_add(&map, entries[i]); |
101 | } |
102 | |
103 | hashmap_free(&map, 0); |
104 | } |
105 | } else { |
106 | /* test map lookups */ |
107 | hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0); |
108 | |
109 | /* fill the map (sparsely if specified) */ |
110 | j = (method & TEST_SPARSE8) ? TEST_SIZE100000 / 10 : TEST_SIZE100000; |
111 | for (i = 0; i < j; i++) { |
112 | hashmap_entry_init(entries[i], hashes[i]); |
113 | hashmap_add(&map, entries[i]); |
114 | } |
115 | |
116 | for (j = 0; j < rounds; j++) { |
117 | for (i = 0; i < TEST_SIZE100000; i++) { |
118 | hashmap_get_from_hash(&map, hashes[i], |
119 | entries[i]->key); |
120 | } |
121 | } |
122 | |
123 | hashmap_free(&map, 0); |
124 | } |
125 | } |
126 | |
127 | #define DELIM" \t\r\n" " \t\r\n" |
128 | |
129 | /* |
130 | * Read stdin line by line and print result of commands to stdout: |
131 | * |
132 | * hash key -> strhash(key) memhash(key) strihash(key) memihash(key) |
133 | * put key value -> NULL / old value |
134 | * get key -> NULL / value |
135 | * remove key -> NULL / old value |
136 | * iterate -> key1 value1\nkey2 value2\n... |
137 | * size -> tablesize numentries |
138 | * |
139 | * perfhashmap method rounds -> test hashmap.[ch] performance |
140 | */ |
141 | int cmd_main(int argc, const char **argv) |
142 | { |
143 | char line[1024]; |
144 | struct hashmap map; |
145 | int icase; |
146 | |
147 | /* init hash map */ |
148 | icase = argc > 1 && !strcmp("ignorecase", argv[1]); |
149 | hashmap_init(&map, (hashmap_cmp_fn) (icase ? test_entry_cmp_icase |
150 | : test_entry_cmp), 0); |
151 | |
152 | /* process commands from stdin */ |
153 | while (fgets(line, sizeof(line), stdin__stdinp)) { |
154 | char *cmd, *p1 = NULL((void*)0), *p2 = NULL((void*)0); |
155 | int l1 = 0, l2 = 0, hash = 0; |
156 | struct test_entry *entry; |
157 | |
158 | /* break line into command and up to two parameters */ |
159 | cmd = strtok(line, DELIM" \t\r\n"); |
160 | /* ignore empty lines */ |
161 | if (!cmd || *cmd == '#') |
162 | continue; |
163 | |
164 | p1 = strtok(NULL((void*)0), DELIM" \t\r\n"); |
165 | if (p1) { |
166 | l1 = strlen(p1); |
167 | hash = icase ? strihash(p1) : strhash(p1); |
168 | p2 = strtok(NULL((void*)0), DELIM" \t\r\n"); |
169 | if (p2) |
170 | l2 = strlen(p2); |
171 | } |
172 | |
173 | if (!strcmp("hash", cmd) && l1) { |
174 | |
175 | /* print results of different hash functions */ |
176 | printf("%u %u %u %u\n", strhash(p1), memhash(p1, l1), |
177 | strihash(p1), memihash(p1, l1)); |
178 | |
179 | } else if (!strcmp("add", cmd) && l1 && l2) { |
180 | |
181 | /* create entry with key = p1, value = p2 */ |
182 | entry = alloc_test_entry(hash, p1, l1, p2, l2); |
183 | |
184 | /* add to hashmap */ |
185 | hashmap_add(&map, entry); |
186 | |
187 | } else if (!strcmp("put", cmd) && l1 && l2) { |
188 | |
189 | /* create entry with key = p1, value = p2 */ |
190 | entry = alloc_test_entry(hash, p1, l1, p2, l2); |
191 | |
192 | /* add / replace entry */ |
193 | entry = hashmap_put(&map, entry); |
194 | |
195 | /* print and free replaced entry, if any */ |
196 | puts(entry ? get_value(entry) : "NULL"); |
197 | free(entry); |
198 | |
199 | } else if (!strcmp("get", cmd) && l1) { |
200 | |
201 | /* lookup entry in hashmap */ |
202 | entry = hashmap_get_from_hash(&map, hash, p1); |
203 | |
204 | /* print result */ |
205 | if (!entry) |
206 | puts("NULL"); |
207 | while (entry) { |
208 | puts(get_value(entry)); |
209 | entry = hashmap_get_next(&map, entry); |
210 | } |
211 | |
212 | } else if (!strcmp("remove", cmd) && l1) { |
213 | |
214 | /* setup static key */ |
215 | struct hashmap_entry key; |
216 | hashmap_entry_init(&key, hash); |
217 | |
218 | /* remove entry from hashmap */ |
219 | entry = hashmap_remove(&map, &key, p1); |
220 | |
221 | /* print result and free entry*/ |
222 | puts(entry ? get_value(entry) : "NULL"); |
223 | free(entry); |
224 | |
225 | } else if (!strcmp("iterate", cmd)) { |
226 | |
227 | struct hashmap_iter iter; |
228 | hashmap_iter_init(&map, &iter); |
229 | while ((entry = hashmap_iter_next(&iter))) |
230 | printf("%s %s\n", entry->key, get_value(entry)); |
231 | |
232 | } else if (!strcmp("size", cmd)) { |
233 | |
234 | /* print table sizes */ |
235 | printf("%u %u\n", map.tablesize, map.size); |
236 | |
237 | } else if (!strcmp("intern", cmd) && l1) { |
238 | |
239 | /* test that strintern works */ |
240 | const char *i1 = strintern(p1); |
241 | const char *i2 = strintern(p1); |
242 | if (strcmp(i1, p1)) |
243 | printf("strintern(%s) returns %s\n", p1, i1); |
244 | else if (i1 == p1) |
245 | printf("strintern(%s) returns input pointer\n", p1); |
246 | else if (i1 != i2) |
247 | printf("strintern(%s) != strintern(%s)", i1, i2); |
248 | else |
249 | printf("%s\n", i1); |
250 | |
251 | } else if (!strcmp("perfhashmap", cmd) && l1 && l2) { |
252 | |
253 | perf_hashmap(atoi(p1), atoi(p2)); |
254 | |
255 | } else { |
256 | |
257 | printf("Unknown command %s\n", cmd); |
258 | |
259 | } |
260 | } |
261 | |
262 | hashmap_free(&map, 1); |
263 | return 0; |
264 | } |