lv_ll.h

API reference for lv_ll.h

Report on GitHub

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+ptrsize

Because 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 needed

Pointer 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_tail allocate a node block with lv_malloc and return a pointer to it.
  • lv_ll_remove unlinks a node from the list but does not free the block — the caller must call lv_free(node) afterwards if appropriate.
  • lv_ll_clear frees 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_custom accepts a cleanup callback that is invoked for each node instead of the default lv_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)
Parameters
NameTypeDescription
ll_pconst 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)
Parameters
NameTypeDescription
ll_pconst 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)
Parameters
NameTypeDescription
ll_pconst lv_ll_t *pointer to linked list
n_actconst 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)
Parameters
NameTypeDescription
ll_pconst lv_ll_t *pointer to linked list
n_actconst 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)
Parameters
NameTypeDescription
ll_pconst lv_ll_t *pointer to linked list

Returns: uint32_t — length of the linked list

Structs

struct

lv_ll_t

Description of a linked list

MemberTypeDescription
n_sizeuint32_t
headlv_ll_node_t *
taillv_ll_node_t *
Used by 17 functions
  • lv_ll_init — param ll_p
  • lv_ll_ins_head — param ll_p
  • lv_ll_ins_prev — param ll_p
  • lv_ll_ins_tail — param ll_p
  • lv_ll_remove — param ll_p
  • lv_ll_clear_custom — param ll_p
  • lv_ll_clear — param ll_p
  • lv_ll_chg_list — param ll_ori_p
  • lv_ll_chg_list — param ll_new_p
  • lv_ll_get_head — param ll_p
  • lv_ll_get_tail — param ll_p
  • lv_ll_get_next — param ll_p
  • lv_ll_get_prev — param ll_p
  • lv_ll_get_len — param ll_p
  • lv_ll_move_before — param ll_p
  • lv_ll_is_empty — param ll_p
  • lv_vector_for_each_destroy_tasks — param task_list

Typedefs

lv_ll_node_t

 
typedef uint8_t lv_ll_node_t

Dummy 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

Indirect dependencies

Last updated on

On this page