#include <stdlib.h>
#include <string.h>

#ifdef USE_NLLIBC
#include <nllibc.h>
#endif

#include "objlist.h"

/*****************************************************************
 * objentry_t
 */

objentry_t objentry_get_next(objentry_t entry)
{
  return entry->next;
}

objentry_t objentry_get_prev(objentry_t entry)
{
  return entry->prev;
}

void *objentry_get_obj(objentry_t entry)
{
  return entry->obj;
}

void *objentry_set_obj(objentry_t entry, void *obj)
{
  return entry->obj = obj;
}

void *objentry_set_free_func(objentry_t entry, objentry_free_func_t free_func)
{
  return entry->free_func = free_func;
}

int objentry_is_referenced(objentry_t entry)
{
  return (entry->ref_count > 0);
}

int objentry_get_ref_count(objentry_t entry)
{
  return entry->ref_count;
}

int objentry_clear_ref_count(objentry_t entry)
{
  return entry->ref_count = 0;
}

int objentry_up_ref_count(objentry_t entry)
{
  return ++(entry->ref_count);
}

int objentry_down_ref_count(objentry_t entry)
{
  return --(entry->ref_count);
}

void *objentry_extract_obj(objentry_t entry)
{
  void *obj;
  obj = objentry_get_obj(entry);
  objentry_set_obj(entry, NULL);
  objentry_set_free_func(entry, NULL);
  objentry_clear_ref_count(entry);
  return obj;
}

void *objentry_insert_obj(objentry_t entry,
			  void *obj, objentry_free_func_t free_func)
{
  objentry_set_obj(entry, obj);
  objentry_set_free_func(entry, free_func);
  objentry_clear_ref_count(entry);
  return obj;
}

objentry_t objentry_extract(objentry_t entry)
{
  entry->prev->next = entry->next;
  entry->next->prev = entry->prev;
  entry->prev = entry;
  entry->next = entry;
  return entry;
}

objentry_t objentry_insert_next(objentry_t to, objentry_t entry)
{
  entry->next = to->next;
  entry->prev = to;
  to->next->prev = entry;
  to->next = entry;
  return entry;
}

objentry_t objentry_insert_prev(objentry_t to, objentry_t entry)
{
  entry->prev = to->prev;
  entry->next = to;
  to->prev->next = entry;
  to->prev = entry;
  return entry;
}

objentry_t objentry_free(objentry_t entry)
{
  if (entry != NULL) {
    free(entry);
  }
  return NULL;
}

objentry_t objentry_done(objentry_t entry)
{
  objentry_free_func_t free_func;
  void *obj;

  if (entry != NULL) {
    if (objentry_is_referenced(entry)) {
      /* referenced */
    }
    free_func = entry->free_func;
    obj = entry->obj;
    memset(entry, 0, sizeof(*entry));
    if ((free_func != NULL) && (obj != NULL))
      free_func(obj);
    entry = NULL;
  }

  return entry;
}

objentry_t objentry_destroy(objentry_t entry)
{
  if (objentry_done(entry) != NULL) {
    /* fail to done */
  }
  entry = objentry_free(entry);
  if (entry != NULL) {
    /* fail to free */
    entry = NULL;
  }

  return entry;
}

objentry_t objentry_alloc(void)
{
  objentry_t entry;

  entry = malloc(sizeof(*entry));
  if (entry == NULL)
    return NULL;

  memset(entry, 0, sizeof(*entry));

  return entry;
}

objentry_t objentry_init(objentry_t entry, void *obj, unsigned int flags,
			 objentry_free_func_t free_func)
{
  entry->prev = entry;
  entry->next = entry;
  entry->obj = obj;
  entry->flags = flags;
  entry->free_func = free_func;
  entry->ref_count = 0;
  return entry;
}

