Tue, 04 Oct 2022 19:25:07 +0200
fix over-optimization of strstr
1. it's actually less performant to frequently read bytes
from an array instead of using the native word length
2. the SBO buffer should be local and not static to allow
multi-threading usage
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
1 | /* |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
3 | * |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
4 | * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
5 | * |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
6 | * Redistribution and use in source and binary forms, with or without |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
7 | * modification, are permitted provided that the following conditions are met: |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
8 | * |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
9 | * 1. Redistributions of source code must retain the above copyright |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
10 | * notice, this list of conditions and the following disclaimer. |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
11 | * |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
12 | * 2. Redistributions in binary form must reproduce the above copyright |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
13 | * notice, this list of conditions and the following disclaimer in the |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
14 | * documentation and/or other materials provided with the distribution. |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
15 | * |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
26 | * POSSIBILITY OF SUCH DAMAGE. |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
27 | */ |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
28 | |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
29 | #include <string.h> |
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
30 | #include "cx/hash_map.h" |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
31 | #include "cx/utils.h" |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
32 | |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
33 | static void cx_hash_map_clear(struct cx_map_s *map) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
34 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
35 | cx_for_n(i, hash_map->bucket_count) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
36 | struct cx_hash_map_element_s *elem = hash_map->buckets[i]; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
37 | if (elem != NULL) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
38 | do { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
39 | struct cx_hash_map_element_s *next = elem->next; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
40 | // free the key data |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
41 | cxFree(map->allocator, elem->key.data.obj); |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
42 | // free the node |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
43 | cxFree(map->allocator, elem); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
44 | // proceed |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
45 | elem = next; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
46 | } while (elem != NULL); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
47 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
48 | // do not leave a dangling pointer |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
49 | hash_map->buckets[i] = NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
50 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
51 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
52 | map->size = 0; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
53 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
54 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
55 | static void cx_hash_map_destructor(struct cx_map_s *map) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
56 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
57 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
58 | // free the buckets |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
59 | cx_hash_map_clear(map); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
60 | cxFree(map->allocator, hash_map->buckets); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
61 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
62 | // free the map structure |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
63 | cxFree(map->allocator, map); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
64 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
65 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
66 | static int cx_hash_map_put( |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
67 | CxMap *map, |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
68 | CxHashKey key, |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
69 | void *value |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
70 | ) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
71 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
72 | CxAllocator *allocator = map->allocator; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
73 | |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
74 | unsigned hash = key.hash; |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
75 | if (hash == 0) { |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
76 | cx_hash_murmur(&key); |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
77 | hash = key.hash; |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
78 | } |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
79 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
80 | size_t slot = hash % hash_map->bucket_count; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
81 | struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
82 | struct cx_hash_map_element_s *prev = NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
83 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
84 | while (elm != NULL && elm->key.hash < hash) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
85 | prev = elm; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
86 | elm = elm->next; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
87 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
88 | |
575
b05935945637
fix #200 - key contents not compared in cx_hash_map_put()
Mike Becker <universe@uap-core.de>
parents:
574
diff
changeset
|
89 | if (elm != NULL && elm->key.hash == hash && elm->key.len == key.len && |
b05935945637
fix #200 - key contents not compared in cx_hash_map_put()
Mike Becker <universe@uap-core.de>
parents:
574
diff
changeset
|
90 | memcmp(elm->key.data.obj, key.data.obj, key.len) == 0) { |
574
d566bd3e6af8
invert if-condition in preparation for the next bugfix
Mike Becker <universe@uap-core.de>
parents:
573
diff
changeset
|
91 | // overwrite existing element |
d566bd3e6af8
invert if-condition in preparation for the next bugfix
Mike Becker <universe@uap-core.de>
parents:
573
diff
changeset
|
92 | elm->data = value; |
d566bd3e6af8
invert if-condition in preparation for the next bugfix
Mike Becker <universe@uap-core.de>
parents:
573
diff
changeset
|
93 | } else { |
575
b05935945637
fix #200 - key contents not compared in cx_hash_map_put()
Mike Becker <universe@uap-core.de>
parents:
574
diff
changeset
|
94 | // allocate new element |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
95 | struct cx_hash_map_element_s *e = cxMalloc(allocator, sizeof(struct cx_hash_map_element_s)); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
96 | if (e == NULL) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
97 | return -1; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
98 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
99 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
100 | // write the value |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
101 | // TODO: depending on future map features, we may want to copy here |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
102 | e->data = value; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
103 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
104 | // copy the key |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
105 | void *kd = cxMalloc(allocator, key.len); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
106 | if (kd == NULL) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
107 | return -1; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
108 | } |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
109 | memcpy(kd, key.data.obj, key.len); |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
110 | e->key.data.obj = kd; |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
111 | e->key.len = key.len; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
112 | e->key.hash = hash; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
113 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
114 | // insert the element into the linked list |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
115 | if (prev == NULL) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
116 | hash_map->buckets[slot] = e; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
117 | } else { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
118 | prev->next = e; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
119 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
120 | e->next = elm; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
121 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
122 | // increase the size |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
123 | map->size++; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
124 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
125 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
126 | return 0; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
127 | } |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
128 | |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
129 | static void cx_hash_map_unlink( |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
130 | struct cx_hash_map_s *hash_map, |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
131 | size_t slot, |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
132 | struct cx_hash_map_element_s *prev, |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
133 | struct cx_hash_map_element_s *elm |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
134 | ) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
135 | // unlink |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
136 | if (prev == NULL) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
137 | hash_map->buckets[slot] = elm->next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
138 | } else { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
139 | prev->next = elm->next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
140 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
141 | // free element |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
142 | cxFree(hash_map->base.allocator, elm->key.data.obj); |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
143 | cxFree(hash_map->base.allocator, elm); |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
144 | // decrease size |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
145 | hash_map->base.size--; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
146 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
147 | |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
148 | /** |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
149 | * Helper function to avoid code duplication. |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
150 | * |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
151 | * @param map the map |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
152 | * @param key the key to look up |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
153 | * @param remove flag indicating whether the looked up entry shall be removed |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
154 | * @return the value corresponding to the key or \c NULL |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
155 | */ |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
156 | static void *cx_hash_map_get_remove( |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
157 | CxMap *map, |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
158 | CxHashKey key, |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
159 | bool remove |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
160 | ) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
161 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
162 | |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
163 | unsigned hash = key.hash; |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
164 | if (hash == 0) { |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
165 | cx_hash_murmur(&key); |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
166 | hash = key.hash; |
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
167 | } |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
168 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
169 | size_t slot = hash % hash_map->bucket_count; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
170 | struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
171 | struct cx_hash_map_element_s *prev = NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
172 | while (elm && elm->key.hash <= hash) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
173 | if (elm->key.hash == hash && elm->key.len == key.len) { |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
174 | if (memcmp(elm->key.data.obj, key.data.obj, key.len) == 0) { |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
175 | void *data = elm->data; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
176 | if (remove) { |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
177 | cx_hash_map_unlink(hash_map, slot, prev, elm); |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
178 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
179 | return data; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
180 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
181 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
182 | prev = elm; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
183 | elm = prev->next; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
184 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
185 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
186 | return NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
187 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
188 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
189 | static void *cx_hash_map_get( |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
190 | CxMap const *map, |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
191 | CxHashKey key |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
192 | ) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
193 | // we can safely cast, because we know when remove=false, the map stays untouched |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
194 | return cx_hash_map_get_remove((CxMap *) map, key, false); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
195 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
196 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
197 | static void *cx_hash_map_remove( |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
198 | CxMap *map, |
563
69a83fad8a35
improve hash key handling
Mike Becker <universe@uap-core.de>
parents:
562
diff
changeset
|
199 | CxHashKey key |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
200 | ) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
201 | return cx_hash_map_get_remove(map, key, true); |
549
d7f0b5a9a985
#189 declare basic map functions
Mike Becker <universe@uap-core.de>
parents:
diff
changeset
|
202 | } |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
203 | |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
204 | static void *cx_hash_map_iter_current_entry(CxIterator const *iter) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
205 | // struct has to have a compatible signature |
573
3f3a0d19db58
remove unused variable (return immediately)
Mike Becker <universe@uap-core.de>
parents:
563
diff
changeset
|
206 | return (struct cx_map_entry_s *) &(iter->kv_data); |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
207 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
208 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
209 | static void *cx_hash_map_iter_current_key(CxIterator const *iter) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
210 | struct cx_hash_map_element_s *elm = iter->elem_handle; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
211 | return &elm->key; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
212 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
213 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
214 | static void *cx_hash_map_iter_current_value(CxIterator const *iter) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
215 | struct cx_hash_map_element_s *elm = iter->elem_handle; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
216 | // TODO: return a pointer to data if this map is storing copies |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
217 | return elm->data; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
218 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
219 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
220 | static bool cx_hash_map_iter_valid(CxIterator const *iter) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
221 | return iter->elem_handle != NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
222 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
223 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
224 | static void cx_hash_map_iter_next(CxIterator *iter) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
225 | struct cx_hash_map_s *map = iter->src_handle; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
226 | struct cx_hash_map_element_s *elm = iter->elem_handle; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
227 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
228 | // remove current element, if asked |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
229 | if (iter->remove) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
230 | // clear the flag |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
231 | iter->remove = false; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
232 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
233 | // determine the next element |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
234 | struct cx_hash_map_element_s *next = elm->next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
235 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
236 | // search the previous element |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
237 | struct cx_hash_map_element_s *prev = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
238 | if (map->buckets[iter->slot] != elm) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
239 | prev = map->buckets[iter->slot]; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
240 | while (prev->next != elm) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
241 | prev = prev->next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
242 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
243 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
244 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
245 | // unlink |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
246 | cx_hash_map_unlink(map, iter->slot, prev, elm); |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
247 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
248 | // advance |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
249 | elm = next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
250 | } else { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
251 | // just advance |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
252 | elm = elm->next; |
560
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
253 | iter->index++; |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
254 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
255 | |
560
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
256 | // search the next bucket, if required |
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
257 | while (elm == NULL && ++iter->slot < map->bucket_count) { |
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
258 | elm = map->buckets[iter->slot]; |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
259 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
260 | |
560
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
261 | // fill the struct with the next element |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
262 | iter->elem_handle = elm; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
263 | if (elm == NULL) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
264 | iter->kv_data.key = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
265 | iter->kv_data.value = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
266 | } else { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
267 | iter->kv_data.key = &elm->key; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
268 | // TODO: pointer to data if this map is storing copies |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
269 | iter->kv_data.value = elm->data; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
270 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
271 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
272 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
273 | static CxIterator cx_hash_map_iterator(CxMap *map) { |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
274 | CxIterator iter; |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
275 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
276 | iter.src_handle = map; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
277 | iter.valid = cx_hash_map_iter_valid; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
278 | iter.next = cx_hash_map_iter_next; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
279 | iter.current = cx_hash_map_iter_current_entry; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
280 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
281 | iter.slot = 0; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
282 | iter.index = 0; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
283 | iter.remove = false; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
284 | |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
285 | if (map->size > 0) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
286 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
560
2d6a3e2dc8ff
fix wrong slot and index numbers
Mike Becker <universe@uap-core.de>
parents:
557
diff
changeset
|
287 | struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
554
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
288 | for (; elm == NULL; iter.slot++) { |
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
289 | elm = hash_map->buckets[iter.slot]; |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
290 | } |
554
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
291 | iter.elem_handle = elm; |
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
292 | iter.kv_data.key = &elm->key; |
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
293 | // TODO: pointer to data if this map is storing copies |
fd3d843b839d
fix kv-pair not initialized
Mike Becker <universe@uap-core.de>
parents:
551
diff
changeset
|
294 | iter.kv_data.value = elm->data; |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
295 | } else { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
296 | iter.elem_handle = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
297 | iter.kv_data.key = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
298 | iter.kv_data.value = NULL; |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
299 | } |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
300 | |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
301 | return iter; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
302 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
303 | |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
304 | static CxIterator cx_hash_map_iterator_keys(CxMap *map) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
305 | CxIterator iter = cx_hash_map_iterator(map); |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
306 | iter.current = cx_hash_map_iter_current_key; |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
307 | return iter; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
308 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
309 | |
551
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
310 | static CxIterator cx_hash_map_iterator_values(CxMap *map) { |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
311 | CxIterator iter = cx_hash_map_iterator(map); |
2946e13c89a4
#189 implement map iterators
Mike Becker <universe@uap-core.de>
parents:
550
diff
changeset
|
312 | iter.current = cx_hash_map_iter_current_value; |
550
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
313 | return iter; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
314 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
315 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
316 | static cx_map_class cx_hash_map_class = { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
317 | cx_hash_map_destructor, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
318 | cx_hash_map_clear, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
319 | cx_hash_map_put, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
320 | cx_hash_map_get, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
321 | cx_hash_map_remove, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
322 | cx_hash_map_iterator, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
323 | cx_hash_map_iterator_keys, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
324 | cx_hash_map_iterator_values, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
325 | }; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
326 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
327 | CxMap *cxHashMapCreate( |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
328 | CxAllocator *allocator, |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
329 | size_t buckets |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
330 | ) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
331 | if (buckets == 0) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
332 | // implementation defined default |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
333 | buckets = 16; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
334 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
335 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
336 | struct cx_hash_map_s *map = cxMalloc(allocator, sizeof(struct cx_hash_map_s)); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
337 | if (map == NULL) return NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
338 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
339 | // initialize hash map members |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
340 | map->bucket_count = buckets; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
341 | map->buckets = cxCalloc(allocator, buckets, sizeof(struct cx_hash_map_element_s *)); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
342 | if (map->buckets == NULL) { |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
343 | cxFree(allocator, map); |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
344 | return NULL; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
345 | } |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
346 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
347 | // initialize base members |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
348 | map->base.cl = &cx_hash_map_class; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
349 | map->base.allocator = allocator; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
350 | map->base.size = 0; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
351 | |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
352 | return (CxMap *) map; |
89b2a83728b1
#189 basic map implementation
Mike Becker <universe@uap-core.de>
parents:
549
diff
changeset
|
353 | } |
562
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
354 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
355 | int cxMapRehash(CxMap *map) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
356 | struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
357 | if (map->size > ((hash_map->bucket_count * 3) >> 2)) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
358 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
359 | size_t new_bucket_count = (map->size * 5) >> 1; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
360 | struct cx_hash_map_element_s **new_buckets = cxCalloc(map->allocator, |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
361 | new_bucket_count, sizeof(struct cx_hash_map_element_s *)); |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
362 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
363 | if (new_buckets == NULL) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
364 | return 1; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
365 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
366 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
367 | // iterate through the elements and assign them to their new slots |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
368 | cx_for_n(slot, hash_map->bucket_count) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
369 | struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
370 | while (elm != NULL) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
371 | struct cx_hash_map_element_s *next = elm->next; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
372 | size_t new_slot = elm->key.hash % new_bucket_count; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
373 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
374 | // find position where to insert |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
375 | struct cx_hash_map_element_s *bucket_next = new_buckets[new_slot]; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
376 | struct cx_hash_map_element_s *bucket_prev = NULL; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
377 | while (bucket_next != NULL && bucket_next->key.hash < elm->key.hash) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
378 | bucket_prev = bucket_next; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
379 | bucket_next = bucket_next->next; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
380 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
381 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
382 | // insert |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
383 | if (bucket_prev == NULL) { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
384 | elm->next = new_buckets[new_slot]; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
385 | new_buckets[new_slot] = elm; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
386 | } else { |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
387 | bucket_prev->next = elm; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
388 | elm->next = bucket_next; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
389 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
390 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
391 | // advance |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
392 | elm = next; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
393 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
394 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
395 | |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
396 | // assign result to the map |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
397 | hash_map->bucket_count = new_bucket_count; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
398 | cxFree(map->allocator, hash_map->buckets); |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
399 | hash_map->buckets = new_buckets; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
400 | } |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
401 | return 0; |
fd3368c20413
#189 #199 implement and test map rehash
Mike Becker <universe@uap-core.de>
parents:
560
diff
changeset
|
402 | } |