lvgl中的链表测试

16 篇文章 1 订阅
4 篇文章 1 订阅

测试代码

#include "lv_ll.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct _lv_task_t
{

    int user_data; /**< Custom user data */
} lv_task_t;

lv_ll_t ll_ori_p;

int main()
{
    lv_ll_init(&ll_ori_p, sizeof(lv_task_t)); //初始化新链表

    lv_task_t *n_act = NULL; //定义节点指针,用于操作节点。

    lv_task_t *n_after = NULL; //定义节点指针,用于操作节点。

    lv_task_t *tr; //定义节点指针,用于遍历链表时操作节点。

    lv_ll_ins_head(&ll_ori_p); //链表添加新的头节点,返回指向新头的指针

    LL_READ(ll_ori_p, tr) //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }

    printf("%s %d\n", __FUNCTION__, __LINE__);

    n_act = lv_ll_ins_tail(&ll_ori_p); //链表尾加新节点,返回指向新节点的指针。

    n_act->user_data = 1; //当前节点上加数据1。

    n_act = lv_ll_ins_prev(&ll_ori_p, n_act); //从指定链表,指定位置前加一个节点,返回指向新节点的指针。

    n_act->user_data = 2; //当前节点上加数据2。

    LL_READ(ll_ori_p, tr) //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }

    printf("%s %d\n", __FUNCTION__, __LINE__);

    LL_READ_BACK(ll_ori_p, tr) //从尾遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }

    printf("%s %d\n", __FUNCTION__, __LINE__);

    n_act = lv_ll_get_head(&ll_ori_p); //拿到链表头指针。

    n_act->user_data = 3; //节点数据值设置为3。

    LL_READ(ll_ori_p, tr) //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }

    n_act = lv_ll_get_next(&ll_ori_p, n_act);                       //从指定链表,指定位置获取下一个节点。
    printf("%s %d %d\n", __FUNCTION__, __LINE__, n_act->user_data); //打印当前节点数据。

    n_after = lv_ll_get_prev(&ll_ori_p, n_act);
    printf("%s %d %d\n", __FUNCTION__, __LINE__, n_after->user_data); //打印当前节点数据。

    // 在同一个链表中,将一个节点移动到另一个节点之前
    lv_ll_move_before(&ll_ori_p, n_act, n_after);
    LL_READ(ll_ori_p, tr) //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }
    printf("%s %d\n", __FUNCTION__, __LINE__);

    lv_ll_rem(&ll_ori_p, n_act);              // 将节点'node_p'从'n_act'链表中删除。它不会释放节点的内存。
    LL_READ(ll_ori_p, tr)                     //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }
    printf("%s %d\n", __FUNCTION__, __LINE__);

    // 将节点移动到一个新的链表
    lv_ll_t ll_new_p;
    lv_ll_init(&ll_new_p, sizeof(lv_task_t));

    lv_ll_chg_list(&ll_ori_p, &ll_new_p, n_act);
    LL_READ(ll_new_p, tr) //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }
    printf("%s %d\n", __FUNCTION__, __LINE__);

    lv_ll_clear(&ll_ori_p); //移除并释放链表中的所有元素。该列表仍然有效,但变为空。
    LL_READ(ll_ori_p, tr)   //从头遍历链表宏。
    {
        printf("%d\n", tr->user_data); //打印当前节点数据。
    }

    return 0;
}

源代码.c

/**
 * @file lv_ll.c
 * Handle linked lists.
 * The nodes are dynamically allocated by the 'lv_mem' module,
 */

/*********************
 *      INCLUDES
 *********************/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "lv_ll.h"

/*********************
 *      DEFINES
 *********************/
#define LL_NODE_META_SIZE (sizeof(lv_ll_node_t*) + sizeof(lv_ll_node_t*))
#define LL_PREV_P_OFFSET(ll_p) (ll_p->n_size)
#define LL_NEXT_P_OFFSET(ll_p) (ll_p->n_size + sizeof(lv_ll_node_t*))

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * prev);
static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * next);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

/**
 * Initialize linked list
 * @param ll_dsc pointer to ll_dsc variable
 * @param node_size the size of 1 node in bytes
 */
void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size)
{
    ll_p->head = NULL;
    ll_p->tail = NULL;
#ifdef LV_MEM_ENV64
    /*Round the size up to 8*/
    if(node_size & 0x7) {
        node_size = node_size & (~0x7);
        node_size += 8;
    }
#else
    /*Round the size up to 4*/
    if(node_size & 0x3) {
        node_size = node_size & (~0x3);
        node_size += 4;
    }
#endif

    ll_p->n_size = node_size;
}

