25
25
#include <stdlib.h>
29
29
size_t len; // Length
30
SDynamicArray * array; /* This is what holds the buckets. These buckets are
30
SDynamicArray * array; /**< This is what holds the buckets. These buckets are
31
31
* in turn also SDynamicArrays; or in template speak:
32
32
* SDynamicArray<SDynamicArray<SMapItem*>*>*
35
CompFunc is_equal; /**< method to check if items are equal. */
36
HashFunc key_hash_func;
42
_s_map_internal_free_array_for_each (SDynamicArray * obj,
47
_s_map_internal_free_bucket_for_each (SDynamicArray * obj,
52
_s_map_internal_find_bucket (SMap * self,
56
_s_map_internal_find_item_in_bucket (SMap * self,
57
SDynamicArray * bucket,
37
61
s_map_item_new (void * key, void * value) {
38
62
SMapItem * self = malloc (sizeof (SMapItem));
46
s_map_item_free (SMapItem * self, FuncPointer free_key,
47
FuncPointer free_value) {
48
FREEFUNC(free_key) (self->key);
49
FREEFUNC(free_value) (self->value);
70
s_map_item_free (SMapItem * self,
72
FreeFunc free_value) {
74
free_value (self->value);
56
81
s_map_new (CompFunc comp_func,
57
HashFunc key_hash_func,
59
FuncPointer free_value) {
82
HashFunc key_hash_func,
84
FreeFunc free_value) {
60
85
SMap * self = malloc (sizeof (SMap));
61
SMapClass * klass = malloc (sizeof (SMapClass));
63
self->priv = malloc (sizeof (SMapPrivate));
66
klass->is_equal = comp_func;
88
self->is_equal = comp_func;
68
90
/* free_* functions need to be checked if they are null and set the pointer
69
91
* to free or s_base_object_free ()... Have to decide which...?
71
klass->free_key = free_key;
72
klass->free_value = free_value;
94
self->free_key = free_key;
96
self->free_key = FREEFUNC(free);
99
self->free_value = free_value;
101
self->free_value = FREEFUNC(free);
74
105
/* if no func is set we have to use some other metod of
76
107
if (key_hash_func == NULL){
77
klass->key_hash_func = s_hash_object;
108
self->key_hash_func = s_hash_object;
79
klass->key_hash_func = key_hash_func;
110
self->key_hash_func = key_hash_func;
82
113
/* We do our own freeing of objects. */
83
self->priv->array = s_dynamic_array_new (S_MAP_DEFAULT_NUMBER_OF_BUCKETS,
114
self->array = s_dynamic_array_new (S_MAP_DEFAULT_NUMBER_OF_BUCKETS,
90
121
s_map_free (SMap * self) {
122
s_dynamic_array_for_each (self->array,
123
FOREACHFUNC(_s_map_internal_free_array_for_each),
125
s_dynamic_array_free (self->array, FALSE);
100
130
s_map_add (SMap * self, spointer key, spointer value) {
101
SDynamicArray * array = self->priv->array;
131
SDynamicArray * array = self->array;
102
132
SMapItem * item = s_map_item_new (key, value);
104
134
/* We have to generate a key to use as an index in the DynamicArray. */
105
HashFunc hash_func = self->klass->key_hash_func;
135
HashFunc hash_func = self->key_hash_func;
106
136
hash_t hash = hash_func (key);
107
137
/* We need to mod it with the max size of the array. */
108
138
hash = hash % S_MAP_DEFAULT_NUMBER_OF_BUCKETS;
110
if (self->priv->len == 0) {
140
if (self->len == 0) {
111
141
/* Since we know that there are no items in the array we can skip the
112
142
* check if the new place is taken. and just and an array to it.
119
149
/* Figure out if the bucket exists. */
120
SDynamicArray * bucket = NULL;
121
if (s_dynamic_array_get (array, hash) == NULL) {
150
SDynamicArray * bucket = _s_map_internal_find_bucket (self, key);
152
if (bucket == NULL) {
122
153
bucket = s_dynamic_array_new (8, NULL);
124
/* We get the bucket */
125
bucket = S_DYNAMIC_ARRAY(s_dynamic_array_get (array, hash));
156
if (_s_map_internal_find_item_in_bucket (self, bucket, key)) {
157
s_warn_print ("Key already exists in SMap\n");
127
160
size_t bucket_len = s_dynamic_array_last_item (bucket);
128
161
s_dynamic_array_set (bucket, bucket_len, item);
133
166
s_map_get (SMap * self, spointer key) {
167
spointer ret_val = NULL;
169
SDynamicArray * bucket = _s_map_internal_find_bucket (self, key);
171
SMapItem * item = _s_map_internal_find_item_in_bucket (self, bucket, key);
173
ret_val = item->value;
181
s_map_remove (SMap * self, spointer key) {
182
SDynamicArray * bucket = _s_map_internal_find_bucket (self, key);
184
SMapItem * item = _s_map_internal_find_item_in_bucket (self, bucket, key);
186
s_map_item_free (item, self->free_key, self->free_value);
190
s_dbg_print ("Could not find item in SMap.\n");
194
_s_map_internal_find_bucket (SMap * self,
196
SDynamicArray * ret_val = NULL;
198
HashFunc hash_func = self->key_hash_func;
199
hash_t hash = hash_func (key);
201
ret_val = s_dynamic_array_get (self->array, hash);
207
_s_map_internal_find_item_in_bucket (SMap * self,
208
SDynamicArray * bucket,
211
for (size_t i = 0; i <= s_dynamic_array_last_item (bucket); i++) {
212
SMapItem * item = SMAPITEM (s_dynamic_array_get(bucket, i));
213
if (self->is_equal (item->key, key)) {
138
s_map_remove (SMap * self, spointer key) {
222
_s_map_internal_free_array_for_each (SDynamicArray * obj,
223
SDynamicArray * item,
225
s_dynamic_array_for_each (item,
226
FOREACHFUNC(_s_map_internal_free_bucket_for_each),
228
s_dynamic_array_free (item, FALSE);
232
_s_map_internal_free_bucket_for_each (SDynamicArray * obj,
235
s_map_item_free (item, self->free_key, self->free_value);