00001
00002 #include <microfeed/microfeedstore.h>
00003 #include <microfeed/microfeedmisc.h>
00004
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <stdio.h>
00008
00009 #define DELTA 10
00010
00011 struct _MicrofeedStore {
00012 void** data;
00013 unsigned int size;
00014 unsigned int reserved;
00015 MicrofeedStoreCompareKeysFunction compare_keys;
00016 MicrofeedStoreGetKeyFunction get_key;
00017 MicrofeedStoreIterator* iterators;
00018 int unsorted;
00019 };
00020
00021 struct _MicrofeedStoreIterator {
00022 MicrofeedStoreIterator* previous;
00023 MicrofeedStoreIterator* next;
00024
00025 MicrofeedStore* store;
00026 unsigned int index;
00027 };
00028
00029 static int get_index(MicrofeedStore* store, const void* key, unsigned int* index);
00030
00031 MicrofeedStore* microfeed_store_new_sorted(MicrofeedStoreCompareKeysFunction compare_keys, MicrofeedStoreGetKeyFunction get_key) {
00032 MicrofeedStore* store;
00033
00034 store = microfeed_memory_allocate(MicrofeedStore);
00035 store->compare_keys = compare_keys;
00036 store->get_key = get_key;
00037
00038 return store;
00039 }
00040
00041 MicrofeedStore* microfeed_store_new_unsorted(MicrofeedStoreCompareKeysFunction compare_keys, MicrofeedStoreGetKeyFunction get_key) {
00042 MicrofeedStore* store;
00043
00044 store = microfeed_store_new_sorted(compare_keys, get_key);
00045 store->unsorted = 1;
00046
00047 return store;
00048 }
00049
00050 void microfeed_store_free(MicrofeedStore* store) {
00051 MicrofeedStoreIterator* iterator;
00052
00053 for (iterator = store->iterators; iterator; iterator = iterator->next) {
00054 iterator->store = NULL;
00055 }
00056 free(store->data);
00057 store->data = NULL;
00058 store->iterators = NULL;
00059 store->size = store->reserved = 0;
00060 free(store);
00061 }
00062
00063 void microfeed_store_foreach(MicrofeedStore* store, MicrofeedStoreForeachFunction foreach, void* user_data) {
00064 int i;
00065
00066 for (i = 0; i < store->size; i++) {
00067 foreach(store->data[i], user_data);
00068 }
00069 }
00070
00071 void* microfeed_store_get_impl(MicrofeedStore* store, const void* key) {
00072 void* data = NULL;
00073 unsigned int index;
00074
00075 if (get_index(store, key, &index)) {
00076 data = store->data[index];
00077 }
00078
00079 return data;
00080 }
00081
00082 void* microfeed_store_get_index_impl(MicrofeedStore* store, unsigned int index) {
00083 void* data = NULL;
00084
00085 if (index < store->size) {
00086 data = store->data[index];
00087 }
00088
00089 return data;
00090 }
00091
00092 unsigned int microfeed_store_get_size(MicrofeedStore* store) {
00093 return store->size;
00094 }
00095
00096 void microfeed_store_insert(MicrofeedStore* store, void* data) {
00097 unsigned int index;
00098
00099 if (!get_index(store, store->get_key(data), &index)) {
00100 if (store->size == store->reserved) {
00101 store->reserved += DELTA;
00102 store->data = realloc(store->data, store->reserved * sizeof(void*));
00103 }
00104
00105 if (index < store->size) {
00106 memmove(store->data + index + 1, store->data + index,
00107 (store->size - index) * sizeof(void*));
00108 }
00109 store->size++;
00110 store->data[index] = data;
00111 }
00112 }
00113
00114 void* microfeed_store_replace(MicrofeedStore* store, void* data) {
00115 unsigned int index;
00116 void* existing;
00117
00118 if (get_index(store, store->get_key(data), &index)) {
00119 existing = store->data[index];
00120 } else {
00121 existing = NULL;
00122 if (store->size == store->reserved) {
00123 store->reserved += DELTA;
00124 store->data = realloc(store->data, store->reserved * sizeof(void*));
00125 }
00126
00127 if (index < store->size) {
00128 memmove(store->data + index + 1, store->data + index,
00129 (store->size - index) * sizeof(void*));
00130 }
00131 store->size++;
00132 }
00133 store->data[index] = data;
00134
00135 return existing;
00136 }
00137
00138 int microfeed_store_remove(MicrofeedStore* store, const void* data) {
00139 int retvalue = 0;
00140 unsigned int index;
00141
00142 if (get_index(store, store->get_key(data), &index)) {
00143 if (index + 1 < store->size) {
00144 memmove(store->data + index, store->data + index + 1,
00145 (store->size - index - 1) * sizeof(void*));
00146 }
00147
00148 store->size--;
00149 if (store->size + 2 * DELTA == store->reserved) {
00150 store->reserved -= DELTA;
00151 store->data = realloc(store->data, store->reserved * sizeof(void*));
00152 }
00153
00154 retvalue = 1;
00155 }
00156
00157 return retvalue;
00158 }
00159
00160 void* microfeed_store_remove_key_impl(MicrofeedStore* store, const void* key) {
00161 void* data = NULL;
00162 unsigned int index;
00163
00164 if (get_index(store, key, &index)) {
00165 data = store->data[index];
00166 if (index + 1 < store->size) {
00167 memmove(store->data + index, store->data + index + 1,
00168 (store->size - index - 1) * sizeof(void*));
00169 }
00170
00171 store->size--;
00172 if (store->size + 2 * DELTA == store->reserved) {
00173 store->reserved -= DELTA;
00174 store->data = realloc(store->data, store->reserved * sizeof(void*));
00175 }
00176 }
00177
00178 return data;
00179 }
00180
00181 void* microfeed_store_remove_index_impl(MicrofeedStore* store, unsigned int index) {
00182 void* data = NULL;
00183
00184 if (index < store->size) {
00185 data = store->data[index];
00186 if (index + 1 < store->size) {
00187 memmove(store->data + index, store->data + index + 1,
00188 (store->size - index - 1) * sizeof(void*));
00189 }
00190
00191 store->size--;
00192 if (store->size + 2 * DELTA == store->reserved) {
00193 store->reserved -= DELTA;
00194 store->data = realloc(store->data, store->reserved * sizeof(void*));
00195 }
00196 }
00197
00198 return data;
00199 }
00200
00201 MicrofeedStoreIterator* microfeed_store_iterate(MicrofeedStore* store, const void* start_key) {
00202 MicrofeedStoreIterator* iterator;
00203 unsigned int index;
00204
00205 iterator = microfeed_memory_allocate(MicrofeedStoreIterator);
00206 iterator->store = store;
00207 if (start_key) {
00208 if (get_index(store, start_key, &index)) {
00209 iterator->index = index;
00210 } else {
00211 iterator->index = store->size;
00212 }
00213 } else {
00214 iterator->index = 0;
00215 }
00216 if (store->iterators) {
00217 store->iterators->previous = iterator;
00218 iterator->next = store->iterators;
00219 } else {
00220 iterator->next = NULL;
00221 }
00222 iterator->previous = NULL;
00223 store->iterators = iterator;
00224
00225 return iterator;
00226 }
00227
00228 int microfeed_store_compare_keys_direct(const void* key1, const void* key2) {
00229
00230 return (key1 == key2 ? 0 : (key1 < key2 ? -1 : 1));
00231 }
00232
00233 const void* microfeed_store_get_key_direct(const void* data) {
00234
00235 return data;
00236 }
00237
00238
00239 void microfeed_store_iterator_free(MicrofeedStoreIterator* iterator) {
00240 if (iterator->next) {
00241 iterator->next->previous = iterator->previous;
00242 }
00243 if (iterator->previous) {
00244 iterator->previous->next = iterator->next;
00245 } else if (iterator->store) {
00246 iterator->store->iterators = iterator->next;
00247 }
00248
00249 iterator->store = NULL;
00250 microfeed_memory_free(iterator);
00251 }
00252
00253 void* microfeed_store_iterator_get_impl(MicrofeedStoreIterator* iterator) {
00254 void* data = NULL;
00255
00256 if (iterator->store && iterator->index < iterator->store->size) {
00257 data = iterator->store->data[iterator->index];
00258 }
00259
00260 return data;
00261 }
00262
00263 void microfeed_store_iterator_next(MicrofeedStoreIterator* iterator) {
00264 if (iterator->store && iterator->index < iterator->store->size) {
00265 iterator->index++;
00266 }
00267 }
00268
00269 static int get_index(MicrofeedStore* store, const void* key, unsigned int* index) {
00270 int retval = 0;
00271 int result;
00272 unsigned int i, min, max;
00273
00274 if (store->unsorted) {
00275 *index = store->size;
00276 for (i = 0; i < store->size; i++) {
00277 if (store->compare_keys(key, store->get_key(store->data[i])) == 0) {
00278 *index = i;
00279 retval = 1;
00280 }
00281 }
00282 } else {
00283 if (store->size == 0) {
00284 *index = 0;
00285 } else if ((result = store->compare_keys(key, store->get_key(store->data[0]))) == 0) {
00286 *index = 0;
00287 retval = 1;
00288 } else if (result < 0) {
00289 *index = 0;
00290 } else if (store->size == 1) {
00291 *index = 1;
00292 } else if ((result = store->compare_keys(key, store->get_key(store->data[store->size - 1]))) == 0) {
00293 *index = store->size -1;
00294 retval = 1;
00295 } else if (result > 0) {
00296 *index = store->size;
00297 } else if (store->size == 2) {
00298 *index = store->size - 1;
00299 } else {
00300 min = i = 0;
00301 max = store->size - 1;
00302
00303 while (min <= max) {
00304 i = (min + max) / 2;
00305 if ((result = store->compare_keys(key, store->get_key(store->data[i]))) == 0) {
00306 retval = 1;
00307 break;
00308 } else if (result < 0) {
00309 max = i - 1;
00310 } else {
00311 i++;
00312 min = i;
00313 }
00314 }
00315
00316 *index = i;
00317 }
00318 }
00319
00320 return retval;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364