10 Commits

5 changed files with 90 additions and 155 deletions

View File

@@ -1,9 +1,12 @@
# ESP32 ESP-IDF and ESP8266 RTOS SDK component for vector (dynamic array)
# ESP32 ESP-IDF component for vector (dynamic array)
## Tested on
1. ESP8266 RTOS_SDK v3.4
2. ESP32 ESP-IDF v5.4
1. [ESP32 ESP-IDF v5.5.1](https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32/index.html)
## SAST Tools
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
## Features
@@ -16,7 +19,7 @@ In an existing project, run the following command to install the component:
```text
cd ../your_project/components
git clone http://git.zh.com.ru/alexey.zholtikov/zh_vector
git clone http://git.zh.com.ru/esp_components/zh_vector
```
In the application, add the component:
@@ -38,7 +41,7 @@ char example[10] = {0};
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_NONE);
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
zh_vector_init(&vector, sizeof(example));
printf("Initial vector size is: %d\n", zh_vector_get_size(&vector));
strcpy(example, "Item 1");

View File

View File

@@ -1,3 +1,7 @@
/**
* @file zh_vector.h
*/
#pragma once
#include "string.h"
@@ -10,13 +14,16 @@ extern "C"
{
#endif
typedef struct // Main structure of vector data.
/**
* @brief Main structure of vector data.
*/
typedef struct
{
void **items; // Array of pointers of vector items.
uint16_t capacity; // Maximum capacity of the vector. @note Used to control the size of allocated memory for array of pointers of vector items. Usually equal to the current number of items in the vector. Automatically changes when items are added or deleted.
uint16_t size; // Number of items in the vector. @note Can be read with zh_vector_get_size().
uint16_t unit; // Vector item size. @note Possible values from 1 to 65535.
bool status; // Vector initialization status flag. @note Used to prevent execution of vector functions without prior vector initialization.
void **items; /*!< Array of pointers of vector items. */
uint16_t capacity; /*!< Maximum capacity of the vector. @note Used to control the size of allocated memory for array of pointers of vector items. Usually equal to the current number of items in the vector. Automatically changes when items are added or deleted. */
uint16_t size; /*!< Number of items in the vector. */
uint16_t unit; /*!< Vector item size. */
bool is_initialized; /*!< Vector initialization status flag. */
} zh_vector_t;
/**
@@ -25,10 +32,7 @@ extern "C"
* @param[in] vector Pointer to main structure of vector data.
* @param[in] unit Size of vector item.
*
* @return
* - ESP_OK if initialization was success
* - ESP_ERR_INVALID_ARG if parameter error
* - ESP_ERR_INVALID_STATE if vector already initialized
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_vector_init(zh_vector_t *vector, uint16_t unit);
@@ -37,10 +41,7 @@ extern "C"
*
* @param[in] vector Pointer to main structure of vector data.
*
* @return
* - ESP_OK if deinitialization was success
* - ESP_ERR_INVALID_ARG if parameter error
* - ESP_ERR_INVALID_STATE if vector not initialized
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_vector_free(zh_vector_t *vector);
@@ -49,9 +50,7 @@ extern "C"
*
* @param[in] vector Pointer to main structure of vector data.
*
* @return
* - Vector size
* - ESP_FAIL if parameter error or vector not initialized
* @return Vector size if success or ESP_FAIL otherwise.
*/
esp_err_t zh_vector_get_size(zh_vector_t *vector);
@@ -61,11 +60,7 @@ extern "C"
* @param[in] vector Pointer to main structure of vector data.
* @param[in] item Pointer to item for add.
*
* @return
* - ESP_OK if add was success
* - ESP_ERR_INVALID_ARG if parameter error
* - ESP_ERR_NO_MEM if memory allocation fail or no free memory in the heap
* - ESP_ERR_INVALID_STATE if vector not initialized
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item);
@@ -76,11 +71,7 @@ extern "C"
* @param[in] index Index of item for change.
* @param[in] item Pointer to new data of item.
*
* @return
* - ESP_OK if change was success
* - ESP_ERR_INVALID_ARG if parameter error
* - ESP_ERR_INVALID_STATE if vector not initialized
* - ESP_FAIL if index does not exist
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_vector_change_item(zh_vector_t *vector, uint16_t index, void *item);
@@ -90,9 +81,7 @@ extern "C"
* @param[in] vector Pointer to main structure of vector data.
* @param[in] index Index of item for get.
*
* @return
* - Pointer to item
* - NULL if parameter error or vector not initialized or if index does not exist
* @return Pointer to item or NULL otherwise.
*/
void *zh_vector_get_item(zh_vector_t *vector, uint16_t index);
@@ -102,11 +91,7 @@ extern "C"
* @param[in] vector Pointer to main structure of vector data.
* @param[in] index Index of item for delete.
*
* @return
* - ESP_OK if delete was success
* - ESP_ERR_INVALID_ARG if parameter error
* - ESP_ERR_INVALID_STATE if vector not initialized
* - ESP_FAIL if index does not exist
* @return ESP_OK if success or an error code otherwise.
*/
esp_err_t zh_vector_delete_item(zh_vector_t *vector, uint16_t index);

