view List.c @ 2:803d6bf22e6d default tip

second commit. it's far to complete..
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Dec 2009 16:19:56 +0900
parents aef83aed7a07
children
line wrap: on
line source

#include<stdlib.h>
/* TODO: malloc.  */
#include"List.h"

/*
 *  doubly-linked list.
 *  interfaces of these routines is based on glib.
 *
 *  Usage:
 *  create new list.
 *  	list = NULL
 *  add new data
 *  	list = _listAddFirst(list, data)
 *  remove data from the list
 *  	list = _listRemove(list, data)
 *  get n-th data
 *  	data = _listGetnthData(list, n)
 *
 *
 *  NOTE:
 *  Although `struct List' is a doubly-linked List, the List
 *  is made as a Ring.  An User's variable is treated as a
 *  head of the list.  And head->prev is last.  And then if
 *  list have only one data, both next and prev field of
 *  head will point to oneself.
 *  If the variable is NULL, it means no data.
 */

List *
_listAddFirst(List* top, void *data)
{
	List *newlist;
	List *last;
	newlist = malloc(sizeof(struct _List));
	newlist->data = data;

	if (!top) {
		newlist->next = newlist;
		newlist->prev = newlist;
		return newlist;
	}
	last = top->prev;
	newlist->next = top;
	newlist->prev = last;

	top->prev = newlist;
	last->next = newlist;
	return newlist;
}

List *
_listRemove(List *top, void *data)
{
	List *t;
	if (top->data==data) {
		if (top->next==top) {
			free(top);
			return NULL;
		}
		List *newtop = top->next;
		top->next->prev = top->prev;
		top->prev->next = top->next;
		free(top);
		return newtop;
	}
	for (t=top->next; t!=top; t=t->next) {
		if (t->data==data) {
			t->next->prev = t->prev;
			t->prev->next = t->next;
			free(t);
			return top;
		}
	}
	return top;
}

void *
_listGetnthData(List *top, int n)
{
	List *t;

	for (t=top; n>0; n--) {
		t = t->next;
		if (t==top) return NULL;
	}

	return t->data;
}
void *
_listGetLastData(List *top)
{
	if (!top) return NULL;
	return top->prev->data;
}

List *
_listMoveLasttoFirst(List *top)
{
	if (!top) return NULL;
	return top->prev;
}

void
_listApply(List *top, ApplyFn fn, void *arg)
{
	List *t = top;
	do {
		fn(t->data, arg);
		t = t->next;
	} while ( t!=top );
}

/*
 *  Iterator's functions.
 *
 *  iter = _listIterator(list);
 *  while ( (data=_listIterNext(iter)!=NULL ) {
 *  	exe(data);
 *  	if (data...) {
 *  		list = _listIterRemove(iter);
 *  	}
 *  }
 */
ListIter *
_listIterator(List *top)
{
	ListIter *iter;
	iter = malloc(sizeof(struct _ListIter));
	iter->head = top;
	iter->next = top;
	return iter;
}

void *
_listIterNext(ListIter *iter)
{
	void *rtn;
	if (!iter->next) return NULL;

	rtn = iter->next->data;
	iter->next = iter->next->next;
	if (iter->next==iter->head) {
		iter->next = NULL;
	}
	return rtn;
}

void
_listIterEnd(ListIter *iter)
{
	free(iter);
}

List *
_listIterRemoveCurrent(ListIter *iter)
{
	List *cur, *p, *n;
	if (!iter->head) return NULL;
	else if (!iter->next) cur = iter->head->prev;
	else cur = iter->next->prev;

	if (cur==iter->head) {
		if (cur->next==iter->head) {
			free(iter->head);
			return NULL;
		}
		iter->head = iter->head->next;
	}
	cur->prev->next = cur->next;
	cur->next->prev = cur->prev;

	free(cur);
	return iter->head;
}


/*
 *  for DEBUG
 */

int
_listRingCheck(List *head)
{
	List *cur = head;

	if (cur->prev->next!=cur) return 0;
	if (cur->next->prev!=cur) return 0;
	do {
		if (cur->prev->next!=cur) return 0;
		if (cur->next->prev!=cur) return 0;
		cur = cur->prev;
	} while (cur!=head);

	if (cur->prev->next!=cur) return 0;
	if (cur->next->prev!=cur) return 0;
	cur = cur->next;
	if (cur->prev->next!=cur) return 0;
	if (cur->next->prev!=cur) return 0;

	return 1;
}