/**
 * Add a new head to a linked list
 * @param ll_p pointer to linked list
 * @return pointer to the new head
 */
void * lv_ll_ins_head(lv_ll_t * ll_p)
{
    lv_ll_node_t * n_new;

    n_new = malloc(ll_p->n_size + LL_NODE_META_SIZE);

    if(n_new != NULL) {
        node_set_prev(ll_p, n_new, NULL);           /*No prev. before the new head*/
        node_set_next(ll_p, n_new, ll_p->head);     /*After new comes the old head*/

        if(ll_p->head != NULL) { /*If there is old head then before it goes the new*/
            node_set_prev(ll_p, ll_p->head, n_new);
        }

        ll_p->head = n_new;         /*Set the new head in the dsc.*/
        if(ll_p->tail == NULL) {/*If there is no tail (1. node) set the tail too*/
            ll_p->tail = n_new;
        }
    }

    return n_new;
}

/**
 * Insert a new node in front of the n_act node
 * @param ll_p pointer to linked list
 * @param n_act pointer a node
 * @return pointer to the new head
 */
void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
{
    lv_ll_node_t * n_new;
    lv_ll_node_t * n_prev;

    if(NULL == ll_p || NULL == n_act) return NULL;

    if(lv_ll_get_head(ll_p) == n_act) {
        n_new = lv_ll_ins_head(ll_p);
        if(n_new == NULL) return NULL;
    } else {
        n_new = malloc(ll_p->n_size + LL_NODE_META_SIZE);
        if(n_new == NULL) return NULL;

        n_prev = lv_ll_get_prev(ll_p, n_act);
        node_set_next(ll_p, n_prev, n_new);
        node_set_prev(ll_p, n_new, n_prev);
        node_set_prev(ll_p, n_act, n_new);
        node_set_next(ll_p, n_new, n_act);
    }

    return n_new;
}

/**
 * Add a new tail to a linked list
 * @param ll_p pointer to linked list
 * @return pointer to the new tail
 */
void * lv_ll_ins_tail(lv_ll_t * ll_p)
{
    lv_ll_node_t * n_new;

    n_new = malloc(ll_p->n_size + LL_NODE_META_SIZE);
    if(n_new == NULL) return NULL;

    if(n_new != NULL) {
        node_set_next(ll_p, n_new, NULL); /*No next after the new tail*/
        node_set_prev(ll_p, n_new, ll_p->tail); /*The prev. before new is tho old tail*/
        if(ll_p->tail != NULL) {    /*If there is old tail then the new comes after it*/
            node_set_next(ll_p, ll_p->tail, n_new);
        }

        ll_p->tail = n_new;      /*Set the new tail in the dsc.*/
        if(ll_p->head == NULL) { /*If there is no head (1. node) set the head too*/
            ll_p->head = n_new;
        }
    }

    return n_new;
}


/**
 * Remove the node 'node_p' from 'll_p' linked list.
 * It does not free the the memory of node.
 * @param ll_p pointer to the linked list of 'node_p'
 * @param node_p pointer to node in 'll_p' linked list
 */
void lv_ll_rem(lv_ll_t  * ll_p, void * node_p)
{
    if(lv_ll_get_head(ll_p) == node_p) {
        /*The new head will be the node after 'n_act'*/
        ll_p->head = lv_ll_get_next(ll_p, node_p);
        if(ll_p->head == NULL) {
            ll_p->tail = NULL;
        } else {
            node_set_prev(ll_p, ll_p->head, NULL);
        }
    } else if(lv_ll_get_tail(ll_p) == node_p) {
        /*The new tail will be the  node before 'n_act'*/
        ll_p->tail = lv_ll_get_prev(ll_p, node_p);
        if(ll_p->tail == NULL) {
            ll_p->head = NULL;
        } else {
            node_set_next(ll_p, ll_p->tail, NULL);
        }
    } else {
        lv_ll_node_t * n_prev = lv_ll_get_prev(ll_p, node_p);
        lv_ll_node_t * n_next = lv_ll_get_next(ll_p, node_p);

        node_set_next(ll_p, n_prev, n_next);
        node_set_prev(ll_p, n_next, n_prev);
    }
}

/**
 * Remove and free all elements from a linked list. The list remain valid but become empty.
 * @param ll_p pointer to linked list
 */
void lv_ll_clear(lv_ll_t * ll_p)
{
    void * i;
    void * i_next;

    i = lv_ll_get_head(ll_p);
    i_next = NULL;

    while(i != NULL) {
        i_next = lv_ll_get_next(ll_p, i);

        lv_ll_rem(ll_p, i);
        free(i);

        i = i_next;
    }
}

