// GList.h
#ifndef GLIST_H_INCLUDED
#define GLIST_H_INCLUDED
#ifdef _cplusplus
extern "C" {
#endif
typedef struct _GList GList;
struct _GList
{
void* data;
GList *next;
GList *prev;
};
typedef void (*GFunc)(void* data, void* user_data);
typedef void (*GDestroyNodify)(void* data);
typedef int (*GCompareFunc)(void* a, void* b);
GList* g_list_alloc(void);
void g_list_free(GList *list);
void g_list_free_full(GList *list, GDestroyNodify free_func);
GList* g_list_append(GList *list, void* data);
GList* g_list_prepend(GList *list, void* data);
GList* g_list_insert(GList *list, void* data, int position);
GList* g_list_remove(GList *list, const void* data);
GList* g_list_find(GList *list, const void* data);
int g_list_index(GList *list, const void* data);
GList* g_list_nth(GList *list, unsigned int n);
void g_list_foreach(GList *list, GFunc func, void* user_data);
GList* g_list_first(GList *list);
GList* g_list_last(GList *list);
unsigned int g_list_length(GList *list);
GList* g_list_copy(GList *list);
#ifdef _cplusplus
}
#endif
#endif // GLIST_H_INCLUDED
// GList.c
#include "GList.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
GList* g_list_alloc(void)
{
GList *list = (GList*)malloc(sizeof(GList));
if (list)
{
memset(list, 0, sizeof(GList));
}
return list;
}
void g_list_free(GList *list)
{
if (list)
{
free(list);
list = NULL;
}
}
void g_list_free_full(GList *list, GDestroyNodify free_func)
{
g_list_foreach(list, (GFunc)free_func, NULL);
g_list_free(list);
}
// Adds a new element on to the end of the list.
GList* g_list_append(GList *list, void* data)
{
GList *new_list;
GList *last;
new_list = g_list_alloc();
new_list->data = data;
new_list->next = NULL;
if (list)
{
last = g_list_last(list);
last->next = new_list;
new_list->prev = last;
return list;
}
else
{
new_list->prev = NULL;
return new_list;
}
}
// Adds a new element on to the start of the list.
GList* g_list_prepend(GList *list, void* data)
{
GList *new_list;
new_list = g_list_alloc();
new_list->data = data;
new_list->next = list;
if (list)
{
new_list->prev = list->prev;
if (list->prev)
{
list->prev->next = new_list;
}
list->prev = new_list;
}
else
{
new_list->prev = NULL;
}
return new_list;
}
GList* g_list_insert(GList *list, void* data, int position)
{
GList *new_list;
GList *tmp_list;
if (position < 0)
{
return g_list_append(list, data);
}
else if (position == 0)
{
return g_list_prepend(list, data);
}
tmp_list = g_list_nth(list, position);
if (!tmp_list)
{
g_list_append(list, data);
}
new_list = g_list_alloc();
new_list->data = data;
new_list->prev = tmp_list->prev;
if (tmp_list->prev)
{
tmp_list->prev->next = new_list;
}
new_list->next = tmp_list;
tmp_list->prev = new_list;
if (tmp_list == list)
{
return new_list;
}
else
{
return list;
}
}
GList* g_list_remove(GList *list, const void* data)
{
GList *tmp;
tmp = list;
while (tmp)
{
if (tmp->data != data)
{
tmp = tmp->next;
}
else
{
if (tmp->prev)
{
tmp->prev->next = tmp->next;
}
if (tmp->next)
{
tmp->next->prev = tmp->prev;
}
if (list == tmp)
{
list = list->next;
}
g_list_free(tmp);
break;
}
}
return list;
}
GList* g_list_find(GList *list, const void* data)
{
while (list)
{
if (list->data == data)
{
break;
}
list = list->next;
}
return list;
}
int g_list_index(GList *list, const void* data)
{
int i = 0;
while (list)
{
if (list->data == data)
{
return i;
}
i++;
list = list->next;
}
return -1;
}
GList* g_list_nth(GList *list, unsigned int n)
{
while ((n-- > 0) && list)
{
list = list->next;
}
return list;
}
void g_list_foreach(GList *list, GFunc func, void* user_data)
{
while (list)
{
GList *next = list->next;
(*func)(list->data, user_data);
list = next; // list = list->next;
}
}
GList* g_list_first(GList *list)
{
if (list)
{
while (list->prev)
{
list = list->prev;
}
}
return list;
}
GList* g_list_last(GList *list)
{
if (list)
{
while (list->next)
{
list = list->next;
}
}
return list;
}
unsigned int g_list_length(GList *list)
{
unsigned int length = 0;
while (list)
{
length++;
list = list->next;
}
return length;
}
GList* g_list_copy(GList *list)
{
GList *new_list = NULL;
if (list)
{
GList *last;
new_list = g_list_alloc();
new_list->data = list->data;
new_list->prev = NULL;
last = new_list;
list = list->next;
while (list)
{
last->next = g_list_alloc();
last->next->prev = last;
last = last->next;
last->data = list->data;
list = list->next;
}
last->next = NULL;
}
return new_list;
}
// main.c
#include <stdio.h>
#include <stdlib.h>
#include "GList.h"
void ShowList(void* data, void* user_data);
/// test
int main()
{
GList *list = NULL;
list = g_list_append(list, "one");
list = g_list_append(list, "two");
list = g_list_append(list, "three");
list = g_list_prepend(list, "four");
list = g_list_insert(list, "five", 3);
GList *first = g_list_first(list);
g_list_foreach(first, ShowList, NULL);
int num = g_list_length(first);
printf("num = %d\n", num);
GList *last = g_list_last(list);
printf("last = %s\n", (char*)last->data);
printf("---------------copy---------------\n");
first = g_list_first(list);
GList *cpy = g_list_copy(first);
g_list_foreach(cpy, ShowList, NULL);
return 0;
}
void ShowList(void* data, void* user_data)
{
printf("%s\n", (char*)data);
}