src/kv_list.c

changeset 1386
748d0d40881e
parent 1384
a2cfbff39e5d
equal deleted inserted replaced
1385:4ebb27ff6f76 1386:748d0d40881e
244 static void cx_kvl_reverse(struct cx_list_s *list) { 244 static void cx_kvl_reverse(struct cx_list_s *list) {
245 cx_kv_list *kv_list = (cx_kv_list*)list; 245 cx_kv_list *kv_list = (cx_kv_list*)list;
246 kv_list->list_methods->reverse(list); 246 kv_list->list_methods->reverse(list);
247 } 247 }
248 248
249 static void cx_kvl_list_iter_next(void *it) {
250 struct cx_iterator_s *iter = it;
251 if (iter->base.remove) {
252 // remove the assigned key from the map before calling the actual function
253 cx_kv_list *kv_list = iter->src_handle.m;
254 cx_kv_list_update_destructors(kv_list);
255 char *node = iter->elem_handle;
256 CxHashKey *key = cx_kv_list_loc_key(kv_list, node + kv_list->list.loc_data);
257 if (key->hash != 0) {
258 kv_list->map_methods->remove(&kv_list->map->map_base.base, *key, NULL);
259 }
260 }
261 iter->base.next_impl(it);
262 }
263
249 static struct cx_iterator_s cx_kvl_iterator( 264 static struct cx_iterator_s cx_kvl_iterator(
250 const struct cx_list_s *list, 265 const struct cx_list_s *list,
251 size_t index, 266 size_t index,
252 bool backward 267 bool backward
253 ) { 268 ) {
254 const cx_kv_list *kv_list = (const cx_kv_list*)list; 269 const cx_kv_list *kv_list = (const cx_kv_list*)list;
255 // TODO: cannot really forward, because mutating iterators must be able to remove the element 270 struct cx_iterator_s iter = kv_list->list_methods->iterator(list, index, backward);
256 return kv_list->list_methods->iterator(list, index, backward); 271 iter.base.next_impl = iter.base.next;
272 iter.base.next = cx_kvl_list_iter_next;
273 return iter;
257 } 274 }
258 275
259 static void cx_kvl_map_deallocate(struct cx_map_s *map) { 276 static void cx_kvl_map_deallocate(struct cx_map_s *map) {
260 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list; 277 cx_kv_list *kv_list = ((struct cx_kv_list_map_s*)map)->list;
261 kv_list->map_methods->deallocate(map); 278 kv_list->map_methods->deallocate(map);
377 next = *(char**)(next + kv_list->list.loc_next); 394 next = *(char**)(next + kv_list->list.loc_next);
378 if (next == NULL) break; 395 if (next == NULL) break;
379 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data); 396 key = cx_kv_list_loc_key(kv_list, next + kv_list->list.loc_data);
380 if (key->hash != 0) break; 397 if (key->hash != 0) break;
381 } 398 }
399
400 // remove previous element if requested
401 if (iter->base.remove) {
402 iter->base.remove = false;
403 cx_kv_list_update_destructors(kv_list);
404 char *elem = iter->elem;
405 char *elem_data = elem + kv_list->list.loc_data;
406 CxHashKey *elem_key = cx_kv_list_loc_key(kv_list, elem_data);
407 // key is guaranteed to exist because iterator only iterates over elems with a key
408 kv_list->map_methods->remove(&kv_list->map->map_base.base, *elem_key, NULL);
409 cx_invoke_advanced_destructor(&kv_list->list.base, elem_data);
410 cx_linked_list_remove(
411 &kv_list->list.begin,
412 &kv_list->list.end,
413 kv_list->list.loc_prev,
414 kv_list->list.loc_next,
415 elem
416 );
417 cxFree(kv_list->list.base.collection.allocator, elem);
418 kv_list->list.base.collection.size--;
419 iter->index--;
420 iter->elem_count--;
421 }
422
423 // advance to the next element, if any
382 if (next == NULL) { 424 if (next == NULL) {
383 iter->index = kv_list->list.base.collection.size; 425 iter->index = kv_list->list.base.collection.size;
384 iter->elem = NULL; 426 iter->elem = NULL;
385 iter->entry = (CxMapEntry){NULL, NULL}; 427 iter->entry = (CxMapEntry){NULL, NULL};
386 return; 428 return;
387 } 429 }
388
389 // TODO: implement removal
390
391 // advance to the next element
392 iter->index++; 430 iter->index++;
393 iter->elem = next; 431 iter->elem = next;
394 iter->entry.key = key; 432 iter->entry.key = key;
395 if (kv_list->list.base.collection.store_pointer) { 433 if (kv_list->list.base.collection.store_pointer) {
396 iter->entry.value = *(void**)(next + kv_list->list.loc_data); 434 iter->entry.value = *(void**)(next + kv_list->list.loc_data);

mercurial