objentry_t objentry_create(void *obj, objentry_free_func_t free_func)
{
  objentry_t entry;

  entry = objentry_alloc();
  if (entry == NULL)
    return NULL;

  if (objentry_init(entry, obj, OBJENTRY_FLAG_ALLOCED, free_func) == NULL) {
    entry = objentry_destroy(entry);
    if (entry != NULL) {
      /* fail to destroy */
      entry = NULL;
    }
  }

  return entry;
}

/*****************************************************************
 * objentrylist_t
 */

int objentrylist_get_count(objentrylist_t entrylist)
{
  return entrylist->count;
}

int objentrylist_clear_count(objentrylist_t entrylist)
{
  return entrylist->count = 0;
}

int objentrylist_up_count(objentrylist_t entrylist)
{
  return ++(entrylist->count);
}

int objentrylist_down_count(objentrylist_t entrylist)
{
  return --(entrylist->count);
}

objentry_t objentrylist_get_head(objentrylist_t entrylist)
{
  return entrylist->list.next;
}

objentry_t objentrylist_get_tail(objentrylist_t entrylist)
{
  return entrylist->list.prev;
}

int objentrylist_is_end(objentrylist_t entrylist, objentry_t entry)
{
  return (entry == &entrylist->list);
}

int objentrylist_is_head(objentrylist_t entrylist, objentry_t entry)
{
  return (entry == objentrylist_get_head(entrylist));
}

int objentrylist_is_tail(objentrylist_t entrylist, objentry_t entry)
{
  return (entry == objentrylist_get_tail(entrylist));
}

int objentrylist_is_empty(objentrylist_t entrylist)
{
  return objentrylist_is_end(entrylist, objentrylist_get_head(entrylist));
}

objentry_t objentrylist_extract(objentrylist_t entrylist, objentry_t entry)
{
  if (objentrylist_is_end(entrylist, entry))
    return NULL;
  objentrylist_down_count(entrylist);
  return objentry_extract(entry);
}

objentry_t objentrylist_extract_next(objentrylist_t entrylist, objentry_t from)
{
  return objentrylist_extract(entrylist, objentry_get_next(from));
}

objentry_t objentrylist_extract_prev(objentrylist_t entrylist, objentry_t from)
{
  return objentrylist_extract(entrylist, objentry_get_prev(from));
}

objentry_t objentrylist_extract_head(objentrylist_t entrylist)
{
  return objentrylist_extract(entrylist, objentrylist_get_head(entrylist));
}

objentry_t objentrylist_extract_tail(objentrylist_t entrylist)
{
  return objentrylist_extract(entrylist, objentrylist_get_tail(entrylist));
}

objentry_t objentrylist_insert_next(objentrylist_t entrylist,
				    objentry_t to, objentry_t entry)
{
  objentrylist_up_count(entrylist);
  return objentry_insert_next(to, entry);
}

objentry_t objentrylist_insert_prev(objentrylist_t entrylist,
				    objentry_t to, objentry_t entry)
{
  objentrylist_up_count(entrylist);
  return objentry_insert_prev(to, entry);
}

objentry_t objentrylist_insert_head(objentrylist_t entrylist, objentry_t entry)
{
  return objentrylist_insert_next(entrylist, &entrylist->list, entry);
}

objentry_t objentrylist_insert_tail(objentrylist_t entrylist, objentry_t entry)
{
  return objentrylist_insert_prev(entrylist, &entrylist->list, entry);
}

objentrylist_t objentrylist_free(objentrylist_t entrylist)
{
  if (entrylist != NULL) {
    free(entrylist);
  }
  return NULL;
}

objentrylist_t objentrylist_done(objentrylist_t entrylist)
{
  objentry_t entry;

  if (entrylist != NULL) {
    while ((entry = objentrylist_extract_head(entrylist)) != NULL) {
      if (entry->flags & OBJENTRY_FLAG_ALLOCED)
	objentry_destroy(entry);
      else
	objentry_done(entry);
    }
    if (objentry_done(&entrylist->list) != NULL) {
      /* fail to done */
    }
    memset(entrylist, 0, sizeof(*entrylist));
    entrylist = NULL;
  }

  return entrylist;
}

