diff --git a/src/include/map.h b/src/include/map.h index 8122a1aa..8a9e3673 100644 --- a/src/include/map.h +++ b/src/include/map.h @@ -72,6 +72,7 @@ typedef struct _map_entry_t { struct rb_node node; void* key; void* val; + free_val_fn free_val_alt; // alternative free function per entry } map_entry_t; map_t* __mg_map_create (copy_key_fn copy_key, free_key_fn free_key, @@ -82,10 +83,29 @@ int __mg_map_clear (map_t* map); int __mg_map_get_size (map_t* map); map_entry_t* __mg_map_find (map_t* map, const void* key); -int __mg_map_insert (map_t* map, const void* key, const void* val); -void* __mg_map_find_or_insert (map_t* map, const void* key, const void* val); -int __mg_map_erase (map_t* map, void* key); -int __mg_map_get_size (map_t* map); + +int __mg_map_insert_ex (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt); +static inline int __mg_map_insert (map_t* map, const void* key, + const void* val) +{ + return __mg_map_insert_ex (map, key, val, NULL); +} + +void* __mg_map_find_or_insert_ex (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt); + +static inline void* __mg_map_find_or_insert (map_t* map, const void* key, + const void* val) +{ + return __mg_map_find_or_insert_ex (map, key, val, NULL); +} + +int __mg_map_replace (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt); + +int __mg_map_erase (map_t* map, void* key); +int __mg_map_get_size (map_t* map); #ifdef __cplusplus } diff --git a/src/misc/map.c b/src/misc/map.c index 13965356..9109011a 100644 --- a/src/misc/map.c +++ b/src/misc/map.c @@ -129,7 +129,8 @@ int __mg_map_destroy (map_t* map) return 0; } -static map_entry_t* new_entry (map_t* map, const void* key, const void* val) +static map_entry_t* new_entry (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt) { map_entry_t* entry; @@ -146,6 +147,8 @@ static map_entry_t* new_entry (map_t* map, const void* key, const void* val) } else entry->val = (void*)val; + + entry->free_val_alt = free_val_alt; } return entry; @@ -160,7 +163,10 @@ static void clear_node (map_t* map, struct rb_node* node) map->free_key (entry->key); } - if (map->free_val) { + if (entry->free_val_alt) { + entry->free_val_alt (entry->val); + } + else if (map->free_val) { map->free_val (entry->val); } @@ -236,7 +242,42 @@ map_entry_t* __mg_map_find (map_t* map, const void* key) return entry; } -int __mg_map_insert (map_t* map, const void* key, const void* val) +int __mg_map_replace (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt) +{ + map_entry_t* entry = NULL; + + entry = __mg_map_find (map, key); + if (entry == NULL) + return -1; + + if (val == entry->val) + return 0; + + WRLOCK_MAP (map); + + if (entry->free_val_alt) { + entry->free_val_alt (entry->val); + } + else if (map->free_val) { + map->free_val (entry->val); + } + + if (map->copy_val) { + entry->val = map->copy_val (val); + } + else + entry->val = (void*)val; + + entry->free_val_alt = free_val_alt; + + UNLOCK_MAP (map); + + return 0; +} + +int __mg_map_insert_ex (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt) { map_entry_t **pentry; map_entry_t *entry; @@ -271,7 +312,7 @@ int __mg_map_insert (map_t* map, const void* key, const void* val) } if (!entry) { - entry = new_entry (map, key, val); + entry = new_entry (map, key, val, free_val_alt); rb_link_node (&entry->node, (struct rb_node*)parent, (struct rb_node**)pentry); __mg_rb_insert_color (&entry->node, &map->root); @@ -293,8 +334,8 @@ int __mg_map_insert (map_t* map, const void* key, const void* val) return 0; } -void* __mg_map_find_or_insert (map_t* map, const void* key, - const void* val) +void* __mg_map_find_or_insert_ex (map_t* map, const void* key, + const void* val, free_val_fn free_val_alt) { map_entry_t **pentry; map_entry_t *entry; @@ -331,7 +372,7 @@ void* __mg_map_find_or_insert (map_t* map, const void* key, UNLOCK_MAP (map); if (entry == NULL) { - entry = new_entry (map, key, val); + entry = new_entry (map, key, val, free_val_alt); WRLOCK_MAP (map);