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