objentrylist_t objentrylist_destroy(objentrylist_t entrylist)
{
  if (objentrylist_done(entrylist) != NULL) {
    /* fail to done */
  }
  entrylist = objentrylist_free(entrylist);
  if (entrylist != NULL) {
    /* fail to free */
    entrylist = NULL;
  }

  return entrylist;
}

objentrylist_t objentrylist_alloc(void)
{
  objentrylist_t entrylist;

  entrylist = malloc(sizeof(*entrylist));
  if (entrylist == NULL)
    return NULL;

  memset(entrylist, 0, sizeof(*entrylist));

  return entrylist;
}

objentrylist_t objentrylist_init(objentrylist_t entrylist)
{
  if (objentry_init(&entrylist->list, NULL, 0, NULL) == NULL)
    return NULL;
  entrylist->count = 0;
  return entrylist;
}

objentrylist_t objentrylist_create(void)
{
  objentrylist_t entrylist;

  entrylist = objentrylist_alloc();
  if (entrylist == NULL)
    return NULL;

  if (objentrylist_init(entrylist) == NULL) {
    entrylist = objentrylist_destroy(entrylist);
    if (entrylist != NULL) {
      /* fail to destroy */
      entrylist = NULL;
    }
  }

  return entrylist;
}

/*****************************************************************
 * objlist_t (basic)
 */

int objlist_get_count(objlist_t list)
{
  return objentrylist_get_count(&list->entries);
}

int objlist_clear_count(objlist_t list)
{
  return objentrylist_clear_count(&list->entries);
}

int objlist_up_count(objlist_t list)
{
  return objentrylist_up_count(&list->entries);
}

int objlist_down_count(objlist_t list)
{
  return objentrylist_down_count(&list->entries);
}

objentry_t objlist_get_head(objlist_t list)
{
  return objentrylist_get_head(&list->entries);
}

objentry_t objlist_get_tail(objlist_t list)
{
  return objentrylist_get_tail(&list->entries);
}

int objlist_is_end(objlist_t list, objentry_t entry)
{
  return objentrylist_is_end(&list->entries, entry);
}

int objlist_is_head(objlist_t list, objentry_t entry)
{
  return objentrylist_is_head(&list->entries, entry);
}

int objlist_is_tail(objlist_t list, objentry_t entry)
{
  return objentrylist_is_tail(&list->entries, entry);
}

int objlist_is_empty(objlist_t list)
{
  return objentrylist_is_empty(&list->entries);
}

objentry_t objlist_extract(objlist_t list, objentry_t entry)
{
  if ((list->current != NULL) && (list->current == entry)) {
    if (!objlist_is_end(list, entry->prev))
      list->current = entry->prev;
    else if (!objlist_is_end(list, entry->next))
      list->current = entry->next;
    else
      list->current = NULL;
  }
  return objentrylist_extract(&list->entries, entry);
}

objentry_t objlist_extract_next(objlist_t list, objentry_t from)
{
  return objlist_extract(list, objentry_get_next(from));
}

objentry_t objlist_extract_prev(objlist_t list, objentry_t from)
{
  return objlist_extract(list, objentry_get_prev(from));
}

objentry_t objlist_extract_head(objlist_t list)
{
  return objlist_extract(list, objlist_get_head(list));
}

objentry_t objlist_extract_tail(objlist_t list)
{
  return objlist_extract(list, objlist_get_tail(list));
}

objentry_t objlist_insert_next(objlist_t list, objentry_t to, objentry_t entry)
{
  list->current = entry;
  return objentrylist_insert_next(&list->entries, to, entry);
}

objentry_t objlist_insert_prev(objlist_t list, objentry_t to, objentry_t entry)
{
  list->current = entry;
  return objentrylist_insert_prev(&list->entries, to, entry);
}

