feat(circle_buff): add lv_circle_buf_t component
This commit is contained in:
1
lvgl.h
1
lvgl.h
@@ -34,6 +34,7 @@ extern "C" {
|
||||
#include "src/misc/lv_rb.h"
|
||||
#include "src/misc/lv_utils.h"
|
||||
#include "src/misc/lv_iter.h"
|
||||
#include "src/misc/lv_circle_buf.h"
|
||||
|
||||
#include "src/tick/lv_tick.h"
|
||||
|
||||
|
||||
@@ -42,13 +42,25 @@ void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size)
|
||||
array->element_size = element_size;
|
||||
|
||||
array->data = lv_malloc(capacity * element_size);
|
||||
array->inner_alloc = true;
|
||||
LV_ASSERT_MALLOC(array->data);
|
||||
}
|
||||
|
||||
void lv_array_init_from_buf(lv_array_t * array, void * buf, uint32_t capacity, uint32_t element_size)
|
||||
{
|
||||
LV_ASSERT_NULL(buf);
|
||||
array->size = 0;
|
||||
array->capacity = capacity;
|
||||
array->element_size = element_size;
|
||||
|
||||
array->data = buf;
|
||||
array->inner_alloc = false;
|
||||
}
|
||||
|
||||
void lv_array_deinit(lv_array_t * array)
|
||||
{
|
||||
if(array->data) {
|
||||
lv_free(array->data);
|
||||
if(array->inner_alloc) lv_free(array->data);
|
||||
array->data = NULL;
|
||||
}
|
||||
|
||||
@@ -122,15 +134,24 @@ lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end)
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
void lv_array_resize(lv_array_t * array, uint32_t new_capacity)
|
||||
bool lv_array_resize(lv_array_t * array, uint32_t new_capacity)
|
||||
{
|
||||
if(array->inner_alloc == false) {
|
||||
LV_LOG_WARN("Cannot resize array with external buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t * data = lv_realloc(array->data, new_capacity * array->element_size);
|
||||
LV_ASSERT_NULL(data);
|
||||
|
||||
if(data == NULL) return false;
|
||||
|
||||
array->data = data;
|
||||
array->capacity = new_capacity;
|
||||
if(array->size > new_capacity) {
|
||||
array->size = new_capacity;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other)
|
||||
@@ -139,7 +160,9 @@ lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other)
|
||||
uint32_t size = other->size;
|
||||
if(array->size + size > array->capacity) {
|
||||
/*array is full*/
|
||||
lv_array_resize(array, array->size + size);
|
||||
if(lv_array_resize(array, array->size + size) == false) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * data = array->data + array->size * array->element_size;
|
||||
@@ -154,7 +177,9 @@ lv_result_t lv_array_push_back(lv_array_t * array, const void * element)
|
||||
|
||||
if(array->size == array->capacity) {
|
||||
/*array is full*/
|
||||
lv_array_resize(array, array->capacity + LV_ARRAY_DEFAULT_CAPACITY);
|
||||
if(lv_array_resize(array, array->capacity + LV_ARRAY_DEFAULT_CAPACITY) == false) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,8 @@ struct _lv_array_t {
|
||||
uint32_t size;
|
||||
uint32_t capacity;
|
||||
uint32_t element_size;
|
||||
|
||||
bool inner_alloc; /* true: data is allocated by the array; false: data is allocated by the user */
|
||||
};
|
||||
|
||||
/**********************
|
||||
@@ -51,13 +53,24 @@ struct _lv_array_t {
|
||||
*/
|
||||
void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size);
|
||||
|
||||
/**
|
||||
* Init an array from a buffer.
|
||||
* @note The buffer must be large enough to store `capacity` elements. The array will not release the buffer and reallocate it.
|
||||
* The user must ensure that the buffer is valid during the lifetime of the array. And release the buffer when the array is no longer needed.
|
||||
* @param array pointer to an `lv_array_t` variable to initialize
|
||||
* @param buf pointer to a buffer to use as the array's data
|
||||
* @param capacity the initial capacity of the array
|
||||
* @param element_size the size of an element in bytes
|
||||
*/
|
||||
void lv_array_init_from_buf(lv_array_t * array, void * buf, uint32_t capacity, uint32_t element_size);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
bool lv_array_resize(lv_array_t * array, uint32_t new_capacity);
|
||||
|
||||
/**
|
||||
* Deinit the array, and free the allocated memory
|
||||
|
||||
296
src/misc/lv_circle_buf.c
Normal file
296
src/misc/lv_circle_buf.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* @file lv_circle_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_assert.h"
|
||||
|
||||
#include "lv_circle_buf.h"
|
||||
#include "lv_array.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_circle_buf_t {
|
||||
lv_array_t array;
|
||||
uint32_t head;
|
||||
uint32_t tail; /**< The next write position */
|
||||
|
||||
bool inner_alloc; /**< true: the array is allocated by the buffer, false: the array is created from an external buffer */
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_circle_buf_t * lv_circle_buf_create(const uint32_t capacity, const uint32_t element_size)
|
||||
{
|
||||
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
|
||||
LV_ASSERT_MALLOC(circle_buf);
|
||||
|
||||
if(circle_buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_array_init(&circle_buf->array, capacity, element_size);
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
circle_buf->inner_alloc = true;
|
||||
|
||||
circle_buf_prepare_empty(circle_buf);
|
||||
|
||||
return circle_buf;
|
||||
}
|
||||
|
||||
lv_circle_buf_t * lv_circle_buf_create_from_buf(void * buf, const uint32_t capacity, const uint32_t element_size)
|
||||
{
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
|
||||
LV_ASSERT_MALLOC(circle_buf);
|
||||
|
||||
if(circle_buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_array_init_from_buf(&circle_buf->array, buf, capacity, element_size);
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
circle_buf->inner_alloc = false;
|
||||
|
||||
circle_buf_prepare_empty(circle_buf);
|
||||
|
||||
return circle_buf;
|
||||
}
|
||||
|
||||
lv_circle_buf_t * lv_circle_buf_create_from_array(const lv_array_t * array)
|
||||
{
|
||||
LV_ASSERT_NULL(array);
|
||||
if(array == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
|
||||
LV_ASSERT_MALLOC(circle_buf);
|
||||
|
||||
if(circle_buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
circle_buf->array = *array;
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
circle_buf->inner_alloc = false;
|
||||
|
||||
circle_buf_prepare_empty(circle_buf);
|
||||
|
||||
return circle_buf;
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_resize(lv_circle_buf_t * circle_buf, const uint32_t capacity)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
if(lv_array_resize(&circle_buf->array, capacity) == false) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
|
||||
circle_buf_prepare_empty(circle_buf);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
void lv_circle_buf_destroy(lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
lv_array_deinit(&circle_buf->array);
|
||||
|
||||
lv_free(circle_buf);
|
||||
}
|
||||
|
||||
uint32_t lv_circle_buf_size(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return circle_buf->tail - circle_buf->head;
|
||||
}
|
||||
|
||||
uint32_t lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return lv_array_capacity(&circle_buf->array);
|
||||
}
|
||||
|
||||
uint32_t lv_circle_buf_remain(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return lv_circle_buf_capacity(circle_buf) - lv_circle_buf_size(circle_buf);
|
||||
}
|
||||
|
||||
bool lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return !lv_circle_buf_size(circle_buf);
|
||||
}
|
||||
|
||||
bool lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return !lv_circle_buf_remain(circle_buf);
|
||||
}
|
||||
|
||||
void lv_circle_buf_reset(lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
lv_array_clear(&circle_buf->array);
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
}
|
||||
|
||||
void * lv_circle_buf_head(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return lv_array_at(&circle_buf->array,
|
||||
circle_buf->head % lv_circle_buf_capacity(circle_buf));
|
||||
}
|
||||
|
||||
void * lv_circle_buf_tail(const lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
return lv_array_at(&circle_buf->array,
|
||||
circle_buf->tail % lv_circle_buf_capacity(circle_buf));
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_read(lv_circle_buf_t * circle_buf, void * data)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
if(lv_circle_buf_is_empty(circle_buf)) {
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_circle_buf_peek_at(circle_buf, 0, data);
|
||||
circle_buf->head++;
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_write(lv_circle_buf_t * circle_buf, const void * data)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
if(lv_circle_buf_is_full(circle_buf)) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_array_assign(&circle_buf->array, circle_buf->tail % lv_circle_buf_capacity(circle_buf), data);
|
||||
circle_buf->tail++;
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
uint32_t lv_circle_buf_fill(lv_circle_buf_t * circle_buf, uint32_t count, lv_circle_buf_fill_cb_t fill_cb,
|
||||
void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
LV_ASSERT_NULL(fill_cb);
|
||||
|
||||
uint32_t filled = 0;
|
||||
while(count > 0 && !lv_circle_buf_is_full(circle_buf)) {
|
||||
void * data = lv_circle_buf_tail(circle_buf);
|
||||
if(fill_cb(data, circle_buf->array.element_size, (int32_t)filled, user_data) == LV_RESULT_OK) {
|
||||
circle_buf->tail++;
|
||||
filled++;
|
||||
}
|
||||
else break;
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
return filled;
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_skip(lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
|
||||
if(lv_circle_buf_is_empty(circle_buf)) {
|
||||
circle_buf->head = 0;
|
||||
circle_buf->tail = 0;
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
circle_buf->head++;
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_peek(const lv_circle_buf_t * circle_buf, void * data)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
LV_ASSERT_NULL(data);
|
||||
|
||||
return lv_circle_buf_peek_at(circle_buf, 0, data);
|
||||
}
|
||||
|
||||
lv_result_t lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf, const uint32_t index, void * data)
|
||||
{
|
||||
LV_ASSERT_NULL(circle_buf);
|
||||
LV_ASSERT_NULL(data);
|
||||
|
||||
const uint32_t real_index = (index % lv_circle_buf_size(circle_buf) + circle_buf->head) % lv_circle_buf_capacity(
|
||||
circle_buf);
|
||||
lv_memcpy(data, lv_array_at(&circle_buf->array, real_index), circle_buf->array.element_size);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf)
|
||||
{
|
||||
const uint32_t required = lv_array_capacity(&circle_buf->array) - lv_array_size(&circle_buf->array);
|
||||
for(uint32_t i = 0; i < required; i++) lv_array_push_back(&circle_buf->array, NULL);
|
||||
}
|
||||
191
src/misc/lv_circle_buf.h
Normal file
191
src/misc/lv_circle_buf.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @file lv_circle_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_CIRCLE_BUF_H
|
||||
#define LV_CIRCLE_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef bool (*lv_circle_buf_fill_cb_t)(void * buf, uint32_t buff_len, int32_t index, void * user_data);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a circle buffer
|
||||
* @param capacity the maximum number of elements in the buffer
|
||||
* @param element_size the size of an element in bytes
|
||||
* @return pointer to the created buffer
|
||||
*/
|
||||
lv_circle_buf_t * lv_circle_buf_create(uint32_t capacity, uint32_t element_size);
|
||||
|
||||
/**
|
||||
* Create a circle buffer from an existing buffer
|
||||
* @param buf pointer to a buffer
|
||||
* @param capacity the maximum number of elements in the buffer
|
||||
* @param element_size the size of an element in bytes
|
||||
* @return pointer to the created buffer
|
||||
*/
|
||||
lv_circle_buf_t * lv_circle_buf_create_from_buf(void * buf, uint32_t capacity, uint32_t element_size);
|
||||
|
||||
/**
|
||||
* Create a circle buffer from an existing array
|
||||
* @param array pointer to an array
|
||||
* @return pointer to the created buffer
|
||||
*/
|
||||
lv_circle_buf_t * lv_circle_buf_create_from_array(const lv_array_t * array);
|
||||
|
||||
/**
|
||||
* Resize the buffer
|
||||
* @param circle_buf pointer to a buffer
|
||||
* @param capacity the new capacity of the buffer
|
||||
* @return LV_RESULT_OK: the buffer is resized; LV_RESULT_INVALID: the buffer is not resized
|
||||
*/
|
||||
lv_result_t lv_circle_buf_resize(lv_circle_buf_t * circle_buf, uint32_t capacity);
|
||||
|
||||
/**
|
||||
* Destroy a circle buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
*/
|
||||
void lv_circle_buf_destroy(lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Get the size of the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return the number of elements in the buffer
|
||||
*/
|
||||
uint32_t lv_circle_buf_size(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Get the capacity of the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return the maximum number of elements in the buffer
|
||||
*/
|
||||
uint32_t lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Get the remaining space in the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return the number of elements that can be written to the buffer
|
||||
*/
|
||||
uint32_t lv_circle_buf_remain(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Check if the buffer is empty
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return true: the buffer is empty; false: the buffer is not empty
|
||||
*/
|
||||
bool lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Check if the buffer is full
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return true: the buffer is full; false: the buffer is not full
|
||||
*/
|
||||
bool lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Reset the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return LV_RESULT_OK: the buffer is reset; LV_RESULT_INVALID: the buffer is not reset
|
||||
*/
|
||||
void lv_circle_buf_reset(lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Get the head of the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return pointer to the head of the buffer
|
||||
*/
|
||||
void * lv_circle_buf_head(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Get the tail of the buffer
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return pointer to the tail of the buffer
|
||||
*/
|
||||
void * lv_circle_buf_tail(const lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Read a value
|
||||
* @param circle_buf pointer to buffer
|
||||
* @param data pointer to a variable to store the read value
|
||||
* @return LV_RESULT_OK: the value is read; LV_RESULT_INVALID: the value is not read
|
||||
*/
|
||||
lv_result_t lv_circle_buf_read(lv_circle_buf_t * circle_buf, void * data);
|
||||
|
||||
/**
|
||||
* Write a value
|
||||
* @param circle_buf pointer to buffer
|
||||
* @param data pointer to the value to write
|
||||
* @return LV_RESULT_OK: the value is written; LV_RESULT_INVALID: the value is not written
|
||||
*/
|
||||
lv_result_t lv_circle_buf_write(lv_circle_buf_t * circle_buf, const void * data);
|
||||
|
||||
/**
|
||||
* Fill the buffer with values
|
||||
* @param circle_buf pointer to buffer
|
||||
* @param count the number of values to fill
|
||||
* @param fill_cb the callback function to fill the buffer
|
||||
* @param user_data
|
||||
* @return the number of values filled
|
||||
*/
|
||||
uint32_t lv_circle_buf_fill(lv_circle_buf_t * circle_buf, uint32_t count, lv_circle_buf_fill_cb_t fill_cb,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Skip a value
|
||||
* @param circle_buf pointer to buffer
|
||||
* @return LV_RESULT_OK: the value is skipped; LV_RESULT_INVALID: the value is not skipped
|
||||
*/
|
||||
lv_result_t lv_circle_buf_skip(lv_circle_buf_t * circle_buf);
|
||||
|
||||
/**
|
||||
* Peek a value
|
||||
* @param circle_buf pointer to buffer
|
||||
* @param data pointer to a variable to store the peeked value
|
||||
* @return LV_RESULT_OK: the value is peeked; LV_RESULT_INVALID: the value is not peeked
|
||||
*/
|
||||
lv_result_t lv_circle_buf_peek(const lv_circle_buf_t * circle_buf, void * data);
|
||||
|
||||
/**
|
||||
* Peek a value at an index
|
||||
* @param circle_buf pointer to buffer
|
||||
* @param index the index of the value to peek, if the index is greater than the size of the buffer, it will return looply.
|
||||
* @param data pointer to a variable to store the peeked value
|
||||
* @return LV_RESULT_OK: the value is peeked; LV_RESULT_INVALID: the value is not peeked
|
||||
*/
|
||||
lv_result_t lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf, uint32_t index, void * data);
|
||||
|
||||
/*************************
|
||||
* GLOBAL VARIABLES
|
||||
*************************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_CIRCLE_BUF_H*/
|
||||
@@ -326,6 +326,8 @@ typedef struct _lv_array_t lv_array_t;
|
||||
|
||||
typedef struct _lv_iter_t lv_iter_t;
|
||||
|
||||
typedef struct _lv_circle_buf_t lv_circle_buf_t;
|
||||
|
||||
typedef struct _lv_draw_buf_t lv_draw_buf_t;
|
||||
|
||||
#if LV_USE_OBJ_PROPERTY
|
||||
|
||||
167
tests/src/test_cases/test_circle_buf.c
Normal file
167
tests/src/test_cases/test_circle_buf.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
#include "../../lvgl_private.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
static lv_circle_buf_t * circle_buf;
|
||||
|
||||
#define circle_buf_CAPACITY 4
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
circle_buf = lv_circle_buf_create(circle_buf_CAPACITY, sizeof(int32_t));
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_capacity(circle_buf), circle_buf_CAPACITY);
|
||||
TEST_ASSERT_EQUAL_UINT32(0, lv_circle_buf_size(circle_buf));
|
||||
|
||||
/**
|
||||
* Write values to the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||
* When the buffer is full, the write operation should return LV_RESULT_INVALID.
|
||||
*/
|
||||
for(int32_t i = 0; i < circle_buf_CAPACITY * 2; i++) {
|
||||
const lv_result_t res = lv_circle_buf_write(circle_buf, &i);
|
||||
|
||||
if(i < circle_buf_CAPACITY) TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
else TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* After writing values to the buffer, the size of the buffer should be equal to the capacity.
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_UINT32(lv_circle_buf_size(circle_buf), circle_buf_CAPACITY);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
lv_circle_buf_destroy(circle_buf);
|
||||
circle_buf = NULL;
|
||||
}
|
||||
|
||||
void test_circle_buf_read_write_peek_values(void)
|
||||
{
|
||||
/**
|
||||
* Read 1 value from the buffer.
|
||||
*/
|
||||
{
|
||||
int32_t value;
|
||||
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
TEST_ASSERT_EQUAL_INT32(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek values will not advance the read and write cursors.
|
||||
* If the peek index is greater than the size of the buffer, it will returns looply.
|
||||
*/
|
||||
for(int32_t i = 0, j = 1; i < circle_buf_CAPACITY * 10; i++, j++) {
|
||||
int32_t value;
|
||||
const lv_result_t res = lv_circle_buf_peek_at(circle_buf, i, &value);
|
||||
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
TEST_ASSERT_EQUAL_INT32(j, value);
|
||||
|
||||
if(j == 3) j = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
|
||||
*/
|
||||
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||
int32_t value;
|
||||
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||
|
||||
if(i < circle_buf_CAPACITY) {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
TEST_ASSERT_EQUAL_INT32(i, value);
|
||||
}
|
||||
else {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After reading values from the buffer, the size of the buffer should be equal to 0.
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
|
||||
}
|
||||
|
||||
void test_circle_buf_skip_values(void)
|
||||
{
|
||||
/**
|
||||
* Skip 1 value from the buffer.
|
||||
*/
|
||||
{
|
||||
const lv_result_t res = lv_circle_buf_skip(circle_buf);
|
||||
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||
* When the buffer is empty, the skip operation should return LV_RESULT_INVALID.
|
||||
*/
|
||||
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||
const lv_result_t res = lv_circle_buf_skip(circle_buf);
|
||||
|
||||
if(i < circle_buf_CAPACITY) {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
}
|
||||
else {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After skipping values from the buffer, the size of the buffer should be equal to 0.
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT32(0, lv_circle_buf_size(circle_buf));
|
||||
}
|
||||
|
||||
void test_circle_buf_read_after_read_and_write(void)
|
||||
{
|
||||
/**
|
||||
* Read 1 value from the buffer.
|
||||
*/
|
||||
{
|
||||
int32_t value;
|
||||
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
TEST_ASSERT_EQUAL_INT32(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 1 value to the buffer.
|
||||
*/
|
||||
{
|
||||
const int32_t value = 4;
|
||||
const lv_result_t res = lv_circle_buf_write(circle_buf, &value);
|
||||
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
}
|
||||
|
||||
const int32_t expected[] = {4, 1, 2, 3};
|
||||
TEST_ASSERT_EQUAL_INT32_ARRAY(expected, ((lv_array_t *)circle_buf)->data, 4);
|
||||
|
||||
/**
|
||||
* Read values from the circle buffer. The max size of the buffer is circle_buf_CAPACITY.
|
||||
* When the buffer is empty, the read operation should return LV_RESULT_INVALID.
|
||||
*/
|
||||
for(int32_t i = 1; i < circle_buf_CAPACITY * 2; i++) {
|
||||
int32_t value;
|
||||
const lv_result_t res = lv_circle_buf_read(circle_buf, &value);
|
||||
|
||||
if(i <= circle_buf_CAPACITY) {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
|
||||
TEST_ASSERT_EQUAL_INT32(i, value);
|
||||
}
|
||||
else {
|
||||
TEST_ASSERT_EQUAL(LV_RESULT_INVALID, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user