diff --git a/src/core/lv_group.h b/src/core/lv_group.h index 5fb7592781..ca60edb129 100644 --- a/src/core/lv_group.h +++ b/src/core/lv_group.h @@ -80,13 +80,13 @@ typedef enum { **********************/ /** - * Init. the group module + * Init the group module * @remarks Internal function, do not call directly. */ void _lv_group_init(void); /** - * Deinit. the group module + * Deinit the group module * @remarks Internal function, do not call directly. */ void _lv_group_deinit(void); diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index c7d1965ce5..6873f25d75 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -25,10 +25,10 @@ #define CHECK_AND_RESIZE_PATH_CONTAINER(P, N) \ do { \ - if ((lv_array_length(&(P)->ops) + (N)) > lv_array_capacity(&(P)->ops)) { \ + if ((lv_array_size(&(P)->ops) + (N)) > lv_array_capacity(&(P)->ops)) { \ lv_array_resize(&(P)->ops, ((P)->ops.capacity << 1)); \ } \ - if ((lv_array_length(&(P)->points) + (N)) > lv_array_capacity(&(P)->points)) { \ + if ((lv_array_size(&(P)->points) + (N)) > lv_array_capacity(&(P)->points)) { \ lv_array_resize(&(P)->points, ((P)->points.capacity << 1)); \ } \ } while(0) @@ -202,8 +202,8 @@ lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality) LV_ASSERT_MALLOC(path); lv_memzero(path, sizeof(lv_vector_path_t)); path->quality = quality; - LV_ARRAY_INIT_CAPACITY(&path->ops, 8, uint8_t); - LV_ARRAY_INIT_CAPACITY(&path->points, 8, lv_fpoint_t); + lv_array_init(&path->ops, 8, sizeof(uint8_t)); + lv_array_init(&path->points, 8, sizeof(lv_fpoint_t)); return path; } @@ -222,8 +222,8 @@ void lv_vector_path_clear(lv_vector_path_t * path) void lv_vector_path_delete(lv_vector_path_t * path) { - lv_array_destroy(&path->ops); - lv_array_destroy(&path->points); + lv_array_deinit(&path->ops); + lv_array_deinit(&path->points); lv_free(path); } @@ -232,8 +232,8 @@ void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p) CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); uint8_t op = LV_VECTOR_PATH_OP_MOVE_TO; - LV_ARRAY_APPEND_VALUE(&path->ops, op); - LV_ARRAY_APPEND(&path->points, p); + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p); } void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p) @@ -246,8 +246,8 @@ void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p) CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); uint8_t op = LV_VECTOR_PATH_OP_LINE_TO; - LV_ARRAY_APPEND_VALUE(&path->ops, op); - LV_ARRAY_APPEND(&path->points, p); + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p); } void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2) @@ -260,9 +260,9 @@ void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, con CHECK_AND_RESIZE_PATH_CONTAINER(path, 2); uint8_t op = LV_VECTOR_PATH_OP_QUAD_TO; - LV_ARRAY_APPEND_VALUE(&path->ops, op); - LV_ARRAY_APPEND(&path->points, p1); - LV_ARRAY_APPEND(&path->points, p2); + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p1); + lv_array_push_back(&path->points, p2); } void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2, @@ -276,10 +276,10 @@ void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, co CHECK_AND_RESIZE_PATH_CONTAINER(path, 3); uint8_t op = LV_VECTOR_PATH_OP_CUBIC_TO; - LV_ARRAY_APPEND_VALUE(&path->ops, op); - LV_ARRAY_APPEND(&path->points, p1); - LV_ARRAY_APPEND(&path->points, p2); - LV_ARRAY_APPEND(&path->points, p3); + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p1); + lv_array_push_back(&path->points, p2); + lv_array_push_back(&path->points, p3); } void lv_vector_path_close(lv_vector_path_t * path) @@ -292,7 +292,7 @@ void lv_vector_path_close(lv_vector_path_t * path) CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); uint8_t op = LV_VECTOR_PATH_OP_CLOSE; - LV_ARRAY_APPEND_VALUE(&path->ops, op); + lv_array_push_back(&path->ops, &op); } void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry) @@ -432,19 +432,15 @@ void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath) { - uint32_t ops_size = lv_array_length(&path->ops); - uint32_t nops_size = lv_array_length(&subpath->ops); - uint32_t point_size = lv_array_length(&path->points); - uint32_t npoint_size = lv_array_length(&subpath->points); + uint32_t ops_size = lv_array_size(&path->ops); + uint32_t nops_size = lv_array_size(&subpath->ops); + uint32_t point_size = lv_array_size(&path->points); + uint32_t npoint_size = lv_array_size(&subpath->points); - lv_array_resize(&path->ops, ops_size + nops_size); - uint8_t * start_ops = lv_array_get(&path->ops, ops_size - 1) + sizeof(lv_vector_path_op_t); - lv_memcpy(start_ops, lv_array_get(&subpath->ops, 0), nops_size * sizeof(lv_vector_path_op_t)); + lv_array_concat(&path->ops, &subpath->ops); path->ops.size = ops_size + nops_size; - lv_array_resize(&path->points, point_size + npoint_size); - uint8_t * start_pt = lv_array_get(&path->points, point_size - 1) + sizeof(lv_fpoint_t); - lv_memcpy(start_pt, lv_array_get(&subpath->points, 0), npoint_size * sizeof(lv_fpoint_t)); + lv_array_concat(&path->points, &subpath->points); path->points.size = point_size + npoint_size; } @@ -489,7 +485,7 @@ void lv_vector_dsc_delete(lv_vector_dsc_t * dsc) _lv_vector_for_each_destroy_tasks(task_list, NULL, NULL); dsc->tasks.task_list = NULL; } - lv_array_destroy(&(dsc->current_dsc.stroke_dsc.dash_pattern)); + lv_array_deinit(&(dsc->current_dsc.stroke_dsc.dash_pattern)); lv_free(dsc); } @@ -590,13 +586,13 @@ void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, if(dash_pattern) { lv_array_clear(dash_array); if(lv_array_capacity(dash_array) == 0) { - LV_ARRAY_INIT_CAPACITY(dash_array, dash_count, float); + lv_array_init(dash_array, dash_count, sizeof(float)); } else { lv_array_resize(dash_array, dash_count); } for(uint16_t i = 0; i < dash_count; i++) { - LV_ARRAY_APPEND_VALUE(dash_array, dash_pattern[i]); + lv_array_push_back(dash_array, &dash_pattern[i]); } } else { /*clear dash*/ @@ -747,7 +743,7 @@ void _lv_vector_for_each_destroy_tasks(lv_ll_t * task_list, vector_draw_task_cb if(task->path) { lv_vector_path_delete(task->path); } - lv_array_destroy(&(task->dsc.stroke_dsc.dash_pattern)); + lv_array_deinit(&(task->dsc.stroke_dsc.dash_pattern)); lv_free(task); task = next_task; diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index b2c72c363d..d5a45bd48c 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -87,25 +87,25 @@ static void _set_paint_shape(Tvg_Paint * obj, const lv_vector_path_t * p) { uint32_t pidx = 0; for(uint32_t i = 0; i < p->ops.size; i++) { - lv_vector_path_op_t * op = LV_ARRAY_GET(&p->ops, i, uint8_t); + lv_vector_path_op_t * op = lv_array_at(&p->ops, i); switch(*op) { case LV_VECTOR_PATH_OP_MOVE_TO: { - lv_fpoint_t * pt = LV_ARRAY_GET(&p->points, pidx, lv_fpoint_t); + lv_fpoint_t * pt = lv_array_at(&p->points, pidx); tvg_shape_move_to(obj, pt->x, pt->y); pidx += 1; } break; case LV_VECTOR_PATH_OP_LINE_TO: { - lv_fpoint_t * pt = LV_ARRAY_GET(&p->points, pidx, lv_fpoint_t); + lv_fpoint_t * pt = lv_array_at(&p->points, pidx); tvg_shape_line_to(obj, pt->x, pt->y); pidx += 1; } break; case LV_VECTOR_PATH_OP_QUAD_TO: { - lv_fpoint_t * pt1 = LV_ARRAY_GET(&p->points, pidx, lv_fpoint_t); - lv_fpoint_t * pt2 = LV_ARRAY_GET(&p->points, pidx + 1, lv_fpoint_t); + lv_fpoint_t * pt1 = lv_array_at(&p->points, pidx); + lv_fpoint_t * pt2 = lv_array_at(&p->points, pidx + 1); - lv_fpoint_t * last_pt = LV_ARRAY_GET(&p->points, pidx - 1, lv_fpoint_t); + lv_fpoint_t * last_pt = lv_array_at(&p->points, pidx - 1); lv_fpoint_t cp[2]; cp[0].x = (last_pt->x + 2 * pt1->x) * (1.0f / 3.0f); @@ -118,9 +118,9 @@ static void _set_paint_shape(Tvg_Paint * obj, const lv_vector_path_t * p) } break; case LV_VECTOR_PATH_OP_CUBIC_TO: { - lv_fpoint_t * pt1 = LV_ARRAY_GET(&p->points, pidx, lv_fpoint_t); - lv_fpoint_t * pt2 = LV_ARRAY_GET(&p->points, pidx + 1, lv_fpoint_t); - lv_fpoint_t * pt3 = LV_ARRAY_GET(&p->points, pidx + 2, lv_fpoint_t); + lv_fpoint_t * pt1 = lv_array_at(&p->points, pidx); + lv_fpoint_t * pt2 = lv_array_at(&p->points, pidx + 1); + lv_fpoint_t * pt3 = lv_array_at(&p->points, pidx + 2); tvg_shape_cubic_to(obj, pt1->x, pt1->y, pt2->x, pt2->y, pt3->x, pt3->y); pidx += 3; @@ -243,7 +243,7 @@ static void _set_paint_stroke(Tvg_Paint * obj, const lv_vector_stroke_dsc_t * ds tvg_shape_set_stroke_join(obj, _lv_stroke_join_to_tvg(dsc->join)); if(!lv_array_is_empty(&dsc->dash_pattern)) { - float * dash_array = LV_ARRAY_GET(&dsc->dash_pattern, 0, float); + float * dash_array = lv_array_at(&dsc->dash_pattern, 0); tvg_shape_set_stroke_dash(obj, dash_array, dsc->dash_pattern.size); } } diff --git a/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/src/draw/vg_lite/lv_draw_vg_lite_vector.c index 87ea482e60..1326588c69 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -236,25 +236,25 @@ static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src uint32_t pidx = 0; for(uint32_t i = 0; i < src->ops.size; i++) { - lv_vector_path_op_t * op = LV_ARRAY_GET(&src->ops, i, uint8_t); + lv_vector_path_op_t * op = lv_array_at(&src->ops, i); switch(*op) { case LV_VECTOR_PATH_OP_MOVE_TO: { - const lv_fpoint_t * pt = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t); + const lv_fpoint_t * pt = lv_array_at(&src->points, pidx); CMP_BOUNDS(pt); lv_vg_lite_path_move_to(dest, pt->x, pt->y); pidx += 1; } break; case LV_VECTOR_PATH_OP_LINE_TO: { - const lv_fpoint_t * pt = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t); + const lv_fpoint_t * pt = lv_array_at(&src->points, pidx); CMP_BOUNDS(pt); lv_vg_lite_path_line_to(dest, pt->x, pt->y); pidx += 1; } break; case LV_VECTOR_PATH_OP_QUAD_TO: { - const lv_fpoint_t * pt1 = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t); - const lv_fpoint_t * pt2 = LV_ARRAY_GET(&src->points, pidx + 1, lv_fpoint_t); + const lv_fpoint_t * pt1 = lv_array_at(&src->points, pidx); + const lv_fpoint_t * pt2 = lv_array_at(&src->points, pidx + 1); CMP_BOUNDS(pt1); CMP_BOUNDS(pt2); lv_vg_lite_path_quad_to(dest, pt1->x, pt1->y, pt2->x, pt2->y); @@ -262,9 +262,9 @@ static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src } break; case LV_VECTOR_PATH_OP_CUBIC_TO: { - const lv_fpoint_t * pt1 = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t); - const lv_fpoint_t * pt2 = LV_ARRAY_GET(&src->points, pidx + 1, lv_fpoint_t); - const lv_fpoint_t * pt3 = LV_ARRAY_GET(&src->points, pidx + 2, lv_fpoint_t); + const lv_fpoint_t * pt1 = lv_array_at(&src->points, pidx); + const lv_fpoint_t * pt2 = lv_array_at(&src->points, pidx + 1); + const lv_fpoint_t * pt3 = lv_array_at(&src->points, pidx + 2); CMP_BOUNDS(pt1); CMP_BOUNDS(pt2); CMP_BOUNDS(pt3); diff --git a/src/misc/lv_anim.h b/src/misc/lv_anim.h index ee5f802e53..bff3b33a44 100644 --- a/src/misc/lv_anim.h +++ b/src/misc/lv_anim.h @@ -169,12 +169,12 @@ struct _lv_anim_t { **********************/ /** - * Init. the animation module + * Init the animation module */ void _lv_anim_core_init(void); /** - * Deinit. the animation module + * Deinit the animation module */ void _lv_anim_core_deinit(void); diff --git a/src/misc/lv_array.c b/src/misc/lv_array.c index 33bc615d4b..4d07949d5c 100644 --- a/src/misc/lv_array.c +++ b/src/misc/lv_array.c @@ -45,63 +45,116 @@ void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size) LV_ASSERT_MALLOC(array->data); } -void lv_array_destroy(lv_array_t * array) +void lv_array_deinit(lv_array_t * array) { if(array->data) { lv_free(array->data); array->data = NULL; } + + array->size = 0; + array->capacity = 0; } -void lv_array_copy(lv_array_t * target, const lv_array_t * array) +void lv_array_copy(lv_array_t * target, const lv_array_t * source) { - if(lv_array_is_empty(array)) { + if(lv_array_is_empty(source)) { return; } - lv_array_destroy(target); - lv_array_init(target, array->capacity, array->element_size); - lv_memcpy(target->data, array->data, array->size * array->element_size); - target->size = array->size; + lv_array_deinit(target); + lv_array_init(target, source->capacity, source->element_size); + lv_memcpy(target->data, source->data, source->size * source->element_size); + target->size = source->size; } -void lv_array_clear(lv_array_t * array) +lv_result_t lv_array_remove(lv_array_t * array, uint32_t index) { - array->size = 0; + if(index >= array->size) { + return LV_RESULT_INVALID; + } + + /*Shortcut*/ + if(index == array->size - 1) { + lv_array_resize(array, array->size - 1); + return LV_RESULT_OK; + } + + uint8_t * start = lv_array_at(array, index); + uint8_t * remaining = start + array->element_size; + uint32_t remaining_size = (array->size - index - 1) * array->element_size; + lv_memcpy(start, remaining, remaining_size); + lv_array_resize(array, array->size - 1); + return LV_RESULT_OK; +} + +lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end) +{ + if(end > array->size) { + end = array->size; + } + + if(start >= end) { + return LV_RESULT_INVALID; + } + + /*Shortcut*/ + if(end == array->size) { + lv_array_resize(array, start); + return LV_RESULT_OK; + } + + uint8_t * start_p = lv_array_at(array, start); + uint8_t * remaining = start_p + (end - start) * array->element_size; + uint32_t remaining_size = (array->size - end) * array->element_size; + lv_memcpy(start_p, remaining, remaining_size); + lv_array_resize(array, array->size - (end - start)); + return LV_RESULT_OK; } void lv_array_resize(lv_array_t * array, uint32_t new_capacity) { - if(new_capacity > array->size) { - if(new_capacity > array->capacity) { - uint8_t * data = lv_malloc(new_capacity * array->element_size); - lv_memcpy(data, array->data, array->size * array->element_size); - lv_free(array->data); - array->data = data; - array->capacity = new_capacity; - } - } - else { + uint8_t * data = lv_realloc(array->data, new_capacity * array->element_size); + LV_ASSERT_NULL(data); + array->data = data; + array->capacity = new_capacity; + if(array->size > new_capacity) { array->size = new_capacity; } } -bool lv_array_append(lv_array_t * array, const uint8_t * element) +lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other) { - if(array->size >= array->capacity) { - // array is full - return false; + LV_ASSERT_NULL(array->data); + uint32_t size = other->size; + if(array->size + size > array->capacity) { + /*array is full*/ + lv_array_resize(array, array->size + size); } - LV_ASSERT_NULL(array->data); - uint8_t * data = (uint8_t *)(array->data + array->size * array->element_size); - lv_memcpy(data, element, array->element_size); - array->size++; - return true; + uint8_t * data = array->data + array->size * array->element_size; + lv_memcpy(data, other->data, array->element_size * size); + array->size += size; + return LV_RESULT_OK; } -uint8_t * lv_array_get(const lv_array_t * array, uint32_t index) +lv_result_t lv_array_push_back(lv_array_t * array, const void * element) { - if(index > (array->size - 1)) { + LV_ASSERT_NULL(array->data); + + if(array->size == array->capacity) { + /*array is full*/ + lv_array_resize(array, array->capacity + 1); + } + + uint8_t * data = array->data + array->size * array->element_size; + lv_memcpy(data, element, array->element_size); + array->size++; + return LV_RESULT_OK; +} + +void * lv_array_at(const lv_array_t * array, uint32_t index) +{ + if(index >= array->size) { return NULL; } @@ -109,22 +162,11 @@ uint8_t * lv_array_get(const lv_array_t * array, uint32_t index) return array->data + index * array->element_size; } -uint32_t lv_array_length(const lv_array_t * array) +lv_result_t lv_array_assign(lv_array_t * array, uint32_t index, const void * value) { - return array->size; -} + uint8_t * data = lv_array_at(array, index); + if(data == NULL) return LV_RESULT_INVALID; -uint32_t lv_array_capacity(const lv_array_t * array) -{ - return array->capacity; -} - -bool lv_array_is_full(const lv_array_t * array) -{ - return array->size == array->capacity; -} - -bool lv_array_is_empty(const lv_array_t * array) -{ - return array->size == 0; + lv_memcpy(data, value, array->element_size); + return LV_RESULT_OK; } diff --git a/src/misc/lv_array.h b/src/misc/lv_array.h index 1e8c7ddb22..3cdb1c6c67 100644 --- a/src/misc/lv_array.h +++ b/src/misc/lv_array.h @@ -17,10 +17,12 @@ extern "C" { #include #include +#include "lv_types.h" + /********************* * DEFINES *********************/ -#define DEFAULT_CAPS 8 +#define LV_ARRAY_DEFAULT_CAPACITY 8 /********************** * TYPEDEFS @@ -38,47 +40,162 @@ typedef struct { * GLOBAL PROTOTYPES **********************/ +/** + * Init an array. + * @param array pointer to an `lv_array_t` variable to initialize + * @param capacity the initial capacity of the array + * @param element_size the size of an element in bytes + */ void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size); -void lv_array_copy(lv_array_t * target, const lv_array_t * array); - -void lv_array_clear(lv_array_t * array); - +/** + * Resize the array to the given capacity. + * @note if the new capacity is smaller than the current size, the array will be truncated. + * @param array pointer to an `lv_array_t` variable + * @param new_capacity the new capacity of the array + */ void lv_array_resize(lv_array_t * array, uint32_t new_capacity); -void lv_array_destroy(lv_array_t * array); +/** + * Deinit the array, and free the allocated memory + * @param array pointer to an `lv_array_t` variable to deinitialize + */ +void lv_array_deinit(lv_array_t * array); -bool lv_array_append(lv_array_t * array, const uint8_t * element); +/** + * Return how many elements are stored in the array. + * @param array pointer to an `lv_array_t` variable + * @return the number of elements stored in the array + */ +static inline uint32_t lv_array_size(const lv_array_t * array) +{ + return array->size; +} -uint8_t * lv_array_get(const lv_array_t * array, uint32_t index); +/** + * Return the capacity of the array, i.e. how many elements can be stored. + * @param array pointer to an `lv_array_t` variable + * @return the capacity of the array + */ +static inline uint32_t lv_array_capacity(const lv_array_t * array) +{ + return array->capacity; +} -uint32_t lv_array_length(const lv_array_t * array); +/** + * Return if the array is empty + * @param array pointer to an `lv_array_t` variable + * @return true: array is empty; false: array is not empty + */ +static inline bool lv_array_is_empty(const lv_array_t * array) +{ + return array->size == 0; +} -uint32_t lv_array_capacity(const lv_array_t * array); +/** + * Return if the array is full + * @param array pointer to an `lv_array_t` variable + * @return true: array is full; false: array is not full + */ +static inline bool lv_array_is_full(const lv_array_t * array) +{ + return array->size == array->capacity; +} -bool lv_array_is_empty(const lv_array_t * array); +/** + * Copy an array to another. + * @note this will create a new array with the same capacity and size as the source array. + * @param target pointer to an `lv_array_t` variable to copy to + * @param source pointer to an `lv_array_t` variable to copy from + */ +void lv_array_copy(lv_array_t * target, const lv_array_t * source); + +/** + * Remove all elements in array. + * @param array pointer to an `lv_array_t` variable + */ +static inline void lv_array_clear(lv_array_t * array) +{ + array->size = 0; +} + +/** + * Remove the element at the specified position in the array. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to remove + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_remove(lv_array_t * array, uint32_t index); + +/** + * Remove from the array either a single element or a range of elements ([start, end)). + * @note This effectively reduces the container size by the number of elements removed. + * @note When start equals to end, the function has no effect. + * @param array pointer to an `lv_array_t` variable + * @param start the index of the first element to be removed + * @param end the index of the first element that is not to be removed + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end); + +/** + * Concatenate two arrays. Adds new elements to the end of the array. + * @note The destination array is automatically expanded as necessary. + * @param array pointer to an `lv_array_t` variable + * @param other pointer to the array to concatenate + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other); + +/** + * Push back element. Adds a new element to the end of the array. + * If the array capacity is not enough for the new element, the array will be resized automatically. + * @param array pointer to an `lv_array_t` variable + * @param element pointer to the element to add + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_push_back(lv_array_t * array, const void * element); + +/** + * Assigns one content to the array, replacing its current content. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to replace + * @param value pointer to the elements to add + * @return true: success; false: error + */ +lv_result_t lv_array_assign(lv_array_t * array, uint32_t index, const void * value); + +/** + * Returns a pointer to the element at position n in the array. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to return + * @return a pointer to the requested element, NULL if `index` is out of range + */ +void * lv_array_at(const lv_array_t * array, uint32_t index); + +/** + * Returns a pointer to the first element in the array. + * @param array pointer to an `lv_array_t` variable + * @return a pointer to the first element in the array + */ +static inline void * lv_array_front(const lv_array_t * array) +{ + return lv_array_at(array, 0); +} + +/** + * Returns a pointer to the last element in the array. + * @param array pointer to an `lv_array_t` variable + */ +static inline void * lv_array_back(const lv_array_t * array) +{ + return lv_array_at(array, lv_array_size(array) - 1); +} -bool lv_array_is_full(const lv_array_t * array); /********************** * MACROS **********************/ -#define LV_ARRAY_INIT(array, type) lv_array_init((array), DEFAULT_CAPS, sizeof(type)) - -#define LV_ARRAY_INIT_CAPACITY(array, caps, type) lv_array_init((array), (caps), sizeof(type)) - -#define LV_ARRAY_APPEND_VALUE(array, element) lv_array_append((array), (uint8_t*)&(element)) - -#define LV_ARRAY_APPEND(array, element) lv_array_append((array), (uint8_t*)(element)) - -#define LV_ARRAY_GET(array, index, type) (type*)lv_array_get((array), (index)) - -#define LV_ARRAY_SET(array, index, data, type) \ - do { \ - type* elem = (type*)lv_array_get((array), (index)); \ - *elem = *((type*)(data)); \ - } while(0) - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/tests/src/test_cases/test_array.c b/tests/src/test_cases/test_array.c index 93fc0a43eb..d8f7aa2a2a 100644 --- a/tests/src/test_cases/test_array.c +++ b/tests/src/test_cases/test_array.c @@ -7,70 +7,96 @@ static lv_array_t array; void setUp(void) { - LV_ARRAY_INIT(&array, int32_t); + lv_array_init(&array, LV_ARRAY_DEFAULT_CAPACITY, sizeof(int32_t)); } void tearDown(void) { - lv_array_destroy(&array); + lv_array_deinit(&array); } void test_array_append_values(void) { - for(int32_t i = 0; i < 10; i++) { - LV_ARRAY_APPEND_VALUE(&array, i); + const int32_t new_size = LV_ARRAY_DEFAULT_CAPACITY + 2; + TEST_ASSERT_EQUAL_UINT32(0, lv_array_size(&array)); + for(int32_t i = 0; i < new_size; i++) { + lv_array_push_back(&array, &i); } - - TEST_ASSERT_EQUAL_UINT32(8, lv_array_length(&array)); + /*push back will automatically extent the array size.*/ + TEST_ASSERT_EQUAL_UINT32(new_size, lv_array_size(&array)); } void test_array_set_get(void) { - uint32_t v = 100; - LV_ARRAY_SET(&array, 0, &v, uint32_t); - uint32_t * r = LV_ARRAY_GET(&array, 0, uint32_t); + int32_t v = 100; + lv_array_push_back(&array, &v); + int32_t * r = lv_array_at(&array, 0); TEST_ASSERT_EQUAL_UINT32(100, *r); } -void test_array_len(void) +void test_array_size(void) { for(int32_t i = 0; i < 10; i++) { - LV_ARRAY_APPEND_VALUE(&array, i); + lv_array_push_back(&array, &i); } TEST_ASSERT_EQUAL_UINT32(1, lv_array_is_full(&array) ? 1 : 0); - TEST_ASSERT_EQUAL_UINT32(8, lv_array_length(&array)); lv_array_clear(&array); TEST_ASSERT_EQUAL_UINT32(1, lv_array_is_empty(&array) ? 1 : 0); - TEST_ASSERT_EQUAL_UINT32(0, lv_array_length(&array)); + TEST_ASSERT_EQUAL_UINT32(0, lv_array_size(&array)); } void test_array_resize(void) { - for(int32_t i = 0; i < 10; i++) { - LV_ARRAY_APPEND_VALUE(&array, i); + for(int32_t i = 0; i < LV_ARRAY_DEFAULT_CAPACITY; i++) { + lv_array_push_back(&array, &i); } + TEST_ASSERT_EQUAL_UINT32(LV_ARRAY_DEFAULT_CAPACITY, lv_array_size(&array)); lv_array_resize(&array, 12); - TEST_ASSERT_EQUAL_UINT32(8, lv_array_length(&array)); + TEST_ASSERT_EQUAL_UINT32(LV_ARRAY_DEFAULT_CAPACITY, lv_array_size(&array)); + TEST_ASSERT_EQUAL_UINT32(12, lv_array_capacity(&array)); lv_array_resize(&array, 6); - TEST_ASSERT_EQUAL_UINT32(6, lv_array_length(&array)); + TEST_ASSERT_EQUAL_UINT32(6, lv_array_size(&array)); + TEST_ASSERT_EQUAL_UINT32(6, lv_array_capacity(&array)); } void test_array_copy(void) { - for(int32_t i = 0; i < 10; i++) { - LV_ARRAY_APPEND_VALUE(&array, i); + for(int32_t i = 0; i < LV_ARRAY_DEFAULT_CAPACITY; i++) { + lv_array_push_back(&array, &i); } - lv_array_t array2; - lv_memset(&array2, 0, sizeof(lv_array_t)); - TEST_ASSERT_EQUAL_UINT32(8, lv_array_length(&array)); + uint32_t array_size = lv_array_size(&array); + lv_array_t array2 = { 0 }; lv_array_copy(&array2, &array); - TEST_ASSERT_EQUAL_UINT32(8, lv_array_length(&array2)); - uint32_t * r = LV_ARRAY_GET(&array2, 1, uint32_t); + TEST_ASSERT_EQUAL_UINT32(array_size, lv_array_size(&array2)); + + uint32_t * r = lv_array_at(&array2, 1); TEST_ASSERT_EQUAL_UINT32(1, *r); - lv_array_destroy(&array2); + lv_array_deinit(&array2); +} + +void test_array_concat(void) +{ + lv_array_t a, b; + lv_array_init(&a, 4, sizeof(int32_t)); + lv_array_init(&b, 4, sizeof(int32_t)); + for(int32_t i = 0; i < 4; i++) { + lv_array_push_back(&a, &i); + lv_array_push_back(&b, &i); + } + + TEST_ASSERT_TRUE(lv_array_concat(&a, &b) == LV_RESULT_OK); + TEST_ASSERT_EQUAL_UINT32(8, lv_array_size(&a)); + + for(int32_t i = 0; i < 8; i++) { + int32_t * v = lv_array_at(&a, i); + TEST_ASSERT_EQUAL_INT32(i % 4, *v); + } + + lv_array_deinit(&a); + lv_array_deinit(&b); } #endif