/************************************************************************** * 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); }