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