/**
 * Move a node to a new linked list
 * @param ll_ori_p pointer to the original (old) linked list
 * @param ll_new_p pointer to the new linked list
 * @param node pointer to a node
 */
void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
{
    lv_ll_rem(ll_ori_p, node);

    /*Set node as head*/
    node_set_prev(ll_new_p, node, NULL);
    node_set_next(ll_new_p, node, ll_new_p->head);

    if(ll_new_p->head != NULL) { /*If there is old head then before it goes the new*/
        node_set_prev(ll_new_p, ll_new_p->head, node);
    }

    ll_new_p->head = node;        /*Set the new head in the dsc.*/
    if(ll_new_p->tail == NULL) {     /*If there is no tail (first node) set the tail too*/
        ll_new_p->tail = node;
    }
}

/**
 * Return with head node of the linked list
 * @param ll_p pointer to linked list
 * @return pointer to the head of 'll_p'
 */
void * lv_ll_get_head(const lv_ll_t * ll_p)
{
    void * head = NULL;

    if(ll_p != NULL)    {
        head = ll_p->head;
    }

    return head;
}

/**
 * Return with tail node of the linked list
 * @param ll_p pointer to linked list
 * @return pointer to the head of 'll_p'
 */
void * lv_ll_get_tail(const lv_ll_t * ll_p)
{
    void * tail = NULL;

    if(ll_p != NULL)    {
        tail = ll_p->tail;
    }

    return tail;
}

/**
 * Return with the pointer of the next node after 'n_act'
 * @param ll_p pointer to linked list
 * @param n_act pointer a node
 * @return pointer to the next node
 */
void * lv_ll_get_next(const lv_ll_t * ll_p, const  void * n_act)
{
    void * next = NULL;

    if(ll_p != NULL)    {
        const lv_ll_node_t * n_act_d = n_act;
        memcpy(&next, n_act_d + LL_NEXT_P_OFFSET(ll_p), sizeof(void *));
    }

    return next;
}

/**
 * Return with the pointer of the previous node after 'n_act'
 * @param ll_p pointer to linked list
 * @param n_act pointer a node
 * @return pointer to the previous node
 */
void * lv_ll_get_prev(const lv_ll_t * ll_p, const  void * n_act)
{
    void * prev = NULL;

    if(ll_p != NULL) {
        const lv_ll_node_t * n_act_d = n_act;
        memcpy(&prev, n_act_d + LL_PREV_P_OFFSET(ll_p), sizeof(void *));
    }

    return prev;
}

void lv_ll_swap(lv_ll_t * ll_p, void * n1_p, void * n2_p)
{
    (void)(ll_p);
    (void)(n1_p);
    (void)(n2_p);
    /*TODO*/
}

/**
 * Move a nodw before an other node in the same linked list
 * @param ll_p pointer to a linked list
 * @param n_act pointer to node to move
 * @param n_after pointer to a node which should be after `n_act`
 */
void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after)
{
    if(n_act == n_after) return;    /*Can't move before itself*/


    void * n_before;
    if(n_after != NULL) n_before = lv_ll_get_prev(ll_p, n_after);
    else n_before = lv_ll_get_tail(ll_p);        /*if `n_after` is NULL `n_act` should be the new tail*/

    if(n_act == n_before) return;   /*Already before `n_after`*/

    /*It's much easier to remove from the list and add again*/
    lv_ll_rem(ll_p, n_act);

    /*Add again by setting the prev. and next nodes*/
    node_set_next(ll_p, n_before, n_act);
    node_set_prev(ll_p, n_act, n_before);
    node_set_prev(ll_p, n_after, n_act);
    node_set_next(ll_p, n_act, n_after);

    /*If `n_act` was moved before NULL then it become the new tail*/
    if(n_after == NULL) ll_p->tail = n_act;

    if(n_before == NULL) ll_p->head = n_act;
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/**
 * Set the 'pervious node pointer' of a node
 * @param ll_p pointer to linked list
 * @param act pointer to a node which prev. node pointer should be set
 * @param prev pointer to a node which should be the previous node before 'act'
 */
static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * prev)
{
    if(act == NULL) return;     /*Can't set the prev node of `NULL`*/

    uint32_t node_p_size = sizeof(lv_ll_node_t *);
    if(prev) memcpy(act + LL_PREV_P_OFFSET(ll_p), &prev, node_p_size);
    else memset(act + LL_PREV_P_OFFSET(ll_p), 0, node_p_size);
}