objentry_t objlist_insert_head(objlist_t list, objentry_t entry)
{
  return objlist_insert_next(list, &list->entries.list, entry);
}

objentry_t objlist_insert_tail(objlist_t list, objentry_t entry)
{
  return objlist_insert_prev(list, &list->entries.list, entry);
}

objlist_t objlist_free(objlist_t list)
{
  if (list != NULL) {
    free(list);
  }
  return NULL;
}

objlist_t objlist_done(objlist_t list)
{
  if (list != NULL) {
    if (objentrylist_done(&list->entries) != NULL) {
      /* fail to done */
    }
    if (objentrylist_done(&list->wait) != NULL) {
      /* fail to done */
    }
    if (objentrylist_done(&list->cache) != NULL) {
      /* fail to done */
    }

    objentry_set_free_func(&list->entry, NULL);
    if (objentry_done(&list->entry) != NULL) {
      /* fail to done */
    }

    memset(list, 0, sizeof(*list));
    list = NULL;
  }

  return list;
}

objlist_t objlist_destroy(objlist_t list)
{
  if (objlist_done(list) != NULL) {
    /* fail to done */
  }
  list = objlist_free(list);
  if (list != NULL) {
    /* fail to free */
    list = NULL;
  }

  return list;
}

static int default_sort_func(objentry_t entry0, objentry_t entry1)
{
  return (char *)entry0->obj - (char *)entry1->obj;
}

objlist_t objlist_alloc(void)
{
  objlist_t list = NULL;

  list = (objlist_t)malloc(sizeof(*list));
  if (list == NULL)
    return NULL;

  memset(list, 0, sizeof(*list));

  return list;
}

static void _objlist_free(void *p)
{
  objlist_destroy((objlist_t)p);
}

objlist_t objlist_init(objlist_t list, objentry_sort_func_t sort_func)
{
  if (sort_func == NULL)
    sort_func = default_sort_func;

  if (objentry_init(&list->entry, list, 0, _objlist_free) == NULL)
    return NULL;

  if (objentrylist_init(&list->entries) == NULL)
    return NULL;
  list->current = NULL;
  list->sort_func = sort_func;

  if (objentrylist_init(&list->wait) == NULL)
    return NULL;

  if (objentrylist_init(&list->cache) == NULL)
    return NULL;
  list->cache_maxcount = 64;

  return list;
}

objlist_t objlist_create(objentry_sort_func_t sort_func)
{
  objlist_t list = NULL;

  list = objlist_alloc();
  if (list == NULL)
    return NULL;

  if (objlist_init(list, sort_func) == NULL) {
    list = objlist_destroy(list);
    if (list != NULL) {
      /* fail to destroy */
      list = NULL;
    }
  }

  return list;
}

objentry_t objlist_create_entry(objlist_t list,
				void *obj, objentry_free_func_t free_func)
{
  objentry_t entry;

  entry = objentrylist_extract_head(&list->cache);
  if (entry == NULL)
    entry = objentry_alloc();
  if (entry == NULL)
    return NULL;

  if (objentry_init(entry, obj, OBJENTRY_FLAG_ALLOCED, free_func) == NULL) {
    objentrylist_insert_head(&list->cache, entry);
    return NULL;
  }

  return entry;
}

objentry_t objlist_destroy_entry(objlist_t list, objentry_t entry)
{
  objentry_t next;

  objentrylist_insert_tail(&list->wait, entry);

  for (entry = objentrylist_get_head(&list->wait);
       !objentrylist_is_end(&list->wait, entry);
       entry = next) {
    next = objentry_get_next(entry);

    if (!objentry_is_referenced(entry)) {
      entry = objentrylist_extract(&list->wait, entry);
      if (entry->flags & OBJENTRY_FLAG_ALLOCED) {
	if (objentrylist_get_count(&list->cache) < list->cache_maxcount) {
	  objentry_done(entry);
	  objentrylist_insert_head(&list->cache, entry);
	} else {
	  objentry_destroy(entry);
	}
      } else {
	objentry_done(entry);
      }
    }
  }

  return NULL;
}

