Linux C double linked for any data type

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

 

posted on 2015-12-25 21:28  zengjf  阅读(407)  评论(0编辑  收藏  举报

导航