/**************************************************************************
* Linux C double linked for any data type
* 声明:
* 提供一种双链接口,可以保存保存任何类型的数据。
*
* 2015-12-25 晴 深圳 南山平山村 曾剑锋
*************************************************************************/
\\\\\\\\-*- 目录 -*-////////
| 一、cat double_linked.h
| 二、cat myerror.h
| 三、cat doulbe_linked.c
| 四、cat main.c
---------------------------
一、cat double_linked.h
#ifndef __DOUBLE_LINK_H__
#define __DOUBLE_LINK_H__
#include <stdio.h>
#include <stdlib.h>
#include "myerror.h"
#include <string.h>
typedef struct DOUBLE_LINKED{
void* datap;
int size;
struct DOUBLE_LINKED* pre;
struct DOUBLE_LINKED* next;
} double_linked;
typedef void(*double_linked_print)(double_linked* data);
typedef int(*double_linked_delete)(void* data, double_linked* linked_data);
void init_double_linked_node(double_linked* node);
int check_data_size(void* data, int size);
void empty_double_linked(double_linked* header);
void _delete_double_linked_node(double_linked* pre, double_linked* next);
void delete_double_linked_node(double_linked* node);
/**
* create a double linked for user
*/
double_linked* create_double_linked(void* data, int size);
void _add_double_linked(double_linked* current, double_linked* pre, double_linked* next);
/**
* top add doulbe linked
*/
int top_add_double_linked(void* data, int size, double_linked* header);
/**
* tail add double linked
*/
int tail_add_double_linked(void* data, int size, double_linked* header);
/**
* print all data in double linked
*/
void print_double_linked(double_linked* header, double_linked_print func);
/**
* empty all data in double linked
*/
void empty_double_linked(double_linked* header);
/**
* delete a element in the double linked
*/
void delete_double_linked(void* data, double_linked* header, double_linked_delete func);
/**
* free all data in the double linked
*/
void free_double_linked(double_linked* header);
#endif
二、cat myerror.h
#ifndef _MYERROR_H
#define _MYERROR_H
//serial error 1
// error 2
// warning 3
// information 4
#define DEBUG1(...) fprintf(stderr,"SERI ERR: " __VA_ARGS__);
#define DEBUG2(...) fprintf(stderr,"ERR: " __VA_ARGS__);
#define DEBUG3(...) fprintf(stdout,"WARNING: " __VA_ARGS__);
#define DEBUG4(...) fprintf(stdout,"INFORMATION: " __VA_ARGS__);
#define DEBUG() fprintf(stdout,"\033[32mbug at func( %s ) : %d\033[0m\n", __func__, __LINE__);
#define ERR(lever ,con, ret , ...) \
do \
{ \
if(con) \
{ \
DEBUG##lever(__VA_ARGS__) \
ret; \
} \
}while(0)
#endif //_MYERROR_H
三、cat doulbe_linked.c
#include "double_linked.h"
void init_double_linked_node(double_linked* node){
node->next = node;
node->pre = node;
node->datap = NULL;
node->size = 0;
}
int check_data_size(void* data, int size){
return ((data != NULL) && (size > 0));
}
/**
* create a double linked for user
*/
double_linked* create_double_linked(void* data, int size){
double_linked* header = malloc(sizeof(double_linked));
ERR(1, NULL == header, goto err, "create double linked fail\n");
init_double_linked_node(header);
if(check_data_size(data, size)){
void* new_data = malloc(size);
ERR(1, NULL == new_data, goto err, "create double linked data fail\n");
memcpy(new_data, data, size);
header->size = size;
header->datap = new_data;
}
return header;
err:
return NULL;
}
void _add_double_linked(double_linked* current, double_linked* pre, double_linked* next){
pre->next = current;
current->next = next;
next->pre = current;
current->pre = pre;
}
/**
* top add doulbe linked
*/
int top_add_double_linked(void* data, int size, double_linked* header){
if(check_data_size(data, size)){
double_linked* node = malloc(sizeof(double_linked));
ERR(1, NULL == header, goto err, "create note fail.\n");
init_double_linked_node(node);
void* new_data = malloc(size);
ERR(1, NULL == new_data, goto err, "create note data fail.\n");
memcpy(new_data, data, size);
node->size = size;
node->datap = new_data;
_add_double_linked(node, header, header->next);
return 0;
}
err:
return -1;
}
/**
* tail add double linked
*/
int tail_add_double_linked(void* data, int size, double_linked* header){
if(check_data_size(data, size)){
double_linked* node = malloc(sizeof(double_linked));
ERR(1, NULL == header, goto err, "create note fail.\n");
init_double_linked_node(node);
void* new_data = malloc(size);
ERR(1, NULL == new_data, goto err, "create note data fail.\n");
memcpy(new_data, data, size);
node->size = size;
node->datap = new_data;
_add_double_linked(node, header->pre, header);
return 0;
}
err:
return -1;
}
/**
* print all data in double linked
*/
void print_double_linked(double_linked* header, double_linked_print func){
double_linked* tmp = header->next;
while(tmp != header){
func(tmp);
tmp = tmp->next;
}
}
void _delete_double_linked_node(double_linked* pre, double_linked* next){
pre->next = next;
next->pre = pre;
}
void delete_double_linked_node(double_linked* node){
_delete_double_linked_node(node->pre, node->next);
if(node->datap){
free(node->datap);
}
init_double_linked_node(node);
free(node);
}
/**
* empty all data in double linked
*/
void empty_double_linked(double_linked* header){
double_linked* tmp = header->next;
double_linked* pre = header;
while(tmp != header){
pre = tmp;
tmp = tmp->next;
delete_double_linked_node(pre);
}
init_double_linked_node(header);
if(header->datap)
free(header->datap);
header->datap = NULL;
header->size = 0;
}
/**
* delete a element in the double linked
*/
void delete_double_linked(void* data, double_linked* header, double_linked_delete func){
double_linked* tmp = header->next;
double_linked* pre = header;
while(tmp != header){
pre = tmp;
tmp = tmp->next;
if(func(data, pre)){
delete_double_linked_node(pre);
}
}
}
void free_double_linked(double_linked* header){
double_linked* tmp = header->next;
double_linked* pre = header;
while(tmp != header){
pre = tmp;
tmp = tmp->next;
delete_double_linked_node(pre);
}
init_double_linked_node(header);
if(header->datap)
free(header->datap);
header->datap = NULL;
header->size = 0;
free(header);
}
四、cat main.c
#include "double_linked.h"
#define NR(x) ((sizeof(x))/sizeof(x[0]))
/**
* test struct
*/
typedef struct STUDENT{
int id;
int score;
}student;
/**
* callback function
*/
void print(double_linked* node);
int delete(void* data, double_linked* node);
int main(int argc, char** argv){
/**
* demo data
*/
student students[4] = {
{1,1},
{2,2},
{2,2},
{3,3},
};
double_linked* header = create_double_linked(NULL, 0);
printf("--------------source--------------->\n");
int i = 0;
for(i = 0; i < NR(students); i++){
printf("student: id = %d, score = %d\n", students[i].id, students[i].score);
}
printf("------------top add--------------->\n");
for(i = 0; i < NR(students); i++){
top_add_double_linked(&students[i],sizeof(student), header);
}
print_double_linked(header, print);
empty_double_linked(header);
printf("-----------tail add-------------->\n");
for(i = 0; i < NR(students); i++){
tail_add_double_linked(&students[i],sizeof(student), header);
}
print_double_linked(header, print);
printf("-----------delete-------------->\n");
student stu = {2,2};
delete_double_linked(&stu, header, delete);
print_double_linked(header, print);
printf("-------------free-------------->\n");
free_double_linked(header);
}
/**
* impelement of the client print
*/
void print(double_linked* node){
student* stu = (student*)(node->datap);
printf("student: id = %d, score = %d\n", stu->id, stu->score);
}
/**
* impelement of the client delete
*/
int delete(void* data, double_linked* node){
student* stu = (student*)(node->datap);
return (((student*)data)->id == stu->id) && (((student*)data)->score == stu->score);
}