1 /* Crit-bit tree based map which supports lookups based on unique
2 * prefixes as well as ordered iteration.
4 * Based on public domain code from Rusty Russel, Adam Langley
7 * Further information about the data structure can be found at:
8 * http://cr.yp.to/critbit.html
9 * http://github.com/agl/critbit
10 * http://ccodearchive.net/info/strmap.html
18 typedef struct Node Node
;
20 struct Map
{ /* struct holding either an item with value v and key u.s or an internal node */
25 void *v
; /* value stored in the map, if non NULL u.s holds the corresponding key */
29 Map child
[2]; /* These point to strings or nodes. */
30 size_t byte_num
; /* The byte number where first bit differs. */
31 uint8_t bit_num
; /* The bit where these children differ. */
34 /* Closest key to this in a non-empty map. */
35 static Map
*closest(Map
*n
, const char *key
)
37 size_t len
= strlen(key
);
38 const uint8_t *bytes
= (const uint8_t *)key
;
40 /* Anything with NULL value is an internal node. */
42 uint8_t direction
= 0;
44 if (n
->u
.n
->byte_num
< len
) {
45 uint8_t c
= bytes
[n
->u
.n
->byte_num
];
46 direction
= (c
>> n
->u
.n
->bit_num
) & 1;
48 n
= &n
->u
.n
->child
[direction
];
53 void *map_get(const Map
*map
, const char *key
)
57 Map
*n
= closest((Map
*)map
, key
);
58 if (strcmp(key
, n
->u
.s
) == 0)
64 void *map_closest(const Map
*map
, const char *prefix
)
67 void *v
= map_get(map
, prefix
);
70 const Map
*m
= map_prefix(map
, prefix
);
76 bool map_contains(const Map
*map
, const char *prefix
)
78 return !map_empty(map_prefix(map
, prefix
));
81 static bool leaf(const char *key
, void *value
, void *data
)
84 return (*nodes
)++ < 1;
87 bool map_leaf(const Map
*map
, const char *prefix
)
90 map_iterate(map_prefix(map
, prefix
), leaf
, &nodes
);
94 bool map_put(Map
*map
, const char *k
, const void *value
)
96 size_t len
= strlen(k
);
97 const uint8_t *bytes
= (const uint8_t *)k
;
101 uint8_t bit_num
, new_dir
;
109 if (!(key
= strdup(k
))) {
117 map
->v
= (void *)value
;
121 /* Find closest existing key. */
122 n
= closest(map
, key
);
124 /* Find where they differ. */
125 for (byte_num
= 0; n
->u
.s
[byte_num
] == key
[byte_num
]; byte_num
++) {
126 if (key
[byte_num
] == '\0') {
134 /* Find which bit differs */
135 uint8_t diff
= (uint8_t)n
->u
.s
[byte_num
] ^ bytes
[byte_num
];
136 /* TODO: bit_num = 31 - __builtin_clz(diff); ? */
137 for (bit_num
= 0; diff
>>= 1; bit_num
++);
139 /* Which direction do we go at this bit? */
140 new_dir
= ((bytes
[byte_num
]) >> bit_num
) & 1;
142 /* Allocate new node. */
143 newn
= malloc(sizeof(*newn
));
149 newn
->byte_num
= byte_num
;
150 newn
->bit_num
= bit_num
;
151 newn
->child
[new_dir
].v
= (void *)value
;
152 newn
->child
[new_dir
].u
.s
= key
;
154 /* Find where to insert: not closest, but first which differs! */
157 uint8_t direction
= 0;
159 if (n
->u
.n
->byte_num
> byte_num
)
161 /* Subtle: bit numbers are "backwards" for comparison */
162 if (n
->u
.n
->byte_num
== byte_num
&& n
->u
.n
->bit_num
< bit_num
)
165 if (n
->u
.n
->byte_num
< len
) {
166 uint8_t c
= bytes
[n
->u
.n
->byte_num
];
167 direction
= (c
>> n
->u
.n
->bit_num
) & 1;
169 n
= &n
->u
.n
->child
[direction
];
172 newn
->child
[!new_dir
] = *n
;
178 void *map_delete(Map
*map
, const char *key
)
180 size_t len
= strlen(key
);
181 const uint8_t *bytes
= (const uint8_t *)key
;
182 Map
*parent
= NULL
, *n
;
192 /* Find closest, but keep track of parent. */
194 /* Anything with NULL value is a node. */
199 if (n
->u
.n
->byte_num
< len
) {
200 c
= bytes
[n
->u
.n
->byte_num
];
201 direction
= (c
>> n
->u
.n
->bit_num
) & 1;
205 n
= &n
->u
.n
->child
[direction
];
208 /* Did we find it? */
209 if (strcmp(key
, n
->u
.s
)) {
218 /* We deleted last node. */
221 Node
*old
= parent
->u
.n
;
222 /* Raise other node to parent. */
223 *parent
= old
->child
[!direction
];
230 static bool iterate(Map n
, bool (*handle
)(const char *, void *, void *), const void *data
)
233 return handle(n
.u
.s
, n
.v
, (void *)data
);
235 return iterate(n
.u
.n
->child
[0], handle
, data
)
236 && iterate(n
.u
.n
->child
[1], handle
, data
);
239 void map_iterate(const Map
*map
, bool (*handle
)(const char *, void *, void *), const void *data
)
245 iterate(*map
, handle
, data
);
253 static bool first(const char *key
, void *value
, void *data
)
261 void *map_first(const Map
*map
, const char **key
)
264 map_iterate(map
, first
, &kv
);
270 const Map
*map_prefix(const Map
*map
, const char *prefix
)
273 size_t len
= strlen(prefix
);
274 const uint8_t *bytes
= (const uint8_t *)prefix
;
276 /* Empty map -> return empty map. */
282 /* We walk to find the top, but keep going to check prefix matches. */
284 uint8_t c
= 0, direction
;
286 if (n
->u
.n
->byte_num
< len
)
287 c
= bytes
[n
->u
.n
->byte_num
];
289 direction
= (c
>> n
->u
.n
->bit_num
) & 1;
290 n
= &n
->u
.n
->child
[direction
];
295 if (strncmp(n
->u
.s
, prefix
, len
)) {
296 /* Convenient return for prefixes which do not appear in map. */
297 static const Map empty_map
;
304 static void clear(Map n
)
307 clear(n
.u
.n
->child
[0]);
308 clear(n
.u
.n
->child
[1]);
315 void map_clear(Map
*map
)
323 static bool copy(Map
*dest
, Map n
)
326 return copy(dest
, n
.u
.n
->child
[0]) &&
327 copy(dest
, n
.u
.n
->child
[1]);
329 if (!map_put(dest
, n
.u
.s
, n
.v
) && map_get(dest
, n
.u
.s
) != n
.v
) {
330 map_delete(dest
, n
.u
.s
);
331 return map_put(dest
, n
.u
.s
, n
.v
);
337 bool map_copy(Map
*dest
, Map
*src
)
339 if (!src
|| !src
->u
.n
)
342 return copy(dest
, *src
);
345 bool map_empty(const Map
*map
)
347 return map
->u
.n
== NULL
;
352 return calloc(1, sizeof(Map
));
355 void map_free(Map
*map
)
363 static bool free_elem(const char *key
, void *value
, void *data
)
369 void map_free_full(Map
*map
)
373 map_iterate(map
, free_elem
, NULL
);