#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <topo_error.h>
#include <topo_list.h>
#include <topo_tree.h>
void
topo_list_append(topo_list_t *lp, void *new)
{
topo_list_t *p = lp->l_prev;
topo_list_t *q = new;
lp->l_prev = q;
q->l_prev = p;
q->l_next = NULL;
if (p != NULL) {
assert(p->l_next == NULL);
p->l_next = q;
} else {
assert(lp->l_next == NULL);
lp->l_next = q;
}
}
void
topo_list_prepend(topo_list_t *lp, void *new)
{
topo_list_t *p = new;
topo_list_t *q = lp->l_next;
lp->l_next = p;
p->l_prev = NULL;
p->l_next = q;
if (q != NULL) {
assert(q->l_prev == NULL);
q->l_prev = p;
} else {
assert(lp->l_prev == NULL);
lp->l_prev = p;
}
}
void
topo_list_insert_before(topo_list_t *lp, void *before_me, void *new)
{
topo_list_t *p = before_me;
topo_list_t *q = new;
if (p == NULL || p->l_prev == NULL) {
topo_list_prepend(lp, new);
return;
}
q->l_prev = p->l_prev;
q->l_next = p;
p->l_prev = q;
q->l_prev->l_next = q;
}
void
topo_list_insert_after(topo_list_t *lp, void *after_me, void *new)
{
topo_list_t *p = after_me;
topo_list_t *q = new;
if (p == NULL || p->l_next == NULL) {
topo_list_append(lp, new);
return;
}
q->l_next = p->l_next;
q->l_prev = p;
p->l_next = q;
q->l_next->l_prev = q;
}
void
topo_list_delete(topo_list_t *lp, void *existing)
{
topo_list_t *p = existing;
if (p->l_prev != NULL)
p->l_prev->l_next = p->l_next;
else
lp->l_next = p->l_next;
if (p->l_next != NULL)
p->l_next->l_prev = p->l_prev;
else
lp->l_prev = p->l_prev;
}
tnode_t *
topo_child_first(tnode_t *pnode)
{
int i;
topo_nodehash_t *nhp;
for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL;
nhp = topo_list_next(nhp)) {
for (i = 0; i < nhp->th_arrlen; ++i) {
if (nhp->th_nodearr[i] != NULL)
return (nhp->th_nodearr[i]);
}
}
return (NULL);
}
tnode_t *
topo_child_next(tnode_t *pnode, tnode_t *node)
{
int i;
int index;
topo_nodehash_t *nhp;
if (node == NULL) {
return (topo_child_first(pnode));
}
index = topo_node_hash(node->tn_phash, node->tn_instance) + 1;
for (nhp = node->tn_phash; nhp != NULL; nhp = topo_list_next(nhp)) {
for (i = index; i < nhp->th_arrlen; ++i) {
if (nhp->th_nodearr[i] != NULL) {
return (nhp->th_nodearr[i]);
}
}
index = 0;
}
return (NULL);
}
int
topo_list_deepcopy(topo_hdl_t *thp, topo_list_t *dest, topo_list_t *src,
size_t elem_sz)
{
void *elem;
if (topo_list_next(dest) != NULL)
return (topo_hdl_seterrno(thp, ETOPO_UNKNOWN));
for (elem = topo_list_next(src); elem != NULL;
elem = topo_list_next(elem)) {
void *elem_copy;
if ((elem_copy = topo_hdl_alloc(thp, elem_sz)) == NULL) {
goto err;
}
(void) memcpy(elem_copy, elem, elem_sz);
topo_list_append(dest, elem_copy);
}
return (0);
err:
elem = topo_list_next(dest);
while (elem != NULL) {
void *tmp = elem;
elem = topo_list_next(elem);
topo_list_delete(dest, tmp);
topo_hdl_free(thp, tmp, elem_sz);
}
return (topo_hdl_seterrno(thp, ETOPO_NOMEM));
}