#ifndef __NLSYS_OBJLIST_H_INCLUDED__
#define __NLSYS_OBJLIST_H_INCLUDED__

typedef struct objentry *objentry_t;
typedef struct objentrylist *objentrylist_t;
typedef struct objlist *objlist_t;

typedef void (*objentry_free_func_t)(void *obj);
typedef int (*objentry_sort_func_t)(objentry_t entry0, objentry_t entry1);
typedef int (*objentry_search_func_t)(objentry_t entry, int arg, void *argp);

struct objentry {
  objentry_t next;
  objentry_t prev;
  void *obj;
  objentry_free_func_t free_func;
  int ref_count;
#define OBJENTRY_FLAG_ALLOCED (1 <<  0)
  unsigned int flags;
};

struct objentrylist {
  struct objentry list;
  int count;
};

struct objlist {
  struct objentry entry;
  struct objentrylist entries;
  objentry_t current;
  objentry_sort_func_t sort_func;

  struct objentrylist wait;

  struct objentrylist cache;
  int cache_maxcount;
};

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

objentry_t objentry_get_next(objentry_t entry);
objentry_t objentry_get_prev(objentry_t entry);
void *objentry_get_obj(objentry_t entry);
void *objentry_set_obj(objentry_t entry, void *obj);
void *objentry_set_free_func(objentry_t entry, objentry_free_func_t free_func);
int objentry_is_referenced(objentry_t entry);
int objentry_get_ref_count(objentry_t entry);
int objentry_clear_ref_count(objentry_t entry);
int objentry_up_ref_count(objentry_t entry);
int objentry_down_ref_count(objentry_t entry);
void *objentry_extract_obj(objentry_t entry);
void *objentry_insert_obj(objentry_t entry,
			  void *obj, objentry_free_func_t free_func);
objentry_t objentry_extract(objentry_t entry);
objentry_t objentry_insert_next(objentry_t to, objentry_t entry);
objentry_t objentry_insert_prev(objentry_t to, objentry_t entry);
objentry_t objentry_free(objentry_t entry);
objentry_t objentry_done(objentry_t entry);
objentry_t objentry_destroy(objentry_t entry);
objentry_t objentry_alloc(void);
objentry_t objentry_init(objentry_t entry, void *obj, unsigned int flags,
			 objentry_free_func_t free_func);
objentry_t objentry_create(void *obj, objentry_free_func_t free_func);

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

int objentrylist_get_count(objentrylist_t entrylist);
int objentrylist_clear_count(objentrylist_t entrylist);
int objentrylist_up_count(objentrylist_t entrylist);
int objentrylist_down_count(objentrylist_t entrylist);
objentry_t objentrylist_get_head(objentrylist_t entrylist);
objentry_t objentrylist_get_tail(objentrylist_t entrylist);
int objentrylist_is_end(objentrylist_t entrylist, objentry_t entry);
int objentrylist_is_head(objentrylist_t entrylist, objentry_t entry);
int objentrylist_is_tail(objentrylist_t entrylist, objentry_t entry);
int objentrylist_is_empty(objentrylist_t entrylist);
objentry_t objentrylist_extract(objentrylist_t entrylist, objentry_t entry);
objentry_t objentrylist_extract_next(objentrylist_t entrylist, objentry_t from);
objentry_t objentrylist_extract_prev(objentrylist_t entrylist, objentry_t from);
objentry_t objentrylist_extract_head(objentrylist_t entrylist);
objentry_t objentrylist_extract_tail(objentrylist_t entrylist);
objentry_t objentrylist_insert_next(objentrylist_t entrylist,
				    objentry_t to, objentry_t entry);
objentry_t objentrylist_insert_prev(objentrylist_t entrylist,
				    objentry_t to, objentry_t entry);
objentry_t objentrylist_insert_head(objentrylist_t entrylist, objentry_t entry);
objentry_t objentrylist_insert_tail(objentrylist_t entrylist, objentry_t entry);
objentrylist_t objentrylist_free(objentrylist_t entrylist);
objentrylist_t objentrylist_done(objentrylist_t entrylist);
objentrylist_t objentrylist_destroy(objentrylist_t entrylist);
objentrylist_t objentrylist_alloc(void);
objentrylist_t objentrylist_init(objentrylist_t entrylist);
objentrylist_t objentrylist_create(void);

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