/**
 * Set the 'next node pointer' of a node
 * @param ll_p pointer to linked list
 * @param act pointer to a node which next node pointer should be set
 * @param next pointer to a node which should be the next node before 'act'
 */
static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * next)
{
    if(act == NULL) return;     /*Can't set the next node of `NULL`*/

    uint32_t node_p_size = sizeof(lv_ll_node_t *);
    if(next) memcpy(act + LL_NEXT_P_OFFSET(ll_p), &next, node_p_size);
    else memset(act + LL_NEXT_P_OFFSET(ll_p), 0, node_p_size);
}


源代码.h

/**
 * @file lv_ll.c
 * Handle linked lists. The nodes are dynamically allocated by the 'lv_mem' module.
 */

#ifndef LV_LL_H
#define LV_LL_H

#ifdef __cplusplus
extern "C"
{
#endif

/*********************
 *      INCLUDES
 *********************/
#include <stdint.h>
#include <stddef.h>

    /*********************
     *      DEFINES
     *********************/

    /**********************
     *      TYPEDEFS
     **********************/

    /*Dummy type to make handling easier*/
    typedef uint8_t lv_ll_node_t;

    /*Description of a linked list*/
    typedef struct
    {
        uint32_t n_size;
        lv_ll_node_t *head;
        lv_ll_node_t *tail;
    } lv_ll_t;

    /**********************
     * GLOBAL PROTOTYPES
     **********************/

    /**
     * Initialize linked list
     * @param ll_dsc pointer to ll_dsc variable
     * @param node_size the size of 1 node in bytes
     */
    void lv_ll_init(lv_ll_t *ll_p, uint32_t node_size);

    /**
     * Add a new head to a linked list
     * @param ll_p pointer to linked list
     * @return pointer to the new head
     */
    void *lv_ll_ins_head(lv_ll_t *ll_p);

    /**
     * Insert a new node in front of the n_act node
     * @param ll_p pointer to linked list
     * @param n_act pointer a node
     * @return pointer to the new head
     */
    void *lv_ll_ins_prev(lv_ll_t *ll_p, void *n_act);

    /**
     * Add a new tail to a linked list
     * @param ll_p pointer to linked list
     * @return pointer to the new tail
     */
    void *lv_ll_ins_tail(lv_ll_t *ll_p);

    /**
     * Remove the node 'node_p' from 'll_p' linked list.
     * It does not free the the memory of node.
     * @param ll_p pointer to the linked list of 'node_p'
     * @param node_p pointer to node in 'll_p' linked list
     */
    void lv_ll_rem(lv_ll_t *ll_p, void *node_p);

    /**
     * Remove and free all elements from a linked list. The list remain valid but become empty.
     * @param ll_p pointer to linked list
     */
    void lv_ll_clear(lv_ll_t *ll_p);

    /**
     * Move a node to a new linked list
     * @param ll_ori_p pointer to the original (old) linked list
     * @param ll_new_p pointer to the new linked list
     * @param node pointer to a node
     */
    void lv_ll_chg_list(lv_ll_t *ll_ori_p, lv_ll_t *ll_new_p, void *node);

    /**
     * Return with head node of the linked list
     * @param ll_p pointer to linked list
     * @return pointer to the head of 'll_p'
     */
    void *lv_ll_get_head(const lv_ll_t *ll_p);

    /**
     * Return with tail node of the linked list
     * @param ll_p pointer to linked list
     * @return pointer to the head of 'll_p'
     */
    void *lv_ll_get_tail(const lv_ll_t *ll_p);

    /**
     * Return with the pointer of the next node after 'n_act'
     * @param ll_p pointer to linked list
     * @param n_act pointer a node
     * @return pointer to the next node
     */
    void *lv_ll_get_next(const lv_ll_t *ll_p, const void *n_act);

    /**
     * Return with the pointer of the previous node after 'n_act'
     * @param ll_p pointer to linked list
     * @param n_act pointer a node
     * @return pointer to the previous node
     */
    void *lv_ll_get_prev(const lv_ll_t *ll_p, const void *n_act);

    /**
     * Move a nodw before an other node in the same linked list
     * @param ll_p pointer to a linked list
     * @param n_act pointer to node to move
     * @param n_after pointer to a node which should be after `n_act`
     */
    void lv_ll_move_before(lv_ll_t *ll_p, void *n_act, void *n_after);

    /**********************
     *      MACROS
     **********************/

#define LL_READ(list, i) for (i = lv_ll_get_head(&list); i != NULL; i = lv_ll_get_next(&list, i))

#define LL_READ_BACK(list, i) for (i = lv_ll_get_tail(&list); i != NULL; i = lv_ll_get_prev(&list, i))

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif

测试结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值