Files
rosetta/sys/ld/image-list.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;
}
}