feat!: main structure of vector changed to double pointer

This commit is contained in:
aZholtikov committed 2026-07-05 10:14:16 +03:00
1 parent d572e79a5b
commit c76486fa82
7 files changed
+599 -354

No files matched your search

+159 -98
View File
@@ -24,56 +24,58 @@
## Возможности
1. **Независимость от типа данных**: Поддерживает любой тип данных (целые числа, числа с плавающей точкой, структуры, пользовательские типы и т.д.)
2. **Автоматическое управление памятью**: Автоматическое выделение и освобождение памяти
3. **Динамическое изменение размера**: Емкость вектора увеличивается и уменьшается по мере необходимости
4. **Максимальная емкость**: До 65 535 элементов (ограничение 16-битного индекса)
5. **Оптимизировано под ESP-IDF**: Использует функции heap_caps для выделения памяти с параметрами памяти
6. **Обработка ошибок**: Комплексная проверка ошибок с детальным логированием
7. **Потокобезопасность**: Является потокобезопасным (использует FreeRTOS mutex)
8. **Минимальные накладные расходы**: Низкие накладные расходы на память и процессор
- **Независимость от типа данных**: Поддерживает любой тип данных (целые числа, числа с плавающей точкой, структуры, пользовательские типы и т.д.)
- **Автоматическое управление памятью**: Автоматическое выделение и освобождение памяти
- **Динамическое изменение размера**: Емкость вектора увеличивается и уменьшается по мере необходимости
- **Максимальная емкость**: До 65 535 элементов (ограничение 16-битного индекса)
- **Оптимизировано под ESP-IDF**: Использует функции heap_caps для выделения памяти с параметрами памяти
- **Обработка ошибок**: Комплексная проверка ошибок с детальным логированием
- **Потокобезопасность**: Является потокобезопасным (использует FreeRTOS mutex)
- **Минимальные накладные расходы**: Низкие накладные расходы на память и процессор
---
## Установка
1. Перейдите в каталог компонентов вашего проекта:
Перейдите в каталог компонентов вашего проекта:
```bash
cd ../ваш_проект/components
```
2. Клонируйте репозиторий:
Клонируйте репозиторий:
```bash
git clone https://github.com/aZholtikov/zh_vector
```
3. В вашем приложении подключите заголовочный файл:
В вашем приложении подключите заголовочный файл:
```c
#include "zh_vector.h"
```
4. Компонент будет автоматически собран вместе с вашим проектом.
Компонент будет автоматически собран вместе с вашим проектом.
---
## Справочник API
Все функции в этой библиотеке используют double pointer (`zh_vector_t **`) для параметра вектора, чтобы обеспечить правильное управление памятью и потокобезопасные операции.
### Структура zh_vector_t
```c
typedef struct
{
void **items; // Массив указателей на элементы вектора
uint16_t capacity; // Максимальная емкость вектора
uint16_t size; // Количество элементов в векторе
uint16_t unit; // Размер элемента вектора (в байтах)
bool is_initialized; // Флаг состояния инициализации вектора
SemaphoreHandle_t mutex; // FreeRTOS mutex для потокобезопасности
} zh_vector_t;
```
Структура объявляется как `typedef struct _zh_vector_t zh_vector_t;` и инкапсулирует внутренние детали реализации.
**Поля (внутренние):**
| Поле | Тип | Описание |
|------|-----|----------|
| `items` | `void **` | Массив указателей на элементы вектора. Items[0..size-1] являются валидными. Выделяется через heap_caps_calloc, перераспределяется через heap_caps_realloc. |
| `capacity` | `uint16_t` | Текущая выделенная емкость (количество слотов). Увеличивается при вставке — может превышать size после удалений. |
| `size` | `uint16_t` | Текущее количество элементов (0 ≤ size ≤ capacity). |
| `unit` | `uint16_t` | Размер (в байтах) одного элемента. Устанавливается при инициализации и не должен меняться. |
| `mutex` | `SemaphoreHandle_t` | FreeRTOS mutex. Создается в zh_vector_init, удаляется в zh_vector_free. Автоматически блокируется/разблокируется в публичных функциях. |
---
@@ -83,39 +85,44 @@ typedef struct
**Параметры:**
- `vector` - Указатель на структуру вектора
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Если указатель на вектор равен NULL, будет выделена память.
- `unit` - Размер каждого элемента в байтах
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор или нулевой размер unit)
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор или нулевой размер unit)
- `ESP_ERR_INVALID_STATE` - Вектор уже инициализирован
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
**Пример:**
```c
zh_vector_t vector = {0};
zh_vector_init(&vector, sizeof(int)); // Для целых чисел
zh_vector_t *vector = NULL;
esp_err_t ret = zh_vector_init(&vector, sizeof(int)); // Для целых чисел
if (ret != ESP_OK) {
// Обработка ошибки
}
// Не забудьте освободить: zh_vector_free(&vector);
```
---
### zh_vector_free()
Деинициализирует вектор и освобождает всю выделенную память.
Деинициализирует вектор и освобождает всю выделенную память. Устанавливает указатель на вектор в NULL.
**Параметры:**
- `vector` - Указатель на структуру вектора
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор)
- `ESP_ERR_INVALID_STATE` - Вектор не инициализирован
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или NULL указатель на вектор)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Вся динамически выделенная память элементов также освобождается.
**Примечание:** Вся динамически выделенная память элементов также освобождается. Указатель на вектор устанавливается в NULL после деинициализации.
---
@@ -125,12 +132,14 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
**Параметры:**
- `vector` - Указатель на структуру вектора
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `size` - Указатель на переменную для сохранения размера. Не должен быть NULL.
**Возвращает:**
- `>= 0` - Количество элементов (успех)
- `ESP_FAIL` - Ошибка (NULL вектор или не инициализирован)
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или size)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
---
@@ -140,15 +149,15 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
**Параметры:**
- `vector` - Указатель на структуру вектора
- `item` - Указатель на элемент для добавления
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `item` - Указатель на элемент для добавления. Не должен быть NULL.
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор или item)
- `ESP_ERR_INVALID_STATE` - Вектор не инициализирован
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или item)
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Функция выделяет память для копии элемента и копирует данные. Все существующие элементы сдвигаются на одну позицию вправо.
@@ -160,15 +169,15 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
**Параметры:**
- `vector` - Указатель на структуру вектора
- `item` - Указатель на элемент для добавления
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `item` - Указатель на элемент для добавления. Не должен быть NULL.
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор или item)
- `ESP_ERR_INVALID_STATE` - Вектор не инициализирован
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или item)
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Функция выделяет память для копии элемента и копирует данные.
@@ -180,34 +189,35 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
**Параметры:**
- `vector` - Указатель на структуру вектора
- `index` - Индекс элемента для изменения (начиная с 0)
- `item` - Указатель на новые данные элемента
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `index` - Индекс элемента для изменения (начиная с 0). Должен быть < размера вектора.
- `item` - Указатель на новые данные элемента. Не должен быть NULL.
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор, item или неверный индекс)
- `ESP_ERR_INVALID_STATE` - Вектор не инициализирован
- `ESP_FAIL` - Индекс вне границ
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор, item или неверный индекс)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
---
### zh_vector_get_item()
Получает элемент по определенному индексу.
Получает элемент по определенному индексу, копируя его в предоставленный буфер пользователя.
**Параметры:**
- `vector` - Указатель на структуру вектора
- `index` - Индекс элемента для получения (начиная с 0)
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `index` - Индекс элемента для получения (начиная с 0).
- `item` - Указатель на буфер размером не менее `unit` байт, куда будет скопирован элемент. Не должен быть NULL.
**Возвращает:**
- Указатель на элемент (успех)
- `NULL` - Ошибка (NULL вектор, не инициализирован или неверный индекс)
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор, NULL указатель item или неверный индекс)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Возвращает указатель на внутренние данные. Не освобождайте этот указатель.
**Примечание:** Эта функция копирует данные элемента в предоставленный буфер. Указатели не возвращаются.
---
@@ -217,17 +227,17 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
**Параметры:**
- `vector` - Указатель на структуру вектора
- `index` - Индекс элемента для удаления (начиная с 0)
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
- `index` - Индекс элемента для удаления (начиная с 0). Должен быть < размера вектора.
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL вектор)
- `ESP_ERR_INVALID_STATE` - Вектор не инициализирован
- `ESP_FAIL` - Индекс вне границ
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или неверный индекс)
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти (при перераспределении)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Все элементы после удаляемого индекса сдвигаются влево на одну позицию.
**Примечание:** Все элементы после удаляемого индекса сдвигаются влево на одну позицию. Память удаленного элемента освобождается.
---
@@ -238,36 +248,58 @@ zh_vector_init(&vector, sizeof(int)); // Для целых чисел
```c
#include "zh_vector.h"
zh_vector_t int_vector = {0};
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
zh_vector_t *vector = NULL;
// Инициализация вектора для целых чисел
zh_vector_init(&int_vector, sizeof(int));
esp_err_t ret = zh_vector_init(&vector, sizeof(int));
if (ret != ESP_OK) {
printf("Ошибка инициализации вектора\n");
return;
}
// Добавление элементов
int val1 = 10;
int val2 = 20;
int val3 = 30;
zh_vector_push_front(&int_vector, &val1);
zh_vector_push_back(&int_vector, &val2);
zh_vector_push_back(&int_vector, &val3);
printf("Размер вектора: %d\n", zh_vector_get_size(&int_vector));
// Доступ к элементам
for (int i = 0; i < zh_vector_get_size(&int_vector); i++) {
int *item = (int *)zh_vector_get_item(&int_vector, i);
printf("Элемент %d: %d\n", i, *item);
zh_vector_push_front(&vector, &val1);
zh_vector_push_back(&vector, &val2);
zh_vector_push_back(&vector, &val3);
size_t size;
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK) {
printf("Размер вектора: %zu\n", size);
}
// Доступ к элементам
for (int i = 0; i < size; i++) {
int item_value;
esp_err_t err = zh_vector_get_item(&vector, (uint16_t)i, &item_value);
if (err == ESP_OK) {
printf("Элемент %d: %d\n", i, item_value);
} else {
printf("Ошибка получения элемента %d: %s\n", i, esp_err_to_name(err));
}
}
// Изменение элемента
int new_val = 100;
zh_vector_change_item(&int_vector, 1, &new_val);
zh_vector_change_item(&vector, 1, &new_val);
// Удаление элемента
zh_vector_delete_item(&int_vector, 0);
zh_vector_delete_item(&vector, 0);
// Очистка
zh_vector_free(&int_vector);
zh_vector_free(&vector);
}
```
---
### Пример со структурой
```c
@@ -279,52 +311,82 @@ typedef struct {
float value;
} my_struct_t;
zh_vector_t struct_vector = {0};
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
zh_vector_t *vector = NULL;
// Инициализация вектора для структур
zh_vector_init(&struct_vector, sizeof(my_struct_t));
esp_err_t ret = zh_vector_init(&vector, sizeof(my_struct_t));
if (ret != ESP_OK) {
printf("Ошибка инициализации вектора\n");
return;
}
// Добавление элементов-структур
my_struct_t item1 = {1, "Item 1", 1.5f};
my_struct_t item2 = {2, "Item 2", 2.5f};
zh_vector_push_front(&struct_vector, &item1);
zh_vector_push_back(&struct_vector, &item2);
zh_vector_push_front(&vector, &item1);
zh_vector_push_back(&vector, &item2);
// Доступ и модификация
my_struct_t *ptr = (my_struct_t *)zh_vector_get_item(&struct_vector, 0);
ptr->value = 10.5f;
my_struct_t item_value;
esp_err_t err = zh_vector_get_item(&vector, 0, &item_value);
if (err == ESP_OK) {
item_value.value = 10.5f;
zh_vector_change_item(&vector, 0, &item_value);
}
// Очистка
zh_vector_free(&struct_vector);
zh_vector_free(&vector);
}
```
---
### Пример со строками (массивы символов)
```c
#include "zh_vector.h"
#include "string.h"
zh_vector_t string_vector = {0};
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
// Инициализация вектора для строк (макс. 100 символов)
zh_vector_t *vector = NULL;
char buffer[100] = {0};
zh_vector_init(&string_vector, sizeof(buffer));
// Инициализация вектора для строк (макс. 100 символов)
esp_err_t ret = zh_vector_init(&vector, sizeof(buffer));
if (ret != ESP_OK) {
printf("Ошибка инициализации вектора\n");
return;
}
// Добавление строк
strcpy(buffer, "Привет");
zh_vector_push_front(&string_vector, &buffer);
zh_vector_push_front(&vector, &buffer);
strcpy(buffer, "Мир");
zh_vector_push_back(&string_vector, &buffer);
// Печать всех строк
for (int i = 0; i < zh_vector_get_size(&string_vector); i++) {
char *str = (char *)zh_vector_get_item(&string_vector, i);
printf("Строка %d: %s\n", i, str);
zh_vector_push_back(&vector, &buffer);
size_t size;
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK) {
// Печать всех строк
for (int i = 0; i < size; i++) {
char str_value[100];
esp_err_t err = zh_vector_get_item(&vector, (uint16_t)i, str_value);
if (err == ESP_OK) {
printf("Строка %d: %s\n", i, str_value);
} else {
printf("Ошибка получения строки %d: %s\n", i, esp_err_to_name(err));
}
}
}
// Очистка
zh_vector_free(&string_vector);
zh_vector_free(&vector);
}
```
@@ -351,9 +413,8 @@ void app_main(void)
|------------|----------|
| `ESP_OK` | Операция выполнена успешно |
| `ESP_ERR_INVALID_ARG` | Неверный аргумент (NULL указатель или нулевой размер) |
| `ESP_ERR_INVALID_STATE` | Вектор не инициализирован или уже инициализирован |
| `ESP_ERR_INVALID_STATE` | Не удалось захватить mutex (редкий системный сбой) |
| `ESP_ERR_NO_MEM` | Ошибка выделения памяти (не хватает памяти) |
| `ESP_FAIL` | Общий сбой (например, индекс вне границ) |
---
@@ -405,4 +466,4 @@ void app_main(void)
---
*Сгенерировано для zh_vector v1.3.0*
*Сгенерировано для zh_vector v2.0.0*