From 4d7f577c7c7f7b2df68d16ec8cf778af84f1df24 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Wed, 31 Jul 2024 19:06:55 +0800 Subject: [PATCH] feat(iter): add lv_iter_t module --- lvgl.h | 1 + src/misc/lv_iter.c | 188 ++++++++++++++++++++++++++++++++++++++++++++ src/misc/lv_iter.h | 66 ++++++++++++++++ src/misc/lv_types.h | 3 + 4 files changed, 258 insertions(+) create mode 100644 src/misc/lv_iter.c create mode 100644 src/misc/lv_iter.h diff --git a/lvgl.h b/lvgl.h index df6140e29..bbb5d0bd8 100644 --- a/lvgl.h +++ b/lvgl.h @@ -33,6 +33,7 @@ extern "C" { #include "src/misc/lv_profiler_builtin.h" #include "src/misc/lv_rb.h" #include "src/misc/lv_utils.h" +#include "src/misc/lv_iter.h" #include "src/tick/lv_tick.h" diff --git a/src/misc/lv_iter.c b/src/misc/lv_iter.c new file mode 100644 index 000000000..9cdeabafe --- /dev/null +++ b/src/misc/lv_iter.c @@ -0,0 +1,188 @@ +/** + * @file lv_iter.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_iter.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_iter_t { + /* Iterator state */ + void * instance; /**< Pointer to the object to iterate over */ + uint32_t elem_size; /**< Size of one element in bytes */ + void * context; /**< Custom context for the iteration */ + uint32_t context_size; /**< Size of the custom context in bytes */ + + /* Peeking */ + void * peek_buff; /**< Buffer to store the next n element */ + uint32_t peek_capacity; /**< Size of the peek buffer in count of elements */ + uint32_t peek_count; /**< Number of elements currently in the peek buffer */ + uint32_t peek_offset; /**< Offset in the peek buffer */ + uint32_t peek_iter_offset;/**< Offset in the peek buffer for the current iteration */ + + /* Callbacks */ + lv_iter_next_cb next_cb; /**< Callback to get the next element */ +}; + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#define PEEK_BUFF_OFFSET(iter, i) (void*)((uint8_t *)(iter)->peek_buff + (i) * (iter)->elem_size) + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_iter_t * lv_iter_create(void * instance, uint32_t elem_size, uint32_t context_size, lv_iter_next_cb next_cb) +{ + lv_iter_t * iter = lv_malloc_zeroed(sizeof(lv_iter_t)); + LV_ASSERT_MALLOC(iter); + + if(iter == NULL) { + LV_LOG_ERROR("Could not allocate memory for iterator"); + return NULL; + } + + iter->instance = instance; + iter->elem_size = elem_size; + iter->context_size = context_size; + iter->next_cb = next_cb; + + if(context_size > 0) { + iter->context = lv_malloc_zeroed(context_size); + LV_ASSERT_MALLOC(iter->context); + } + + return iter; +} + +void * lv_iter_get_context(lv_iter_t * iter) +{ + return iter->context; +} + +void lv_iter_destroy(lv_iter_t * iter) +{ + if(iter->context_size > 0) lv_free(iter->context); + if(iter->peek_buff != NULL) lv_free(iter->peek_buff); + + lv_free(iter); +} + +void lv_iter_make_peekable(lv_iter_t * iter, uint32_t capacity) +{ + + if(capacity == 0 || iter->peek_buff != NULL) return; + iter->peek_capacity = capacity; + iter->peek_buff = lv_malloc_zeroed(iter->peek_capacity * iter->elem_size); + LV_ASSERT_MALLOC(iter->peek_buff); +} + +lv_result_t lv_iter_next(lv_iter_t * iter, void * elem) +{ + if(iter->peek_buff != NULL) { + if(iter->peek_iter_offset >= iter->peek_capacity) return LV_RESULT_INVALID; + if(iter->peek_iter_offset < iter->peek_count) { + void * buff = PEEK_BUFF_OFFSET(iter, iter->peek_iter_offset); + if(elem) lv_memcpy(elem, buff, iter->elem_size); + lv_memmove(iter->peek_buff, PEEK_BUFF_OFFSET(iter, iter->peek_iter_offset + 1), + (iter->peek_count - iter->peek_iter_offset - 1) * iter->elem_size); + iter->peek_iter_offset = 0; + iter->peek_offset = 0; + iter->peek_count--; + return LV_RESULT_OK; + } + } + + lv_result_t iter_res = iter->next_cb(iter->instance, iter->context, elem); + if(iter_res == LV_RESULT_INVALID) return LV_RESULT_INVALID; + + if(iter->peek_buff != NULL) { + iter->peek_count = 0; + iter->peek_offset = 0; + iter->peek_iter_offset = 0; + } + + return iter_res; +} + +lv_result_t lv_iter_peek(lv_iter_t * iter, void * elem) +{ + if(iter->peek_buff == NULL || iter->peek_count > iter->peek_capacity) return LV_RESULT_INVALID; + + if(iter->peek_offset >= iter->peek_count) { + uint32_t required = iter->peek_offset + 1 - iter->peek_count; + while(required --> 0) { + void * buff = PEEK_BUFF_OFFSET(iter, iter->peek_count); + lv_result_t iter_res = iter->next_cb(iter->instance, iter->context, buff); + if(iter_res == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + iter->peek_count++; + } + } + + void * buff = PEEK_BUFF_OFFSET(iter, iter->peek_offset); + lv_memcpy(elem, buff, iter->elem_size); + + return LV_RESULT_OK; +} + +lv_result_t lv_iter_peek_advance(lv_iter_t * iter) +{ + if(iter->peek_buff == NULL || iter->peek_offset + 1 >= iter->peek_capacity) return LV_RESULT_INVALID; + iter->peek_offset++; + return LV_RESULT_OK; +} + +lv_result_t lv_iter_peek_reset(lv_iter_t * iter) +{ + if(iter->peek_buff == NULL) return LV_RESULT_INVALID; + + iter->peek_offset = 0; + return LV_RESULT_OK; +} + +void lv_iter_inspect(lv_iter_t * iter, lv_iter_inspect_cb inspect_cb) +{ + void * elem = lv_malloc_zeroed(iter->elem_size); + LV_ASSERT_MALLOC(elem); + + if(elem == NULL) { + LV_LOG_ERROR("Could not allocate memory for element"); + return; + } + + while(lv_iter_next(iter, elem) == LV_RESULT_OK) { + inspect_cb(elem); + } + + lv_free(elem); +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/src/misc/lv_iter.h b/src/misc/lv_iter.h new file mode 100644 index 000000000..bcda307a9 --- /dev/null +++ b/src/misc/lv_iter.h @@ -0,0 +1,66 @@ +/** +* @file lv_iter.h +* + */ + + +#ifndef LV_ITER_H +#define LV_ITER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "lv_types.h" +#include "lv_assert.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef lv_result_t (*lv_iter_next_cb)(void * instance, void * context, void * elem); +typedef void (*lv_iter_inspect_cb)(void * elem); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_iter_t * lv_iter_create(void * instance, uint32_t elem_size, uint32_t context_size, lv_iter_next_cb next_cb); + +void * lv_iter_get_context(lv_iter_t * iter); + +void lv_iter_destroy(lv_iter_t * iter); + +lv_result_t lv_iter_next(lv_iter_t * iter, void * elem); + +void lv_iter_make_peekable(lv_iter_t * iter, uint32_t capacity); + +lv_result_t lv_iter_peek(lv_iter_t * iter, void * elem); + +lv_result_t lv_iter_peek_advance(lv_iter_t * iter); + +lv_result_t lv_iter_peek_reset(lv_iter_t * iter); + +void lv_iter_inspect(lv_iter_t * iter, lv_iter_inspect_cb inspect_cb); + +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ITER_H*/ diff --git a/src/misc/lv_types.h b/src/misc/lv_types.h index 4e02c1366..636bc1a11 100644 --- a/src/misc/lv_types.h +++ b/src/misc/lv_types.h @@ -326,6 +326,9 @@ typedef struct lv_glfw_texture_t lv_glfw_texture_t; typedef uint32_t lv_prop_id_t; +struct _lv_iter_t; +typedef struct _lv_iter_t lv_iter_t; + typedef struct lv_draw_buf_t lv_draw_buf_t; #if LV_USE_OBJ_PROPERTY