Linux C single linked for any data type
/************************************************************************** * Linux C single linked for any data type * 声明: * 提供一种单链接口,可以保存保存任何类型的数据,有时候这种需求在 * 很多场合还是会用到的。 * * 2015-7-5 晴 深圳 南山平山村 曾剑锋 *************************************************************************/ \\\\\\\\\-*- 目录 -*-///////// | 一、cat single_linked.h | 二、cat myerror.h | 三、cat single_linked.c | 四、cat main.c \\\\\\\\\\\\\\\////////////// 一、cat single_linked.h #ifndef __SINGLE_LINKED_H__ #define __SINGLE_LINKED_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "myerror.h" typedef struct SINGLE_LINKED{ void* datap; int size; struct SINGLE_LINKED* next; } single_linked; typedef void (*single_linked_print)(void* data); typedef int (*single_linked_delete)(void* data, void* linked_delete); /** * you should giving a vilid data dan size for save */ int check_data_size(void *data, int size); /** * create a single linked header */ single_linked* create_single_linked(void* data, int size); /** * add data to single linked at top */ int top_add_single_linked(void* data, int size, single_linked* header); /** * add data to single linked at tail */ int tail_add_single_linked(void* data, int size, single_linked* header); /** * delete data in single linked */ int delete_single_linked(void* data, single_linked* header, single_linked_delete func); /** * print all data in single linked */ void print_single_linked(single_linked* header, single_linked_print func); /** * empty the single linked */ void empty_single_linked(single_linked* header); /** * free all data in single linked */ void free_single_linked(single_linked* header); #endif //__SINGLE_LINKED_H__ 二、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 single_linked.c #include "single_linked.h" /** * create a single linked as header */ single_linked* create_single_linked(void *data, int size){ single_linked* header = malloc(sizeof(single_linked)); ERR(1, NULL == header, goto err; "create single linked header fail.\n"); header->next = NULL; header->datap = NULL; header->size = 0; if(check_data_size(data,size)){ void* new_data = malloc(size); ERR(1, NULL == new_data, goto new_data_err; "create single linked header with data fail.\n"); memcpy(new_data, data, size); header->size = size; header->datap = new_data; } return header; new_data_err: free(header); err: return NULL; } int check_data_size(void* data, int size){ return ((data != NULL) && (size > 0)); } int top_add_single_linked(void* data, int size, single_linked* header){ ERR(1, NULL == header, return -1, "the header was NULL in top add single linked\n"); single_linked* new_node = NULL; if(check_data_size(data, size)){ single_linked* new_node = malloc(sizeof(single_linked)); ERR(1, NULL == new_node, goto err; "top add malloc node fail.\n"); new_node->next = NULL; new_node->datap = NULL; new_node->size = 0; void* new_data = malloc(size); ERR(1, NULL == new_data, goto err1; "top add malloc data fail.\n"); memcpy(new_data, data, size); new_node->size = size; new_node->datap = new_data; new_node->next = header->next; /** * I had pazzled at this point with (header->next = new_node->next) */ header->next = new_node; } return 0; err1: free(new_node); err: return -1; } /** * add data to single linked at tail */ int tail_add_single_linked(void* data, int size, single_linked* header){ ERR(1, NULL == header, return -1, "the header was NULL in tail add single linked\n"); single_linked* new_node = NULL; if(check_data_size(data, size)){ single_linked* new_node = malloc(sizeof(single_linked)); ERR(1, NULL == new_node, goto err; "top add malloc node fail.\n"); new_node->next = NULL; new_node->datap = NULL; new_node->size = 0; void* new_data = malloc(size); ERR(1, NULL == new_data, goto err1; "top add malloc data fail.\n"); memcpy(new_data, data, size); new_node->size = size; new_node->datap = new_data; //new_node->next = header->next; while(header->next) header = header->next; /** * I had pazzled at this point with (header->next = new_node->next) */ header->next = new_node; } return 0; err1: free(new_node); err: return -1; } /** * delete data in single linked */ int delete_single_linked(void* data, single_linked* header, single_linked_delete func){ ERR(1, ((NULL == data) || (NULL == header) || (NULL == func)), return; "you shouldn't giving NULL for delete single linkde\n"); single_linked* tmp = header->next; single_linked* pre = header; while(tmp){ /** * you should giving a return value to decision delete this or not */ if(func(data, tmp->datap)){ pre->next = tmp->next; tmp->next = NULL; free(tmp->datap); free(tmp); tmp = pre->next; }else{ pre = tmp; tmp = tmp->next; } } return 0; } /** * print all data in single linked */ void print_single_linked(single_linked* header, single_linked_print func){ ERR(1, ((NULL == header) || (NULL == func)), return; "you shouldn't giving NULL for print single linkde\n"); single_linked* tmp = header->next; while(tmp){ func(tmp); tmp = tmp->next; } } /** * free all data in single linked */ void free_single_linked(single_linked* header){ ERR(1, NULL == header, return; "free a header with NULL\n"); single_linked* tmp = header->next; single_linked* pre = header->next; while(tmp){ pre = tmp; tmp = tmp->next; free(pre->datap); free(pre); } if(header->datap != NULL){ free(header->datap); header->datap = NULL; } header->next = NULL; free(header); header == NULL; } void empty_single_linked(single_linked* header){ ERR(1, NULL == header, return, "empty header was NULL\n"); single_linked* tmp = header->next; single_linked* pre = header->next; while(tmp){ pre = tmp; tmp = tmp->next; free(pre->datap); free(pre); } if(header->datap != NULL){ free(header->datap); header->datap = NULL; } header->next = NULL; header->size = 0; } 四、cat main.c #include "single_linked.h" #define NR(x) ((sizeof(x))/sizeof(x[0])) /** * test struct */ typedef struct STUDENT{ int id; int score; }student; /** * callback function */ void print(void* data); int delete(void* data, void* linked_data); int main(int argc, char** argv){ /** * demo data */ student students[4] = { {1,1}, {2,2}, {2,2}, {3,3}, }; single_linked* header = create_single_linked(NULL, 0); int i = 0; printf("--------------source------------------>\n"); for(i = 0; i < NR(students); i++){ printf("student: id = %d, score = %d \n", students[i].id, students[i].score); } printf("--------------tail add---------------->\n"); for(i = 0; i < NR(students); i++){ //top_add_single_linked(&students[i], sizeof(student), header); tail_add_single_linked(&students[i], sizeof(student), header); } print_single_linked(header, print); empty_single_linked(header); printf("--------------top add---------------->\n"); for(i = 0; i < NR(students); i++){ //top_add_single_linked(&students[i], sizeof(student), header); top_add_single_linked(&students[i], sizeof(student), header); } print_single_linked(header, print); printf("--------------delete---------------->\n"); student stu = {2,2}; delete_single_linked(&stu, header, delete); print_single_linked(header, print); printf("---------------free----------------->\n"); free_single_linked(header); } void print(void* data){ student* stu = (((single_linked*)data)->datap); printf("student: id = %d, score = %d \n", stu->id, stu->score); } int delete(void* data, void* linked_data){ return (((student*)data)->id == ((student*)linked_data)->id) && (((student*)data)->score == ((student*)linked_data)->score); }