774 lines
35 KiB
Markdown
774 lines
35 KiB
Markdown
# zh_vector - Компонент вектора (динамического массива) для ESP-IDF
|
|
|
|
## Содержание
|
|
|
|
- [Обзор](#обзор)
|
|
- [Возможности](#возможности)
|
|
- [Установка](#установка)
|
|
- [Справочник API](#справочник-api)
|
|
- [Примеры использования](#примеры-использования)
|
|
- [Технические характеристики](#технические-характеристики)
|
|
- [Коды ошибок](#коды-ошибок)
|
|
- [Вклад в проект](#вклад-в-проект)
|
|
- [Лицензия](#лицензия)
|
|
|
|
---
|
|
|
|
## Обзор
|
|
|
|
`zh_vector` — это легковесный и эффективный компонент вектора (динамического массива) для ESP-IDF (Espressif IoT Development Framework). Он предоставляет гибкий контейнер, который может хранить элементы любого типа данных с автоматическим управлением памятью. Вектор автоматически изменяет размер при добавлении или удалении элементов, что делает его идеальным для динамического управления данными во встраиваемых системах.
|
|
|
|
Компонент разработан специально для микроконтроллеров ESP32 и использует функции управления кучей ESP-IDF для оптимального выделения памяти с различными параметрами памяти (внутренняя/внешняя RAM).
|
|
|
|
---
|
|
|
|
## Возможности
|
|
|
|
- **Независимость от типа данных**: Поддерживает любой тип данных (целые числа, числа с плавающей точкой, структуры, пользовательские типы и т.д.)
|
|
- **Автоматическое управление памятью**: Автоматическое выделение и освобождение памяти
|
|
- **Динамическое изменение размера**: Емкость вектора увеличивается и уменьшается по мере необходимости
|
|
- **Максимальная емкость**: До 65 535 элементов (ограничение 16-битного индекса)
|
|
- **Оптимизировано под ESP-IDF**: Использует функции heap_caps для выделения памяти с параметрами памяти
|
|
- **Обработка ошибок**: Комплексная проверка ошибок с детальным логированием
|
|
- **Потокобезопасность**: Является потокобезопасным (использует FreeRTOS mutex)
|
|
- **Минимальные накладные расходы**: Низкие накладные расходы на память и процессор
|
|
|
|
---
|
|
|
|
## Установка
|
|
|
|
Перейдите в каталог компонентов вашего проекта:
|
|
|
|
```bash
|
|
cd ../ваш_проект/components
|
|
```
|
|
|
|
Клонируйте репозиторий:
|
|
|
|
```bash
|
|
git clone https://github.com/aZholtikov/zh_vector
|
|
```
|
|
|
|
В вашем приложении подключите заголовочный файл:
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
```
|
|
|
|
Компонент будет автоматически собран вместе с вашим проектом.
|
|
|
|
---
|
|
|
|
## Справочник API
|
|
|
|
Все функции в этой библиотеке используют double pointer (`zh_vector_t **`) для параметра вектора, чтобы обеспечить правильное управление памятью и потокобезопасные операции.
|
|
|
|
### Структура 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. Автоматически блокируется/разблокируется в публичных функциях. |
|
|
|
|
---
|
|
|
|
### zh_vector_init()
|
|
|
|
Инициализирует вектор.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Если указатель на вектор равен NULL, будет выделена память.
|
|
- `unit` - Размер каждого элемента в байтах
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор или нулевой размер unit)
|
|
- `ESP_ERR_INVALID_STATE` - Вектор уже инициализирован
|
|
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
|
|
|
|
**Пример:**
|
|
|
|
```c
|
|
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` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или NULL указатель на вектор)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Вся динамически выделенная память элементов также освобождается. Указатель на вектор устанавливается в NULL после деинициализации.
|
|
|
|
---
|
|
|
|
### zh_vector_get_capacity()
|
|
|
|
Получает текущую выделенную емкость вектора (максимальное количество элементов без перераспределения).
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `capacity` - Указатель на переменную для сохранения емкости. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или capacity)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Емкость может быть больше текущего размера (например, после удалений), и уменьшается лениво при size < capacity/2 (или когда size становится 0).
|
|
|
|
---
|
|
|
|
### zh_vector_get_size()
|
|
|
|
Получает текущее количество элементов в векторе.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `size` - Указатель на переменную для сохранения размера. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или size)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
---
|
|
|
|
### zh_vector_push_front()
|
|
|
|
Добавляет элемент в начало вектора.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `item` - Указатель на элемент для добавления. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или item)
|
|
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Функция выделяет память для копии элемента и копирует данные. Все существующие элементы сдвигаются на одну позицию вправо.
|
|
|
|
---
|
|
|
|
### zh_vector_push_back()
|
|
|
|
Добавляет элемент в конец вектора.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `item` - Указатель на элемент для добавления. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или item)
|
|
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Функция выделяет память для копии элемента и копирует данные.
|
|
|
|
---
|
|
|
|
### zh_vector_change_item()
|
|
|
|
Изменяет элемент по определенному индексу.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `index` - Индекс элемента для изменения (начиная с 0). Должен быть < размера вектора.
|
|
- `item` - Указатель на новые данные элемента. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор, item или неверный индекс)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex или item равен NULL
|
|
|
|
---
|
|
|
|
### zh_vector_get_item()
|
|
|
|
Получает элемент по определенному индексу, копируя его в предоставленный буфер пользователя.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `index` - Индекс элемента для получения (начиная с 0).
|
|
- `item` - Указатель на буфер размером не менее `unit` байт, куда будет скопирован элемент. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор, NULL указатель item или неверный индекс)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Эта функция копирует данные элемента в предоставленный буфер. Указатели не возвращаются.
|
|
|
|
---
|
|
|
|
### zh_vector_delete_item()
|
|
|
|
Удаляет элемент по определенному индексу и сдвигает все последующие элементы.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `index` - Индекс элемента для удаления (начиная с 0). Должен быть < размера вектора.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или неверный индекс)
|
|
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти (при перераспределении)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Все элементы после удаляемого индекса сдвигаются влево на одну позицию. Память удаленного элемента освобождается.
|
|
|
|
---
|
|
|
|
### zh_vector_delete_back()
|
|
|
|
Удаляет последний элемент из вектора.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор, NULL вектор или вектор пуст)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Память удаленного элемента освобождается. Если размер падает ниже половины емкости, емкость уменьшается (такое же поведение, как в zh_vector_delete_item).
|
|
|
|
---
|
|
|
|
### zh_vector_delete_front()
|
|
|
|
Удаляет первый элемент из вектора.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор, NULL вектор или вектор пуст)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Память удаленного элемента освобождается, и все последующие элементы сдвигаются влево на одну позицию. Если размер падает ниже половины емкости, емкость уменьшается (такое же поведение, как в zh_vector_delete_item).
|
|
|
|
---
|
|
|
|
### zh_vector_find_item()
|
|
|
|
Находит первое вхождение элемента в векторе.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `item` - Указатель на элемент для поиска. Не должен быть NULL.
|
|
- `index` - Указатель на переменную для сохранения найденного индекса. Будет установлен в -1, если элемент не найден. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех (элемент найден)
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор, NULL указатель item или NULL указатель index)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
- `ESP_ERR_NOT_FOUND` - Элемент не найден (index установлен в -1)
|
|
|
|
**Примечание:** Использует memcmp для сравнения элементов. Возвращает индекс первого вхождения. Переменная index устанавливается в -1, если элемент не найден.
|
|
|
|
---
|
|
|
|
### zh_vector_find_item_in_field()
|
|
|
|
Находит первое вхождение значения в определенном поле внутри структур, хранящихся в векторе.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
- `sample_struct` - Указатель на образец структуры того же типа, что и хранится в векторе. Не должен быть NULL.
|
|
- `item` - Указатель на поле внутри структуры (например, `&sample.id`). Используется для вычисления смещения поля внутри структуры. Не должен быть NULL.
|
|
- `size` - Размер (в байтах) поля для сравнения. Должен быть > 0.
|
|
- `value` - Указатель на значение для поиска. Не должен быть NULL.
|
|
- `start` - Начальный индекс для поиска (начиная с 0). Должен быть < размера вектора.
|
|
- `index` - Указатель на переменную для сохранения найденного индекса. Будет установлен в -1, если значение не найдено. Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех (значение найдено)
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель, нулевой размер или неверный начальный индекс)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
- `ESP_ERR_NOT_FOUND` - Значение не найдено (index установлен в -1)
|
|
|
|
**Примечание:** Эта функция вычисляет смещение поля внутри структуры, используя указатели `item` и `sample_struct` (смещение = `item - sample_struct`), затем ищет указанное значение `value` в этом поле во всех элементах вектора, начиная с заданного индекса. Использует memcmp для сравнения. Полезно для поиска в векторах структур без копирования всей структуры.
|
|
|
|
---
|
|
|
|
### zh_vector_remove_duplicates()
|
|
|
|
Удаляет дублирующиеся элементы из вектора, оставляя только первое вхождение каждого элемента.
|
|
|
|
**Параметры:**
|
|
|
|
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL.
|
|
|
|
**Возвращает:**
|
|
|
|
- `ESP_OK` - Успех
|
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на указатель на вектор или NULL указатель на вектор)
|
|
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
|
|
|
|
**Примечание:** Использует memcmp для сравнения элементов. Сохраняется только первое вхождение каждого уникального элемента. Функция сохраняет порядок первых вхождений.
|
|
|
|
---
|
|
|
|
## Примеры использования
|
|
|
|
### Базовый пример: Вектор целых чисел
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
// Инициализация вектора для целых чисел
|
|
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(&vector, &val1);
|
|
zh_vector_push_back(&vector, &val2);
|
|
zh_vector_push_back(&vector, &val3);
|
|
uint16_t size = 0;
|
|
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 = 0;
|
|
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(&vector, 1, &new_val);
|
|
// Удаление элемента
|
|
zh_vector_delete_item(&vector, 0);
|
|
// Очистка
|
|
zh_vector_free(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Пример со структурой
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
typedef struct
|
|
{
|
|
int id;
|
|
char name[32];
|
|
float value;
|
|
} my_struct_t;
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
// Инициализация вектора для структур
|
|
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(&vector, &item1);
|
|
zh_vector_push_back(&vector, &item2);
|
|
// Доступ и модификация
|
|
my_struct_t item_value = {0};
|
|
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(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Пример со строками (массивы символов)
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
char buffer[100] = {0};
|
|
// Инициализация вектора для строк (макс. 100 символов)
|
|
esp_err_t ret = zh_vector_init(&vector, sizeof(buffer));
|
|
if (ret != ESP_OK)
|
|
{
|
|
printf("Ошибка инициализации вектора\n");
|
|
return;
|
|
}
|
|
// Добавление строк
|
|
strcpy(buffer, "Привет");
|
|
zh_vector_push_front(&vector, &buffer);
|
|
strcpy(buffer, "Мир");
|
|
zh_vector_push_back(&vector, &buffer);
|
|
uint16_t size = 0;
|
|
ret = zh_vector_get_size(&vector, &size);
|
|
if (ret == ESP_OK)
|
|
{
|
|
// Печать всех строк
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
char str_value[100] = {0};
|
|
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_remove_duplicates(&vector);
|
|
// Очистка
|
|
zh_vector_free(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Пример удаления дубликатов
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
// Инициализация вектора для целых чисел
|
|
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 = 10;
|
|
int val4 = 30;
|
|
int val5 = 20;
|
|
zh_vector_push_back(&vector, &val1);
|
|
zh_vector_push_back(&vector, &val2);
|
|
zh_vector_push_back(&vector, &val3);
|
|
zh_vector_push_back(&vector, &val4);
|
|
zh_vector_push_back(&vector, &val5);
|
|
uint16_t size = 0;
|
|
ret = zh_vector_get_size(&vector, &size);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Размер вектора перед удалением дубликатов: %zu\n", size);
|
|
}
|
|
// Удаление дубликатов
|
|
zh_vector_remove_duplicates(&vector);
|
|
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 = 0;
|
|
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));
|
|
}
|
|
}
|
|
// Очистка
|
|
zh_vector_free(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Пример поиска элемента
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
// Инициализация вектора для целых чисел
|
|
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_back(&vector, &val1);
|
|
zh_vector_push_back(&vector, &val2);
|
|
zh_vector_push_back(&vector, &val3);
|
|
// Поиск элемента
|
|
int search_item = 20;
|
|
int32_t found_index = -1;
|
|
ret = zh_vector_find_item(&vector, &search_item, &found_index);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Элемент %d найден по индексу %ld\n", search_item, found_index);
|
|
}
|
|
else
|
|
{
|
|
printf("Элемент %d не найден (index=%ld)\n", search_item, found_index);
|
|
}
|
|
// Поиск несуществующего элемента
|
|
search_item = 100;
|
|
found_index = -1;
|
|
ret = zh_vector_find_item(&vector, &search_item, &found_index);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Элемент %d найден по индексу %ld\n", search_item, found_index);
|
|
}
|
|
else
|
|
{
|
|
printf("Элемент %d не найден (index=%ld)\n", search_item, found_index);
|
|
}
|
|
// Очистка
|
|
zh_vector_free(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Пример поиска элемента по полю
|
|
|
|
```c
|
|
#include "zh_vector.h"
|
|
|
|
typedef struct
|
|
{
|
|
int id;
|
|
char name[32];
|
|
float value;
|
|
} my_struct_t;
|
|
|
|
void app_main(void)
|
|
{
|
|
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
zh_vector_t *vector = NULL;
|
|
// Инициализация вектора для структур
|
|
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};
|
|
my_struct_t item3 = {3, "Item 3", 3.5f};
|
|
zh_vector_push_back(&vector, &item1);
|
|
zh_vector_push_back(&vector, &item2);
|
|
zh_vector_push_back(&vector, &item3);
|
|
// Поиск структуры по значению поля (поиск по полю id)
|
|
int search_id = 2;
|
|
int32_t found_index = -1;
|
|
// Вычисление смещения поля 'id' внутри структуры
|
|
my_struct_t sample = {0};
|
|
ret = zh_vector_find_item_in_field(&vector, &sample, &sample.id, sizeof(sample.id), &search_id, 0, &found_index);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Структура с id=%d найдена по индексу %ld\n", search_id, found_index);
|
|
// Получение найденной структуры
|
|
my_struct_t found_item = {0};
|
|
ret = zh_vector_get_item(&vector, (uint16_t)found_index, &found_item);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Найденный элемент: id=%d, name=%s, value=%.1f\n", found_item.id, found_item.name, found_item.value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("Структура с id=%d не найдена (index=%ld)\n", search_id, found_index);
|
|
}
|
|
// Поиск несуществующего id
|
|
search_id = 100;
|
|
found_index = -1;
|
|
ret = zh_vector_find_item_in_field(&vector, &sample, &sample.id, sizeof(sample.id), &search_id, 0, &found_index);
|
|
if (ret == ESP_OK)
|
|
{
|
|
printf("Структура с id=%d найдена по индексу %ld\n", search_id, found_index);
|
|
}
|
|
else
|
|
{
|
|
printf("Структура с id=%d не найдена (index=%ld)\n", search_id, found_index);
|
|
}
|
|
// Очистка
|
|
zh_vector_free(&vector);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Технические характеристики
|
|
|
|
| Параметр | Значение |
|
|
|----------|----------|
|
|
| **Максимальная емкость** | 65 535 элементов |
|
|
| **Тип индекса** | uint16_t (16-бит) |
|
|
| **Управление памятью** | heap_caps_calloc, heap_caps_realloc, heap_caps_free |
|
|
| **Параметры памяти** | MALLOC_CAP_8BIT |
|
|
| **Потокобезопасность** | Является потокобезопасным (использует FreeRTOS mutex) |
|
|
| **Версия ESP-IDF** | >= 5.0 |
|
|
| **Платформа** | Серия ESP32 |
|
|
| **Язык** | C (C99) |
|
|
|
|
---
|
|
|
|
## Коды ошибок
|
|
|
|
| Код ошибки | Описание |
|
|
|------------|----------|
|
|
| `ESP_OK` | Операция выполнена успешно |
|
|
| `ESP_ERR_INVALID_ARG` | Неверный аргумент (NULL указатель или нулевой размер) |
|
|
| `ESP_ERR_INVALID_STATE` | Не удалось захватить mutex (редкий системный сбой) |
|
|
| `ESP_ERR_NO_MEM` | Ошибка выделения памяти (не хватает памяти) |
|
|
| `ESP_ERR_NOT_FOUND` | Элемент не найден (для zh_vector_find_item) |
|
|
|
|
---
|
|
|
|
## Вклад в проект
|
|
|
|
Вклад приветствуется! Чтобы внести свой вклад:
|
|
|
|
1. Сделайте форк репозитория
|
|
2. Создайте ветку функции (`git checkout -b feature/AmazingFeature`)
|
|
3. Закоммитьте ваши изменения (`git commit -m 'Add some AmazingFeature'`)
|
|
4. Отправьте в ветку (`git push origin feature/AmazingFeature`)
|
|
5. Откройте Pull Request
|
|
|
|
Пожалуйста, убедитесь, что ваш код следует существующему стилю и включает соответствующую документацию.
|
|
|
|
---
|
|
|
|
## Лицензия
|
|
|
|
Этот проект лицензирован по лицензии Apache, версия 2.0 - см. файл [LICENSE](LICENSE) для подробной информации.
|
|
|
|
### Apache License, Version 2.0
|
|
|
|
Авторское право (c) 2026 Алексей Жолтиков
|
|
|
|
Лицензировано по лицензии Apache License, Version 2.0 (далее — "Лицензия");
|
|
вы не можете использовать этот файл, кроме случаев, предусмотренных Лицензией.
|
|
Копию Лицензии можно получить по адресу:
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Если иное не требуется действующим законодательством или не согласовано в письменном виде,
|
|
программное обеспечение, распространяемое по Лицензии, распространяется на условиях "КАК ЕСТЬ",
|
|
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, явных или подразумеваемых, включая, но не ограничиваясь, гарантии
|
|
ТОВАРНОГО СОСТОЯНИЯ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ.
|
|
Смотрите Лицензию для получения конкретных прав и ограничений.
|
|
|
|
---
|
|
|
|
## Дополнительные заметки
|
|
|
|
- **Накладные расходы памяти**: Каждый элемент требует дополнительной памяти для указателя во внутреннем массиве указателей
|
|
- **Производительность**: O(1) для получения/установки по индексу, O(n) для вставки/удаления в середине
|
|
- **Лучшие практики**:
|
|
- Всегда инициализируйте вектор перед использованием
|
|
- Освобождайте вектор по завершении, чтобы избежать утечек памяти
|
|
- Учитывайте ограничение максимального размера (65 535 элементов)
|
|
- Для обработки строк рассмотрите использование буферов фиксированного размера
|
|
|
|
---
|
|
|
|
*Сгенерировано для zh_vector v2.5.0*
|