View File

@@ -1 +1 @@
1.0.0
1.0.2

View File

@@ -2,159 +2,115 @@
static const char *TAG = "zh_vector";
#define ZH_LOGI(msg, ...) ESP_LOGI(TAG, msg, ##__VA_ARGS__)
#define ZH_LOGE(msg, err, ...) ESP_LOGE(TAG, "[%s:%d:%s] " msg, __FILE__, __LINE__, esp_err_to_name(err), ##__VA_ARGS__)
#define ZH_ERROR_CHECK(cond, err, cleanup, msg, ...) \
if (!(cond)) \
{ \
ZH_LOGE(msg, err, ##__VA_ARGS__); \
cleanup; \
return err; \
}
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity);
esp_err_t zh_vector_init(zh_vector_t *vector, uint16_t unit)
{
ESP_LOGI(TAG, "Vector initialization begin.");
if (vector == NULL || unit == 0)
{
ESP_LOGE(TAG, "Vector initialization fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (vector->status == true)
{
ESP_LOGE(TAG, "Vector initialization fail. Vector already initialized.");
return ESP_ERR_INVALID_STATE;
}
ZH_LOGI("Vector initialization begin.");
ZH_ERROR_CHECK(vector != NULL && unit != 0, ESP_ERR_INVALID_ARG, NULL, "Vector initialization failed. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == false, ESP_ERR_INVALID_STATE, NULL, "Vector initialization failed. Vector is already initialized.");
vector->capacity = 0;
vector->size = 0;
vector->unit = unit;
vector->status = true;
ESP_LOGI(TAG, "Vector initialization success.");
vector->is_initialized = true;
ZH_LOGI("Vector initialization success.");
return ESP_OK;
}
esp_err_t zh_vector_free(zh_vector_t *vector)
{
ESP_LOGI(TAG, "Vector deletion begin.");
if (vector == NULL)
{
ESP_LOGE(TAG, "Vector deletion fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (vector->status == false)
{
ESP_LOGE(TAG, "Vector deletion fail. Vector not initialized.");
return ESP_ERR_INVALID_STATE;
}
ZH_LOGI("Vector deletion begin.");
ZH_ERROR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Vector deletion failed. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == true, ESP_ERR_INVALID_STATE, NULL, "Vector deletion fail. Vector not initialized.");
for (uint16_t i = 0; i < vector->size; ++i)
{
heap_caps_free(vector->items[i]);
}
vector->status = false;
ESP_LOGI(TAG, "Vector deletion success.");
heap_caps_free(vector->items);
vector->is_initialized = false;
ZH_LOGI("Vector deletion success.");
return ESP_OK;
}
esp_err_t zh_vector_get_size(zh_vector_t *vector)
{
ESP_LOGI(TAG, "Getting vector size begin.");
if (vector == NULL || vector->status == false)
{
ESP_LOGE(TAG, "Getting vector size fail. Invalid argument or vector not initialized.");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Getting vector size success. Size: %d.", vector->size);
ZH_LOGI("Getting vector size begin.");
ZH_ERROR_CHECK(vector != NULL, ESP_FAIL, NULL, "Getting vector size fail. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == true, ESP_FAIL, NULL, "Getting vector size fail. Vector not initialized.");
ZH_LOGI("Getting vector size success.");
return vector->size;
}
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item)
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item) // -V2008
{
ESP_LOGI(TAG, "Adding item to vector begin.");
if (vector == NULL || item == NULL)
{
ESP_LOGE(TAG, "Adding item to vector fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (vector->status == false)
{
ESP_LOGE(TAG, "Adding item to vector fail. Vector not initialized.");
return ESP_ERR_INVALID_STATE;
}
ZH_LOGI("Adding item to vector begin.");
ZH_ERROR_CHECK(vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Adding item to vector fail. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == true, ESP_ERR_INVALID_STATE, NULL, "Adding item to vector fail. Vector not initialized.");
if (vector->capacity == vector->size)
{
if (_resize(vector, vector->capacity + 1) == ESP_ERR_NO_MEM)
{
ESP_LOGE(TAG, "Adding item to vector fail. Memory allocation fail or no free memory in the heap.");
return ESP_ERR_NO_MEM;
}
esp_err_t err = _resize(vector, vector->capacity + 1);
ZH_ERROR_CHECK(err == ESP_OK, err, NULL, "Adding item to vector fail. Memory allocation fail or no free memory in the heap.");
}
vector->items[vector->size] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
if (vector->items[vector->size] == NULL)
{
ESP_LOGE(TAG, "Adding item to vector fail. Memory allocation fail or no free memory in the heap.");
return ESP_ERR_NO_MEM;
}
ZH_ERROR_CHECK(vector->items[vector->size] != NULL, ESP_ERR_NO_MEM, NULL, "Adding item to vector fail. Memory allocation fail or no free memory in the heap.");
memcpy(vector->items[vector->size++], item, vector->unit);
ESP_LOGI(TAG, "Adding item to vector success.");
ZH_LOGI("Adding item to vector success.");
return ESP_OK;
}
esp_err_t zh_vector_change_item(zh_vector_t *vector, uint16_t index, void *item)
{
ESP_LOGI(TAG, "Changing item in vector begin.");
if (vector == NULL || item == NULL)
{
ESP_LOGE(TAG, "Changing item in vector fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (vector->status == false)
{
ESP_LOGE(TAG, "Changing item in vector fail. Vector not initialized.");
return ESP_ERR_INVALID_STATE;
}
if (index < vector->size)
{
ZH_LOGI("Changing item in vector begin.");
ZH_ERROR_CHECK(vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Changing item in vector fail. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == true, ESP_ERR_INVALID_STATE, NULL, "Changing item in vector fail. Vector not initialized.");
ZH_ERROR_CHECK(index < vector->size, ESP_FAIL, NULL, "Changing item in vector fail. Index does not exist.");
memcpy(vector->items[index], item, vector->unit);
ESP_LOGI(TAG, "Changing item in vector success.");
ZH_LOGI("Changing item in vector success.");
return ESP_OK;
}
ESP_LOGE(TAG, "Changing item in vector fail. Index does not exist.");
return ESP_FAIL;
}
void *zh_vector_get_item(zh_vector_t *vector, uint16_t index)
{
ESP_LOGI(TAG, "Getting item from vector begin.");
ZH_LOGI("Getting item from vector begin.");
if (vector == NULL)
{
ESP_LOGE(TAG, "Getting item from vector fail. Invalid argument.");
ZH_LOGE("Getting item from vector fail. Invalid argument.", ESP_ERR_INVALID_ARG);
return NULL;
}
if (vector->status == false)
if (vector->is_initialized == false)
{
ESP_LOGE(TAG, "Getting item from vector fail. Vector not initialized.");
ZH_LOGE("Getting item from vector fail. Vector not initialized.", ESP_ERR_INVALID_STATE);
return NULL;
}
if (index < vector->size)
{
void *item = vector->items[index];
ESP_LOGI(TAG, "Getting item from vector success.");
return item;
ZH_LOGI("Getting item from vector success.");
return vector->items[index];
}
else
{
ESP_LOGE(TAG, "Getting item from vector fail. Index does not exist.");
ZH_LOGE("Getting item from vector fail. Index does not exist.", ESP_FAIL);
return NULL;
}
}
esp_err_t zh_vector_delete_item(zh_vector_t *vector, uint16_t index)
{
ESP_LOGI(TAG, "Deleting item in vector begin.");
if (vector == NULL)
{
ESP_LOGE(TAG, "Deleting item in vector fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (vector->status == false)
{
ESP_LOGE(TAG, "Deleting item in vector fail. Vector not initialized.");
return ESP_ERR_INVALID_STATE;
}
if (index < vector->size)
{
ZH_LOGI("Deleting item in vector begin.");
ZH_ERROR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in vector fail. Invalid argument.");
ZH_ERROR_CHECK(vector->is_initialized == true, ESP_ERR_INVALID_STATE, NULL, "Deleting item in vector fail. Vector not initialized.");
ZH_ERROR_CHECK(index < vector->size, ESP_FAIL, NULL, "Deleting item in vector fail. Index does not exist.");
heap_caps_free(vector->items[index]);
for (uint8_t i = index; i < (vector->size - 1); ++i)
{
@@ -163,26 +119,17 @@ esp_err_t zh_vector_delete_item(zh_vector_t *vector, uint16_t index)
}
--vector->size;
_resize(vector, vector->capacity - 1);
ESP_LOGI(TAG, "Deleting item in vector success.");
ZH_LOGI("Deleting item in vector success.");
return ESP_OK;
}
ESP_LOGE(TAG, "Deleting item in vector fail. Index does not exist.");
return ESP_FAIL;
}
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity)
{
ESP_LOGI(TAG, "Vector resize begin.");
if (capacity != 0)
{
vector->items = heap_caps_realloc(vector->items, sizeof(void *) * capacity, MALLOC_CAP_8BIT);
if (vector->items == NULL)
{
ESP_LOGE(TAG, "Vector resize fail. Memory allocation fail or no free memory in the heap.");
return ESP_ERR_NO_MEM;
}
ZH_ERROR_CHECK(vector->items != NULL, ESP_ERR_NO_MEM, NULL, "Memory allocation fail or no free memory in the heap.");
}
vector->capacity = capacity;
ESP_LOGI(TAG, "Vector resize success. New capacity: %d.", vector->capacity);
return ESP_OK;
}