doc: updated readme

This commit is contained in:
aZholtikov committed 2026-08-30 17:37:50 +03:00
1 parent fb17cd1844
commit 865acc77a2
4 files changed
+310 -1567

No files matched your search

+305 -10
View File
@@ -1,13 +1,5 @@
# ESP32 ESP-IDF component for vector (dynamic array)
## Wiki
[EN](WIKI_EN.md) | [RU](WIKI_RU.md)
## Tested on
1. [ESP32 ESP-IDF v6.0.0](https://docs.espressif.com/projects/esp-idf/en/v6.0/esp32/index.html)
## SAST Tools
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
@@ -26,7 +18,7 @@
In an existing project, run the following command to install the component:
```text
```bash
cd ../your_project/components
git clone https://github.com/aZholtikov/zh_vector
```
@@ -39,4 +31,307 @@ In the application, add the component:
## Examples
See Wiki [EN](WIKI_EN.md#usage-examples) | [RU](WIKI_RU.md#примеры-использования)
### Basic Example: Integer Vector
```c
#include "zh_vector.h"
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, sizeof(int));
if (ret != ESP_OK)
{
printf("Vector initialization error\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("Vector size: %u\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("Element %d: %d\n", i, item_value);
}
else
{
printf("Error getting element %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);
}
```
### Struct Example
```c
#include "zh_vector.h"
typedef struct
{
int id;
char name[32];
float value;
} my_struct_t;
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, sizeof(my_struct_t));
if (ret != ESP_OK)
{
printf("Vector initialization error\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);
}
```
### String Example (Char Arrays)
```c
#include "zh_vector.h"
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, 100);
if (ret != ESP_OK)
{
printf("Vector initialization error\n");
return;
}
char *str1 = malloc(100);
char *str2 = malloc(100);
if (str1 && str2)
{
strcpy(str1, "Hello");
strcpy(str2, "World");
zh_vector_push_back(&vector, str1);
zh_vector_push_back(&vector, str2);
free(str1);
free(str2);
}
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("String %d: %s\n", i, str_value);
}
else
{
printf("Error getting string %d: %s\n", i, esp_err_to_name(err));
}
}
}
zh_vector_remove_duplicates(&vector);
zh_vector_free(&vector);
}
```
### Remove Duplicates Example
```c
#include "zh_vector.h"
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, sizeof(int));
if (ret != ESP_OK)
{
printf("Vector initialization error\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("Vector size before removing duplicates: %u\n", size);
}
zh_vector_remove_duplicates(&vector);
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK)
{
printf("Vector size after removing duplicates: %u\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("Element %d: %d\n", i, item_value);
}
else
{
printf("Error getting element %d: %s\n", i, esp_err_to_name(err));
}
}
zh_vector_free(&vector);
}
```
---
### Find Item Example
```c
#include "zh_vector.h"
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, sizeof(int));
if (ret != ESP_OK)
{
printf("Vector initialization error\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("Element %d found at index %d\n", search_item, (int)found_index);
}
else
{
printf("Element %d not found (index=%d)\n", search_item, (int)found_index);
}
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, (int)found_index);
}
else
{
printf("Element %d not found (index=%d)\n", search_item, (int)found_index);
}
zh_vector_free(&vector);
}
```
---
### Find Item in Field Example
```c
#include "zh_vector.h"
typedef struct
{
int id;
char name[32];
float value;
} my_struct_t;
zh_vector_t *vector = NULL;
void app_main(void)
{
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
esp_err_t ret = zh_vector_init(&vector, sizeof(my_struct_t));
if (ret != ESP_OK)
{
printf("Vector initialization error\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);
int search_id = 2;
int32_t found_index = -1;
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("Struct with id=%d found at index %d\n", search_id, (int)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("Found item: id=%d, name=%s, value=%.1f\n", found_item.id, found_item.name, found_item.value);
}
}
else
{
printf("Struct with id=%d not found (index=%d)\n", search_id, (int)found_index);
}
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("Struct with id=%d found at index %d\n", search_id, (int)found_index);
}
else
{
printf("Struct with id=%d not found (index=%d)\n", search_id, (int)found_index);
}
zh_vector_free(&vector);
}
```
-778
View File
@@ -1,778 +0,0 @@
# zh_vector - Vector (Dynamic Array) Component for ESP-IDF
## Table of Contents
- [Overview](#overview)
- [Features](#features)
- [Installation](#installation)
- [API Reference](#api-reference)
- [Usage Examples](#usage-examples)
- [Technical Specifications](#technical-specifications)
- [Error Codes](#error-codes)
- [Contributing](#contributing)
- [License](#license)
---
## Overview
`zh_vector` is a lightweight, efficient vector (dynamic array) component for ESP-IDF (Espressif IoT Development Framework). It provides a flexible container that can store elements of any data type with automatic memory management. The vector automatically resizes as items are added or removed, making it ideal for dynamic data management in embedded systems.
The component is designed specifically for ESP32 microcontrollers and uses ESP-IDF's heap management functions for optimal memory allocation with different memory caps (internal/external RAM).
---
## Features
1. **Type Agnostic**: Supports any data type (integers, floats, structs, custom types, etc.)
2. **Automatic Memory Management**: Automatic memory allocation and deallocation
3. **Dynamic Resizing**: Vector capacity grows and shrinks as needed
4. **Maximum Capacity**: Up to 65,535 elements (16-bit index limit)
5. **ESP-IDF Optimized**: Uses heap_caps functions for memory allocation with memory caps
6. **Error Handling**: Comprehensive error checking with detailed logging
7. **Thread-Safe**: Thread-safe (uses FreeRTOS mutex)
8. **Minimal Overhead**: Low memory and CPU overhead
---
## Installation
Navigate to your project's components directory:
```bash
cd ../your_project/components
```
Clone the repository:
```bash
git clone https://github.com/aZholtikov/zh_vector
```
In your application, include the header:
```c
#include "zh_vector.h"
```
The component will be automatically built with your project.
---
## API Reference
All functions in this library use double pointer (`zh_vector_t **`) for the vector parameter to allow for proper memory management and thread-safe operations.
### zh_vector_t Structure
The structure is declared as `typedef struct _zh_vector_t zh_vector_t;` and encapsulates internal implementation details.
**Fields (internal):**
| Field | Type | Description |
| ------- | ------ | ------------- |
| `items` | `void **` | Array of element pointers. Items[0..size-1] are valid. Allocated via heap_caps_calloc, reallocated via heap_caps_realloc. |
| `capacity` | `uint16_t` | Current allocated capacity (number of slots). Grows on insertion - may exceed size after deletions. |
| `size` | `uint16_t` | Current number of elements (0 ≤ size ≤ capacity). |
| `unit` | `uint16_t` | Size (in bytes) of a single element. Set once in zh_vector_init() and immutable. |
| `mutex` | `SemaphoreHandle_t` | FreeRTOS mutex. Created in zh_vector_init(), deleted in zh_vector_free. Automatically locked/unlocked in public functions. |
---
### zh_vector_init()
Initializes the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must point to NULL for creating a new vector. Must be NULL
- `unit` - Size of each element in bytes. Must be > 0
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or zero unit size)
- `ESP_ERR_INVALID_STATE` - Vector already initialized
- `ESP_ERR_NO_MEM` - Memory allocation failed
**Example:**
```c
zh_vector_t *vector = NULL;
esp_err_t ret = zh_vector_init(&vector, sizeof(int)); // For integers
if (ret != ESP_OK) {
// Handle error
}
// Don't forget to free: zh_vector_free(&vector);
```
---
### zh_vector_free()
Deinitializes the vector and frees all allocated memory. Sets the vector pointer to NULL.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or NULL vector)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** All dynamically allocated element memory is also freed. The vector pointer is set to NULL after deinitialization.
---
### zh_vector_get_capacity()
Gets the current allocated capacity of the vector (maximum number of elements without reallocation).
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `capacity` - Pointer to variable to store the capacity. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or capacity pointer)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** Capacity may be larger than the current size (e.g., after deletions). Capacity reduction occurs automatically when `capacity / 2 > size` or when size becomes 0.
---
### zh_vector_get_size()
Gets the current number of elements in the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `size` - Pointer to variable to store the size. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or size pointer)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
---
### zh_vector_push_front()
Adds an element to the beginning of the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `item` - Pointer to the element to add. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or item pointer)
- `ESP_ERR_NO_MEM` - Memory allocation failed
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** The function allocates memory for a copy of the item and copies the data. All existing elements are shifted right by one position.
---
### zh_vector_push_back()
Adds an element to the end of the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `item` - Pointer to the element to add. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or item pointer)
- `ESP_ERR_NO_MEM` - Memory allocation failed
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** The function allocates memory for a copy of the item and copies the data.
---
### zh_vector_change_item()
Changes an element at a specific index.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `index` - Index of the element to change (0-based). Must be < vector size.
- `item` - Pointer to the new element data. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer, item pointer, or invalid index)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex or item is NULL
---
### zh_vector_get_item()
Retrieves an element at a specific index by copying it into the user-provided buffer.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `index` - Index of the element to get (0-based)
- `item` - Pointer to a buffer of at least `unit` bytes where the element will be copied. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer, NULL item pointer, or invalid index)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** This function copies the element data into the provided buffer. No pointers are returned.
---
### zh_vector_delete_item()
Deletes an element at a specific index and shifts all subsequent elements.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `index` - Index of the element to delete (0-based). Must be < vector size
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or invalid index)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex or internal error
**Note:** All elements after the deleted index are shifted left by one position. The deleted item's memory is freed. Capacity is automatically reduced when `capacity / 2 > size` or when size becomes 0.
---
### zh_vector_delete_back()
Removes the last element from the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer, NULL vector, or vector is empty)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** The deleted item's memory is freed. Capacity is automatically reduced when `capacity / 2 > size` or when size becomes 0 (same behaviour as zh_vector_delete_item).
---
### zh_vector_delete_front()
Removes the first element from the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer, NULL vector, or vector is empty)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** The deleted item's memory is freed, and all subsequent elements are shifted left by one position. Capacity is automatically reduced when `capacity / 2 > size` or when size becomes 0 (same behaviour as zh_vector_delete_item).
---
### 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 of type `int32_t` 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_find_item_in_field()
Finds the first occurrence of a value in a specific field within structures stored in the vector.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
- `sample_struct` - Pointer to a sample structure of the same type as stored in the vector. Must not be NULL
- `item` - Pointer to the field within the structure (e.g., `&sample.id`). Used to calculate the field offset within the structure. Must not be NULL
- `size` - Size (in bytes) of the field to compare. Must be > 0
- `value` - Pointer to the value to search for. Must not be NULL
- `start` - Starting index for the search (0-based). Must be < vector size
- `index` - Pointer to variable of type `int32_t` to store the found index. Will be set to -1 if value is not found. Must not be NULL
**Returns:**
- `ESP_OK` - Success (value found)
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL pointer, zero size, or invalid start index)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
- `ESP_ERR_NOT_FOUND` - Value not found (index set to -1)
**Note:** This function calculates the offset of the field within the structure using `item` and `sample_struct` pointers (offset = `item - sample_struct`), then searches for the specified `value` in that field across all vector elements starting from the given index. Uses memcmp for comparison. Useful for searching in vectors of structures without copying the entire structure.
---
### zh_vector_remove_duplicates()
Removes duplicate elements from the vector, keeping only the first occurrence of each element.
**Parameters:**
- `vector` - Pointer to pointer to vector structure (`zh_vector_t **`). Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL vector pointer or NULL vector)
- `ESP_ERR_INVALID_STATE` - Failed to acquire mutex (rare system error)
**Note:** Uses memcmp to compare elements. Only the first occurrence of each unique element is preserved. The function preserves the order of first occurrences.
---
## Usage Examples
### Basic Example: Integer Vector
```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_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("Vector size: %u\n", size);
}
// Access elements
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("Element %d: %d\n", i, item_value);
}
else
{
printf("Error getting element %d: %s\n", i, esp_err_to_name(err));
}
}
// Change element
int new_val = 100;
zh_vector_change_item(&vector, 1, &new_val);
// Delete element
zh_vector_delete_item(&vector, 0);
// Cleanup
zh_vector_free(&vector);
}
```
---
### Struct Example
```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;
// Initialize vector for structs
esp_err_t ret = zh_vector_init(&vector, sizeof(my_struct_t));
if (ret != ESP_OK)
{
printf("Vector initialization error\n");
return;
}
// Add struct elements
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);
// Access and modify
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);
}
// Cleanup
zh_vector_free(&vector);
}
```
---
### String Example (Char Arrays)
```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 strings (100 char max)
esp_err_t ret = zh_vector_init(&vector, 100);
if (ret != ESP_OK)
{
printf("Vector initialization error\n");
return;
}
// Add strings (each string allocated separately)
char *str1 = malloc(100);
char *str2 = malloc(100);
if (str1 && str2)
{
strcpy(str1, "Hello");
strcpy(str2, "World");
zh_vector_push_back(&vector, str1);
zh_vector_push_back(&vector, str2);
free(str1);
free(str2);
}
uint16_t size = 0;
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK)
{
// Print all strings
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("String %d: %s\n", i, str_value);
}
else
{
printf("Error getting string %d: %s\n", i, esp_err_to_name(err));
}
}
}
// Remove duplicates (if any)
zh_vector_remove_duplicates(&vector);
// Cleanup
zh_vector_free(&vector);
}
```
---
### Remove Duplicates 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 with duplicates
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("Vector size before removing duplicates: %u\n", size);
}
// Remove duplicates
zh_vector_remove_duplicates(&vector);
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK)
{
printf("Vector size after removing duplicates: %u\n", size);
}
// Access remaining elements
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("Element %d: %d\n", i, item_value);
}
else
{
printf("Error getting element %d: %s\n", i, esp_err_to_name(err));
}
}
// Cleanup
zh_vector_free(&vector);
}
```
---
### 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;
int32_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, (int)found_index);
}
else
{
printf("Element %d not found (index=%d)\n", search_item, (int)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, (int)found_index);
}
else
{
printf("Element %d not found (index=%d)\n", search_item, (int)found_index);
}
// Cleanup
zh_vector_free(&vector);
}
```
---
### Find Item in Field Example
```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;
// Initialize vector for structs
esp_err_t ret = zh_vector_init(&vector, sizeof(my_struct_t));
if (ret != ESP_OK)
{
printf("Vector initialization error\n");
return;
}
// Add struct elements
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);
// Find struct by field value (searching by id field)
int search_id = 2;
int32_t found_index = -1;
// Calculate offset of 'id' field within the structure
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("Struct with id=%d found at index %d\n", search_id, (int)found_index);
// Get the found struct
my_struct_t found_item = {0};
ret = zh_vector_get_item(&vector, (uint16_t)found_index, &found_item);
if (ret == ESP_OK)
{
printf("Found item: id=%d, name=%s, value=%.1f\n", found_item.id, found_item.name, found_item.value);
}
}
else
{
printf("Struct with id=%d not found (index=%d)\n", search_id, (int)found_index);
}
// Find non-existing 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("Struct with id=%d found at index %d\n", search_id, (int)found_index);
}
else
{
printf("Struct with id=%d not found (index=%d)\n", search_id, (int)found_index);
}
// Cleanup
zh_vector_free(&vector);
}
```
---
## Technical Specifications
| Parameter | Value |
| ----------- | ------- |
| **Maximum Capacity** | 65,535 elements |
| **Index Type** | uint16_t (16-bit) |
| **Memory Management** | heap_caps_calloc, heap_caps_realloc, heap_caps_free |
| **Memory Caps** | MALLOC_CAP_8BIT |
| **Thread Safety** | Thread-safe (uses FreeRTOS mutex) |
| **ESP-IDF Version** | >= 5.0 |
| **Platform** | ESP32 series |
| **Language** | C (C99) |
---
## Error Codes
| Error Code | Description |
| ------------ | ------------- |
| `ESP_OK` | Operation successful |
| `ESP_ERR_INVALID_ARG` | Invalid argument (NULL pointer, zero size, or invalid index) |
| `ESP_ERR_INVALID_STATE` | Failed to acquire mutex or internal error (e.g., item is NULL) |
| `ESP_ERR_NO_MEM` | Memory allocation failed (out of memory) |
| `ESP_ERR_NOT_FOUND` | Element not found (for zh_vector_find_item and zh_vector_find_item_in_field) |
---
## Contributing
Contributions are welcome! To contribute:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
Please ensure your code follows the existing style and includes appropriate documentation.
---
## License
This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file for details.
### Apache License, Version 2.0
Copyright (c) 2026 Alexey Zholtikov
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
## Additional Notes
- **Memory Overhead**: Each element requires additional memory for the pointer in the internal pointer array
- **Performance**: O(1) for get/set by index, O(n) for insert/delete in the middle
- **Best Practices**:
- Always initialize the vector before use
- Free the vector when done to avoid memory leaks
- Consider the maximum size limit (65,535 elements)
- For string handling, consider using fixed-size buffers
---
*Generated for zh_vector v2.5.0*
-778
View File
@@ -1,778 +0,0 @@
# zh_vector - Компонент вектора (динамического массива) для ESP-IDF
## Содержание
- [Обзор](#обзор)
- [Возможности](#возможности)
- [Установка](#установка)
- [Справочник API](#справочник-api)
- [Примеры использования](#примеры-использования)
- [Технические характеристики](#технические-характеристики)
- [Коды ошибок](#коды-ошибок)
- [Вклад в проект](#вклад-в-проект)
- [Лицензия](#лицензия)
---
## Обзор
`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. **Минимальные накладные расходы**: Низкие накладные расходы на память и процессор
---
## Установка
Перейдите в каталог компонентов вашего проекта:
```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` - Размер каждого элемента в байтах. Должен быть > 0
**Возвращает:**
- `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 (редкий системный сбой)
**Примечание:** Емкость может быть больше текущего размера (например, после удалений). Уменьшение емкости происходит автоматически при удалении элементов, когда `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_INVALID_STATE` - Не удалось захватить mutex или внутренняя ошибка
**Примечание:** Все элементы после удаляемого индекса сдвигаются влево на одну позицию. Память удаленного элемента освобождается. Емкость автоматически уменьшается, когда `capacity / 2 > size` или когда размер становится 0.
---
### zh_vector_delete_back()
Удаляет последний элемент из вектора.
**Параметры:**
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель на вектор, NULL вектор или вектор пуст)
- `ESP_ERR_INVALID_STATE` - Не удалось захватить mutex (редкий системный сбой)
**Примечание:** Память удаленного элемента освобождается. Емкость автоматически уменьшается, когда `capacity / 2 > size` или когда размер становится 0 (такое же поведение, как в 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 (редкий системный сбой)
**Примечание:** Память удаленного элемента освобождается, и все последующие элементы сдвигаются влево на одну позицию. Емкость автоматически уменьшается, когда `capacity / 2 > size` или когда размер становится 0 (такое же поведение, как в zh_vector_delete_item).
---
### zh_vector_find_item()
Находит первое вхождение элемента в векторе.
**Параметры:**
- `vector` - Указатель на указатель на структуру вектора (`zh_vector_t **`). Не должен быть NULL
- `item` - Указатель на элемент для поиска. Не должен быть NULL
- `index` - Указатель на переменную типа `int32_t` для сохранения найденного индекса. Будет установлен в -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` - Указатель на переменную типа `int32_t` для сохранения найденного индекса. Будет установлен в -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("Размер вектора: %u\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;
// Инициализация вектора для строк (макс. 100 символов)
esp_err_t ret = zh_vector_init(&vector, 100);
if (ret != ESP_OK)
{
printf("Ошибка инициализации вектора\n");
return;
}
// Добавление строк (каждая строка выделяется отдельно)
char *str1 = malloc(100);
char *str2 = malloc(100);
if (str1 && str2)
{
strcpy(str1, "Привет");
strcpy(str2, "Мир");
zh_vector_push_back(&vector, str1);
zh_vector_push_back(&vector, str2);
free(str1);
free(str2);
}
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("Размер вектора перед удалением дубликатов: %u\n", size);
}
// Удаление дубликатов
zh_vector_remove_duplicates(&vector);
ret = zh_vector_get_size(&vector, &size);
if (ret == ESP_OK)
{
printf("Размер вектора после удаления дубликатов: %u\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 найден по индексу %d\n", search_item, (int)found_index);
}
else
{
printf("Элемент %d не найден (index=%d)\n", search_item, (int)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, (int)found_index);
}
else
{
printf("Элемент %d не найден (index=%d)\n", search_item, (int)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 найдена по индексу %d\n", search_id, (int)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=%d)\n", search_id, (int)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 найдена по индексу %d\n", search_id, (int)found_index);
}
else
{
printf("Структура с id=%d не найдена (index=%d)\n", search_id, (int)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 или внутренняя ошибка (например, элемент равен NULL) |
| `ESP_ERR_NO_MEM` | Ошибка выделения памяти (не хватает памяти) |
| `ESP_ERR_NOT_FOUND` | Элемент не найден (для zh_vector_find_item и zh_vector_find_item_in_field) |
---
## Вклад в проект
Вклад приветствуется! Чтобы внести свой вклад:
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*
+5 -1
View File
@@ -140,7 +140,7 @@ extern "C"
*
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails or item is NULL
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails or element at index is NULL
*/
esp_err_t zh_vector_change_item(zh_vector_t **vector, uint16_t index, const void *item);
@@ -154,6 +154,10 @@ extern "C"
* @return ESP_OK on success
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails or item is NULL
*
* @note The element at the specified index must exist and be non-NULL.
* This is guaranteed if the vector was properly initialized and no
* internal corruption occurred.
*/
esp_err_t zh_vector_get_item(zh_vector_t **vector, uint16_t index, void *item);