diff --git a/WIKI_EN.md b/WIKI_EN.md index 96512e8..498c12b 100644 --- a/WIKI_EN.md +++ b/WIKI_EN.md @@ -260,6 +260,27 @@ Deletes an element at a specific index and shifts all subsequent elements. --- +### zh_vector_find_item() + +Finds the first occurrence of an element in the vector. + +**Parameters:** + +- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL. +- `item` - Pointer to the element to find. Must not be NULL. +- `index` - Pointer to variable to store the found index. Will be set to -1 if element is not found. Must not be NULL. + +**Returns:** + +- `ESP_OK` - Success (element found) +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer, NULL item pointer, or NULL index pointer) +- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error) +- `ESP_ERR_NOT_FOUND` - Element not found (index set to -1) + +**Note:** Uses memcmp to compare elements. Returns the index of the first occurrence. The index variable is set to -1 if the element is not found. + +--- + ### zh_vector_remove_duplicates() Removes duplicate elements from the vector, keeping only the first occurrence of each element. @@ -467,6 +488,53 @@ void app_main(void) --- +### Find Item Example + +```c +#include "zh_vector.h" + +void app_main(void) +{ + esp_log_level_set("zh_vector", ESP_LOG_ERROR); + zh_vector_t *vector = NULL; + // Initialize vector for integers + esp_err_t ret = zh_vector_init(&vector, sizeof(int)); + if (ret != ESP_OK) { + printf("Vector initialization error\n"); + return; + } + // Add elements + 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); + // Find element + int search_item = 20; + int16_t found_index = -1; + ret = zh_vector_find_item(&vector, &search_item, &found_index); + if (ret == ESP_OK) { + printf("Element %d found at index %d\n", search_item, found_index); + } else { + printf("Element %d not found (index=%d)\n", search_item, found_index); + } + // Find non-existing element + search_item = 100; + found_index = -1; + ret = zh_vector_find_item(&vector, &search_item, &found_index); + if (ret == ESP_OK) { + printf("Element %d found at index %d\n", search_item, found_index); + } else { + printf("Element %d not found (index=%d)\n", search_item, found_index); + } + // Cleanup + zh_vector_free(&vector); +} +``` + +--- + ## Technical Specifications | Parameter | Value | @@ -490,6 +558,7 @@ void app_main(void) | `ESP_ERR_INVALID_ARG` | Invalid argument (NULL pointer or zero size) | | `ESP_ERR_INVALID_STATE` | Failed to acquire mutex (rare system error) | | `ESP_ERR_NO_MEM` | Memory allocation failed (out of memory) | +| `ESP_ERR_NOT_FOUND` | Element not found (for zh_vector_find_item) | --- @@ -541,4 +610,4 @@ limitations under the License. --- -*Generated for zh_vector v2.2.0* +*Generated for zh_vector v2.3.0* diff --git a/WIKI_RU.md b/WIKI_RU.md index 2aa5918..269d2c7 100644 --- a/WIKI_RU.md +++ b/WIKI_RU.md @@ -63,7 +63,7 @@ git clone https://github.com/aZholtikov/zh_vector Все функции в этой библиотеке используют double pointer (`zh_vector_t **`) для параметра вектора, чтобы обеспечить правильное управление памятью и потокобезопасные операции. -### Структура zh_vector_t +### zh_vector_t Structure Структура объявляется как `typedef struct _zh_vector_t zh_vector_t;` и инкапсулирует внутренние детали реализации. @@ -72,7 +72,7 @@ git clone https://github.com/aZholtikov/zh_vector | Поле | Тип | Описание | |------|-----|----------| | `items` | `void **` | Массив указателей на элементы вектора. Items[0..size-1] являются валидными. Выделяется через heap_caps_calloc, перераспределяется через heap_caps_realloc. | -| `capacity` | `uint16_t` | Текущая выделенная емкость (количество слотов). Увеличивае��ся при вставке — может превышать size после удалений. | +| `capacity` | `uint16_t` | Текущая выделенная емкость (количество слотов). Увеличивается при вставке — может превышать size после удалений. | | `size` | `uint16_t` | Текущее количество элементов (0 ≤ size ≤ capacity). | | `unit` | `uint16_t` | Размер (в байтах) одного элемента. Устанавливается при инициализации и не должен меняться. | | `mutex` | `SemaphoreHandle_t` | FreeRTOS mutex. Создается в zh_vector_init, удаляется в zh_vector_free. Автоматически блокируется/разблокируется в публичных функциях. | @@ -260,6 +260,27 @@ if (ret != ESP_OK) { --- +### 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_remove_duplicates() Удаляет дублирующиеся элементы из вектора, оставляя только первое вхождение каждого элемента. @@ -467,6 +488,53 @@ void app_main(void) --- +### Пример поиска элемента + +```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; + int16_t found_index = -1; + ret = zh_vector_find_item(&vector, &search_item, &found_index); + if (ret == ESP_OK) { + printf("Элемент %d найден по индексу %d\n", search_item, found_index); + } else { + printf("Элемент %d не найден (index=%d)\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 найден по индексу %d\n", search_item, found_index); + } else { + printf("Элемент %d не найден (index=%d)\n", search_item, found_index); + } + // Очистка + zh_vector_free(&vector); +} +``` + +--- + ## Технические характеристики | Параметр | Значение | @@ -490,6 +558,7 @@ void app_main(void) | `ESP_ERR_INVALID_ARG` | Неверный аргумент (NULL указатель или нулевой размер) | | `ESP_ERR_INVALID_STATE` | Не удалось захватить mutex (редкий системный сбой) | | `ESP_ERR_NO_MEM` | Ошибка выделения памяти (не хватает памяти) | +| `ESP_ERR_NOT_FOUND` | Элемент не найден (для zh_vector_find_item) | --- @@ -541,4 +610,4 @@ void app_main(void) --- -*Сгенерировано для zh_vector v2.2.0* +*Сгенерировано для zh_vector v2.3.0* \ No newline at end of file diff --git a/idf_component.yml b/idf_component.yml index 6a59c60..d9e23af 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -1,6 +1,6 @@ description: ESP32 ESP-IDF component for vector (dynamic array) url: https://github.com/aZholtikov/zh_vector -version: "2.2.0" +version: "2.3.0" license: "Apache-2.0" maintainers: - "Alexey Zholtikov " diff --git a/include/zh_vector.h b/include/zh_vector.h index caad5b7..bfc5766 100644 --- a/include/zh_vector.h +++ b/include/zh_vector.h @@ -211,6 +211,27 @@ extern "C" */ esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector); + /** + * @brief Searches for an item equal to the given data in the vector. + * + * Compares the provided item with each element in the vector using `memcmp`. + * If a match is found, its index (0‑based) is written to `*index` and `ESP_OK` is returned. + * If no match is found, `*index` is set to `-1` and `ESP_ERR_NOT_FOUND` is returned. + * + * @note Thread-safe: internally locks/unlocks the mutex. + * @note The search is linear O(n). + * + * @param[in] vector Double pointer to vector structure (`zh_vector_t **`). Must not be `NULL`. + * @param[in] item Pointer to the data to search for. Must not be `NULL`. + * @param[out] index Pointer to store the found index (0‑based) or `-1` if not found. Must not be `NULL`. + * + * @return ESP_OK if the item is found. + * @return ESP_ERR_NOT_FOUND if the item is not present in the vector. + * @return ESP_ERR_INVALID_ARG if any pointer argument is `NULL` or `*vector == NULL` (not initialized). + * @return ESP_ERR_INVALID_STATE if the internal mutex cannot be acquired (rare, system error). + */ + esp_err_t zh_vector_find_item(zh_vector_t **vector, const void *item, int16_t *index); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/version.txt b/version.txt index e3a4f19..cc6612c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.2.0 \ No newline at end of file +2.3.0 \ No newline at end of file diff --git a/zh_vector.c b/zh_vector.c index 859e9e0..96b602f 100644 --- a/zh_vector.c +++ b/zh_vector.c @@ -234,6 +234,27 @@ esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector) // -V2008 return ESP_OK; } +esp_err_t zh_vector_find_item(zh_vector_t **vector, const void *item, int16_t *index) +{ + ZH_LOGI("Finding item in vector begin."); + ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL && index != NULL, ESP_ERR_INVALID_ARG, NULL, "Finding item in vector failed. Invalid argument."); + ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Finding item in vector failed. Failed to acquire mutex."); + *index = -1; + for (uint16_t i = 0; i < (*vector)->size; ++i) + { + if (memcmp((*vector)->items[i], item, (*vector)->unit) == 0) + { + *index = (int16_t)i; + xSemaphoreGive((*vector)->mutex); + ZH_LOGI("Finding item in vector success (found)."); + return ESP_OK; + } + } + xSemaphoreGive((*vector)->mutex); + ZH_LOGI("Finding item in vector success (not found)."); + return ESP_ERR_NOT_FOUND; +} + static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity) { if (capacity < vector->size)