/*****************************************************************
 * objlist_t (for obj)
 */

void *objlist_extract_obj(objlist_t list, objentry_t entry)
{
  void *obj = NULL;
  entry = objlist_extract(list, entry);
  if (entry != NULL) {
    obj = objentry_extract_obj(entry);
    objlist_destroy_entry(list, entry);
  }
  return obj;
}

void *objlist_extract_obj_next(objlist_t list, objentry_t from)
{
  return objlist_extract_obj(list, objentry_get_next(from));
}

void *objlist_extract_obj_prev(objlist_t list, objentry_t from)
{
  return objlist_extract_obj(list, objentry_get_prev(from));
}

void *objlist_extract_obj_head(objlist_t list)
{
  return objlist_extract_obj(list, objlist_get_head(list));
}

void *objlist_extract_obj_tail(objlist_t list)
{
  return objlist_extract_obj(list, objlist_get_tail(list));
}

objentry_t objlist_insert_obj_next(objlist_t list, objentry_t to,
				   void *obj, objentry_free_func_t free_func)
{
  objentry_t entry;
  entry = objlist_create_entry(list, obj, free_func);
  if (entry != NULL)
    entry = objlist_insert_next(list, to, entry);
  return entry;
}

objentry_t objlist_insert_obj_prev(objlist_t list, objentry_t to,
				   void *obj, objentry_free_func_t free_func)
{
  objentry_t entry;
  entry = objlist_create_entry(list, obj, free_func);
  if (entry != NULL)
    entry = objlist_insert_prev(list, to, entry);
  return entry;
}

objentry_t objlist_insert_obj_head(objlist_t list,
				   void *obj, objentry_free_func_t free_func)
{
  return objlist_insert_obj_next(list, &list->entries.list, obj, free_func);
}

objentry_t objlist_insert_obj_tail(objlist_t list,
				   void *obj, objentry_free_func_t free_func)
{
  return objlist_insert_obj_prev(list, &list->entries.list, obj, free_func);
}

/*****************************************************************
 * objlist_t (for sort)
 */

objentry_t objlist_insert_sort_to_tail(objlist_t list, objentry_t from,
				       objentry_t entry)
{
  for (; !objlist_is_end(list, from); from = from->next) {
    if (list->sort_func(entry, from) < 0)
      break;
  }
  return objlist_insert_prev(list, from, entry);
}

objentry_t objlist_insert_sort_to_head(objlist_t list, objentry_t from,
				       objentry_t entry)
{
  for (; !objlist_is_end(list, from); from = from->prev) {
    if (list->sort_func(entry, from) >= 0)
      break;
  }
  return objlist_insert_next(list, from, entry);
}

objentry_t objlist_insert_sort_from_head(objlist_t list, objentry_t entry)
{
  return objlist_insert_sort_to_tail(list, objlist_get_head(list), entry);
}

objentry_t objlist_insert_sort_from_tail(objlist_t list, objentry_t entry)
{
  return objlist_insert_sort_to_head(list, objlist_get_tail(list), entry);
}

objentry_t objlist_insert_sort(objlist_t list, objentry_t entry)
{
  objentry_t head, tail;

  head = objlist_get_head(list);
  tail = objlist_get_tail(list);

  if (objlist_is_end(list, head)) {
    return objlist_insert_sort_from_head(list, entry);
  } else if (list->sort_func(entry, head) <= 0) {
    return objlist_insert_sort_from_head(list, entry);
  } else if (list->sort_func(entry, tail) >= 0) {
    return objlist_insert_sort_from_tail(list, entry);
  } else {
    if (list->current) {
      if (list->sort_func(list->current, entry) <= 0) {
	head = list->current;
      } else {
	tail = list->current;
      }
      if (list->sort_func(entry, head) < list->sort_func(tail, entry)) {
	return objlist_insert_sort_to_tail(list, head, entry);
      } else {
	return objlist_insert_sort_to_head(list, tail, entry);
      }
    }
  }

  return objlist_insert_sort_from_head(list, entry);
}

