aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cheesemap.c63
-rw-r--r--cheesemap.h19
-rw-r--r--makefile2
3 files changed, 78 insertions, 6 deletions
diff --git a/cheesemap.c b/cheesemap.c
index cd4048f..58d1b53 100644
--- a/cheesemap.c
+++ b/cheesemap.c
@@ -76,6 +76,7 @@ static inline bool cm_ctrl_is_empty(uint8_t v) {
/* group ops */
static inline group_t cm_group_load(const uint8_t* ctrl);
static inline bitmask_t cm_group_empty_or_deleted(group_t group);
+static inline bitmask_t cm_group_full(group_t group);
/* scalar implementation */
static inline group_t cm_group_repeat(uint8_t v) {
@@ -94,6 +95,10 @@ static inline bitmask_t cm_group_empty_or_deleted(group_t group) {
return group & cm_group_repeat(CM_CTRL_DELETED);
}
+static inline bitmask_t cm_group_full(group_t group) {
+ return ~cm_group_empty_or_deleted(group);
+}
+
/* static ctrl's */
const uint8_t CM_CTRL_STATIC_EMPTY[CM_GROUP_SIZE] = {[0 ... CM_GROUP_SIZE - 1] =
CM_CTRL_EMPTY};
@@ -204,6 +209,7 @@ static bool cm_raw_resize(struct cheesemap_raw* map,
cm_raw_new_with(&new_map, fns, key_size, value_size, new_capacity);
if (!success) return success;
+
return true;
}
@@ -292,3 +298,60 @@ void cm_new(struct cheesemap* map, uintptr_t key_size, uintptr_t value_size,
};
*map = (struct cheesemap){key_size, value_size, fns, cm_raw_new()};
}
+
+void cm_drop(struct cheesemap* map) {
+ assert(map != NULL);
+
+ cm_raw_drop(&map->raw, map->key_size, map->value_size, &map->fns);
+ memset(map, 0, sizeof(*map));
+}
+
+/* iterator */
+static inline uint8_t* cm_raw_iter_next_entry(const struct cheesemap_raw_iter* iter, uint8_t* old_entry, uintptr_t entry_size) {
+ assert(iter != NULL);
+ return old_entry - entry_size * CM_GROUP_SIZE;
+}
+
+void cm_raw_iter_init(struct cheesemap_raw_iter* iter,const struct cheesemap_raw* map, uintptr_t entry_size, uintptr_t start_index){
+ assert(map != NULL);
+ assert(start_index % CM_GROUP_SIZE == 0);
+ memset(iter, 0, sizeof(*iter));
+
+ uintptr_t buckets = map->bucket_mask + 1;
+ assert(buckets > start_index);
+
+ uint8_t* ctrl = &map->ctrl[start_index];
+ uint8_t* entry = cm_raw_elem_at(map, start_index, entry_size);
+
+ group_t group = cm_group_load(ctrl);
+ bitmask_t mask = cm_group_full(group);
+
+ iter->curr_mask = mask;
+ iter->curr_index = start_index;
+ iter->n_ctrl = ctrl + CM_GROUP_SIZE;
+ iter->n_entry = cm_raw_iter_next_entry(iter, entry, entry_size);
+ iter->end = map->ctrl + buckets;
+}
+
+bool cheesemap_raw_iter_next(struct cheesemap_raw_iter* iter, uintptr_t entry_size, uintptr_t* out_index) {
+ assert(iter != NULL);
+ assert(out_index != NULL);
+
+ while (true) {
+ if (iter->curr_mask != 0) {
+ uintptr_t bit = cm_ctz(iter->curr_mask);
+ *out_index = iter->curr_index + bit;
+ iter->curr_mask &= iter->curr_mask - 1;
+ return true;
+ }
+
+ if (iter->n_ctrl >= iter->end)
+ return false;
+
+ group_t group = cm_group_load(iter->n_ctrl);
+ iter->curr_mask = cm_group_full(group);
+ iter->curr_index += CM_GROUP_SIZE;
+ iter->n_ctrl += CM_GROUP_SIZE;
+ iter->n_entry = cm_raw_iter_next_entry(iter, iter->n_entry, entry_size);
+ }
+}
diff --git a/cheesemap.h b/cheesemap.h
index 8002fbb..f8991b1 100644
--- a/cheesemap.h
+++ b/cheesemap.h
@@ -129,12 +129,21 @@ struct cheesemap {
void cm_new(struct cheesemap* map, uintptr_t key_size, uintptr_t value_size,
uint8_t* mem_usr, cm_malloc_fn malloc, cm_free_fn free,
uint8_t* map_usr, cm_hash_fn hash, cm_compare_fn compare);
+void cm_drop(struct cheesemap* map);
-static inline void cm_drop(struct cheesemap* map) {
- assert(map != NULL);
+////////////////////////////////
+// cheesemap iterators
+//
- cm_raw_drop(&map->raw, map->key_size, map->value_size, &map->fns);
- memset(map, 0, sizeof(*map));
-}
+struct cheesemap_raw_iter {
+ bitmask_t curr_mask;
+ uintptr_t curr_index;
+ uint8_t* n_ctrl;
+ uint8_t* n_entry;
+ uint8_t* end;
+};
+
+void cm_raw_iter_init(struct cheesemap_raw_iter* iter,const struct cheesemap_raw* map, uintptr_t entry_size, uintptr_t start_index);
+bool cheesemap_raw_iter_next(struct cheesemap_raw_iter* iter, uintptr_t entry_size, uintptr_t* out_index);
#endif
diff --git a/makefile b/makefile
index 03f0e1d..49de51e 100644
--- a/makefile
+++ b/makefile
@@ -33,7 +33,7 @@ CM_CC_FLAGS += -DCM_OPT_ASSERT_PATH='$(CM_OPT_ASSERT_PATH)'
all:: $(CM_OBJECT)
$(CM_OBJECT): $(CM_SOURCE)
- $(CC) $(CM_CC_FLAGS) -c $^ -o $@
+ $(CC) $(CM_CC_FLAGS) -c $< -o $@
ifeq ($(CM_OPT_ENABLE_DEMO),1)
.PHONY: all