4547 lines
183 KiB
C
4547 lines
183 KiB
C
#include "zh_vector.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
static const char *TAG = "zh_vector";
|
|
|
|
#define ZH_VECTOR_LOGE(msg, ...) ESP_LOGE(TAG, "[%s:%d] " msg, __FILE__, __LINE__, ##__VA_ARGS__)
|
|
#define ZH_VECTOR_LOGI(msg, ...) ESP_LOGI(TAG, "[%s:%d] " msg, __FILE__, __LINE__, ##__VA_ARGS__)
|
|
|
|
#define ZH_VECTOR_CHECK(cond, err, msg) \
|
|
if (!(cond)) \
|
|
{ \
|
|
ZH_VECTOR_LOGE(msg); \
|
|
return err; \
|
|
}
|
|
|
|
#define ZH_VECTOR_VALIDATE(cond, err, msg) \
|
|
do { \
|
|
if (!(cond)) { \
|
|
ZH_VECTOR_LOGE(msg); \
|
|
return err; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define ZH_VECTOR_INIT(type) zh_vector_init(sizeof(type))
|
|
|
|
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity);
|
|
|
|
esp_err_t zh_vector_init(zh_vector_t *vector, uint16_t unit)
|
|
{
|
|
ZH_VECTOR_LOGI("Vector initialization begin.");
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Vector initialization fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(unit > 0, ESP_ERR_INVALID_ARG, "Vector initialization fail. Unit size must be greater than 0.");
|
|
ZH_VECTOR_CHECK(vector->status == false, ESP_ERR_INVALID_STATE, "Vector initialization fail. Vector already initialized.");
|
|
vector->capacity = 0;
|
|
vector->size = 0;
|
|
vector->unit = unit;
|
|
vector->status = true;
|
|
ZH_VECTOR_LOGI("Vector initialization success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_free(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Vector deletion begin.");
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Vector deletion fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Vector deletion fail. Vector not initialized.");
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (vector->items[i] != NULL)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
}
|
|
if (vector->items != NULL)
|
|
{
|
|
heap_caps_free(vector->items);
|
|
vector->items = NULL;
|
|
}
|
|
vector->capacity = 0;
|
|
vector->size = 0;
|
|
vector->unit = 0;
|
|
vector->status = false;
|
|
ZH_VECTOR_LOGI("Vector deletion success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_get_size(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Getting vector size begin.");
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_FAIL, "Getting vector size fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_FAIL, "Getting vector size fail. Vector not initialized.");
|
|
ZH_VECTOR_LOGI("Getting vector size success. Size: %d.", vector->size);
|
|
return vector->size;
|
|
}
|
|
|
|
esp_err_t zh_vector_push_back(zh_vector_t *vector, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Adding item to vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Adding item to vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Adding item to vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Adding item to vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size < UINT16_MAX, ESP_ERR_INVALID_SIZE, "Adding item to vector fail. Maximum size exceeded.");
|
|
|
|
if (vector->capacity == vector->size)
|
|
{
|
|
uint16_t new_capacity = (vector->capacity == 0) ? 1 : vector->capacity * 2;
|
|
ZH_VECTOR_CHECK(new_capacity <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Adding item to vector fail. Capacity exceeds maximum allowed size.");
|
|
|
|
esp_err_t resize_err = _resize(vector, new_capacity);
|
|
ZH_VECTOR_CHECK(resize_err == ESP_OK, ESP_ERR_NO_MEM, "Adding item to vector fail. Memory allocation failed during resize.");
|
|
}
|
|
|
|
vector->items[vector->size] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[vector->size] != NULL, ESP_ERR_NO_MEM, "Adding item to vector fail. Memory allocation failed.");
|
|
|
|
memcpy(vector->items[vector->size], item, vector->unit);
|
|
vector->size++;
|
|
|
|
ZH_VECTOR_LOGI("Adding item to vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_emplace_back(zh_vector_t *vector, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Emplacing item to vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Emplacing item to vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Emplacing item to vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Emplacing item to vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size < UINT16_MAX, ESP_ERR_INVALID_SIZE, "Emplacing item to vector fail. Maximum size exceeded.");
|
|
|
|
if (vector->capacity == vector->size)
|
|
{
|
|
uint16_t new_capacity = (vector->capacity == 0) ? 1 : vector->capacity * 2;
|
|
ZH_VECTOR_CHECK(new_capacity <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Emplacing item to vector fail. Capacity exceeds maximum allowed size.");
|
|
|
|
esp_err_t resize_err = _resize(vector, new_capacity);
|
|
ZH_VECTOR_CHECK(resize_err == ESP_OK, ESP_ERR_NO_MEM, "Emplacing item to vector fail. Memory allocation failed during resize.");
|
|
}
|
|
|
|
vector->items[vector->size] = item;
|
|
vector->size++;
|
|
|
|
ZH_VECTOR_LOGI("Emplacing item to vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_change_item(zh_vector_t *vector, uint16_t index, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Changing item in vector begin.");
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Changing item in vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Changing item in vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Changing item in vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index < vector->size, ESP_FAIL, "Changing item in vector fail. Index does not exist.");
|
|
|
|
memcpy(vector->items[index], item, vector->unit);
|
|
ZH_VECTOR_LOGI("Changing item in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void *zh_vector_get_item(zh_vector_t *vector, uint16_t index)
|
|
{
|
|
ZH_VECTOR_LOGI("Getting item from vector begin.");
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Getting item from vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Getting item from vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index < vector->size, NULL, "Getting item from vector fail. Index does not exist.");
|
|
|
|
void *item = vector->items[index];
|
|
ZH_VECTOR_LOGI("Getting item from vector success.");
|
|
return item;
|
|
}
|
|
|
|
void *zh_vector_at(zh_vector_t *vector, uint16_t index)
|
|
{
|
|
ZH_VECTOR_LOGI("Accessing item at index begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Accessing item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Accessing item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index < vector->size, NULL, "Accessing item fail. Index out of bounds.");
|
|
|
|
ZH_VECTOR_LOGI("Accessing item at index success.");
|
|
return vector->items[index];
|
|
}
|
|
|
|
esp_err_t zh_vector_delete_item(zh_vector_t *vector, uint16_t index)
|
|
{
|
|
ZH_VECTOR_LOGI("Deleting item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Deleting item in vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Deleting item in vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index < vector->size, ESP_FAIL, "Deleting item in vector fail. Index out of bounds.");
|
|
|
|
heap_caps_free(vector->items[index]);
|
|
for (uint16_t i = index; i < vector->size - 1; ++i)
|
|
{
|
|
vector->items[i] = vector->items[i + 1];
|
|
}
|
|
vector->items[--vector->size] = NULL;
|
|
|
|
if (vector->size < vector->capacity / 2)
|
|
{
|
|
esp_err_t resize_err = _resize(vector, vector->capacity / 2);
|
|
ZH_VECTOR_CHECK(resize_err == ESP_OK, ESP_ERR_NO_MEM, "Deleting item in vector fail. Memory allocation failed during resize.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Deleting item in vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_remove(zh_vector_t *vector, uint16_t index)
|
|
{
|
|
ZH_VECTOR_LOGI("Removing item from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index < vector->size, ESP_FAIL, "Removing item fail. Index out of bounds.");
|
|
|
|
heap_caps_free(vector->items[index]);
|
|
|
|
for (uint16_t i = index; i < vector->size - 1; ++i)
|
|
{
|
|
vector->items[i] = vector->items[i + 1];
|
|
}
|
|
|
|
vector->items[--vector->size] = NULL;
|
|
|
|
ZH_VECTOR_LOGI("Removing item from vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
void zh_vector_foreach(zh_vector_t *vector, void (*callback)(void *item)) {
|
|
for (uint16_t i = 0; i < vector->size; ++i) {
|
|
callback(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
esp_err_t zh_vector_iterate(zh_vector_t *vector, void (*callback)(void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Iterating over vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Iterating over vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(callback != NULL, ESP_ERR_INVALID_ARG, "Iterating over vector fail. Callback is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Iterating over vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
callback(vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Iterating over vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_foreach(zh_vector_t *vector, void (*callback)(void *item, void *context), void *context)
|
|
{
|
|
ZH_VECTOR_LOGI("Iterating over vector with context begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Iterating over vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(callback != NULL, ESP_ERR_INVALID_ARG, "Iterating over vector fail. Callback is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Iterating over vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
callback(vector->items[i], context);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Iterating over vector with context success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_clear(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Clearing vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Clearing vector fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Clearing vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = 0;
|
|
ZH_VECTOR_LOGI("Clearing vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_clear_and_shrink(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Clearing and shrinking vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Clearing and shrinking vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Clearing and shrinking vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = 0;
|
|
|
|
esp_err_t err = _resize(vector, 0);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Clearing and shrinking vector fail. Failed to resize capacity.");
|
|
|
|
ZH_VECTOR_LOGI("Clearing and shrinking vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_reserve(zh_vector_t *vector, uint16_t new_capacity)
|
|
{
|
|
ZH_VECTOR_LOGI("Reserving vector capacity begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Reserving vector capacity fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Reserving vector capacity fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(new_capacity > vector->capacity, ESP_OK, "Reserving vector capacity skipped. New capacity is less than or equal to current capacity.");
|
|
|
|
return _resize(vector, new_capacity);
|
|
}
|
|
|
|
esp_err_t zh_vector_shrink_to_fit(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Shrinking vector capacity to fit size begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Shrinking vector capacity fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Shrinking vector capacity fail. Vector not initialized.");
|
|
|
|
if (vector->capacity > vector->size)
|
|
{
|
|
return _resize(vector, vector->size);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Shrinking vector capacity skipped. Capacity already fits size.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
bool zh_vector_is_empty(zh_vector_t *vector)
|
|
{
|
|
return (vector == NULL || vector->status == false || vector->size == 0);
|
|
}
|
|
|
|
esp_err_t zh_vector_copy(zh_vector_t *dest, const zh_vector_t *src)
|
|
{
|
|
ZH_VECTOR_LOGI("Copying vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(dest != NULL, ESP_ERR_INVALID_ARG, "Copying vector fail. Destination vector is NULL.");
|
|
ZH_VECTOR_CHECK(src != NULL, ESP_ERR_INVALID_ARG, "Copying vector fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(src->status == true, ESP_ERR_INVALID_STATE, "Copying vector fail. Source vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(dest, src->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying vector fail. Failed to initialize destination vector.");
|
|
|
|
err = zh_vector_reserve(dest, src->capacity);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying vector fail. Failed to reserve memory for destination vector.");
|
|
|
|
for (uint16_t i = 0; i < src->size; ++i)
|
|
{
|
|
err = zh_vector_push_back(dest, src->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying vector fail. Failed to copy item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Copying vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_swap(zh_vector_t *vector1, zh_vector_t *vector2)
|
|
{
|
|
ZH_VECTOR_LOGI("Swapping vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Swapping vectors fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Swapping vectors fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Swapping vectors fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Swapping vectors fail. Second vector not initialized.");
|
|
|
|
zh_vector_t temp = *vector1;
|
|
*vector1 = *vector2;
|
|
*vector2 = temp;
|
|
|
|
ZH_VECTOR_LOGI("Swapping vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity)
|
|
{
|
|
ZH_VECTOR_LOGI("Vector resize begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Vector resize fail. Invalid argument.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Vector resize fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(capacity > 0, ESP_ERR_INVALID_ARG, "Vector resize fail. Capacity must be greater than 0.");
|
|
ZH_VECTOR_CHECK(capacity <= UINT16_MAX, ESP_ERR_INVALID_ARG, "Vector resize fail. Capacity exceeds maximum allowed size.");
|
|
|
|
if (capacity == vector->capacity)
|
|
{
|
|
ZH_VECTOR_LOGI("Vector resize skipped. Capacity already matches the requested size.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
if (capacity < vector->size)
|
|
{
|
|
for (uint16_t i = capacity; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
vector->size = capacity;
|
|
}
|
|
|
|
void **new_items = heap_caps_realloc(vector->items, capacity * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(new_items != NULL, ESP_ERR_NO_MEM, "Vector resize fail. Memory allocation failed.");
|
|
|
|
vector->items = new_items;
|
|
vector->capacity = capacity;
|
|
|
|
ZH_VECTOR_LOGI("Vector resize success. New capacity: %d.", capacity);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Fills the entire vector with the specified item.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to fill the vector with.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*
|
|
* Example usage:
|
|
* @code
|
|
* zh_vector_t vector;
|
|
* zh_vector_init(&vector, sizeof(int));
|
|
* int value = 42;
|
|
* zh_vector_resize(&vector, 10);
|
|
* zh_vector_fill(&vector, &value);
|
|
* @endcode
|
|
*/
|
|
esp_err_t zh_vector_fill(zh_vector_t *vector, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Filling vector with item begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Filling vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
memcpy(vector->items[i], item, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Filling vector with item success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_resize_and_fill(zh_vector_t *vector, uint16_t new_size, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Resizing and filling vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Resizing and filling vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Resizing and filling vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Resizing and filling vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(new_size <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Resizing vector fail. New size exceeds maximum allowed size.");
|
|
|
|
if (new_size > vector->capacity)
|
|
{
|
|
esp_err_t err = _resize(vector, new_size);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Resizing and filling vector fail. Failed to resize capacity.");
|
|
}
|
|
|
|
for (uint16_t i = vector->size; i < new_size; ++i)
|
|
{
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Resizing and filling vector fail. Memory allocation failed.");
|
|
memcpy(vector->items[i], item, vector->unit);
|
|
}
|
|
|
|
vector->size = new_size;
|
|
|
|
ZH_VECTOR_LOGI("Resizing and filling vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_resize_exact(zh_vector_t *vector, uint16_t new_size)
|
|
{
|
|
ZH_VECTOR_LOGI("Resizing vector with exact size begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Resizing vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Resizing vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(new_size <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Resizing vector fail. New size exceeds maximum allowed size.");
|
|
|
|
esp_err_t err = _resize(vector, new_size);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Resizing vector fail. Failed to resize capacity.");
|
|
|
|
if (new_size > vector->size)
|
|
{
|
|
for (uint16_t i = vector->size; i < new_size; ++i)
|
|
{
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Resizing vector fail. Memory allocation failed.");
|
|
}
|
|
}
|
|
else if (new_size < vector->size)
|
|
{
|
|
for (uint16_t i = new_size; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
}
|
|
|
|
vector->size = new_size;
|
|
ZH_VECTOR_LOGI("Resizing vector with exact size success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_resize_no_init(zh_vector_t *vector, uint16_t new_size)
|
|
{
|
|
ZH_VECTOR_LOGI("Resizing vector without initialization begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Resizing vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Resizing vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(new_size <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Resizing vector fail. New size exceeds maximum allowed size.");
|
|
|
|
if (new_size > vector->capacity)
|
|
{
|
|
esp_err_t err = _resize(vector, new_size);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Resizing vector fail. Failed to resize capacity.");
|
|
}
|
|
|
|
if (new_size < vector->size)
|
|
{
|
|
for (uint16_t i = new_size; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
}
|
|
|
|
vector->size = new_size;
|
|
ZH_VECTOR_LOGI("Resizing vector without initialization success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the index of the specified item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to find.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the found item, or -1 if the item is not found.
|
|
*
|
|
* Example usage:
|
|
* @code
|
|
* zh_vector_t vector;
|
|
* zh_vector_init(&vector, sizeof(int));
|
|
* int value = 42;
|
|
* zh_vector_push_back(&vector, &value);
|
|
* int index = zh_vector_find(&vector, &value, int_cmp);
|
|
* @endcode
|
|
*/
|
|
int zh_vector_find(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding item in vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, -1, "Finding item in vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding item in vector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding item in vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_if(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding item in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, -1, "Finding item fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding item fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
ZH_VECTOR_LOGI("Item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_last(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding last item in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding last item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, -1, "Finding last item fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding last item fail. Vector not initialized.");
|
|
|
|
for (int i = vector->size - 1; i >= 0; --i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
ZH_VECTOR_LOGI("Last item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Last item not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_range(zh_vector_t *vector, uint16_t start, uint16_t end, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding item in range of vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, -1, "Finding item fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, -1, "Finding item fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, -1, "Finding item fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, -1, "Finding item fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
ZH_VECTOR_LOGI("Item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in range of vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all indices of items in the vector that satisfy a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param indices Pointer to an array of indices (allocated dynamically).
|
|
* @param count Pointer to store the number of found indices.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_indices(zh_vector_t *vector, bool (*predicate)(const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all indices in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding indices fail. Vector not initialized.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding indices fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all indices in vector with predicate success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all indices of items in a specified range of the vector that satisfy a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param indices Pointer to an array of indices (allocated dynamically).
|
|
* @param count Pointer to store the number of found indices.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_range_indices(zh_vector_t *vector, uint16_t start, uint16_t end, bool (*predicate)(const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding indices in range of vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding indices fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding indices fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Finding indices fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Finding indices fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Finding indices fail. Start index must be less than end index.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc((end - start) * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding indices fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding indices in range of vector with predicate success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Sorts the elements of the vector in ascending order.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*
|
|
* Example usage:
|
|
* @code
|
|
* zh_vector_t vector;
|
|
* zh_vector_init(&vector, sizeof(int));
|
|
* int values[] = {3, 1, 4, 1, 5};
|
|
* for (int i = 0; i < 5; ++i) {
|
|
* zh_vector_push_back(&vector, &values[i]);
|
|
* }
|
|
* zh_vector_sort(&vector, int_cmp);
|
|
* @endcode
|
|
*/
|
|
esp_err_t zh_vector_sort(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Sorting vector fail. Vector not initialized.");
|
|
|
|
if (vector->size <= 1)
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector skipped. Vector is empty or has only one element.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
qsort(vector->items, vector->size, sizeof(void *), cmp);
|
|
|
|
ZH_VECTOR_LOGI("Sorting vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_sort_descending(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector in descending order begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Sorting vector fail. Vector not initialized.");
|
|
|
|
if (vector->size <= 1)
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector skipped. Vector is empty or has only one element.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
int reverse_cmp(const void *a, const void *b)
|
|
{
|
|
return -cmp(a, b);
|
|
}
|
|
|
|
qsort(vector->items, vector->size, sizeof(void *), reverse_cmp);
|
|
|
|
ZH_VECTOR_LOGI("Sorting vector in descending order success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_reverse(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Reversing vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Reversing vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Reversing vector fail. Vector not initialized.");
|
|
|
|
if (vector->size <= 1)
|
|
{
|
|
ZH_VECTOR_LOGI("Reversing vector skipped. Vector is empty or has only one element.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < vector->size / 2; ++i)
|
|
{
|
|
void *temp = vector->items[i];
|
|
vector->items[i] = vector->items[vector->size - i - 1];
|
|
vector->items[vector->size - i - 1] = temp;
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Reversing vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
uint16_t zh_vector_capacity(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Getting vector capacity begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, 0, "Getting vector capacity fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, 0, "Getting vector capacity fail. Vector not initialized.");
|
|
|
|
ZH_VECTOR_LOGI("Getting vector capacity success. Capacity: %d.", vector->capacity);
|
|
return vector->capacity;
|
|
}
|
|
|
|
uint16_t zh_vector_capacity_left(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Getting vector free capacity begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, 0, "Getting vector free capacity fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, 0, "Getting vector free capacity fail. Vector not initialized.");
|
|
|
|
uint16_t free_capacity = vector->capacity - vector->size;
|
|
ZH_VECTOR_LOGI("Getting vector free capacity success. Free capacity: %d.", free_capacity);
|
|
return free_capacity;
|
|
}
|
|
|
|
esp_err_t zh_vector_resize(zh_vector_t *vector, uint16_t new_size)
|
|
{
|
|
ZH_VECTOR_LOGI("Resizing vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Resizing vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Resizing vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(new_size <= UINT16_MAX, ESP_ERR_INVALID_SIZE, "Resizing vector fail. New size exceeds maximum allowed size.");
|
|
|
|
if (new_size > vector->capacity)
|
|
{
|
|
esp_err_t err = _resize(vector, new_size);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Resizing vector fail. Failed to resize capacity.");
|
|
}
|
|
|
|
if (new_size > vector->size)
|
|
{
|
|
for (uint16_t i = vector->size; i < new_size; ++i)
|
|
{
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Resizing vector fail. Memory allocation failed.");
|
|
}
|
|
}
|
|
else if (new_size < vector->size)
|
|
{
|
|
for (uint16_t i = new_size; i < vector->size; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = NULL;
|
|
}
|
|
}
|
|
|
|
vector->size = new_size;
|
|
ZH_VECTOR_LOGI("Resizing vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_pop_back(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Popping item from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Popping item from vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Popping item from vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, ESP_FAIL, "Popping item from vector fail. Vector is empty.");
|
|
|
|
heap_caps_free(vector->items[vector->size - 1]);
|
|
vector->items[vector->size - 1] = NULL;
|
|
vector->size--;
|
|
|
|
ZH_VECTOR_LOGI("Popping item from vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_insert(zh_vector_t *vector, uint16_t index, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Inserting item into vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Inserting item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Inserting item fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Inserting item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index <= vector->size, ESP_FAIL, "Inserting item fail. Index out of bounds.");
|
|
|
|
if (vector->capacity == vector->size)
|
|
{
|
|
uint16_t new_capacity = (vector->capacity == 0) ? 1 : vector->capacity * 2;
|
|
esp_err_t resize_err = _resize(vector, new_capacity);
|
|
ZH_VECTOR_CHECK(resize_err == ESP_OK, ESP_ERR_NO_MEM, "Inserting item fail. Memory allocation failed during resize.");
|
|
}
|
|
|
|
for (uint16_t i = vector->size; i > index; --i)
|
|
{
|
|
vector->items[i] = vector->items[i - 1];
|
|
}
|
|
|
|
vector->items[index] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[index] != NULL, ESP_ERR_NO_MEM, "Inserting item fail. Memory allocation failed.");
|
|
|
|
memcpy(vector->items[index], item, vector->unit);
|
|
vector->size++;
|
|
|
|
ZH_VECTOR_LOGI("Inserting item into vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
zh_vector_t *zh_vector_clone(const zh_vector_t *src)
|
|
{
|
|
ZH_VECTOR_LOGI("Cloning vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(src != NULL, NULL, "Cloning vector fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(src->status == true, NULL, "Cloning vector fail. Source vector not initialized.");
|
|
|
|
zh_vector_t *clone = heap_caps_calloc(1, sizeof(zh_vector_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(clone != NULL, NULL, "Cloning vector fail. Memory allocation failed.");
|
|
|
|
esp_err_t err = zh_vector_init(clone, src->unit);
|
|
if (err != ESP_OK)
|
|
{
|
|
heap_caps_free(clone);
|
|
return NULL;
|
|
}
|
|
|
|
err = zh_vector_reserve(clone, src->capacity);
|
|
if (err != ESP_OK)
|
|
{
|
|
zh_vector_free(clone);
|
|
heap_caps_free(clone);
|
|
return NULL;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < src->size; ++i)
|
|
{
|
|
err = zh_vector_push_back(clone, src->items[i]);
|
|
if (err != ESP_OK)
|
|
{
|
|
zh_vector_free(clone);
|
|
heap_caps_free(clone);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Cloning vector success.");
|
|
return clone;
|
|
}
|
|
|
|
bool zh_vector_compare(const zh_vector_t *vector1, const zh_vector_t *vector2, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Comparing vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, false, "Comparing vectors fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, false, "Comparing vectors fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, false, "Comparing vectors fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, false, "Comparing vectors fail. Second vector not initialized.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, false, "Comparing vectors fail. Comparison function is NULL.");
|
|
|
|
if (vector1->size != vector2->size)
|
|
{
|
|
ZH_VECTOR_LOGI("Comparing vectors fail. Sizes are different.");
|
|
return false;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[i]) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Comparing vectors fail. Items at index %d are different.", i);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Comparing vectors success. Vectors are equal.");
|
|
return true;
|
|
}
|
|
|
|
bool zh_vector_compare_ranges(zh_vector_t *vector1, uint16_t start1, uint16_t end1, zh_vector_t *vector2, uint16_t start2, uint16_t end2, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Comparing ranges of two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, false, "Comparing ranges fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, false, "Comparing ranges fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, false, "Comparing ranges fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, false, "Comparing ranges fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, false, "Comparing ranges fail. Second vector not initialized.");
|
|
ZH_VECTOR_CHECK(start1 < vector1->size && end1 <= vector1->size, false, "Comparing ranges fail. Range out of bounds in first vector.");
|
|
ZH_VECTOR_CHECK(start2 < vector2->size && end2 <= vector2->size, false, "Comparing ranges fail. Range out of bounds in second vector.");
|
|
ZH_VECTOR_CHECK((end1 - start1) == (end2 - start2), false, "Comparing ranges fail. Ranges have different lengths.");
|
|
|
|
for (uint16_t i = 0; i < (end1 - start1); ++i)
|
|
{
|
|
if (cmp(vector1->items[start1 + i], vector2->items[start2 + i]) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Ranges are different at index: %d.", i);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Ranges are equal.");
|
|
return true;
|
|
}
|
|
|
|
esp_err_t zh_vector_filter(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Filtering vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Filtering vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Filtering vector fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Filtering vector fail. Vector not initialized.");
|
|
|
|
uint16_t write_index = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
if (write_index != i)
|
|
{
|
|
vector->items[write_index] = vector->items[i];
|
|
}
|
|
write_index++;
|
|
}
|
|
else
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
for (uint16_t i = write_index; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = write_index;
|
|
|
|
ZH_VECTOR_LOGI("Filtering vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_map(zh_vector_t *vector, void (*func)(void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Mapping function over vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Mapping function fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, ESP_ERR_INVALID_ARG, "Mapping function fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Mapping function fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
func(vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Mapping function over vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void *zh_vector_reduce(zh_vector_t *vector, void *(*func)(void *acc, void *item), void *initial)
|
|
{
|
|
ZH_VECTOR_LOGI("Reducing vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Reducing vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, NULL, "Reducing vector fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Reducing vector fail. Vector not initialized.");
|
|
|
|
void *acc = initial;
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
acc = func(acc, vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Reducing vector success.");
|
|
return acc;
|
|
}
|
|
|
|
void *zh_vector_accumulate(zh_vector_t *vector, void *initial, void *(*func)(void *acc, void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Accumulating values in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Accumulating values fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, NULL, "Accumulating values fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Accumulating values fail. Vector not initialized.");
|
|
|
|
void *acc = initial;
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
acc = func(acc, vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Accumulating values in vector success.");
|
|
return acc;
|
|
}
|
|
|
|
/**
|
|
* @brief Accumulates values in a specified range of the vector using a user-defined function.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param initial Initial value for the accumulation.
|
|
* @param func Accumulation function that takes the current accumulator and an item.
|
|
* @return Accumulated value.
|
|
*/
|
|
void *zh_vector_accumulate_range(zh_vector_t *vector, uint16_t start, uint16_t end, void *initial, void *(*func)(void *acc, void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Accumulating values in range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Accumulating values fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, NULL, "Accumulating values fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Accumulating values fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, NULL, "Accumulating values fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, NULL, "Accumulating values fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, NULL, "Accumulating values fail. Start index must be less than end index.");
|
|
|
|
void *acc = initial;
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
acc = func(acc, vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Accumulating values in range of vector success.");
|
|
return acc;
|
|
}
|
|
|
|
esp_err_t zh_vector_swap_items(zh_vector_t *vector, uint16_t index1, uint16_t index2)
|
|
{
|
|
ZH_VECTOR_LOGI("Swapping items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Swapping items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Swapping items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index1 < vector->size, ESP_FAIL, "Swapping items fail. Index1 out of bounds.");
|
|
ZH_VECTOR_CHECK(index2 < vector->size, ESP_FAIL, "Swapping items fail. Index2 out of bounds.");
|
|
|
|
void *temp = vector->items[index1];
|
|
vector->items[index1] = vector->items[index2];
|
|
vector->items[index2] = temp;
|
|
|
|
ZH_VECTOR_LOGI("Swapping items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
bool zh_vector_contains(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Checking if vector contains item begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, false, "Checking item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, false, "Checking item fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, false, "Checking item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, false, "Checking item fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Item found in vector.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in vector.");
|
|
return false;
|
|
}
|
|
|
|
esp_err_t zh_vector_extend(zh_vector_t *dest, const zh_vector_t *src)
|
|
{
|
|
ZH_VECTOR_LOGI("Extending vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(dest != NULL, ESP_ERR_INVALID_ARG, "Extending vector fail. Destination vector is NULL.");
|
|
ZH_VECTOR_CHECK(src != NULL, ESP_ERR_INVALID_ARG, "Extending vector fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(dest->status == true, ESP_ERR_INVALID_STATE, "Extending vector fail. Destination vector not initialized.");
|
|
ZH_VECTOR_CHECK(src->status == true, ESP_ERR_INVALID_STATE, "Extending vector fail. Source vector not initialized.");
|
|
ZH_VECTOR_CHECK(dest->unit == src->unit, ESP_ERR_INVALID_ARG, "Extending vector fail. Unit sizes do not match.");
|
|
|
|
for (uint16_t i = 0; i < src->size; ++i)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(dest, src->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Extending vector fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Extending vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **zh_vector_to_array(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Converting vector to array begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Converting vector to array fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Converting vector to array fail. Vector not initialized.");
|
|
|
|
void **array = heap_caps_malloc(vector->size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(array != NULL, NULL, "Converting vector to array fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
array[i] = vector->items[i];
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Converting vector to array success.");
|
|
return array;
|
|
}
|
|
|
|
esp_err_t zh_vector_remove_if(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing items from vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Removing items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing items fail. Vector not initialized.");
|
|
|
|
uint16_t write_index = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (!predicate(vector->items[i]))
|
|
{
|
|
if (write_index != i)
|
|
{
|
|
vector->items[write_index] = vector->items[i];
|
|
}
|
|
write_index++;
|
|
}
|
|
else
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
for (uint16_t i = write_index; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = write_index;
|
|
|
|
ZH_VECTOR_LOGI("Removing items from vector with predicate success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes all items from the vector that do not satisfy a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_remove_if_not(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing items from vector that do not satisfy predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Removing items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing items fail. Vector not initialized.");
|
|
|
|
uint16_t write_index = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
if (write_index != i)
|
|
{
|
|
vector->items[write_index] = vector->items[i];
|
|
}
|
|
write_index++;
|
|
}
|
|
else
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
for (uint16_t i = write_index; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = write_index;
|
|
|
|
ZH_VECTOR_LOGI("Removing items from vector that do not satisfy predicate success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_replace(zh_vector_t *vector, bool (*predicate)(const void *), void *new_item)
|
|
{
|
|
ZH_VECTOR_LOGI("Replacing items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Replacing items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Replacing items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(new_item != NULL, ESP_ERR_INVALID_ARG, "Replacing items fail. New item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Replacing items fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Replacing items fail. Memory allocation failed.");
|
|
memcpy(vector->items[i], new_item, vector->unit);
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Replacing items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes all occurrences of the specified item from the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to remove.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*
|
|
* Example usage:
|
|
* @code
|
|
* zh_vector_t vector;
|
|
* zh_vector_init(&vector, sizeof(int));
|
|
* int value = 42;
|
|
* zh_vector_push_back(&vector, &value);
|
|
* zh_vector_remove_all(&vector, &value, int_cmp);
|
|
* @endcode
|
|
*/
|
|
esp_err_t zh_vector_remove_all(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing all occurrences of item from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing all occurrences fail. Vector not initialized.");
|
|
|
|
uint16_t write_index = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) != 0)
|
|
{
|
|
if (write_index != i)
|
|
{
|
|
vector->items[write_index] = vector->items[i];
|
|
}
|
|
write_index++;
|
|
}
|
|
else
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
for (uint16_t i = write_index; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = write_index;
|
|
|
|
ZH_VECTOR_LOGI("Removing all occurrences of item from vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_replace_all(zh_vector_t *vector, void *old_item, void *new_item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Replacing all occurrences of item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Replacing all occurrences fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(old_item != NULL, ESP_ERR_INVALID_ARG, "Replacing all occurrences fail. Old item is NULL.");
|
|
ZH_VECTOR_CHECK(new_item != NULL, ESP_ERR_INVALID_ARG, "Replacing all occurrences fail. New item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Replacing all occurrences fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Replacing all occurrences fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], old_item) == 0)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Replacing all occurrences fail. Memory allocation failed.");
|
|
memcpy(vector->items[i], new_item, vector->unit);
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Replacing all occurrences of item in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
uint16_t zh_vector_count_if(zh_vector_t *vector, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Counting items in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, 0, "Counting items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, 0, "Counting items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, 0, "Counting items fail. Vector not initialized.");
|
|
|
|
uint16_t count = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Counting items in vector with predicate success. Count: %d.", count);
|
|
return count;
|
|
}
|
|
|
|
esp_err_t zh_vector_merge(zh_vector_t *dest, const zh_vector_t *src)
|
|
{
|
|
ZH_VECTOR_LOGI("Merging vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(dest != NULL, ESP_ERR_INVALID_ARG, "Merging vectors fail. Destination vector is NULL.");
|
|
ZH_VECTOR_CHECK(src != NULL, ESP_ERR_INVALID_ARG, "Merging vectors fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(dest->status == true, ESP_ERR_INVALID_STATE, "Merging vectors fail. Destination vector not initialized.");
|
|
ZH_VECTOR_CHECK(src->status == true, ESP_ERR_INVALID_STATE, "Merging vectors fail. Source vector not initialized.");
|
|
ZH_VECTOR_CHECK(dest->unit == src->unit, ESP_ERR_INVALID_ARG, "Merging vectors fail. Unit sizes do not match.");
|
|
|
|
for (uint16_t i = 0; i < src->size; ++i)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(dest, src->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Merging vectors fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Merging vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_unique(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing duplicates fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size;)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
zh_vector_remove(vector, j);
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_remove_duplicates(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing duplicates fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size;)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
zh_vector_remove(vector, j);
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes duplicate items from the vector using a comparison function.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_remove_duplicates_with_predicate(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing duplicates fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size;)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
zh_vector_remove(vector, j);
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Removing duplicates from vector with predicate success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **zh_vector_to_array(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Converting vector to array begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Converting vector to array fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Converting vector to array fail. Vector not initialized.");
|
|
|
|
void **array = heap_caps_malloc(vector->size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(array != NULL, NULL, "Converting vector to array fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
array[i] = vector->items[i];
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Converting vector to array success.");
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* @brief Partitions the vector into two parts based on a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param true_part Pointer to the vector to store items satisfying the predicate.
|
|
* @param false_part Pointer to the vector to store items not satisfying the predicate.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_partition(zh_vector_t *vector, bool (*predicate)(const void *), zh_vector_t *true_part, zh_vector_t *false_part)
|
|
{
|
|
ZH_VECTOR_LOGI("Partitioning vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(true_part != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. True part is NULL.");
|
|
ZH_VECTOR_CHECK(false_part != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. False part is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Partitioning vector fail. Vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(true_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to initialize true part.");
|
|
|
|
err = zh_vector_init(false_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to initialize false part.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
err = zh_vector_push_back(true_part, vector->items[i]);
|
|
}
|
|
else
|
|
{
|
|
err = zh_vector_push_back(false_part, vector->items[i]);
|
|
}
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Partitioning vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Partitions a specified range of the vector into two parts based on a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param true_part Pointer to the vector to store items satisfying the predicate.
|
|
* @param false_part Pointer to the vector to store items not satisfying the predicate.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_partition_range(zh_vector_t *vector, uint16_t start, uint16_t end, bool (*predicate)(const void *), zh_vector_t *true_part, zh_vector_t *false_part)
|
|
{
|
|
ZH_VECTOR_LOGI("Partitioning range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Partitioning range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Partitioning range fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(true_part != NULL, ESP_ERR_INVALID_ARG, "Partitioning range fail. True part is NULL.");
|
|
ZH_VECTOR_CHECK(false_part != NULL, ESP_ERR_INVALID_ARG, "Partitioning range fail. False part is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Partitioning range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Partitioning range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Partitioning range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Partitioning range fail. Start index must be less than end index.");
|
|
|
|
esp_err_t err = zh_vector_init(true_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning range fail. Failed to initialize true part.");
|
|
|
|
err = zh_vector_init(false_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning range fail. Failed to initialize false part.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
err = zh_vector_push_back(true_part, vector->items[i]);
|
|
}
|
|
else
|
|
{
|
|
err = zh_vector_push_back(false_part, vector->items[i]);
|
|
}
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning range fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Partitioning range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_copy_if(const zh_vector_t *src, zh_vector_t *dest, bool (*predicate)(const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Copying items from vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(src != NULL, ESP_ERR_INVALID_ARG, "Copying items fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(dest != NULL, ESP_ERR_INVALID_ARG, "Copying items fail. Destination vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Copying items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(src->status == true, ESP_ERR_INVALID_STATE, "Copying items fail. Source vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(dest, src->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying items fail. Failed to initialize destination vector.");
|
|
|
|
for (uint16_t i = 0; i < src->size; ++i)
|
|
{
|
|
if (predicate(src->items[i]))
|
|
{
|
|
err = zh_vector_push_back(dest, src->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying items fail. Failed to add item.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Copying items from vector with predicate success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Rotates the vector by the specified number of positions.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param positions Number of positions to rotate (positive for right, negative for left).
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_rotate(zh_vector_t *vector, int16_t positions)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Rotating vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Rotating vector fail. Vector not initialized.");
|
|
|
|
if (vector->size <= 1 || positions == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector skipped. Vector is empty, has only one element, or positions is zero.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
positions = positions % vector->size;
|
|
if (positions < 0)
|
|
{
|
|
positions += vector->size;
|
|
}
|
|
|
|
void **temp = heap_caps_malloc(vector->size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Rotating vector fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
temp[(i + positions) % vector->size] = vector->items[i];
|
|
}
|
|
|
|
memcpy(vector->items, temp, vector->size * sizeof(void *));
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Rotating vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_find_all(zh_vector_t *vector, bool (*predicate)(const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all items in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding all items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding all items fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding all items fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding all items fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding all items fail. Vector not initialized.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding all items fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all items in vector with predicate success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_intersect(const zh_vector_t *vector1, const zh_vector_t *vector2, zh_vector_t *result, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding intersection of two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Intersection fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Intersection fail. Second vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(result, vector1->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Intersection fail. Failed to initialize result vector.");
|
|
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
for (uint16_t j = 0; j < vector2->size; ++j)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[j]) == 0)
|
|
{
|
|
err = zh_vector_push_back(result, vector1->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Intersection fail. Failed to add item to result vector.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding intersection of two vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the intersection of two sorted vectors.
|
|
*
|
|
* @param vector1 Pointer to the first sorted vector.
|
|
* @param vector2 Pointer to the second sorted vector.
|
|
* @param result Pointer to the vector to store the intersection.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_intersect_sorted(zh_vector_t *vector1, zh_vector_t *vector2, zh_vector_t *result, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding intersection of two sorted vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Intersection fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Intersection fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Intersection fail. Second vector not initialized.");
|
|
|
|
uint16_t i = 0, j = 0;
|
|
while (i < vector1->size && j < vector2->size)
|
|
{
|
|
int comparison = cmp(vector1->items[i], vector2->items[j]);
|
|
if (comparison == 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, vector1->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Intersection fail. Failed to add item to result vector.");
|
|
i++;
|
|
j++;
|
|
}
|
|
else if (comparison < 0)
|
|
{
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding intersection of two sorted vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_union(const zh_vector_t *vector1, const zh_vector_t *vector2, zh_vector_t *result, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding union of two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Union fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Union fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Union fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Union fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Union fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Union fail. Second vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(result, vector1->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Union fail. Failed to initialize result vector.");
|
|
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
err = zh_vector_push_back(result, vector1->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Union fail. Failed to add item from first vector.");
|
|
}
|
|
|
|
for (uint16_t i = 0; i < vector2->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < result->size; ++j)
|
|
{
|
|
if (cmp(vector2->items[i], result->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
err = zh_vector_push_back(result, vector2->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Union fail. Failed to add item from second vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding union of two vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_difference(const zh_vector_t *vector1, const zh_vector_t *vector2, zh_vector_t *result, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding difference of two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Difference fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Difference fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Difference fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Difference fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Difference fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Difference fail. Second vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(result, vector1->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Difference fail. Failed to initialize result vector.");
|
|
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < vector2->size; ++j)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
err = zh_vector_push_back(result, vector1->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Difference fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding difference of two vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_symmetric_difference(const zh_vector_t *vector1, const zh_vector_t *vector2, zh_vector_t *result, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding symmetric difference of two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, ESP_ERR_INVALID_ARG, "Symmetric difference fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, ESP_ERR_INVALID_ARG, "Symmetric difference fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Symmetric difference fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Symmetric difference fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, ESP_ERR_INVALID_STATE, "Symmetric difference fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, ESP_ERR_INVALID_STATE, "Symmetric difference fail. Second vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(result, vector1->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Symmetric difference fail. Failed to initialize result vector.");
|
|
|
|
// Добавляем элементы из vector1, которых нет в vector2
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < vector2->size; ++j)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
err = zh_vector_push_back(result, vector1->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Symmetric difference fail. Failed to add item from first vector.");
|
|
}
|
|
}
|
|
|
|
// Добавляем элементы из vector2, которых нет в vector1
|
|
for (uint16_t i = 0; i < vector2->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < vector1->size; ++j)
|
|
{
|
|
if (cmp(vector2->items[i], vector1->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
err = zh_vector_push_back(result, vector2->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Symmetric difference fail. Failed to add item from second vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding symmetric difference of two vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_shuffle(zh_vector_t *vector)
|
|
{
|
|
ZH_VECTOR_LOGI("Shuffling vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Shuffling vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Shuffling vector fail. Vector not initialized.");
|
|
|
|
srand((unsigned int)time(NULL)); // Инициализация генератора случайных чисел
|
|
return mid;
|
|
}
|
|
else if (result < 0)
|
|
{
|
|
left = mid + 1;
|
|
}
|
|
else
|
|
{
|
|
right = mid - 1;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
void *zh_vector_min(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding minimum item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding minimum fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding minimum fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding minimum fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, NULL, "Finding minimum fail. Vector is empty.");
|
|
|
|
void *min_item = vector->items[0];
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], min_item) < 0)
|
|
{
|
|
min_item = vector->items[i];
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding minimum item in vector success.");
|
|
return min_item;
|
|
}
|
|
|
|
void *zh_vector_max(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding maximum item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding maximum fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding maximum fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding maximum fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, NULL, "Finding maximum fail. Vector is empty.");
|
|
|
|
void *max_item = vector->items[0];
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], max_item) > 0)
|
|
{
|
|
max_item = vector->items[i];
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding maximum item in vector success.");
|
|
return max_item;
|
|
}
|
|
|
|
esp_err_t zh_vector_fill(zh_vector_t *vector, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Filling vector with item begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Filling vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
memcpy(vector->items[i], item, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Filling vector with item success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_fill_range(zh_vector_t *vector, uint16_t start, uint16_t end, void *item)
|
|
{
|
|
ZH_VECTOR_LOGI("Filling range of items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Filling range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Filling range fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Filling range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Filling range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Filling range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Filling range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
memcpy(vector->items[i], item, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Filling range of items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_fill_with_generator(zh_vector_t *vector, void *(*generator)(uint16_t index))
|
|
{
|
|
ZH_VECTOR_LOGI("Filling vector with generated values begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(generator != NULL, ESP_ERR_INVALID_ARG, "Filling vector fail. Generator function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Filling vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
void *generated_value = generator(i);
|
|
ZH_VECTOR_CHECK(generated_value != NULL, ESP_ERR_NO_MEM, "Filling vector fail. Generator returned NULL.");
|
|
|
|
memcpy(vector->items[i], generated_value, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Filling vector with generated values success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
bool zh_vector_is_sorted(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Checking if vector is sorted begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, false, "Checking if vector is sorted fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, false, "Checking if vector is sorted fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, false, "Checking if vector is sorted fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i - 1], vector->items[i]) > 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Vector is not sorted.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Vector is sorted.");
|
|
return true;
|
|
}
|
|
|
|
esp_err_t zh_vector_remove_range(zh_vector_t *vector, uint16_t start, uint16_t end)
|
|
{
|
|
ZH_VECTOR_LOGI("Removing range of items from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Removing range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Removing range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Removing range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
{
|
|
void *temp = vector1->items[start1 + i];
|
|
vector1->items[start1 + i] = vector2->items[start2 + i];
|
|
vector2->items[start2 + i] = temp;
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Swapping ranges between vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_copy_range(const zh_vector_t *src, uint16_t start, uint16_t end, zh_vector_t *dest)
|
|
{
|
|
ZH_VECTOR_LOGI("Copying range of items from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(src != NULL, ESP_ERR_INVALID_ARG, "Copying range fail. Source vector is NULL.");
|
|
ZH_VECTOR_CHECK(dest != NULL, ESP_ERR_INVALID_ARG, "Copying range fail. Destination vector is NULL.");
|
|
ZH_VECTOR_CHECK(src->status == true, ESP_ERR_INVALID_STATE, "Copying range fail. Source vector not initialized.");
|
|
ZH_VECTOR_CHECK(dest->status == true, ESP_ERR_INVALID_STATE, "Copying range fail. Destination vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < src->size, ESP_FAIL, "Copying range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= src->size, ESP_FAIL, "Copying range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Copying range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(dest, src->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Copying range fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Copying range of items from vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_reverse_range(zh_vector_t *vector, uint16_t start, uint16_t end)
|
|
{
|
|
ZH_VECTOR_LOGI("Reversing range of items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Reversing range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Reversing range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Reversing range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Reversing range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Reversing range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = 0; i < (end - start) / 2; ++i)
|
|
{
|
|
void *temp = vector->items[start + i];
|
|
vector->items[start + i] = vector->items[end - i - 1];
|
|
vector->items[end - i - 1] = temp;
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Reversing range of items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_swap(zh_vector_t *vector, uint16_t index1, uint16_t index2)
|
|
{
|
|
ZH_VECTOR_LOGI("Swapping items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Swapping items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Swapping items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(index1 < vector->size, ESP_FAIL, "Swapping items fail. Index1 out of bounds.");
|
|
ZH_VECTOR_CHECK(index2 < vector->size, ESP_FAIL, "Swapping items fail. Index2 out of bounds.");
|
|
|
|
void *temp = vector->items[index1];
|
|
vector->items[index1] = vector->items[index2];
|
|
vector->items[index2] = temp;
|
|
|
|
ZH_VECTOR_LOGI("Swapping items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_rotate_left(zh_vector_t *vector, uint16_t positions)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector left begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Rotating vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Rotating vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, ESP_FAIL, "Rotating vector fail. Vector is empty.");
|
|
|
|
positions = positions % vector->size;
|
|
if (positions == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector left skipped. No positions to rotate.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **temp = heap_caps_malloc(positions * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Rotating vector fail. Memory allocation failed.");
|
|
|
|
// Сохраняем первые `positions` элементов
|
|
memcpy(temp, vector->items, positions * sizeof(void *));
|
|
|
|
// Сдвигаем оставшиеся элементы
|
|
memmove(vector->items, vector->items + positions, (vector->size - positions) * sizeof(void *));
|
|
|
|
// Переносим сохраненные элементы в конец
|
|
memcpy(vector->items + (vector->size - positions), temp, positions * sizeof(void *));
|
|
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Rotating vector left success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_rotate_right(zh_vector_t *vector, uint16_t positions)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector right begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Rotating vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Rotating vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, ESP_FAIL, "Rotating vector fail. Vector is empty.");
|
|
|
|
positions = positions % vector->size;
|
|
if (positions == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating vector right skipped. No positions to rotate.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **temp = heap_caps_malloc(positions * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Rotating vector fail. Memory allocation failed.");
|
|
|
|
// Сохраняем последние `positions` элементов
|
|
memcpy(temp, vector->items + (vector->size - positions), positions * sizeof(void *));
|
|
|
|
// Сдвигаем оставшиеся элементы
|
|
memmove(vector->items + positions, vector->items, (vector->size - positions) * sizeof(void *));
|
|
|
|
// Переносим сохраненные элементы в начало
|
|
memcpy(vector->items, temp, positions * sizeof(void *));
|
|
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Rotating vector right success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
|
|
esp_err_t zh_vector_find_duplicates(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *duplicates)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding duplicates in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(duplicates != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Duplicates vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(duplicates->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Duplicates vector not initialized.");
|
|
|
|
if (vector->size <= 1)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding duplicates skipped. Vector is empty or has only one element.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(duplicates, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding duplicates fail. Failed to add duplicate.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding duplicates in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds duplicates in a specified range of the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param cmp Comparison function to compare items.
|
|
* @param duplicates Pointer to the vector to store duplicates.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_duplicates_in_range(zh_vector_t *vector, uint16_t start, uint16_t end, int (*cmp)(const void *, const void *), zh_vector_t *duplicates)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding duplicates in range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(duplicates != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Duplicates vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(duplicates->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Duplicates vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Finding duplicates fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Finding duplicates fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Finding duplicates fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < end; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(duplicates, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding duplicates fail. Failed to add duplicate.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding duplicates in range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t zh_vector_sort(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Sorting vector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Sorting vector fail. Vector not initialized.");
|
|
|
|
if (vector->size <= 1)
|
|
{
|
|
ZH_VECTOR_LOGI("Sorting vector skipped. Vector is empty or has only one element.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
qsort(vector->items, vector->size, sizeof(void *), cmp);
|
|
|
|
ZH_VECTOR_LOGI("Sorting vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
uint16_t zh_vector_count(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Counting occurrences of item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, 0, "Counting occurrences fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, 0, "Counting occurrences fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, 0, "Counting occurrences fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, 0, "Counting occurrences fail. Vector not initialized.");
|
|
|
|
uint16_t count = 0;
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) == 0)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Counting occurrences of item in vector success. Count: %d.", count);
|
|
return count;
|
|
}
|
|
|
|
esp_err_t zh_vector_remove_all(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing all occurrences of item from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing all occurrences fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing all occurrences fail. Vector not initialized.");
|
|
|
|
uint16_t write_index = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) != 0)
|
|
{
|
|
if (write_index != i)
|
|
{
|
|
vector->items[write_index] = vector->items[i];
|
|
}
|
|
write_index++;
|
|
}
|
|
else
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
}
|
|
}
|
|
|
|
for (uint16_t i = write_index; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = NULL;
|
|
}
|
|
|
|
vector->size = write_index;
|
|
|
|
ZH_VECTOR_LOGI("Removing all occurrences of item from vector success. New size: %d.", vector->size);
|
|
return ESP_OK;
|
|
}
|
|
|
|
int zh_vector_find_first_of(zh_vector_t *vector, zh_vector_t *other, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first matching item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, -1, "Finding first matching item fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, -1, "Finding first matching item fail. Other vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = 0; j < other->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("First matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("No matching item found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_last_of(zh_vector_t *vector, zh_vector_t *other, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding last matching item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding last matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, -1, "Finding last matching item fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding last matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding last matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, -1, "Finding last matching item fail. Other vector not initialized.");
|
|
|
|
for (int i = vector->size - 1; i >= 0; --i)
|
|
{
|
|
for (uint16_t j = 0; j < other->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Last matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("No matching item found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_mismatch(zh_vector_t *vector1, zh_vector_t *vector2, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first mismatch between two vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, -1, "Finding mismatch fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, -1, "Finding mismatch fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding mismatch fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, -1, "Finding mismatch fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, -1, "Finding mismatch fail. Second vector not initialized.");
|
|
|
|
uint16_t min_size = (vector1->size < vector2->size) ? vector1->size : vector2->size;
|
|
|
|
for (uint16_t i = 0; i < min_size; ++i)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[i]) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Mismatch found at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("No mismatch found between vectors.");
|
|
return -1;
|
|
}
|
|
|
|
esp_err_t zh_vector_transform(zh_vector_t *vector, void *(*func)(void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Transforming vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Transforming vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, ESP_ERR_INVALID_ARG, "Transforming vector fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Transforming vector fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
vector->items[i] = func(vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Transforming vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Transforms items in a specified range of the vector using a user-defined function.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param func Transformation function to apply to each item.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_transform_range(zh_vector_t *vector, uint16_t start, uint16_t end, void *(*func)(void *item))
|
|
{
|
|
ZH_VECTOR_LOGI("Transforming range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Transforming range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(func != NULL, ESP_ERR_INVALID_ARG, "Transforming range fail. Function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Transforming range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Transforming range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Transforming range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Transforming range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
vector->items[i] = func(vector->items[i]);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Transforming range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first occurrence of a subvector in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param subvector Pointer to the subvector to find.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first occurrence of the subvector, or -1 if not found.
|
|
*/
|
|
int zh_vector_find_subvector(zh_vector_t *vector, zh_vector_t *subvector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector != NULL, -1, "Finding subvector fail. Subvector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding subvector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding subvector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->status == true, -1, "Finding subvector fail. Subvector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->size <= vector->size, -1, "Finding subvector fail. Subvector is larger than vector.");
|
|
|
|
for (uint16_t i = 0; i <= vector->size - subvector->size; ++i)
|
|
{
|
|
bool match = true;
|
|
for (uint16_t j = 0; j < subvector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i + j], subvector->items[j]) != 0)
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
ZH_VECTOR_LOGI("Subvector found at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Subvector not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_subvector(zh_vector_t *vector, zh_vector_t *subvector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector != NULL, -1, "Finding subvector fail. Subvector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding subvector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding subvector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->status == true, -1, "Finding subvector fail. Subvector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->size <= vector->size, -1, "Finding subvector fail. Subvector is larger than vector.");
|
|
|
|
for (uint16_t i = 0; i <= vector->size - subvector->size; ++i)
|
|
{
|
|
bool match = true;
|
|
for (uint16_t j = 0; j < subvector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i + j], subvector->items[j]) != 0)
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
ZH_VECTOR_LOGI("Subvector found at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Subvector not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
int zh_vector_find_max(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding maximum item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding maximum fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding maximum fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding maximum fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, -1, "Finding maximum fail. Vector is empty.");
|
|
|
|
int max_index = 0;
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[max_index]) > 0)
|
|
{
|
|
max_index = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Maximum item found in vector at index: %d.", max_index);
|
|
return max_index;
|
|
}
|
|
|
|
int zh_vector_find_min(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding minimum item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding minimum fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding minimum fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding minimum fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, -1, "Finding minimum fail. Vector is empty.");
|
|
|
|
int min_index = 0;
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[min_index]) < 0)
|
|
{
|
|
min_index = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Minimum item found in vector at index: %d.", min_index);
|
|
return min_index;
|
|
}
|
|
|
|
esp_err_t zh_vector_replace_range(zh_vector_t *vector, uint16_t start, uint16_t end, void *new_item)
|
|
{
|
|
ZH_VECTOR_LOGI("Replacing range of items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Replacing range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(new_item != NULL, ESP_ERR_INVALID_ARG, "Replacing range fail. New item is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Replacing range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Replacing range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Replacing range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Replacing range fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
heap_caps_free(vector->items[i]);
|
|
vector->items[i] = heap_caps_calloc(1, vector->unit, MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(vector->items[i] != NULL, ESP_ERR_NO_MEM, "Replacing range fail. Memory allocation failed.");
|
|
memcpy(vector->items[i], new_item, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Replacing range of items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
bool zh_vector_is_equal(zh_vector_t *vector1, zh_vector_t *vector2, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Checking if two vectors are equal begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector1 != NULL, false, "Checking equality fail. First vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector2 != NULL, false, "Checking equality fail. Second vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector1->status == true, false, "Checking equality fail. First vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector2->status == true, false, "Checking equality fail. Second vector not initialized.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, false, "Checking equality fail. Comparison function is NULL.");
|
|
|
|
if (vector1->size != vector2->size)
|
|
{
|
|
ZH_VECTOR_LOGI("Vectors are not equal. Sizes differ.");
|
|
return false;
|
|
}
|
|
|
|
for (uint16_t i = 0; i < vector1->size; ++i)
|
|
{
|
|
if (cmp(vector1->items[i], vector2->items[i]) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Vectors are not equal. Items differ at index: %d.", i);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Vectors are equal.");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Performs a binary search for an item in a sorted vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to search for.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the found item, or -1 if the item is not found.
|
|
*/
|
|
int zh_vector_binary_search(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Performing binary search in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Binary search fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, -1, "Binary search fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Binary search fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Binary search fail. Vector not initialized.");
|
|
|
|
int left = 0;
|
|
int right = vector->size - 1;
|
|
|
|
while (left <= right)
|
|
{
|
|
int mid = left + (right - left) / 2;
|
|
int result = cmp(item, vector->items[mid]);
|
|
|
|
if (result == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Item found in vector at index: %d.", mid);
|
|
return mid;
|
|
}
|
|
else if (result < 0)
|
|
{
|
|
right = mid - 1;
|
|
}
|
|
else
|
|
{
|
|
left = mid + 1;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Item not found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that match the specified item.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to match.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param matches Pointer to the vector to store matching items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_matches(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *), zh_vector_t *matches)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all matches in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding matches fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, ESP_ERR_INVALID_ARG, "Finding matches fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding matches fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(matches != NULL, ESP_ERR_INVALID_ARG, "Finding matches fail. Matches vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding matches fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(matches->status == true, ESP_ERR_INVALID_STATE, "Finding matches fail. Matches vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) == 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(matches, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding matches fail. Failed to add item to matches vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all matches in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Splits the vector into multiple parts of specified size.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param part_size Size of each part.
|
|
* @param parts Pointer to an array of vectors to store the parts (allocated dynamically).
|
|
* @param part_count Pointer to store the number of parts.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_split(zh_vector_t *vector, uint16_t part_size, zh_vector_t **parts, uint16_t *part_count)
|
|
{
|
|
ZH_VECTOR_LOGI("Splitting vector into parts begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(part_size > 0, ESP_ERR_INVALID_ARG, "Splitting vector fail. Part size must be greater than 0.");
|
|
ZH_VECTOR_CHECK(parts != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. Parts pointer is NULL.");
|
|
ZH_VECTOR_CHECK(part_count != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. Part count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Splitting vector fail. Vector not initialized.");
|
|
|
|
*part_count = (vector->size + part_size - 1) / part_size;
|
|
*parts = heap_caps_malloc(*part_count * sizeof(zh_vector_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*parts != NULL, ESP_ERR_NO_MEM, "Splitting vector fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < *part_count; ++i)
|
|
{
|
|
esp_err_t err = zh_vector_init(&(*parts)[i], vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Splitting vector fail. Failed to initialize part vector.");
|
|
|
|
uint16_t start = i * part_size;
|
|
uint16_t end = (start + part_size > vector->size) ? vector->size : start + part_size;
|
|
|
|
for (uint16_t j = start; j < end; ++j)
|
|
{
|
|
err = zh_vector_push_back(&(*parts)[i], vector->items[j]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Splitting vector fail. Failed to add item to part vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Splitting vector into parts success. Number of parts: %d.", *part_count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Flattens a vector of vectors into a single vector.
|
|
*
|
|
* @param vector Pointer to the vector of vectors.
|
|
* @param result Pointer to the resulting flattened vector.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_flatten(zh_vector_t *vector, zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Flattening vector of vectors begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Flattening vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Flattening vector fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Flattening vector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Flattening vector fail. Result vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
zh_vector_t *subvector = (zh_vector_t *)vector->items[i];
|
|
ZH_VECTOR_CHECK(subvector != NULL, ESP_ERR_INVALID_ARG, "Flattening vector fail. Subvector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector->status == true, ESP_ERR_INVALID_STATE, "Flattening vector fail. Subvector not initialized.");
|
|
|
|
for (uint16_t j = 0; j < subvector->size; ++j)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, subvector->items[j]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Flattening vector fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Flattening vector of vectors success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Rotates a specified range of the vector by the given number of positions.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param positions Number of positions to rotate (positive for right, negative for left).
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_rotate_range(zh_vector_t *vector, uint16_t start, uint16_t end, int16_t positions)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Rotating range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Rotating range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Rotating range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Rotating range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Rotating range fail. Start index must be less than end index.");
|
|
|
|
uint16_t range_size = end - start;
|
|
positions = positions % range_size;
|
|
if (positions < 0)
|
|
{
|
|
positions += range_size;
|
|
}
|
|
|
|
if (positions == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating range skipped. No positions to rotate.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **temp = heap_caps_malloc(range_size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Rotating range fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < range_size; ++i)
|
|
{
|
|
temp[(i + positions) % range_size] = vector->items[start + i];
|
|
}
|
|
|
|
memcpy(vector->items + start, temp, range_size * sizeof(void *));
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Rotating range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Rotates a subvector (subarray) of the vector by the given number of positions.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the subvector.
|
|
* @param end End index of the subvector (exclusive).
|
|
* @param positions Number of positions to rotate (positive for right, negative for left).
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_rotate_subvector(zh_vector_t *vector, uint16_t start, uint16_t end, int16_t positions)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating subvector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Rotating subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Rotating subvector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Rotating subvector fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Rotating subvector fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Rotating subvector fail. Start index must be less than end index.");
|
|
|
|
uint16_t range_size = end - start;
|
|
positions = positions % range_size;
|
|
if (positions < 0)
|
|
{
|
|
positions += range_size;
|
|
}
|
|
|
|
if (positions == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Rotating subvector skipped. No positions to rotate.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void **temp = heap_caps_malloc(range_size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Rotating subvector fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < range_size; ++i)
|
|
{
|
|
temp[(i + positions) % range_size] = vector->items[start + i];
|
|
}
|
|
|
|
memcpy(vector->items + start, temp, range_size * sizeof(void *));
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Rotating subvector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first item in the vector that does not match any item in another vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param other Pointer to the other vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first non-matching item, or -1 if all items match.
|
|
*/
|
|
int zh_vector_find_first_not_of(zh_vector_t *vector, zh_vector_t *other, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first non-matching item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first non-matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, -1, "Finding first non-matching item fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first non-matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first non-matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, -1, "Finding first non-matching item fail. Other vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < other->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
ZH_VECTOR_LOGI("First non-matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("All items in vector match items in other vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the last item in the vector that does not match any item in another vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param other Pointer to the other vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the last non-matching item, or -1 if all items match.
|
|
*/
|
|
int zh_vector_find_last_not_of(zh_vector_t *vector, zh_vector_t *other, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding last non-matching item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding last non-matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, -1, "Finding last non-matching item fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding last non-matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding last non-matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, -1, "Finding last non-matching item fail. Other vector not initialized.");
|
|
|
|
for (int i = vector->size - 1; i >= 0; --i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < other->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
ZH_VECTOR_LOGI("Last non-matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("All items in vector match items in other vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Permutes the items in the vector according to the specified order.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param order Array of indices specifying the new order.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_permute(zh_vector_t *vector, const uint16_t *order)
|
|
{
|
|
ZH_VECTOR_LOGI("Permuting vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Permuting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(order != NULL, ESP_ERR_INVALID_ARG, "Permuting vector fail. Order array is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Permuting vector fail. Vector not initialized.");
|
|
|
|
void **temp = heap_caps_malloc(vector->size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Permuting vector fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
temp[i] = vector->items[order[i]];
|
|
}
|
|
|
|
memcpy(vector->items, temp, vector->size * sizeof(void *));
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Permuting vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Permutes the items in a specified range of the vector according to the given order.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param order Array of indices specifying the new order within the range.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_permute_range(zh_vector_t *vector, uint16_t start, uint16_t end, const uint16_t *order)
|
|
{
|
|
ZH_VECTOR_LOGI("Permuting range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Permuting range fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(order != NULL, ESP_ERR_INVALID_ARG, "Permuting range fail. Order array is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Permuting range fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Permuting range fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Permuting range fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Permuting range fail. Start index must be less than end index.");
|
|
|
|
uint16_t range_size = end - start;
|
|
void **temp = heap_caps_malloc(range_size * sizeof(void *), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(temp != NULL, ESP_ERR_NO_MEM, "Permuting range fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < range_size; ++i)
|
|
{
|
|
temp[i] = vector->items[start + order[i]];
|
|
}
|
|
|
|
memcpy(vector->items + start, temp, range_size * sizeof(void *));
|
|
heap_caps_free(temp);
|
|
|
|
ZH_VECTOR_LOGI("Permuting range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Generates values for the vector using a generator function.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param generator Generator function that takes an index and returns a value.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_generate(zh_vector_t *vector, void *(*generator)(uint16_t index))
|
|
{
|
|
ZH_VECTOR_LOGI("Generating values for vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Generating values fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(generator != NULL, ESP_ERR_INVALID_ARG, "Generating values fail. Generator function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Generating values fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
void *value = generator(i);
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_NO_MEM, "Generating values fail. Generator returned NULL.");
|
|
|
|
memcpy(vector->items[i], value, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Generating values for vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first item in the vector that is not within a specified range.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first non-matching item, or -1 if all items match.
|
|
*/
|
|
int zh_vector_find_first_not_in_range(zh_vector_t *vector, uint16_t start, uint16_t end, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first non-matching item in range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first non-matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first non-matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first non-matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, -1, "Finding first non-matching item fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, -1, "Finding first non-matching item fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, -1, "Finding first non-matching item fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (i < start || i >= end)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[start]) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("First non-matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("All items in vector match the range.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all ranges in the vector that satisfy a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param ranges Pointer to an array of ranges (allocated dynamically).
|
|
* @param count Pointer to store the number of found ranges.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_ranges(zh_vector_t *vector, bool (*predicate)(const void *), uint16_t **ranges, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all ranges in vector with predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding ranges fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding ranges fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(ranges != NULL, ESP_ERR_INVALID_ARG, "Finding ranges fail. Ranges pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding ranges fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding ranges fail. Vector not initialized.");
|
|
|
|
*count = 0;
|
|
*ranges = heap_caps_malloc(vector->size * 2 * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*ranges != NULL, ESP_ERR_NO_MEM, "Finding ranges fail. Memory allocation failed.");
|
|
|
|
uint16_t start = 0;
|
|
bool in_range = false;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
if (!in_range)
|
|
{
|
|
start = i;
|
|
in_range = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (in_range)
|
|
{
|
|
(*ranges)[(*count)++] = start;
|
|
(*ranges)[(*count)++] = i;
|
|
in_range = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (in_range)
|
|
{
|
|
(*ranges)[(*count)++] = start;
|
|
(*ranges)[(*count)++] = vector->size;
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all ranges in vector with predicate success. Found: %d ranges.", *count / 2);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first item in the vector that matches any item in a specified range of another vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param other Pointer to the other vector.
|
|
* @param start Start index of the range in the other vector.
|
|
* @param end End index of the range in the other vector (exclusive).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first matching item, or -1 if no match is found.
|
|
*/
|
|
int zh_vector_find_first_of_range(zh_vector_t *vector, zh_vector_t *other, uint16_t start, uint16_t end, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first matching item in range of another vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first matching item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, -1, "Finding first matching item fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first matching item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first matching item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, -1, "Finding first matching item fail. Other vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < other->size, -1, "Finding first matching item fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= other->size, -1, "Finding first matching item fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, -1, "Finding first matching item fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = start; j < end; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("First matching item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("No matching item found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that do not match any item in another vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param other Pointer to the other vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param indices Pointer to an array of indices (allocated dynamically).
|
|
* @param count Pointer to store the number of found indices.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_not_of(zh_vector_t *vector, zh_vector_t *other, int (*cmp)(const void *, const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all non-matching items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding non-matching items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(other != NULL, ESP_ERR_INVALID_ARG, "Finding non-matching items fail. Other vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding non-matching items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding non-matching items fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding non-matching items fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding non-matching items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(other->status == true, ESP_ERR_INVALID_STATE, "Finding non-matching items fail. Other vector not initialized.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding non-matching items fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t j = 0; j < other->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], other->items[j]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all non-matching items in vector success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first item in the vector that is not equal to the specified item.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first non-equal item, or -1 if all items are equal.
|
|
*/
|
|
int zh_vector_find_first_not_equal(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first non-equal item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first non-equal item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, -1, "Finding first non-equal item fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first non-equal item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first non-equal item fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], item) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("First non-equal item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("All items in vector are equal to the specified item.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the last item in the vector that is not equal to the specified item.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param item Pointer to the item to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the last non-equal item, or -1 if all items are equal.
|
|
*/
|
|
int zh_vector_find_last_not_equal(zh_vector_t *vector, void *item, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding last non-equal item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding last non-equal item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(item != NULL, -1, "Finding last non-equal item fail. Item is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding last non-equal item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding last non-equal item fail. Vector not initialized.");
|
|
|
|
for (int i = vector->size - 1; i >= 0; --i)
|
|
{
|
|
if (cmp(vector->items[i], item) != 0)
|
|
{
|
|
ZH_VECTOR_LOGI("Last non-equal item found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("All items in vector are equal to the specified item.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Partitions the vector into two parts based on a comparison with a specified value.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param value Pointer to the value to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param less_than Pointer to the vector to store items less than the value.
|
|
* @param greater_or_equal Pointer to the vector to store items greater than or equal to the value.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_partition_by_value(zh_vector_t *vector, void *value, int (*cmp)(const void *, const void *), zh_vector_t *less_than, zh_vector_t *greater_or_equal)
|
|
{
|
|
ZH_VECTOR_LOGI("Partitioning vector by value begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Value is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(less_than != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Less-than vector is NULL.");
|
|
ZH_VECTOR_CHECK(greater_or_equal != NULL, ESP_ERR_INVALID_ARG, "Partitioning vector fail. Greater-or-equal vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Partitioning vector fail. Vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(less_than, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to initialize less-than vector.");
|
|
|
|
err = zh_vector_init(greater_or_equal, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to initialize greater-or-equal vector.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], value) < 0)
|
|
{
|
|
err = zh_vector_push_back(less_than, vector->items[i]);
|
|
}
|
|
else
|
|
{
|
|
err = zh_vector_push_back(greater_or_equal, vector->items[i]);
|
|
}
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Partitioning vector fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Partitioning vector by value success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Generates values for a specified range of the vector using a generator function.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param generator Generator function that takes an index and returns a value.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_generate_range(zh_vector_t *vector, uint16_t start, uint16_t end, void *(*generator)(uint16_t index))
|
|
{
|
|
ZH_VECTOR_LOGI("Generating values for range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Generating values fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(generator != NULL, ESP_ERR_INVALID_ARG, "Generating values fail. Generator function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Generating values fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Generating values fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Generating values fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Generating values fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
void *value = generator(i);
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_NO_MEM, "Generating values fail. Generator returned NULL.");
|
|
|
|
memcpy(vector->items[i], value, vector->unit);
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Generating values for range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the first duplicate item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Index of the first duplicate item, or -1 if no duplicates are found.
|
|
*/
|
|
int zh_vector_find_first_duplicate(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding first duplicate in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, -1, "Finding first duplicate fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, -1, "Finding first duplicate fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, -1, "Finding first duplicate fail. Vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
ZH_VECTOR_LOGI("First duplicate found in vector at index: %d.", i);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("No duplicates found in vector.");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all unique items in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param unique Pointer to the vector to store unique items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_unique(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *unique)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding unique items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding unique items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding unique items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(unique != NULL, ESP_ERR_INVALID_ARG, "Finding unique items fail. Unique vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding unique items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(unique->status == true, ESP_ERR_INVALID_STATE, "Finding unique items fail. Unique vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
bool is_unique = true;
|
|
for (uint16_t j = 0; j < unique->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], unique->items[j]) == 0)
|
|
{
|
|
is_unique = false;
|
|
break;
|
|
}
|
|
}
|
|
if (is_unique)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(unique, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding unique items fail. Failed to add item.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding unique items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes duplicate items in a specified range of the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_remove_duplicates_in_range(zh_vector_t *vector, uint16_t start, uint16_t end, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing duplicates in range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing duplicates fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, ESP_FAIL, "Removing duplicates fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, ESP_FAIL, "Removing duplicates fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, ESP_FAIL, "Removing duplicates fail. Start index must be less than end index.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < end;)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
zh_vector_remove(vector, j);
|
|
end--; // Уменьшаем конец диапазона после удаления
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Removing duplicates in range of vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the longest subvector in the vector that satisfies a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param start Pointer to store the start index of the subvector.
|
|
* @param length Pointer to store the length of the subvector.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_longest_subvector(zh_vector_t *vector, bool (*predicate)(const void *), uint16_t *start, uint16_t *length)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding longest subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding longest subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding longest subvector fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(start != NULL, ESP_ERR_INVALID_ARG, "Finding longest subvector fail. Start pointer is NULL.");
|
|
ZH_VECTOR_CHECK(length != NULL, ESP_ERR_INVALID_ARG, "Finding longest subvector fail. Length pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding longest subvector fail. Vector not initialized.");
|
|
|
|
uint16_t max_start = 0, max_length = 0;
|
|
uint16_t current_start = 0, current_length = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
if (current_length == 0)
|
|
{
|
|
current_start = i;
|
|
}
|
|
current_length++;
|
|
}
|
|
else
|
|
{
|
|
if (current_length > max_length)
|
|
{
|
|
max_start = current_start;
|
|
max_length = current_length;
|
|
}
|
|
current_length = 0;
|
|
}
|
|
}
|
|
|
|
if (current_length > max_length)
|
|
{
|
|
max_start = current_start;
|
|
max_length = current_length;
|
|
}
|
|
|
|
*start = max_start;
|
|
*length = max_length;
|
|
|
|
ZH_VECTOR_LOGI("Finding longest subvector in vector success. Start: %d, Length: %d.", max_start, max_length);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all duplicate items in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param duplicates Pointer to the vector to store duplicate items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_duplicates(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *duplicates)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all duplicates in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(duplicates != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Duplicates vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(duplicates->status == true, ESP_ERR_INVALID_STATE, "Finding duplicates fail. Duplicates vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
for (uint16_t j = i + 1; j < vector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(duplicates, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding duplicates fail. Failed to add duplicate.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all duplicates in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the most frequent item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param most_frequent Pointer to store the most frequent item.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_most_frequent(zh_vector_t *vector, int (*cmp)(const void *, const void *), void **most_frequent)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding most frequent item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding most frequent item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding most frequent item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(most_frequent != NULL, ESP_ERR_INVALID_ARG, "Finding most frequent item fail. Output pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding most frequent item fail. Vector not initialized.");
|
|
|
|
uint16_t max_count = 0;
|
|
*most_frequent = NULL;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
uint16_t count = 0;
|
|
for (uint16_t j = 0; j < vector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
if (count > max_count)
|
|
{
|
|
max_count = count;
|
|
*most_frequent = vector->items[i];
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding most frequent item in vector success. Count: %d.", max_count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Splits the vector into two parts based on a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param true_part Pointer to the vector to store items satisfying the predicate.
|
|
* @param false_part Pointer to the vector to store items not satisfying the predicate.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_split_by_predicate(zh_vector_t *vector, bool (*predicate)(const void *), zh_vector_t *true_part, zh_vector_t *false_part)
|
|
{
|
|
ZH_VECTOR_LOGI("Splitting vector by predicate begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(true_part != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. True part is NULL.");
|
|
ZH_VECTOR_CHECK(false_part != NULL, ESP_ERR_INVALID_ARG, "Splitting vector fail. False part is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Splitting vector fail. Vector not initialized.");
|
|
|
|
esp_err_t err = zh_vector_init(true_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Splitting vector fail. Failed to initialize true part.");
|
|
|
|
err = zh_vector_init(false_part, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Splitting vector fail. Failed to initialize false part.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
err = zh_vector_push_back(true_part, vector->items[i]);
|
|
}
|
|
else
|
|
{
|
|
err = zh_vector_push_back(false_part, vector->items[i]);
|
|
}
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Splitting vector fail. Failed to add item.");
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Splitting vector by predicate success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the longest sequence of identical items in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param start Pointer to store the start index of the sequence.
|
|
* @param length Pointer to store the length of the sequence.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_longest_sequence(zh_vector_t *vector, int (*cmp)(const void *, const void *), uint16_t *start, uint16_t *length)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding longest sequence in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding longest sequence fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding longest sequence fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(start != NULL, ESP_ERR_INVALID_ARG, "Finding longest sequence fail. Start pointer is NULL.");
|
|
ZH_VECTOR_CHECK(length != NULL, ESP_ERR_INVALID_ARG, "Finding longest sequence fail. Length pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding longest sequence fail. Vector not initialized.");
|
|
|
|
uint16_t max_start = 0, max_length = 0;
|
|
uint16_t current_start = 0, current_length = 1;
|
|
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[i - 1]) == 0)
|
|
{
|
|
current_length++;
|
|
}
|
|
else
|
|
{
|
|
if (current_length > max_length)
|
|
{
|
|
max_start = current_start;
|
|
max_length = current_length;
|
|
}
|
|
current_start = i;
|
|
current_length = 1;
|
|
}
|
|
}
|
|
|
|
if (current_length > max_length)
|
|
{
|
|
max_start = current_start;
|
|
max_length = current_length;
|
|
}
|
|
|
|
*start = max_start;
|
|
*length = max_length;
|
|
|
|
ZH_VECTOR_LOGI("Finding longest sequence in vector success. Start: %d, Length: %d.", max_start, max_length);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all occurrences of a subvector in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param subvector Pointer to the subvector to find.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param indices Pointer to an array of starting indices (allocated dynamically).
|
|
* @param count Pointer to store the number of found occurrences.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_subvectors(zh_vector_t *vector, zh_vector_t *subvector, int (*cmp)(const void *, const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all occurrences of subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Subvector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding subvector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->status == true, ESP_ERR_INVALID_STATE, "Finding subvector fail. Subvector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->size <= vector->size, ESP_FAIL, "Finding subvector fail. Subvector is larger than vector.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding subvector fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i <= vector->size - subvector->size; ++i)
|
|
{
|
|
bool match = true;
|
|
for (uint16_t j = 0; j < subvector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i + j], subvector->items[j]) != 0)
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all occurrences of subvector in vector success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes all duplicate items from the vector globally.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_remove_duplicates_globally(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Removing all duplicates globally from vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Removing duplicates fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Removing duplicates fail. Vector not initialized.");
|
|
|
|
zh_vector_t unique;
|
|
esp_err_t err = zh_vector_init(&unique, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Removing duplicates fail. Failed to initialize unique vector.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
bool is_duplicate = false;
|
|
for (uint16_t j = 0; j < unique.size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], unique.items[j]) == 0)
|
|
{
|
|
is_duplicate = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!is_duplicate)
|
|
{
|
|
err = zh_vector_push_back(&unique, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Removing duplicates fail. Failed to add unique item.");
|
|
}
|
|
}
|
|
|
|
zh_vector_clear(vector);
|
|
for (uint16_t i = 0; i < unique.size; ++i)
|
|
{
|
|
err = zh_vector_push_back(vector, unique.items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Removing duplicates fail. Failed to copy unique item.");
|
|
}
|
|
|
|
zh_vector_free(&unique);
|
|
ZH_VECTOR_LOGI("Removing all duplicates globally from vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the median item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the median item, or NULL if the vector is empty.
|
|
*/
|
|
void *zh_vector_find_median(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding median in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding median fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding median fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding median fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, NULL, "Finding median fail. Vector is empty.");
|
|
|
|
zh_vector_t sorted;
|
|
esp_err_t err = zh_vector_copy(&sorted, vector);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, NULL, "Finding median fail. Failed to copy vector.");
|
|
|
|
zh_vector_sort(&sorted, cmp);
|
|
|
|
void *median = sorted.items[sorted.size / 2];
|
|
zh_vector_free(&sorted);
|
|
|
|
ZH_VECTOR_LOGI("Finding median in vector success.");
|
|
return median;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the mode (most frequent item) in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the mode item, or NULL if the vector is empty.
|
|
*/
|
|
void *zh_vector_find_mode(zh_vector_t *vector, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding mode in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding mode fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding mode fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding mode fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, NULL, "Finding mode fail. Vector is empty.");
|
|
|
|
void *mode = NULL;
|
|
uint16_t max_count = 0;
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
uint16_t count = 0;
|
|
for (uint16_t j = 0; j < vector->size; ++j)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[j]) == 0)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
if (count > max_count)
|
|
{
|
|
max_count = count;
|
|
mode = vector->items[i];
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding mode in vector success. Count: %d.", max_count);
|
|
return mode;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the k-th largest item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param k The rank of the largest item to find (1-based index).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the k-th largest item, or NULL if k is out of bounds.
|
|
*/
|
|
void *zh_vector_find_kth_largest(zh_vector_t *vector, uint16_t k, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding k-th largest item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding k-th largest fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding k-th largest fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding k-th largest fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(k > 0 && k <= vector->size, NULL, "Finding k-th largest fail. k is out of bounds.");
|
|
|
|
zh_vector_t sorted;
|
|
esp_err_t err = zh_vector_copy(&sorted, vector);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, NULL, "Finding k-th largest fail. Failed to copy vector.");
|
|
|
|
zh_vector_sort(&sorted, cmp);
|
|
|
|
void *kth_largest = sorted.items[sorted.size - k];
|
|
zh_vector_free(&sorted);
|
|
|
|
ZH_VECTOR_LOGI("Finding k-th largest item in vector success.");
|
|
return kth_largest;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the k-th smallest item in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param k The rank of the smallest item to find (1-based index).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the k-th smallest item, or NULL if k is out of bounds.
|
|
*/
|
|
void *zh_vector_find_kth_smallest(zh_vector_t *vector, uint16_t k, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding k-th smallest item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding k-th smallest fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding k-th smallest fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding k-th smallest fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(k > 0 && k <= vector->size, NULL, "Finding k-th smallest fail. k is out of bounds.");
|
|
|
|
zh_vector_t sorted;
|
|
esp_err_t err = zh_vector_copy(&sorted, vector);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, NULL, "Finding k-th smallest fail. Failed to copy vector.");
|
|
|
|
zh_vector_sort(&sorted, cmp);
|
|
|
|
void *kth_smallest = sorted.items[k - 1];
|
|
zh_vector_free(&sorted);
|
|
|
|
ZH_VECTOR_LOGI("Finding k-th smallest item in vector success.");
|
|
return kth_smallest;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that are greater than the specified value.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param value Pointer to the value to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the results.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_greater_than(zh_vector_t *vector, void *value, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all items greater than value in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Value is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Result vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], value) > 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding items fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all items greater than value in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that are less than the specified value.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param value Pointer to the value to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the results.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_less_than(zh_vector_t *vector, void *value, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all items less than value in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Value is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Result vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], value) < 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding items fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all items less than value in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that are between two specified values.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param lower Pointer to the lower bound.
|
|
* @param upper Pointer to the upper bound.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the results.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_between(zh_vector_t *vector, void *lower, void *upper, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all items between two values in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(lower != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Lower bound is NULL.");
|
|
ZH_VECTOR_CHECK(upper != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Upper bound is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Result vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], lower) >= 0 && cmp(vector->items[i], upper) <= 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding items fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all items between two values in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the item in the vector that is closest to the specified value.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param value Pointer to the value to compare.
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the closest item, or NULL if the vector is empty.
|
|
*/
|
|
void *zh_vector_find_closest(zh_vector_t *vector, void *value, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding closest item in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding closest item fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(value != NULL, NULL, "Finding closest item fail. Value is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding closest item fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding closest item fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(vector->size > 0, NULL, "Finding closest item fail. Vector is empty.");
|
|
|
|
void *closest = vector->items[0];
|
|
for (uint16_t i = 1; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], value) < cmp(closest, value))
|
|
{
|
|
closest = vector->items[i];
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding closest item in vector success.");
|
|
return closest;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all peak items in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param peaks Pointer to the vector to store peak items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_peaks(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *peaks)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding peaks in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding peaks fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding peaks fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(peaks != NULL, ESP_ERR_INVALID_ARG, "Finding peaks fail. Peaks vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding peaks fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(peaks->status == true, ESP_ERR_INVALID_STATE, "Finding peaks fail. Peaks vector not initialized.");
|
|
|
|
for (uint16_t i = 1; i < vector->size - 1; ++i)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[i - 1]) > 0 && cmp(vector->items[i], vector->items[i + 1]) > 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(peaks, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding peaks fail. Failed to add peak.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding peaks in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all valley items in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param valleys Pointer to the vector to store valley items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_valleys(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *valleys)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding valleys in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding valleys fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding valleys fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(valleys != NULL, ESP_ERR_INVALID_ARG, "Finding valleys fail. Valleys vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding valleys fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(valleys->status == true, ESP_ERR_INVALID_STATE, "Finding valleys fail. Valleys vector not initialized.");
|
|
|
|
for (uint16_t i = 1; i < vector->size - 1; ++i)
|
|
{
|
|
if (cmp(vector->items[i], vector->items[i - 1]) < 0 && cmp(vector->items[i], vector->items[i + 1]) < 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(valleys, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding valleys fail. Failed to add valley.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding valleys in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all outliers in the vector based on a predicate.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param predicate Predicate function to evaluate items.
|
|
* @param outliers Pointer to the vector to store outlier items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_outliers(zh_vector_t *vector, bool (*predicate)(const void *), zh_vector_t *outliers)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding outliers in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding outliers fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(predicate != NULL, ESP_ERR_INVALID_ARG, "Finding outliers fail. Predicate is NULL.");
|
|
ZH_VECTOR_CHECK(outliers != NULL, ESP_ERR_INVALID_ARG, "Finding outliers fail. Outliers vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding outliers fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(outliers->status == true, ESP_ERR_INVALID_STATE, "Finding outliers fail. Outliers vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (predicate(vector->items[i]))
|
|
{
|
|
esp_err_t err = zh_vector_push_back(outliers, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding outliers fail. Failed to add outlier.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding outliers in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the median item in a specified range of the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param start Start index of the range.
|
|
* @param end End index of the range (exclusive).
|
|
* @param cmp Comparison function to compare items.
|
|
* @return Pointer to the median item, or NULL if the range is invalid.
|
|
*/
|
|
void *zh_vector_find_median_range(zh_vector_t *vector, uint16_t start, uint16_t end, int (*cmp)(const void *, const void *))
|
|
{
|
|
ZH_VECTOR_LOGI("Finding median in range of vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, NULL, "Finding median fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, NULL, "Finding median fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, NULL, "Finding median fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(start < vector->size, NULL, "Finding median fail. Start index out of bounds.");
|
|
ZH_VECTOR_CHECK(end <= vector->size, NULL, "Finding median fail. End index out of bounds.");
|
|
ZH_VECTOR_CHECK(start < end, NULL, "Finding median fail. Start index must be less than end index.");
|
|
|
|
uint16_t range_size = end - start;
|
|
zh_vector_t temp;
|
|
esp_err_t err = zh_vector_init(&temp, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, NULL, "Finding median fail. Failed to initialize temporary vector.");
|
|
|
|
for (uint16_t i = start; i < end; ++i)
|
|
{
|
|
err = zh_vector_push_back(&temp, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, NULL, "Finding median fail. Failed to copy item.");
|
|
}
|
|
|
|
zh_vector_sort(&temp, cmp);
|
|
void *median = temp.items[range_size / 2];
|
|
zh_vector_free(&temp);
|
|
|
|
ZH_VECTOR_LOGI("Finding median in range of vector success.");
|
|
return median;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the k closest items to a specified value in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param value Pointer to the value to compare.
|
|
* @param k Number of closest items to find.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the closest items.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_k_closest(zh_vector_t *vector, void *value, uint16_t k, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding k closest items in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding k closest items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(value != NULL, ESP_ERR_INVALID_ARG, "Finding k closest items fail. Value is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding k closest items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding k closest items fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding k closest items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding k closest items fail. Result vector not initialized.");
|
|
ZH_VECTOR_CHECK(k > 0 && k <= vector->size, ESP_ERR_INVALID_ARG, "Finding k closest items fail. Invalid k value.");
|
|
|
|
zh_vector_t distances;
|
|
esp_err_t err = zh_vector_init(&distances, sizeof(int));
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding k closest items fail. Failed to initialize distances vector.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
int distance = cmp(vector->items[i], value);
|
|
err = zh_vector_push_back(&distances, &distance);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding k closest items fail. Failed to calculate distance.");
|
|
}
|
|
|
|
for (uint16_t i = 0; i < k; ++i)
|
|
{
|
|
int min_index = zh_vector_find_min(&distances, cmp);
|
|
err = zh_vector_push_back(result, vector->items[min_index]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding k closest items fail. Failed to add item to result.");
|
|
zh_vector_change_item(&distances, min_index, (void *)&INT_MAX); // Исключаем найденный элемент
|
|
}
|
|
|
|
zh_vector_free(&distances);
|
|
ZH_VECTOR_LOGI("Finding k closest items in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all items in the vector that are outside a specified range.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param lower Pointer to the lower bound.
|
|
* @param upper Pointer to the upper bound.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the results.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_out_of_range(zh_vector_t *vector, void *lower, void *upper, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all items outside range in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(lower != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Lower bound is NULL.");
|
|
ZH_VECTOR_CHECK(upper != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Upper bound is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding items fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding items fail. Result vector not initialized.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (cmp(vector->items[i], lower) < 0 || cmp(vector->items[i], upper) > 0)
|
|
{
|
|
esp_err_t err = zh_vector_push_back(result, vector->items[i]);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding items fail. Failed to add item to result vector.");
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all items outside range in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the longest increasing subsequence in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the subsequence.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_longest_increasing_subsequence(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding longest increasing subsequence in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding subsequence fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding subsequence fail. Result vector not initialized.");
|
|
|
|
uint16_t *lengths = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
uint16_t *previous = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(lengths != NULL && previous != NULL, ESP_ERR_NO_MEM, "Finding subsequence fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
lengths[i] = 1;
|
|
previous[i] = UINT16_MAX;
|
|
for (uint16_t j = 0; j < i; ++j)
|
|
{
|
|
if (cmp(vector->items[j], vector->items[i]) < 0 && lengths[j] + 1 > lengths[i])
|
|
{
|
|
lengths[i] = lengths[j] + 1;
|
|
previous[i] = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t max_length = 0, max_index = 0;
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (lengths[i] > max_length)
|
|
{
|
|
max_length = lengths[i];
|
|
max_index = i;
|
|
}
|
|
}
|
|
|
|
zh_vector_clear(result);
|
|
for (uint16_t i = max_index; i != UINT16_MAX; i = previous[i])
|
|
{
|
|
zh_vector_push_back(result, vector->items[i]);
|
|
}
|
|
|
|
heap_caps_free(lengths);
|
|
heap_caps_free(previous);
|
|
|
|
ZH_VECTOR_LOGI("Finding longest increasing subsequence in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the longest decreasing subsequence in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the subsequence.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_longest_decreasing_subsequence(zh_vector_t *vector, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding longest decreasing subsequence in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding subsequence fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding subsequence fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding subsequence fail. Result vector not initialized.");
|
|
|
|
uint16_t *lengths = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
uint16_t *previous = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(lengths != NULL && previous != NULL, ESP_ERR_NO_MEM, "Finding subsequence fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
lengths[i] = 1;
|
|
previous[i] = UINT16_MAX;
|
|
for (uint16_t j = 0; j < i; ++j)
|
|
{
|
|
if (cmp(vector->items[j], vector->items[i]) > 0 && lengths[j] + 1 > lengths[i])
|
|
{
|
|
lengths[i] = lengths[j] + 1;
|
|
previous[i] = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t max_length = 0, max_index = 0;
|
|
for (uint16_t i = 0; i < vector->size; ++i)
|
|
{
|
|
if (lengths[i] > max_length)
|
|
{
|
|
max_length = lengths[i];
|
|
max_index = i;
|
|
}
|
|
}
|
|
|
|
zh_vector_clear(result);
|
|
for (uint16_t i = max_index; i != UINT16_MAX; i = previous[i])
|
|
{
|
|
zh_vector_push_back(result, vector->items[i]);
|
|
}
|
|
|
|
heap_caps_free(lengths);
|
|
heap_caps_free(previous);
|
|
|
|
ZH_VECTOR_LOGI("Finding longest decreasing subsequence in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds the most common subvector in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param subvector_size Size of the subvector to find.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param result Pointer to the vector to store the most common subvector.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_most_common_subvector(zh_vector_t *vector, uint16_t subvector_size, int (*cmp)(const void *, const void *), zh_vector_t *result)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding most common subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector_size > 0, ESP_ERR_INVALID_ARG, "Finding subvector fail. Subvector size must be greater than 0.");
|
|
ZH_VECTOR_CHECK(subvector_size <= vector->size, ESP_ERR_INVALID_ARG, "Finding subvector fail. Subvector size is larger than vector.");
|
|
ZH_VECTOR_CHECK(result != NULL, ESP_ERR_INVALID_ARG, "Finding subvector fail. Result vector is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding subvector fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(result->status == true, ESP_ERR_INVALID_STATE, "Finding subvector fail. Result vector not initialized.");
|
|
|
|
uint16_t max_count = 0;
|
|
zh_vector_t temp_result;
|
|
esp_err_t err = zh_vector_init(&temp_result, vector->unit);
|
|
ZH_VECTOR_CHECK(err == ESP_OK, err, "Finding subvector fail. Failed to initialize temporary vector.");
|
|
|
|
for (uint16_t i = 0; i <= vector->size - subvector_size; ++i)
|
|
{
|
|
uint16_t count = 0;
|
|
for (uint16_t j = i + 1; j <= vector->size - subvector_size; ++j)
|
|
{
|
|
bool match = true;
|
|
for (uint16_t k = 0; k < subvector_size; ++k)
|
|
{
|
|
if (cmp(vector->items[i + k], vector->items[j + k]) != 0)
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
if (count > max_count)
|
|
{
|
|
max_count = count;
|
|
zh_vector_clear(&temp_result);
|
|
for (uint16_t k = 0; k < subvector_size; ++k)
|
|
{
|
|
zh_vector_push_back(&temp_result, vector->items[i + k]);
|
|
}
|
|
}
|
|
}
|
|
|
|
zh_vector_clear(result);
|
|
for (uint16_t i = 0; i < temp_result.size; ++i)
|
|
{
|
|
zh_vector_push_back(result, temp_result.items[i]);
|
|
}
|
|
|
|
zh_vector_free(&temp_result);
|
|
|
|
ZH_VECTOR_LOGI("Finding most common subvector in vector success.");
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Finds all permutations of a subvector in the vector.
|
|
*
|
|
* @param vector Pointer to the vector.
|
|
* @param subvector Pointer to the subvector to find permutations of.
|
|
* @param cmp Comparison function to compare items.
|
|
* @param indices Pointer to an array of starting indices (allocated dynamically).
|
|
* @param count Pointer to store the number of found permutations.
|
|
* @return ESP_OK on success, or an error code otherwise.
|
|
*/
|
|
esp_err_t zh_vector_find_all_permutations(zh_vector_t *vector, zh_vector_t *subvector, int (*cmp)(const void *, const void *), uint16_t **indices, uint16_t *count)
|
|
{
|
|
ZH_VECTOR_LOGI("Finding all permutations of subvector in vector begin.");
|
|
|
|
ZH_VECTOR_CHECK(vector != NULL, ESP_ERR_INVALID_ARG, "Finding permutations fail. Vector is NULL.");
|
|
ZH_VECTOR_CHECK(subvector != NULL, ESP_ERR_INVALID_ARG, "Finding permutations fail. Subvector is NULL.");
|
|
ZH_VECTOR_CHECK(cmp != NULL, ESP_ERR_INVALID_ARG, "Finding permutations fail. Comparison function is NULL.");
|
|
ZH_VECTOR_CHECK(indices != NULL, ESP_ERR_INVALID_ARG, "Finding permutations fail. Indices pointer is NULL.");
|
|
ZH_VECTOR_CHECK(count != NULL, ESP_ERR_INVALID_ARG, "Finding permutations fail. Count pointer is NULL.");
|
|
ZH_VECTOR_CHECK(vector->status == true, ESP_ERR_INVALID_STATE, "Finding permutations fail. Vector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->status == true, ESP_ERR_INVALID_STATE, "Finding permutations fail. Subvector not initialized.");
|
|
ZH_VECTOR_CHECK(subvector->size <= vector->size, ESP_FAIL, "Finding permutations fail. Subvector is larger than vector.");
|
|
|
|
*count = 0;
|
|
*indices = heap_caps_malloc(vector->size * sizeof(uint16_t), MALLOC_CAP_8BIT);
|
|
ZH_VECTOR_CHECK(*indices != NULL, ESP_ERR_NO_MEM, "Finding permutations fail. Memory allocation failed.");
|
|
|
|
for (uint16_t i = 0; i <= vector->size - subvector->size; ++i)
|
|
{
|
|
bool match = true;
|
|
for (uint16_t j = 0; j < subvector->size; ++j)
|
|
{
|
|
bool found = false;
|
|
for (uint16_t k = 0; k < subvector->size; ++k)
|
|
{
|
|
if (cmp(vector->items[i + j], subvector->items[k]) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
(*indices)[(*count)++] = i;
|
|
}
|
|
}
|
|
|
|
ZH_VECTOR_LOGI("Finding all permutations of subvector in vector success. Found: %d.", *count);
|
|
return ESP_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|