lv_ll.h
API reference for lv_ll.h
Doubly-linked list that embeds user data directly inside each node allocation.
Memory layout
Unlike a textbook linked list that holds a data pointer inside each node, lv_ll allocates a single flat block per node and places the user data at the beginning of that block. The prev / next bookkeeping pointers are appended after the user data:
+---------------------------------+------------------+------------------+
| user data (n_size bytes, | prev pointer | next pointer |
| rounded up for alignment) | (sizeof ptr) | (sizeof ptr) |
| ^--- pointer returned to | | |
| the caller | | |
+---------------------------------+------------------+------------------+
offset 0 offset n_size offset n_size+ptrsizeBecause the returned pointer already is the user data pointer, callers only need a cast — no ->data indirection is required. This keeps usage sites clean and avoids a level of indirection on every access:
my_item_t *item = lv_ll_ins_tail(&my_list);
item->x = 10; // write directly, no ->data neededPointer arithmetic using the offsets defined by LL_PREV_P_OFFSET / LL_NEXT_P_OFFSET (in lv_ll.c) is used internally to read and write the prev / next fields without exposing them to callers.
Ownership semantics
lv_ll owns the node allocation but not the resources referenced by the data stored in each node.
lv_ll_ins_head/lv_ll_ins_prev/lv_ll_ins_tailallocate a node block withlv_mallocand return a pointer to it.lv_ll_removeunlinks a node from the list but does not free the block — the caller must calllv_free(node)afterwards if appropriate.lv_ll_clearfrees every node block (the flat allocation described above). It does not chase any pointers stored inside the user data portion. If the stored structs themselves contain heap-allocated members, those will leak unless the caller frees them first (or last).lv_ll_clear_customaccepts acleanupcallback that is invoked for each node instead of the defaultlv_free. Use this when the stored data needs deep cleanup:
static void my_cleanup(void * node)
{
my_item_t * item = node;
lv_free(item->inner_buf); // free owned sub-allocation
lv_ll_remove(&my_list, node);
lv_free(node); // free the node block itself
}
lv_ll_clear_custom(&my_list, my_cleanup);Functions
lv_ll_get_head
Return with head node of the linked list
void * lv_ll_get_head(const lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | const lv_ll_t * | pointer to linked list |
Returns: void * — pointer to the head of 'll_p'
lv_ll_get_tail
Return with tail node of the linked list
void * lv_ll_get_tail(const lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | const lv_ll_t * | pointer to linked list |
Returns: void * — pointer to the tail of 'll_p'
lv_ll_get_next
Return with the pointer of the next node after 'n_act'
void * lv_ll_get_next(const lv_ll_t *ll_p, const void *n_act)| Name | Type | Description |
|---|---|---|
ll_p | const lv_ll_t * | pointer to linked list |
n_act | const void * | pointer a node |
Returns: void * — pointer to the next node
lv_ll_get_prev
Return with the pointer of the previous node after 'n_act'
void * lv_ll_get_prev(const lv_ll_t *ll_p, const void *n_act)| Name | Type | Description |
|---|---|---|
ll_p | const lv_ll_t * | pointer to linked list |
n_act | const void * | pointer a node |
Returns: void * — pointer to the previous node
lv_ll_get_len
Return the length of the linked list.
uint32_t lv_ll_get_len(const lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | const lv_ll_t * | pointer to linked list |
Returns: uint32_t — length of the linked list
lv_ll_init
Initialize linked list
void lv_ll_init(lv_ll_t *ll_p, uint32_t node_size)lv_ll_ins_head
Add a new head to a linked list
void * lv_ll_ins_head(lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to linked list |
Returns: void * — pointer to the new head
lv_ll_ins_prev
Insert a new node in front of the n_act node
void * lv_ll_ins_prev(lv_ll_t *ll_p, void *n_act)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to linked list |
n_act | void * | pointer a node |
Returns: void * — pointer to the new node
lv_ll_ins_tail
Add a new tail to a linked list
void * lv_ll_ins_tail(lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to linked list |
Returns: void * — pointer to the new tail
lv_ll_remove
Remove the node 'node_p' from 'll_p' linked list. It does not free the memory of node.
void lv_ll_remove(lv_ll_t *ll_p, void *node_p)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to the linked list of 'node_p' |
node_p | void * | pointer to node in 'll_p' linked list May be NULL. |
lv_ll_clear_custom
Remove and optionally clean up all elements from a linked list via a custom callback. If cleanup is NULL the node block is simply freed with lv_free. If cleanup is provided it is called for every node instead of lv_free; the callback is then responsible for both releasing any owned sub-resources and freeing the node block itself.
void lv_ll_clear_custom(lv_ll_t *ll_p, void(*cleanup)(void *))lv_ll_clear
Remove and free all elements from a linked list. The list remain valid but become empty.
void lv_ll_clear(lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to linked list |
lv_ll_chg_list
Move a node to a new linked list
void lv_ll_chg_list(lv_ll_t *ll_ori_p, lv_ll_t *ll_new_p, void *node, bool head)lv_ll_move_before
Move a node before another node in the same linked list
void lv_ll_move_before(lv_ll_t *ll_p, void *n_act, void *n_after)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to a linked list |
n_act | void * | pointer to node to move |
n_after | void * | pointer to a node which should be after n_act. May be NULL. When NULL n_act is moved to the tail. |
lv_ll_is_empty
Check if a linked list is empty
bool lv_ll_is_empty(lv_ll_t *ll_p)| Name | Type | Description |
|---|---|---|
ll_p | lv_ll_t * | pointer to a linked list |
Returns: bool — true: the linked list is empty; false: not empty
Structs
lv_ll_t
Description of a linked list
| Member | Type | Description |
|---|---|---|
n_size | uint32_t | |
head | lv_ll_node_t * | |
tail | lv_ll_node_t * |
Used by 17 functions
lv_ll_init— paramll_plv_ll_ins_head— paramll_plv_ll_ins_prev— paramll_plv_ll_ins_tail— paramll_plv_ll_remove— paramll_plv_ll_clear_custom— paramll_plv_ll_clear— paramll_plv_ll_chg_list— paramll_ori_plv_ll_chg_list— paramll_new_plv_ll_get_head— paramll_plv_ll_get_tail— paramll_plv_ll_get_next— paramll_plv_ll_get_prev— paramll_plv_ll_get_len— paramll_plv_ll_move_before— paramll_plv_ll_is_empty— paramll_plv_vector_for_each_destroy_tasks— paramtask_list
Typedefs
lv_ll_node_t
typedef uint8_t lv_ll_node_tDummy type to make handling easier
Macros
LV_LL_READ
#define LV_LL_READ(list, i) \
for(i = lv_ll_get_head(list); i != NULL; i = lv_ll_get_next(list, i))LV_LL_READ_BACK
#define LV_LL_READ_BACK(list, i) \
for(i = lv_ll_get_tail(list); i != NULL; i = lv_ll_get_prev(list, i))Dependencies
Last updated on