Files
2026-06-15 18:52:56 +03:00

17 KiB

zh_vector - Компонент вектора (динамического массива) для ESP-IDF

Содержание


Обзор

zh_vector — это легковесный и эффективный компонент вектора (динамического массива) для ESP-IDF (Espressif IoT Development Framework). Он предоставляет гибкий контейнер, который может хранить элементы любого типа данных с автоматическим управлением памятью. Вектор автоматически изменяет размер при добавлении или удалении элементов, что делает его идеальным для динамического управления данными во встраиваемых системах.

Компонент разработан специально для микроконтроллеров ESP32 и использует функции управления кучей ESP-IDF для оптимального выделения памяти с различными параметрами памяти (внутренняя/внешняя RAM).


Возможности

  1. Независимость от типа данных: Поддерживает любой тип данных (целые числа, числа с плавающей точкой, структуры, пользовательские типы и т.д.)
  2. Автоматическое управление памятью: Автоматическое выделение и освобождение памяти
  3. Динамическое изменение размера: Емкость вектора увеличивается и уменьшается по мере необходимости
  4. Максимальная емкость: До 65 535 элементов (ограничение 16-битного индекса)
  5. Оптимизировано под ESP-IDF: Использует функции heap_caps для выделения памяти с параметрами памяти
  6. Обработка ошибок: Комплексная проверка ошибок с детальным логированием
  7. Потокобезопасность: Является потокобезопасным (использует FreeRTOS mutex)
  8. Минимальные накладные расходы: Низкие накладные расходы на память и процессор

Установка

  1. Перейдите в каталог компонентов вашего проекта:
cd ../ваш_проект/components
  1. Клонируйте репозиторий:
git clone https://github.com/aZholtikov/zh_vector
  1. В вашем приложении подключите заголовочный файл:
#include "zh_vector.h"
  1. Компонент будет автоматически собран вместе с вашим проектом.

Справочник API

Структура zh_vector_t

typedef struct
{
    void **items;            // Массив указателей на элементы вектора
    uint16_t capacity;       // Максимальная емкость вектора
    uint16_t size;           // Количество элементов в векторе
    uint16_t unit;           // Размер элемента вектора (в байтах)
    bool is_initialized;     // Флаг состояния инициализации вектора
    SemaphoreHandle_t mutex; // FreeRTOS mutex для потокобезопасности
} zh_vector_t;

zh_vector_init()

Инициализирует вектор.

Параметры:

  • vector - Указатель на структуру вектора
  • unit - Размер каждого элемента в байтах

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор или нулевой размер unit)
  • ESP_ERR_INVALID_STATE - Вектор уже инициализирован

Пример:

zh_vector_t vector = {0};
zh_vector_init(&vector, sizeof(int)); // Для целых чисел

zh_vector_free()

Деинициализирует вектор и освобождает всю выделенную память.

Параметры:

  • vector - Указатель на структуру вектора

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор)
  • ESP_ERR_INVALID_STATE - Вектор не инициализирован

Примечание: Вся динамически выделенная память элементов также освобождается.


zh_vector_get_size()

Получает текущее количество элементов в векторе.

Параметры:

  • vector - Указатель на структуру вектора

Возвращает:

  • >= 0 - Количество элементов (успех)
  • ESP_FAIL - Ошибка (NULL вектор или не инициализирован)

zh_vector_push_front()

Добавляет элемент в начало вектора.

Параметры:

  • vector - Указатель на структуру вектора
  • item - Указатель на элемент для добавления

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор или item)
  • ESP_ERR_INVALID_STATE - Вектор не инициализирован
  • ESP_ERR_NO_MEM - Ошибка выделения памяти

Примечание: Функция выделяет память для копии элемента и копирует данные. Все существующие элементы сдвигаются на одну позицию вправо.


zh_vector_push_back()

Добавляет элемент в конец вектора.

Параметры:

  • vector - Указатель на структуру вектора
  • item - Указатель на элемент для добавления

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор или item)
  • ESP_ERR_INVALID_STATE - Вектор не инициализирован
  • ESP_ERR_NO_MEM - Ошибка выделения памяти

Примечание: Функция выделяет память для копии элемента и копирует данные.


zh_vector_change_item()

Изменяет элемент по определенному индексу.

Параметры:

  • vector - Указатель на структуру вектора
  • index - Индекс элемента для изменения (начиная с 0)
  • item - Указатель на новые данные элемента

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор, item или неверный индекс)
  • ESP_ERR_INVALID_STATE - Вектор не инициализирован
  • ESP_FAIL - Индекс вне границ

zh_vector_get_item()

Получает элемент по определенному индексу.

Параметры:

  • vector - Указатель на структуру вектора
  • index - Индекс элемента для получения (начиная с 0)

Возвращает:

  • Указатель на элемент (успех)
  • NULL - Ошибка (NULL вектор, не инициализирован или неверный индекс)

Примечание: Возвращает указатель на внутренние данные. Не освобождайте этот указатель.


zh_vector_delete_item()

Удаляет элемент по определенному индексу и сдвигает все последующие элементы.

Параметры:

  • vector - Указатель на структуру вектора
  • index - Индекс элемента для удаления (начиная с 0)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL вектор)
  • ESP_ERR_INVALID_STATE - Вектор не инициализирован
  • ESP_FAIL - Индекс вне границ

Примечание: Все элементы после удаляемого индекса сдвигаются влево на одну позицию.


Примеры использования

Базовый пример: Вектор целых чисел

#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_init(&int_vector, sizeof(int));
    // Добавление элементов
    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);
    }
    // Изменение элемента
    int new_val = 100;
    zh_vector_change_item(&int_vector, 1, &new_val);
    // Удаление элемента
    zh_vector_delete_item(&int_vector, 0);
    // Очистка
    zh_vector_free(&int_vector);
}

Пример со структурой

#include "zh_vector.h"

typedef struct {
    int id;
    char name[32];
    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_init(&struct_vector, sizeof(my_struct_t));
    // Добавление элементов-структур
    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);
    // Доступ и модификация
    my_struct_t *ptr = (my_struct_t *)zh_vector_get_item(&struct_vector, 0);
    ptr->value = 10.5f;
    // Очистка
    zh_vector_free(&struct_vector);
}

Пример со строками (массивы символов)

#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 символов)
    char buffer[100] = {0};
    zh_vector_init(&string_vector, sizeof(buffer));
    // Добавление строк
    strcpy(buffer, "Привет");
    zh_vector_push_front(&string_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_free(&string_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 Вектор не инициализирован или уже инициализирован
ESP_ERR_NO_MEM Ошибка выделения памяти (не хватает памяти)
ESP_FAIL Общий сбой (например, индекс вне границ)

Вклад в проект

Вклад приветствуется! Чтобы внести свой вклад:

  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 для подробной информации.

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 v1.3.0