feat: initial

This commit is contained in:
Alexey Zholtikov 2025-04-06 12:43:01 +03:00
parent 0ee1d9f4dc
commit c2243dfa4f
8 changed files with 379 additions and 8 deletions

6
.gitignore vendored
View File

@ -1,5 +1 @@
.DS_Store
.vscode
build
sdkconfig
sdkconfig.old
.DS_Store

View File

@ -1 +1 @@
idf_component_register(SRCS "main.c" INCLUDE_DIRS "include")
idf_component_register(SRCS "zh_vector.c" INCLUDE_DIRS "include")

View File

@ -1,3 +1,74 @@
# esp_component_template
# ESP32 ESP-IDF and ESP8266 RTOS SDK component for vector (dynamic array)
esp_component_template
## Tested on
1. ESP8266 RTOS_SDK v3.4
2. ESP32 ESP-IDF v5.4
## Features
1. Support of any data types.
2. The maximum size of the veсtor is 65535 elements.
## Using
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
```
In the application, add the component:
```c
#include "zh_vector.h"
```
## Example
Create, add, read, modify and delete items:
```c
#include "zh_vector.h"
zh_vector_t vector = {0};
char example[10] = {0};
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_NONE);
zh_vector_init(&vector, sizeof(example));
printf("Initial vector size is: %d\n", zh_vector_get_size(&vector));
strcpy(example, "Item 1");
zh_vector_push_back(&vector, &example);
strcpy(example, "Item 2");
zh_vector_push_back(&vector, &example);
strcpy(example, "Item 3");
zh_vector_push_back(&vector, &example);
strcpy(example, "Item 4");
zh_vector_push_back(&vector, &example);
strcpy(example, "Item 5");
zh_vector_push_back(&vector, &example);
printf("Add 5 items. New vector size is: %d\n", zh_vector_get_size(&vector));
for (uint16_t i = 0; i < zh_vector_get_size(&vector); ++i)
{
printf("Item position %d is: %s\n", i, (char *)zh_vector_get_item(&vector, i));
}
strcpy(example, "Item 6");
zh_vector_change_item(&vector, 3, &example);
printf("Change item on 3 position.\n");
for (uint16_t i = 0; i < zh_vector_get_size(&vector); ++i)
{
printf("Item position %d is: %s\n", i, (char *)zh_vector_get_item(&vector, i));
}
zh_vector_delete_item(&vector, 2);
printf("Delete item on 2 position. New vector size is: %d\n", zh_vector_get_size(&vector));
for (uint16_t i = 0; i < zh_vector_get_size(&vector); ++i)
{
printf("Item position %d is: %s\n", i, (char *)zh_vector_get_item(&vector, i));
}
zh_vector_free(&vector);
}
```

View File

115
include/zh_vector.h Normal file
View File

@ -0,0 +1,115 @@
#pragma once
#include "string.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct // Main structure of vector data.
{
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.
} zh_vector_t;
/**
* @brief Initialize vector.
*
* @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
*/
esp_err_t zh_vector_init(zh_vector_t *vector, uint16_t unit);
/**
* @brief Deinitialize vector. Free all allocated memory.
*
* @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
*/
esp_err_t zh_vector_free(zh_vector_t *vector);
/**
* @brief Get current vector size.
*
* @param[in] vector Pointer to main structure of vector data.
*
* @return
* - Vector size
* - ESP_FAIL if parameter error or vector not initialized
*/
esp_err_t zh_vector_get_size(zh_vector_t *vector);
/**
* @brief Add item at end of vector.
*
* @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
*/
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item);
/**
* @brief Change item by index.
*
* @param[in] vector Pointer to main structure of vector data.
* @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
*/
esp_err_t zh_vector_change_item(zh_vector_t *vector, uint16_t index, void *item);
/**
* @brief Get item by index.
*
* @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
*/
void *zh_vector_get_item(zh_vector_t *vector, uint16_t index);
/**
* @brief Delete item by index and shifts all elements in vector.
*
* @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
*/
esp_err_t zh_vector_delete_item(zh_vector_t *vector, uint16_t index);
#ifdef __cplusplus
}
#endif

0
main.c
View File

View File

@ -0,0 +1 @@
1.0.0

188
zh_vector.c Normal file
View File

@ -0,0 +1,188 @@
#include "zh_vector.h"
static const char *TAG = "zh_vector";
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;
}
vector->capacity = 0;
vector->size = 0;
vector->unit = unit;
vector->status = true;
ESP_LOGI(TAG, "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;
}
for (uint16_t i = 0; i < vector->size; ++i)
{
heap_caps_free(vector->items[i]);
}
vector->status = false;
ESP_LOGI(TAG, "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);
return vector->size;
}
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item)
{
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;
}
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;
}
}
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;
}
memcpy(vector->items[vector->size++], item, vector->unit);
ESP_LOGI(TAG, "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)
{
memcpy(vector->items[index], item, vector->unit);
ESP_LOGI(TAG, "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.");
if (vector == NULL)
{
ESP_LOGE(TAG, "Getting item from vector fail. Invalid argument.");
return NULL;
}
if (vector->status == false)
{
ESP_LOGE(TAG, "Getting item from vector fail. Vector not initialized.");
return NULL;
}
if (index < vector->size)
{
void *item = vector->items[index];
ESP_LOGI(TAG, "Getting item from vector success.");
return item;
}
else
{
ESP_LOGE(TAG, "Getting item from vector fail. Index does not exist.");
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)
{
heap_caps_free(vector->items[index]);
for (uint8_t i = index; i < (vector->size - 1); ++i)
{
vector->items[i] = vector->items[i + 1];
vector->items[i + 1] = NULL;
}
--vector->size;
_resize(vector, vector->capacity - 1);
ESP_LOGI(TAG, "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;
}
}
vector->capacity = capacity;
ESP_LOGI(TAG, "Vector resize success. New capacity: %d.", vector->capacity);
return ESP_OK;
}