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 }