list.h
struct node_info {
struct node_info *prev;
struct node_info *next;
char priv[];
};
struct list_info {
struct node_info *head;
void (*add)(struct list_info *,
const void *data_entry,
size_t data_size);
void (*add_tail)(struct list_info *,
const void *data_entry,
size_t data_size);
void (*del)(struct list_info *,
struct node_info *,
size_t data_size);
};
#define list_for_each(cur, head) \
for (cur = (head)->next; \
(cur) != (head); \
cur = (cur)->next)
#define list_for_each_safe(cur, tmp, head) \
for (cur = (head)->next, tmp = (cur)->next; \
(cur) != (head); \
cur = tmp, tmp = (tmp)->next)
#define ENTRY(node, type) ((type*)(node->priv))
void list_init(struct list_info*);
void list_destroy(struct list_info*);
list.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
static void __list_add(struct node_info *prev,
struct node_info *next,
const void *data_entry, size_t data_size)
{
struct node_info *node = (struct node_info *)malloc(sizeof(struct node_info) + data_size);
memcpy(node->priv, data_entry, data_size);
node->prev = prev;
node->next = next;
prev->next = node;
next->prev = node;
}
static void list_add(struct list_info *info,
const void *data_entry, size_t data_size)
{
__list_add(info->head, info->head->next,
data_entry, data_size);
}
static void list_add_tail(struct list_info *info,
const void *data_entry, size_t data_size)
{
__list_add(info->head->prev, info->head,
data_entry, data_size);
}
static void list_del(struct list_info *info,
struct node_info *node,
size_t data_size)
{
node->prev->next = node->next;
node->next->prev = node->prev;
node->prev = node;
node->next = node;
if (data_size) {
memset(node->priv, 0, data_size);
}
free(node);
}
void list_init(struct list_info *info)
{
info->head = (struct node_info *)malloc(sizeof(struct node_info));
info->head->prev = info->head;
info->head->next = info->head;
info->add = list_add;
info->add_tail = list_add_tail;
info->del = list_del;
}
void list_destroy(struct list_info *info)
{
struct node_info *cur = info->head->next;
for (; cur != info->head; cur = info->head->next) {
list_del(info, cur, 0);
}
free(info->head);
}
main.c
#include <stdio.h>
#include "list.h"
struct data {
const char *name;
size_t age;
};
int main()
{
struct list_info list;
list_init(&list);
const char *s[] = {
"jackee",
"johny",
"kate",
"mary",
"mary",
"mike",
};
struct data data_tmp = {0};
size_t i = 0;
for (i = 0; i < sizeof(s) / sizeof(char*); i++) {
data_tmp.name = s[i];
data_tmp.age = 20 + i;
list.add_tail(&list, &data_tmp, sizeof(data_tmp));
}
struct node_info *cur = NULL;
struct node_info *tmp = NULL;
list_for_each_safe(cur, tmp, list.head) {
if (!strcmp(ENTRY(cur, struct data)->name, "mary")) {
list.del(&list, cur, sizeof(struct data));
/* break;*/
}
list_for_each(cur, list.head) {
printf("%s: %ld\n", ENTRY(cur, struct data)->name, ENTRY(cur, struct data)->age);
}
list_destroy(&list);
return 0;
}