summaryrefslogtreecommitdiff
path: root/lib/lvgl/src/misc/lv_ll.c
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-06-01 15:41:47 +1000
committerjacqueline <me@jacqueline.id.au>2023-06-01 15:41:47 +1000
commitdd27c3530432ea0b09f01e604bf577f31d8ef841 (patch)
treebbf86cf81a78f0ff0b07f31f1c390db473f26fd3 /lib/lvgl/src/misc/lv_ll.c
parent6fd588e970470b15936187980829916d0dbe77bb (diff)
downloadtangara-fw-dd27c3530432ea0b09f01e604bf577f31d8ef841.tar.gz
convert lvgl from submodule to a plain old directory
Diffstat (limited to 'lib/lvgl/src/misc/lv_ll.c')
m---------lib/lvgl0
-rw-r--r--lib/lvgl/src/misc/lv_ll.c408
2 files changed, 408 insertions, 0 deletions
diff --git a/lib/lvgl b/lib/lvgl
deleted file mode 160000
-Subproject 0732400e7b564dd0e7dc4a924619d8e19c5b23a
diff --git a/lib/lvgl/src/misc/lv_ll.c b/lib/lvgl/src/misc/lv_ll.c
new file mode 100644
index 00000000..e7582316
--- /dev/null
+++ b/lib/lvgl/src/misc/lv_ll.c
@@ -0,0 +1,408 @@
+/**
+ * @file lv_ll.c
+ * Handle linked lists.
+ * The nodes are dynamically allocated by the 'lv_mem' module,
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_ll.h"
+#include "lv_mem.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_p pointer to lv_ll_t 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_ARCH_64
+ /*Round the size up to 8*/
+ node_size = (node_size + 7) & (~0x7);
+#else
+ /*Round the size up to 4*/
+ node_size = (node_size + 3) & (~0x3);
+#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 = lv_mem_alloc(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 node
+ */
+void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
+{
+ lv_ll_node_t * n_new;
+
+ 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 = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
+ if(n_new == NULL) return NULL;
+
+ lv_ll_node_t * n_prev;
+ 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 = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
+
+ 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 the 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 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_remove(lv_ll_t * ll_p, void * node_p)
+{
+ if(ll_p == NULL) return;
+
+ 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_remove(ll_p, i);
+ lv_mem_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
+ * @param head true: be the head in the new list
+ * false be the tail in the new list
+ */
+void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head)
+{
+ _lv_ll_remove(ll_ori_p, node);
+
+ if(head) {
+ /*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;
+ }
+ }
+ else {
+ /*Set node as tail*/
+ node_set_prev(ll_new_p, node, ll_new_p->tail);
+ node_set_next(ll_new_p, node, NULL);
+
+ if(ll_new_p->tail != NULL) { /*If there is old tail then after it goes the new*/
+ node_set_next(ll_new_p, ll_new_p->tail, node);
+ }
+
+ ll_new_p->tail = node; /*Set the new tail in the dsc.*/
+ if(ll_new_p->head == NULL) { /*If there is no head (first node) set the head too*/
+ ll_new_p->head = 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)
+{
+ if(ll_p == NULL) return NULL;
+ return ll_p->head;
+}
+
+/**
+ * Return with tail node of the linked list
+ * @param ll_p pointer to linked list
+ * @return pointer to the tail of 'll_p'
+ */
+void * _lv_ll_get_tail(const lv_ll_t * ll_p)
+{
+ if(ll_p == NULL) return NULL;
+ return ll_p->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)
+{
+ /*Pointer to the next node is stored in the end of this node.
+ *Go there and return the address found there*/
+ const lv_ll_node_t * n_act_d = n_act;
+ n_act_d += LL_NEXT_P_OFFSET(ll_p);
+ return *((lv_ll_node_t **)n_act_d);
+}
+
+/**
+ * Return with the pointer of the previous node before '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)
+{
+ /*Pointer to the prev. node is stored in the end of this node.
+ *Go there and return the address found there*/
+ const lv_ll_node_t * n_act_d = n_act;
+ n_act_d += LL_PREV_P_OFFSET(ll_p);
+ return *((lv_ll_node_t **)n_act_d);
+}
+
+/**
+ * Return the length of the linked list.
+ * @param ll_p pointer to linked list
+ * @return length of the linked list
+ */
+uint32_t _lv_ll_get_len(const lv_ll_t * ll_p)
+{
+ uint32_t len = 0;
+ void * node;
+
+ for(node = _lv_ll_get_head(ll_p); node != NULL; node = _lv_ll_get_next(ll_p, node)) {
+ len++;
+ }
+
+ return len;
+}
+
+/**
+ * Move a node 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_remove(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_act` was moved before `NULL` then it's the new head*/
+ if(n_before == NULL) ll_p->head = n_act;
+}
+
+/**
+ * Check if a linked list is empty
+ * @param ll_p pointer to a linked list
+ * @return true: the linked list is empty; false: not empty
+ */
+bool _lv_ll_is_empty(lv_ll_t * ll_p)
+{
+ if(ll_p == NULL) return true;
+
+ if(ll_p->head == NULL && ll_p->tail == NULL) return true;
+
+ return false;
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+/**
+ * Set the previous 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`*/
+
+ uint8_t * act8 = (uint8_t *)act;
+
+ act8 += LL_PREV_P_OFFSET(ll_p);
+
+ lv_ll_node_t ** act_node_p = (lv_ll_node_t **) act8;
+ lv_ll_node_t ** prev_node_p = (lv_ll_node_t **) &prev;
+
+ *act_node_p = *prev_node_p;
+}
+
+/**
+ * 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`*/
+ uint8_t * act8 = (uint8_t *)act;
+
+ act8 += LL_NEXT_P_OFFSET(ll_p);
+ lv_ll_node_t ** act_node_p = (lv_ll_node_t **) act8;
+ lv_ll_node_t ** next_node_p = (lv_ll_node_t **) &next;
+
+ *act_node_p = *next_node_p;
+}