#include "image-list.h" #include "hash.h" #include #include #include #include static BTREE_DEFINE_SIMPLE_GET( struct image_list_entry, uint64_t, e_node, e_hash, get_entry); static BTREE_DEFINE_SIMPLE_INSERT( struct image_list_entry, e_node, e_hash, put_entry); void image_list_init(struct image_list *list) { memset(list, 0x0, sizeof *list); } void image_list_cleanup(struct image_list *list) { } extern struct image_list_bucket *convert_to_bucket( struct btree *tree, struct image_list_leaf *leaf) { btree_delete(tree, &leaf->l_base.e_node); struct image_list_bucket *bucket = malloc(sizeof *bucket); if (!bucket) { return NULL; } bucket->b_base.e_hash = leaf->l_base.e_hash; bucket->b_base.e_type = IMAGE_LIST_ENTRY_BUCKET; put_entry(tree, &bucket->b_base); queue_push_back(&bucket->b_items, &leaf->l_base.e_entry); return bucket; } extern void image_list_put( struct image_list *list, struct image_list_leaf *item) { uint64_t hash = hash_string(item->l_name); item->l_base.e_type = IMAGE_LIST_ENTRY_LEAF; item->l_base.e_hash = hash; struct image_list_entry *entry = get_entry(&list->l_items, hash); if (!entry) { put_entry(&list->l_items, &item->l_base); return; } if (entry->e_type == IMAGE_LIST_ENTRY_BUCKET) { struct image_list_bucket *bucket = (struct image_list_bucket *)entry; queue_push_back(&bucket->b_items, &item->l_base.e_entry); return; } struct image_list_leaf *leaf = (struct image_list_leaf *)entry; struct image_list_bucket *bucket = convert_to_bucket(&list->l_items, leaf); if (!bucket) { return; } queue_push_back(&bucket->b_items, &item->l_base.e_entry); } extern struct image_list_leaf *image_list_get( struct image_list *list, const char *name) { uint64_t hash = hash_string(name); struct image_list_entry *entry = get_entry(&list->l_items, hash); if (!entry) { return NULL; } switch (entry->e_type) { case IMAGE_LIST_ENTRY_LEAF: { struct image_list_leaf *leaf = (struct image_list_leaf *)entry; if (!strcmp(leaf->l_name, name)) { return leaf; } break; } case IMAGE_LIST_ENTRY_BUCKET: { struct image_list_bucket *bucket = (struct image_list_bucket *)entry; struct queue_entry *cur = queue_first(&bucket->b_items); while (cur) { struct image_list_leaf *leaf = QUEUE_CONTAINER( struct image_list_leaf, l_base.e_entry, cur); if (!strcmp(leaf->l_name, name)) { return leaf; } cur = queue_next(cur); break; } } default: break; } return NULL; } void image_list_iterator_begin( struct image_list_iterator *it, struct image_list *list) { memset(it, 0x0, sizeof *it); struct btree_node *node = btree_first(&list->l_items); if (!node) { return; } while (1) { it->it_cur = QUEUE_CONTAINER( struct image_list_entry, e_node, node); if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) { it->it_leaf = (struct image_list_leaf *)it->it_cur; return; } struct image_list_bucket *bucket = (struct image_list_bucket *)it->it_cur; struct queue_entry *entry = queue_first(&bucket->b_items); if (!entry) { node = btree_next(node); continue; } it->it_leaf = QUEUE_CONTAINER( struct image_list_leaf, l_base.e_entry, entry); break; } } void image_list_iterator_move_next(struct image_list_iterator *it) { if (!it->it_cur || !it->it_leaf) { return; } while (1) { if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) { /* current entry is a leaf */ struct queue_entry *next = queue_next(&it->it_leaf->l_base.e_entry); if (next) { it->it_leaf = QUEUE_CONTAINER( struct image_list_leaf, l_base.e_entry, next); } } struct btree_node *node = btree_next(&it->it_cur->e_node); if (!node) { it->it_cur = NULL; it->it_leaf = NULL; return; } it->it_cur = BTREE_CONTAINER( struct image_list_entry, e_node, node); if (it->it_cur->e_type == IMAGE_LIST_ENTRY_LEAF) { /* next entry is a leaf */ it->it_leaf = (struct image_list_leaf *)it->it_cur; return; } struct image_list_bucket *bucket = (struct image_list_bucket *)it->it_cur; struct queue_entry *entry = queue_first(&bucket->b_items); if (!entry) { continue; } it->it_leaf = QUEUE_CONTAINER( struct image_list_leaf, l_base.e_entry, entry); break; } }