212 lines
4.3 KiB
C
212 lines
4.3 KiB
C
#include "image-list.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include <mango/log.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|
|
}
|