int objlist_get_count(objlist_t list);
int objlist_clear_count(objlist_t list);
int objlist_up_count(objlist_t list);
int objlist_down_count(objlist_t list);
objentry_t objlist_get_head(objlist_t list);
objentry_t objlist_get_tail(objlist_t list);
int objlist_is_end(objlist_t list, objentry_t entry);
int objlist_is_head(objlist_t list, objentry_t entry);
int objlist_is_tail(objlist_t list, objentry_t entry);
int objlist_is_empty(objlist_t list);
objentry_t objlist_extract(objlist_t list, objentry_t entry);
objentry_t objlist_extract_next(objlist_t list, objentry_t from);
objentry_t objlist_extract_prev(objlist_t list, objentry_t from);
objentry_t objlist_extract_head(objlist_t list);
objentry_t objlist_extract_tail(objlist_t list);
objentry_t objlist_insert_next(objlist_t list, objentry_t to, objentry_t entry);
objentry_t objlist_insert_prev(objlist_t list, objentry_t to, objentry_t entry);
objentry_t objlist_insert_head(objlist_t list, objentry_t entry);
objentry_t objlist_insert_tail(objlist_t list, objentry_t entry);
objlist_t objlist_free(objlist_t list);
objlist_t objlist_done(objlist_t list);
objlist_t objlist_destroy(objlist_t list);
objlist_t objlist_alloc(void);
objlist_t objlist_init(objlist_t list, objentry_sort_func_t sort_func);
objlist_t objlist_create(objentry_sort_func_t sort_func);
objentry_t objlist_create_entry(objlist_t list,
				void *obj, objentry_free_func_t free_func);
objentry_t objlist_destroy_entry(objlist_t list, objentry_t entry);

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

void *objlist_extract_obj(objlist_t list, objentry_t entry);
void *objlist_extract_obj_next(objlist_t list, objentry_t from);
void *objlist_extract_obj_prev(objlist_t list, objentry_t from);
void *objlist_extract_obj_head(objlist_t list);
void *objlist_extract_obj_tail(objlist_t list);
objentry_t objlist_insert_obj_next(objlist_t list, objentry_t to,
				   void *obj, objentry_free_func_t free_func);
objentry_t objlist_insert_obj_prev(objlist_t list, objentry_t to,
				   void *obj, objentry_free_func_t free_func);
objentry_t objlist_insert_obj_head(objlist_t list,
				   void *obj, objentry_free_func_t free_func);
objentry_t objlist_insert_obj_tail(objlist_t list,
				   void *obj, objentry_free_func_t free_func);

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

objentry_t objlist_insert_sort_to_tail(objlist_t list, objentry_t from,
				       objentry_t entry);
objentry_t objlist_insert_sort_to_head(objlist_t list, objentry_t from,
				       objentry_t entry);
objentry_t objlist_insert_sort_from_head(objlist_t list, objentry_t entry);
objentry_t objlist_insert_sort_from_tail(objlist_t list, objentry_t entry);
objentry_t objlist_insert_sort(objlist_t list, objentry_t 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);
objentry_t objlist_search_to_head(objlist_t list, objentry_t from,
				  objentry_search_func_t search_func,
				  int arg, void *argp);
objentry_t objlist_search_from_head(objlist_t list,
				    objentry_search_func_t search_func,
				    int arg, void *argp);
objentry_t objlist_search_from_tail(objlist_t list,
				    objentry_search_func_t search_func,
				    int arg, void *argp);

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

objlist_t objlist_extract_list(objlist_t list, objentry_t from, objentry_t to);
objlist_t objlist_extract_list_next(objlist_t list, objentry_t from);
objlist_t objlist_extract_list_prev(objlist_t list, objentry_t to);
objlist_t objlist_extract_list_head(objlist_t list, objentry_t to);
objlist_t objlist_extract_list_tail(objlist_t list, objentry_t from);
objlist_t objlist_extract_list_all(objlist_t list);
objlist_t objlist_insert_list_next(objlist_t list, objentry_t to,
				   objlist_t insert);
objlist_t objlist_insert_list_prev(objlist_t list, objentry_t to,
				   objlist_t insert);
objlist_t objlist_insert_list_head(objlist_t list, objlist_t insert);
objlist_t objlist_insert_list_tail(objlist_t list, objlist_t insert);

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

objlist_t objentry_get_objlist(objentry_t entry);
objlist_t objlist_get_objlist_next(objlist_t list);
objlist_t objlist_get_objlist_prev(objlist_t list);
objlist_t objlist_get_objlist_head(objlist_t list);
objlist_t objlist_get_objlist_tail(objlist_t list);
int objlist_is_objlist_end(objlist_t list, objlist_t objlist);
int objlist_is_objlist_head(objlist_t list, objlist_t objlist);
int objlist_is_objlist_tail(objlist_t list, objlist_t objlist);
objlist_t objlist_extract_objlist(objlist_t list, objlist_t objlist);
objlist_t objlist_extract_objlist_next(objlist_t list, objlist_t from);
objlist_t objlist_extract_objlist_prev(objlist_t list, objlist_t from);
objlist_t objlist_extract_objlist_head(objlist_t list);
objlist_t objlist_extract_objlist_tail(objlist_t list);
objlist_t objlist_insert_objlist_next(objlist_t list, objlist_t to, objlist_t objlist);
objlist_t objlist_insert_objlist_prev(objlist_t list, objlist_t to, objlist_t objlist);
objlist_t objlist_insert_objlist_head(objlist_t list, objlist_t objlist);
objlist_t objlist_insert_objlist_tail(objlist_t list, objlist_t objlist);

#endif