/*****************************************************************
 * objlist_t (for search)
 */

objentry_t objlist_search_to_tail(objlist_t list, objentry_t from,
				  objentry_search_func_t search_func,
				  int arg, void *argp)
{
  for (; !objlist_is_end(list, from); from = from->next) {
    if (search_func(from, arg, argp))
      return from;
  }
  return NULL;
}

objentry_t objlist_search_to_head(objlist_t list, objentry_t from,
				  objentry_search_func_t search_func,
				  int arg, void *argp)
{
  for (; !objlist_is_end(list, from); from = from->prev) {
    if (search_func(from, arg, argp))
      return from;
  }
  return NULL;
}

objentry_t objlist_search_from_head(objlist_t list,
				    objentry_search_func_t search_func,
				    int arg, void *argp)
{
  return objlist_search_to_tail(list, objlist_get_head(list), search_func,
				arg, argp);
}

objentry_t objlist_search_from_tail(objlist_t list,
				    objentry_search_func_t search_func,
				    int arg, void *argp)
{
  return objlist_search_to_head(list, objlist_get_tail(list), search_func,
				arg, argp);
}

/*****************************************************************
 * objlist_t (for list)
 */

objlist_t objlist_extract_list(objlist_t list, objentry_t from, objentry_t to)
{
  objlist_t newlist;
  objentry_t entry, next;

  newlist = objlist_create(list->sort_func);
  if (newlist == NULL)
    return NULL;

  if (objlist_is_end(list, from) || objlist_is_end(list, to))
    return newlist;

  for (entry = from;; entry = next) {
    next = objentry_get_next(entry);
    entry = objlist_extract(list, entry);
    objlist_insert_tail(newlist, entry);
    if (entry == to)
      break;
  }

  return newlist;
}

objlist_t objlist_extract_list_next(objlist_t list, objentry_t from)
{
  return objlist_extract_list_tail(list, objentry_get_next(from));
}

objlist_t objlist_extract_list_prev(objlist_t list, objentry_t to)
{
  return objlist_extract_list_head(list, objentry_get_prev(to));
}

objlist_t objlist_extract_list_head(objlist_t list, objentry_t to)
{
  return objlist_extract_list(list, objlist_get_head(list), to);
}

objlist_t objlist_extract_list_tail(objlist_t list, objentry_t from)
{
  return objlist_extract_list(list, from, objlist_get_tail(list));
}

objlist_t objlist_extract_list_all(objlist_t list)
{
  return objlist_extract_list(list, objlist_get_head(list), objlist_get_tail(list));
}

objlist_t objlist_insert_list_next(objlist_t list, objentry_t to,
				   objlist_t insert)
{
  objentry_t entry, next;

  for (entry = objlist_get_head(insert);
       !objlist_is_end(insert, entry);
       entry = next) {
    next = objentry_get_next(entry);
    entry = objlist_extract(insert, entry);
    objlist_insert_next(list, to, entry);
    to = entry;
  }

  for (entry = objentrylist_get_head(&insert->wait);
       !objentrylist_is_end(&insert->wait, entry);
       entry = next) {
    next = objentry_get_next(entry);
    entry = objentrylist_extract(&insert->wait, entry);
    objentrylist_insert_tail(&list->wait, entry);
  }

  objlist_destroy(insert);

  return list;
}

objlist_t objlist_insert_list_prev(objlist_t list, objentry_t to,
				   objlist_t insert)
{
  objentry_t entry, prev, next;

  for (entry = objlist_get_tail(insert);
       !objlist_is_end(insert, entry);
       entry = prev) {
    prev = objentry_get_prev(entry);
    entry = objlist_extract(insert, entry);
    objlist_insert_prev(list, to, entry);
    to = entry;
  }

  for (entry = objentrylist_get_head(&insert->wait);
       !objentrylist_is_end(&insert->wait, entry);
       entry = next) {
    next = objentry_get_next(entry);
    entry = objentrylist_extract(&insert->wait, entry);
    objentrylist_insert_tail(&list->wait, entry);
  }

  objlist_destroy(insert);

  return list;
}

objlist_t objlist_insert_list_head(objlist_t list, objlist_t insert)
{
  return objlist_insert_list_next(list, &list->entries.list, insert);
}

objlist_t objlist_insert_list_tail(objlist_t list, objlist_t insert)
{
  return objlist_insert_list_prev(list, &list->entries.list, insert);
}

/*****************************************************************
 * objlist_t (for objlist)
 */

objlist_t objentry_get_objlist(objentry_t entry)
{
  return objentry_get_obj(entry);
}

objlist_t objlist_get_objlist_next(objlist_t list)
{
  return objentry_get_objlist(objentry_get_next(&list->entry));
}

objlist_t objlist_get_objlist_prev(objlist_t list)
{
  return objentry_get_objlist(objentry_get_prev(&list->entry));
}

objlist_t objlist_get_objlist_head(objlist_t list)
{
  return objentry_get_objlist(objlist_get_head(list));
}

objlist_t objlist_get_objlist_tail(objlist_t list)
{
  return objentry_get_objlist(objlist_get_tail(list));
}

int objlist_is_objlist_end(objlist_t list, objlist_t objlist)
{
  return objlist_is_end(list, &objlist->entry);
}

int objlist_is_objlist_head(objlist_t list, objlist_t objlist)
{
  return objlist_is_head(list, &objlist->entry);
}

int objlist_is_objlist_tail(objlist_t list, objlist_t objlist)
{
  return objlist_is_tail(list, &objlist->entry);
}

objlist_t objlist_extract_objlist(objlist_t list, objlist_t objlist)
{
  objentry_t entry;
  entry = objlist_extract(list, &objlist->entry);
  return (entry == NULL) ? NULL : objentry_get_objlist(entry);
}

objlist_t objlist_extract_objlist_next(objlist_t list, objlist_t from)
{
  objlist_t objlist;
  objlist = objlist_get_objlist_next(from);
  return (objlist == NULL) ? NULL : objlist_extract_objlist(list, objlist);
}

objlist_t objlist_extract_objlist_prev(objlist_t list, objlist_t from)
{
  objlist_t objlist;
  objlist = objlist_get_objlist_prev(from);
  return (objlist == NULL) ? NULL : objlist_extract_objlist(list, objlist);
}

objlist_t objlist_extract_objlist_head(objlist_t list)
{
  objlist_t objlist;
  objlist = objlist_get_objlist_head(list);
  return (objlist == NULL) ? NULL : objlist_extract_objlist(list, objlist);
}

objlist_t objlist_extract_objlist_tail(objlist_t list)
{
  objlist_t objlist;
  objlist = objlist_get_objlist_tail(list);
  return (objlist == NULL) ? NULL : objlist_extract_objlist(list, objlist);
}

objlist_t objlist_insert_objlist_next(objlist_t list, objlist_t to, objlist_t objlist)
{
  return objentry_get_objlist(objlist_insert_next(list, &to->entry, &objlist->entry));
}

objlist_t objlist_insert_objlist_prev(objlist_t list, objlist_t to, objlist_t objlist)
{
  return objentry_get_objlist(objlist_insert_prev(list, &to->entry, &objlist->entry));
}

objlist_t objlist_insert_objlist_head(objlist_t list, objlist_t objlist)
{
  return objentry_get_objlist(objlist_insert_head(list, &objlist->entry));
}

objlist_t objlist_insert_objlist_tail(objlist_t list, objlist_t objlist)
{
  return objentry_get_objlist(objlist_insert_tail(list, &objlist->entry));
}
