perf: updated error checks
This commit is contained in:
1 parent
1891599e66
commit
9e81485984
2 files changed
+208
-85
No files matched your search
+38
-31
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stddef.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
@@ -62,36 +64,38 @@ extern "C"
|
|||||||
*
|
*
|
||||||
* Frees all allocated elements, the items array, the mutex, and the vector
|
* Frees all allocated elements, the items array, the mutex, and the vector
|
||||||
* structure itself. The vector pointer is set to NULL after deletion.
|
* structure itself. The vector pointer is set to NULL after deletion.
|
||||||
|
* The vector is marked as deleting and the function waits until all
|
||||||
|
* operations in progress finish (reference counter drops to zero).
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle to be freed (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle to be freed (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL
|
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted, mutex acquisition fails or deletion is already in progress
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_free(zh_vector_t **vector);
|
esp_err_t zh_vector_free(zh_vector_t **vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the current number of elements in the vector.
|
* @brief Get the current number of elements in the vector.
|
||||||
*
|
*
|
||||||
* @param[in] vector Pointer to the vector handle (must not be NULL)
|
* @param[in] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[out] size Pointer to receive the current size (must not be NULL)
|
* @param[out] size Pointer to receive the current size (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_get_size(zh_vector_t **vector, uint16_t *size);
|
esp_err_t zh_vector_get_size(zh_vector_t **vector, uint16_t *size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the current capacity of the vector.
|
* @brief Get the current capacity of the vector.
|
||||||
*
|
*
|
||||||
* @param[in] vector Pointer to the vector handle (must not be NULL)
|
* @param[in] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[out] capacity Pointer to receive the current capacity (must not be NULL)
|
* @param[out] capacity Pointer to receive the current capacity (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_get_capacity(zh_vector_t **vector, uint16_t *capacity);
|
esp_err_t zh_vector_get_capacity(zh_vector_t **vector, uint16_t *capacity);
|
||||||
|
|
||||||
@@ -102,12 +106,12 @@ extern "C"
|
|||||||
* a copy of the provided item at index 0. The vector capacity
|
* a copy of the provided item at index 0. The vector capacity
|
||||||
* will be increased if necessary.
|
* will be increased if necessary.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] item Pointer to the item to insert (must not be NULL)
|
* @param[in] item Pointer to the item to insert (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
* @return ESP_ERR_NO_MEM if vector is full or element allocation fails
|
* @return ESP_ERR_NO_MEM if vector is full or element allocation fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_push_front(zh_vector_t **vector, const void *item);
|
esp_err_t zh_vector_push_front(zh_vector_t **vector, const void *item);
|
||||||
@@ -118,12 +122,12 @@ extern "C"
|
|||||||
* Creates a copy of the provided item and adds it to the end of the vector.
|
* Creates a copy of the provided item and adds it to the end of the vector.
|
||||||
* The vector capacity will be increased if necessary.
|
* The vector capacity will be increased if necessary.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] item Pointer to the item to append (must not be NULL)
|
* @param[in] item Pointer to the item to append (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
* @return ESP_ERR_NO_MEM if vector is full or element allocation fails
|
* @return ESP_ERR_NO_MEM if vector is full or element allocation fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_push_back(zh_vector_t **vector, const void *item);
|
esp_err_t zh_vector_push_back(zh_vector_t **vector, const void *item);
|
||||||
@@ -134,26 +138,26 @@ extern "C"
|
|||||||
* Copies the provided item into the existing element at the given index.
|
* Copies the provided item into the existing element at the given index.
|
||||||
* The element must already exist and be non-NULL.
|
* The element must already exist and be non-NULL.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] index Index of the element to replace (must be < size)
|
* @param[in] index Index of the element to replace (must be < size)
|
||||||
* @param[in] item Pointer to the new item data (must not be NULL)
|
* @param[in] item Pointer to the new item data (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails or element at index is NULL
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted, mutex acquisition fails or the element at index is NULL
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_change_item(zh_vector_t **vector, uint16_t index, const void *item);
|
esp_err_t zh_vector_change_item(zh_vector_t **vector, uint16_t index, const void *item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve a copy of the element at the specified index.
|
* @brief Retrieve a copy of the element at the specified index.
|
||||||
*
|
*
|
||||||
* @param[in] vector Pointer to the vector handle (must not be NULL)
|
* @param[in] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] index Index of the element to retrieve (must be < size)
|
* @param[in] index Index of the element to retrieve (must be < size)
|
||||||
* @param[out] item Pointer to buffer where the element will be copied (must not be NULL)
|
* @param[out] item Pointer to buffer where the element will be copied (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL or index is out of bounds
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails or item is NULL
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*
|
*
|
||||||
* @note The element at the specified index must exist and be non-NULL.
|
* @note The element at the specified index must exist and be non-NULL.
|
||||||
* This is guaranteed if the vector was properly initialized and no
|
* This is guaranteed if the vector was properly initialized and no
|
||||||
@@ -167,12 +171,12 @@ extern "C"
|
|||||||
* Frees the element's memory, shifts remaining elements, and updates size.
|
* Frees the element's memory, shifts remaining elements, and updates size.
|
||||||
* Capacity may be reduced if it exceeds twice the current size.
|
* Capacity may be reduced if it exceeds twice the current size.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] index Index of the element to delete (must be < size)
|
* @param[in] index Index of the element to delete (must be < size)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or index is out of bounds
|
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or index is out of bounds
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_delete_item(zh_vector_t **vector, uint16_t index);
|
esp_err_t zh_vector_delete_item(zh_vector_t **vector, uint16_t index);
|
||||||
|
|
||||||
@@ -182,11 +186,11 @@ extern "C"
|
|||||||
* Frees the last element's memory and updates size.
|
* Frees the last element's memory and updates size.
|
||||||
* Capacity may be reduced if it exceeds twice the current size.
|
* Capacity may be reduced if it exceeds twice the current size.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or vector is empty
|
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or vector is empty
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_delete_back(zh_vector_t **vector);
|
esp_err_t zh_vector_delete_back(zh_vector_t **vector);
|
||||||
|
|
||||||
@@ -196,11 +200,11 @@ extern "C"
|
|||||||
* Frees the first element's memory, shifts remaining elements, and updates size.
|
* Frees the first element's memory, shifts remaining elements, and updates size.
|
||||||
* Capacity may be reduced if it exceeds twice the current size.
|
* Capacity may be reduced if it exceeds twice the current size.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or vector is empty
|
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL or vector is empty
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_delete_front(zh_vector_t **vector);
|
esp_err_t zh_vector_delete_front(zh_vector_t **vector);
|
||||||
|
|
||||||
@@ -210,11 +214,11 @@ extern "C"
|
|||||||
* Compares elements using memcmp and removes subsequent duplicates.
|
* Compares elements using memcmp and removes subsequent duplicates.
|
||||||
* Elements are compared based on their raw binary content.
|
* Elements are compared based on their raw binary content.
|
||||||
*
|
*
|
||||||
* @param[in,out] vector Pointer to the vector handle (must not be NULL)
|
* @param[in,out] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL
|
* @return ESP_ERR_INVALID_ARG if vector or *vector is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector);
|
esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector);
|
||||||
|
|
||||||
@@ -224,13 +228,13 @@ extern "C"
|
|||||||
* Searches for an element whose binary content matches the provided item
|
* Searches for an element whose binary content matches the provided item
|
||||||
* using memcmp. Returns the index of the first match or -1 if not found.
|
* using memcmp. Returns the index of the first match or -1 if not found.
|
||||||
*
|
*
|
||||||
* @param[in] vector Pointer to the vector handle (must not be NULL)
|
* @param[in] vector Pointer to the pointer to the vector handle (must not be NULL)
|
||||||
* @param[in] item Pointer to the item to search for (must not be NULL)
|
* @param[in] item Pointer to the item to search for (must not be NULL)
|
||||||
* @param[out] index Pointer to receive the found index (-1 if not found) (must not be NULL)
|
* @param[out] index Pointer to receive the found index (-1 if not found) (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
* @return ESP_ERR_INVALID_ARG if any parameter is NULL
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
* @return ESP_ERR_NOT_FOUND if item is not found in the vector
|
* @return ESP_ERR_NOT_FOUND if item is not found in the vector
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_find_item(zh_vector_t **vector, const void *item, int32_t *index);
|
esp_err_t zh_vector_find_item(zh_vector_t **vector, const void *item, int32_t *index);
|
||||||
@@ -239,23 +243,26 @@ extern "C"
|
|||||||
* @brief Find an element by comparing a specific field within structures.
|
* @brief Find an element by comparing a specific field within structures.
|
||||||
*
|
*
|
||||||
* Searches for an element where a specified field (identified by offset
|
* Searches for an element where a specified field (identified by offset
|
||||||
* and size) matches the provided value. Comparison starts from the
|
* and size) matches the provided value. The offset is derived from the
|
||||||
* specified index.
|
* address difference between `item` and `sample_struct` and must lie
|
||||||
|
* within the element together with the field size. Comparison starts
|
||||||
|
* from the specified index.
|
||||||
*
|
*
|
||||||
* @param[in] vector Pointer to the vector handle containing structures (must not be NULL)
|
* @param[in] vector Pointer to the pointer to the vector handle containing structures (must not be NULL)
|
||||||
* @param[in] sample_struct Pointer to a sample structure (used for field offset calculation) (must not be NULL)
|
* @param[in] sample_struct Pointer to a sample structure (used for field offset calculation) (must not be NULL)
|
||||||
* @param[in] item Pointer to the field within the structure (e.g., `&sample.id`). Used to calculate the field offset (must not be NULL)
|
* @param[in] item Pointer to the field within the structure (e.g., `&sample.id`). Used to calculate the field offset (must not be NULL)
|
||||||
* @param[in] size Size of the field in bytes (must be > 0)
|
* @param[in] size Size of the field in bytes (must be > 0 and the field must fit within the element)
|
||||||
* @param[in] value Pointer to the value to match against the field (must not be NULL)
|
* @param[in] value Pointer to the value to match against the field (must not be NULL)
|
||||||
* @param[in] start Index to begin searching from (must be < size)
|
* @param[in] start Index to begin searching from (must be < size)
|
||||||
* @param[out] index Pointer to receive the found index (-1 if not found) (must not be NULL)
|
* @param[out] index Pointer to receive the found index (-1 if not found) (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK on success
|
* @return ESP_OK on success
|
||||||
* @return ESP_ERR_INVALID_ARG if any parameter is invalid
|
* @return ESP_ERR_INVALID_ARG if any parameter is invalid, the field offset with size exceeds the element size,
|
||||||
* @return ESP_ERR_INVALID_STATE if mutex acquisition fails
|
* or *index is NULL when size is zero
|
||||||
|
* @return ESP_ERR_INVALID_STATE if the vector is being deleted or mutex acquisition fails
|
||||||
* @return ESP_ERR_NOT_FOUND if no matching element is found
|
* @return ESP_ERR_NOT_FOUND if no matching element is found
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_vector_find_item_in_field(zh_vector_t **vector, const void *sample_struct, const void *item, size_t size, const void *value, uint16_t start, int32_t *index);
|
esp_err_t zh_vector_find_item_in_field(zh_vector_t **vector, const void *sample_struct, const void *item, uint16_t size, const void *value, uint16_t start, int32_t *index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+170
-54
@@ -32,8 +32,35 @@ struct _zh_vector_t
|
|||||||
uint16_t size; /*!< Current number of elements in the vector */
|
uint16_t size; /*!< Current number of elements in the vector */
|
||||||
uint16_t unit; /*!< Size of each element in bytes */
|
uint16_t unit; /*!< Size of each element in bytes */
|
||||||
SemaphoreHandle_t mutex; /*!< FreeRTOS mutex for thread-safe operations */
|
SemaphoreHandle_t mutex; /*!< FreeRTOS mutex for thread-safe operations */
|
||||||
|
portMUX_TYPE lock; /*!< Critical section guard for deleting flag and reference counter */
|
||||||
|
bool deleting; /*!< Flag indicating the vector is being deleted and new operations must be rejected */
|
||||||
|
uint16_t refcount; /*!< Number of public operations currently in progress */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register an in-progress operation on the vector.
|
||||||
|
*
|
||||||
|
* Increments the reference counter unless the vector is already being
|
||||||
|
* deleted. The check and the increment are performed atomically within
|
||||||
|
* a critical section.
|
||||||
|
*
|
||||||
|
* @param vector Pointer to the vector
|
||||||
|
*
|
||||||
|
* @return true if the operation is allowed and the reference counter was incremented
|
||||||
|
* @return false if the vector is being deleted
|
||||||
|
*/
|
||||||
|
static bool _zh_vector_take(zh_vector_t *vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregister a finished operation on the vector.
|
||||||
|
*
|
||||||
|
* Decrements the reference counter within a critical section so that
|
||||||
|
* a pending deletion can proceed once no operations remain in progress.
|
||||||
|
*
|
||||||
|
* @param vector Pointer to the vector
|
||||||
|
*/
|
||||||
|
static void _zh_vector_give(zh_vector_t *vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Resize the vector's internal items array.
|
* @brief Resize the vector's internal items array.
|
||||||
*
|
*
|
||||||
@@ -54,8 +81,9 @@ static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity);
|
|||||||
* @brief Delete an element at the specified index and shift remaining elements.
|
* @brief Delete an element at the specified index and shift remaining elements.
|
||||||
*
|
*
|
||||||
* Frees the element's memory, shifts elements after the index one position left,
|
* Frees the element's memory, shifts elements after the index one position left,
|
||||||
* and updates size. Automatically shrinks capacity if it exceeds twice the size
|
* and updates size. Releases all internal storage when the vector becomes empty.
|
||||||
* or if the vector becomes empty.
|
* Otherwise shrinks capacity to twice the size when capacity exceeds four and
|
||||||
|
* half the capacity is at least four times the size.
|
||||||
*
|
*
|
||||||
* @param vector Pointer to the vector
|
* @param vector Pointer to the vector
|
||||||
* @param index Index of the element to delete
|
* @param index Index of the element to delete
|
||||||
@@ -80,16 +108,19 @@ static inline uint16_t _calc_new_capacity(uint16_t current);
|
|||||||
esp_err_t zh_vector_init(zh_vector_t **vector, uint16_t unit)
|
esp_err_t zh_vector_init(zh_vector_t **vector, uint16_t unit)
|
||||||
{
|
{
|
||||||
ZH_LOGI("Vector initialization begin.");
|
ZH_LOGI("Vector initialization begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && unit > 0, ESP_ERR_INVALID_ARG, NULL, "Vector initialization failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && unit != 0, ESP_ERR_INVALID_ARG, NULL, "Vector initialization failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(*vector == NULL, ESP_ERR_INVALID_STATE, NULL, "Vector initialization failed. Vector is already initialized.");
|
ZH_ERROR_CHECK(*vector == NULL, ESP_ERR_INVALID_STATE, NULL, "Vector initialization failed. Vector is already initialized.");
|
||||||
*vector = heap_caps_calloc(1, sizeof(zh_vector_t), MALLOC_CAP_8BIT);
|
*vector = heap_caps_calloc(1, sizeof(zh_vector_t), MALLOC_CAP_8BIT);
|
||||||
ZH_ERROR_CHECK(*vector != NULL, ESP_ERR_NO_MEM, NULL, "Vector initialization failed. Failed to allocate vector structure.");
|
ZH_ERROR_CHECK(*vector != NULL, ESP_ERR_NO_MEM, NULL, "Vector initialization failed. Failed to allocate vector structure.");
|
||||||
(*vector)->mutex = xSemaphoreCreateMutex();
|
(*vector)->mutex = xSemaphoreCreateMutex();
|
||||||
ZH_ERROR_CHECK((*vector)->mutex != NULL, ESP_ERR_NO_MEM, heap_caps_free(*vector); *vector = NULL, "Vector initialization failed. Failed to create mutex.");
|
ZH_ERROR_CHECK((*vector)->mutex != NULL, ESP_ERR_NO_MEM, heap_caps_free(*vector); *vector = NULL, "Vector initialization failed. Failed to create mutex.");
|
||||||
|
portMUX_INITIALIZE(&(*vector)->lock);
|
||||||
(*vector)->items = NULL;
|
(*vector)->items = NULL;
|
||||||
(*vector)->capacity = 0;
|
(*vector)->capacity = 0;
|
||||||
(*vector)->size = 0;
|
(*vector)->size = 0;
|
||||||
(*vector)->unit = unit;
|
(*vector)->unit = unit;
|
||||||
|
(*vector)->deleting = false;
|
||||||
|
(*vector)->refcount = 0;
|
||||||
ZH_LOGI("Vector initialization success.");
|
ZH_LOGI("Vector initialization success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -99,6 +130,23 @@ esp_err_t zh_vector_free(zh_vector_t **vector)
|
|||||||
ZH_LOGI("Vector deletion begin.");
|
ZH_LOGI("Vector deletion begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Vector deletion failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Vector deletion failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Vector deletion failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Vector deletion failed. Failed to acquire mutex.");
|
||||||
|
taskENTER_CRITICAL(&(*vector)->lock);
|
||||||
|
ZH_ERROR_CHECK((*vector)->deleting == false, ESP_ERR_INVALID_STATE, taskEXIT_CRITICAL(&(*vector)->lock); xSemaphoreGive((*vector)->mutex), "Vector deletion failed. The vector is being deleted.");
|
||||||
|
(*vector)->deleting = true;
|
||||||
|
taskEXIT_CRITICAL(&(*vector)->lock);
|
||||||
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
uint16_t refcount;
|
||||||
|
taskENTER_CRITICAL(&(*vector)->lock);
|
||||||
|
refcount = (*vector)->refcount;
|
||||||
|
taskEXIT_CRITICAL(&(*vector)->lock);
|
||||||
|
if (refcount == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
for (uint16_t i = 0; i < (*vector)->size; ++i)
|
for (uint16_t i = 0; i < (*vector)->size; ++i)
|
||||||
{
|
{
|
||||||
if ((*vector)->items[i] != NULL)
|
if ((*vector)->items[i] != NULL)
|
||||||
@@ -123,9 +171,11 @@ esp_err_t zh_vector_get_size(zh_vector_t **vector, uint16_t *size)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Getting vector size begin.");
|
ZH_LOGI("Getting vector size begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && size != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting vector size failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && size != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting vector size failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Getting vector size failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Getting vector size failed. The vector is being deleted.");
|
||||||
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Getting vector size failed. Failed to acquire mutex.");
|
||||||
*size = (*vector)->size;
|
*size = (*vector)->size;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Getting vector size success.");
|
ZH_LOGI("Getting vector size success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -134,9 +184,11 @@ esp_err_t zh_vector_get_capacity(zh_vector_t **vector, uint16_t *capacity)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Getting vector capacity begin.");
|
ZH_LOGI("Getting vector capacity begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && capacity != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting vector capacity failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && capacity != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting vector capacity failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Getting vector capacity failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Getting vector capacity failed. The vector is being deleted.");
|
||||||
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Getting vector capacity failed. Failed to acquire mutex.");
|
||||||
*capacity = (*vector)->capacity;
|
*capacity = (*vector)->capacity;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Getting vector capacity success.");
|
ZH_LOGI("Getting vector capacity success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -145,15 +197,17 @@ esp_err_t zh_vector_push_front(zh_vector_t **vector, const void *item)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Adding item to beginning of vector begin.");
|
ZH_LOGI("Adding item to beginning of vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Adding item to beginning of vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Adding item to beginning of vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Adding item to beginning of vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Adding item to beginning of vector failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK((*vector)->size < UINT16_MAX, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to beginning of vector failed. Vector is full.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Adding item to beginning of vector failed. Failed to acquire mutex.");
|
||||||
|
ZH_ERROR_CHECK((*vector)->size < UINT16_MAX, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to beginning of vector failed. Vector is full.");
|
||||||
if ((*vector)->capacity == (*vector)->size)
|
if ((*vector)->capacity == (*vector)->size)
|
||||||
{
|
{
|
||||||
uint16_t new_capacity = _calc_new_capacity((*vector)->capacity);
|
uint16_t new_capacity = _calc_new_capacity((*vector)->capacity);
|
||||||
ZH_ERROR_CHECK(_resize(*vector, new_capacity) == ESP_OK, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to beginning of vector failed. Memory reallocation failed.");
|
ZH_ERROR_CHECK(new_capacity > (*vector)->capacity, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to beginning of vector failed. Cannot grow beyond current capacity.");
|
||||||
|
ZH_ERROR_CHECK(_resize(*vector, new_capacity) == ESP_OK, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to beginning of vector failed. Memory reallocation failed.");
|
||||||
}
|
}
|
||||||
void *new_item = heap_caps_calloc(1, (*vector)->unit, MALLOC_CAP_8BIT);
|
void *new_item = heap_caps_calloc(1, (*vector)->unit, MALLOC_CAP_8BIT);
|
||||||
ZH_ERROR_CHECK(new_item != NULL, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to beginning of vector failed. Element allocation failed.");
|
ZH_ERROR_CHECK(new_item != NULL, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to beginning of vector failed. Element allocation failed.");
|
||||||
for (uint16_t i = (*vector)->size; i > 0; --i)
|
for (uint16_t i = (*vector)->size; i > 0; --i)
|
||||||
{
|
{
|
||||||
(*vector)->items[i] = (*vector)->items[i - 1];
|
(*vector)->items[i] = (*vector)->items[i - 1];
|
||||||
@@ -162,6 +216,7 @@ esp_err_t zh_vector_push_front(zh_vector_t **vector, const void *item)
|
|||||||
memcpy((*vector)->items[0], item, (*vector)->unit);
|
memcpy((*vector)->items[0], item, (*vector)->unit);
|
||||||
(*vector)->size++;
|
(*vector)->size++;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Adding item to beginning of vector success.");
|
ZH_LOGI("Adding item to beginning of vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -170,19 +225,22 @@ esp_err_t zh_vector_push_back(zh_vector_t **vector, const void *item)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Adding item to vector begin.");
|
ZH_LOGI("Adding item to vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Adding item to vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Adding item to vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Adding item to vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Adding item to vector failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK((*vector)->size < UINT16_MAX, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to vector failed. Vector is full.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Adding item to vector failed. Failed to acquire mutex.");
|
||||||
|
ZH_ERROR_CHECK((*vector)->size < UINT16_MAX, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to vector failed. Vector is full.");
|
||||||
if ((*vector)->capacity == (*vector)->size)
|
if ((*vector)->capacity == (*vector)->size)
|
||||||
{
|
{
|
||||||
uint16_t new_capacity = _calc_new_capacity((*vector)->capacity);
|
uint16_t new_capacity = _calc_new_capacity((*vector)->capacity);
|
||||||
ZH_ERROR_CHECK(_resize(*vector, new_capacity) == ESP_OK, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to vector failed. Memory reallocation failed.");
|
ZH_ERROR_CHECK(new_capacity > (*vector)->capacity, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to vector failed. Cannot grow beyond current capacity.");
|
||||||
|
ZH_ERROR_CHECK(_resize(*vector, new_capacity) == ESP_OK, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to vector failed. Memory reallocation failed.");
|
||||||
}
|
}
|
||||||
uint16_t idx = (*vector)->size;
|
uint16_t idx = (*vector)->size;
|
||||||
(*vector)->items[idx] = heap_caps_calloc(1, (*vector)->unit, MALLOC_CAP_8BIT);
|
(*vector)->items[idx] = heap_caps_calloc(1, (*vector)->unit, MALLOC_CAP_8BIT);
|
||||||
ZH_ERROR_CHECK((*vector)->items[idx] != NULL, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex), "Adding item to vector failed. Element allocation failed.");
|
ZH_ERROR_CHECK((*vector)->items[idx] != NULL, ESP_ERR_NO_MEM, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Adding item to vector failed. Element allocation failed.");
|
||||||
memcpy((*vector)->items[idx], item, (*vector)->unit);
|
memcpy((*vector)->items[idx], item, (*vector)->unit);
|
||||||
(*vector)->size++;
|
(*vector)->size++;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Adding item to vector success.");
|
ZH_LOGI("Adding item to vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -191,11 +249,13 @@ esp_err_t zh_vector_change_item(zh_vector_t **vector, uint16_t index, const void
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Changing item in vector begin.");
|
ZH_LOGI("Changing item in vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Changing item in vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Changing item in vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Changing item in vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Changing item in vector failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Changing item in vector failed. Index out of bounds.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Changing item in vector failed. Failed to acquire mutex.");
|
||||||
ZH_ERROR_CHECK((*vector)->items[index] != NULL, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Changing item in vector failed. Item is NULL.");
|
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Changing item in vector failed. Index out of bounds.");
|
||||||
|
ZH_ERROR_CHECK((*vector)->items[index] != NULL, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Changing item in vector failed. Item is NULL.");
|
||||||
memcpy((*vector)->items[index], item, (*vector)->unit);
|
memcpy((*vector)->items[index], item, (*vector)->unit);
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Changing item in vector success.");
|
ZH_LOGI("Changing item in vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -204,11 +264,13 @@ esp_err_t zh_vector_get_item(zh_vector_t **vector, uint16_t index, void *item)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Getting item from vector begin.");
|
ZH_LOGI("Getting item from vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting item from vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL, ESP_ERR_INVALID_ARG, NULL, "Getting item from vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Getting item from vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Getting item from vector failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Getting item from vector failed. Index out of bounds.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Getting item from vector failed. Failed to acquire mutex.");
|
||||||
ZH_ERROR_CHECK((*vector)->items[index] != NULL, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Getting item from vector failed. Item is NULL.");
|
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Getting item from vector failed. Index out of bounds.");
|
||||||
|
ZH_ERROR_CHECK((*vector)->items[index] != NULL, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Getting item from vector failed. Item is NULL.");
|
||||||
memcpy(item, (*vector)->items[index], (*vector)->unit);
|
memcpy(item, (*vector)->items[index], (*vector)->unit);
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Getting item from vector success.");
|
ZH_LOGI("Getting item from vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -217,10 +279,12 @@ esp_err_t zh_vector_delete_item(zh_vector_t **vector, uint16_t index)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Deleting item in vector begin.");
|
ZH_LOGI("Deleting item in vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Deleting item in vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Deleting item in vector failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Deleting item in vector failed. Index out of bounds.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Deleting item in vector failed. Failed to acquire mutex.");
|
||||||
ZH_ERROR_CHECK(_delete(*vector, index) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Deleting item in vector failed. Internal error.");
|
ZH_ERROR_CHECK(index < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in vector failed. Index out of bounds.");
|
||||||
|
ZH_ERROR_CHECK(_delete(*vector, index) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in vector failed. Internal error.");
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Deleting item in vector success.");
|
ZH_LOGI("Deleting item in vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -229,10 +293,12 @@ esp_err_t zh_vector_delete_back(zh_vector_t **vector)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Deleting item in back begin.");
|
ZH_LOGI("Deleting item in back begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in back failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in back failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Deleting item in back failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Deleting item in back failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK((*vector)->size > 0, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Deleting item in back failed. Vector is empty.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Deleting item in back failed. Failed to acquire mutex.");
|
||||||
ZH_ERROR_CHECK(_delete(*vector, (*vector)->size - 1) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Deleting item in back failed. Internal error.");
|
ZH_ERROR_CHECK((*vector)->size > 0, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in back failed. Vector is empty.");
|
||||||
|
ZH_ERROR_CHECK(_delete(*vector, (*vector)->size - 1) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in back failed. Internal error.");
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Deleting item in back success.");
|
ZH_LOGI("Deleting item in back success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -241,10 +307,12 @@ esp_err_t zh_vector_delete_front(zh_vector_t **vector)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Deleting item in front begin.");
|
ZH_LOGI("Deleting item in front begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in front failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Deleting item in front failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Deleting item in front failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Deleting item in front failed. The vector is being deleted.");
|
||||||
ZH_ERROR_CHECK((*vector)->size > 0, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Deleting item in front failed. Vector is empty.");
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Deleting item in front failed. Failed to acquire mutex.");
|
||||||
ZH_ERROR_CHECK(_delete(*vector, 0) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Deleting item in front failed. Internal error.");
|
ZH_ERROR_CHECK((*vector)->size > 0, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in front failed. Vector is empty.");
|
||||||
|
ZH_ERROR_CHECK(_delete(*vector, 0) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Deleting item in front failed. Internal error.");
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Deleting item in front success.");
|
ZH_LOGI("Deleting item in front success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -253,17 +321,26 @@ esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector)
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Removing duplicates from vector begin.");
|
ZH_LOGI("Removing duplicates from vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Removing duplicates from vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL, ESP_ERR_INVALID_ARG, NULL, "Removing duplicates from vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Removing duplicates from vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Removing duplicates from vector failed. The vector is being deleted.");
|
||||||
if ((*vector)->size >= 2)
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Removing duplicates from vector failed. Failed to acquire mutex.");
|
||||||
|
ZH_ERROR_CHECK((*vector)->size > 0, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Removing duplicates from vector failed. Vector is empty.");
|
||||||
|
for (uint16_t i = 0; i < (*vector)->size; ++i)
|
||||||
{
|
{
|
||||||
for (uint16_t i = 0; i < (*vector)->size - 1; ++i)
|
if ((*vector)->items[i] == NULL)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
uint16_t j = i + 1;
|
uint16_t j = i + 1;
|
||||||
while (j < (*vector)->size)
|
while (j < (*vector)->size)
|
||||||
{
|
{
|
||||||
|
if ((*vector)->items[j] == NULL)
|
||||||
|
{
|
||||||
|
++j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (memcmp((*vector)->items[i], (*vector)->items[j], (*vector)->unit) == 0)
|
if (memcmp((*vector)->items[i], (*vector)->items[j], (*vector)->unit) == 0)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(_delete(*vector, j) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex), "Removing duplicates from vector failed. Internal error.");
|
ZH_ERROR_CHECK(_delete(*vector, j) == ESP_OK, ESP_ERR_INVALID_STATE, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Removing duplicates from vector failed. Internal error.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -271,8 +348,8 @@ esp_err_t zh_vector_remove_duplicates(zh_vector_t **vector)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Removing duplicates from vector success.");
|
ZH_LOGI("Removing duplicates from vector success.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -281,61 +358,89 @@ esp_err_t zh_vector_find_item(zh_vector_t **vector, const void *item, int32_t *i
|
|||||||
{
|
{
|
||||||
ZH_LOGI("Finding item in vector begin.");
|
ZH_LOGI("Finding item in vector begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL && index != NULL, ESP_ERR_INVALID_ARG, NULL, "Finding item in vector failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && item != NULL && index != NULL, ESP_ERR_INVALID_ARG, NULL, "Finding item in vector failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Finding item in vector failed. Failed to acquire mutex.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Finding item in vector failed. The vector is being deleted.");
|
||||||
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Finding item in vector failed. Failed to acquire mutex.");
|
||||||
*index = -1;
|
*index = -1;
|
||||||
for (uint16_t i = 0; i < (*vector)->size; ++i)
|
for (uint16_t i = 0; i < (*vector)->size; ++i)
|
||||||
{
|
{
|
||||||
|
if ((*vector)->items[i] == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (memcmp((*vector)->items[i], item, (*vector)->unit) == 0)
|
if (memcmp((*vector)->items[i], item, (*vector)->unit) == 0)
|
||||||
{
|
{
|
||||||
*index = (int32_t)i;
|
*index = (int32_t)i;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Finding item in vector success (found).");
|
ZH_LOGI("Finding item in vector success (found).");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Finding item in vector success (not found).");
|
ZH_LOGI("Finding item in vector success (not found).");
|
||||||
return ESP_ERR_NOT_FOUND;
|
return ESP_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_vector_find_item_in_field(zh_vector_t **vector, const void *sample_struct, const void *item, size_t size, const void *value, uint16_t start, int32_t *index)
|
esp_err_t zh_vector_find_item_in_field(zh_vector_t **vector, const void *sample_struct, const void *item, uint16_t size, const void *value, uint16_t start, int32_t *index)
|
||||||
{
|
{
|
||||||
ZH_LOGI("Finding field in structure begin.");
|
ZH_LOGI("Finding field in structure begin.");
|
||||||
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && sample_struct != NULL && item != NULL && value != NULL && index != NULL && size > 0, ESP_ERR_INVALID_ARG, NULL, "Finding field in structure failed. Invalid argument.");
|
ZH_ERROR_CHECK(vector != NULL && *vector != NULL && sample_struct != NULL && item != NULL && value != NULL && index != NULL, ESP_ERR_INVALID_ARG, NULL, "Finding field in structure failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, NULL, "Finding field in structure failed. Mutex acquire failed.");
|
ZH_ERROR_CHECK(size > 0, ESP_ERR_INVALID_ARG, *index = -1, "Finding field in structure failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(start < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Finding field in structure failed. Start index out of bounds.");
|
ZH_ERROR_CHECK(_zh_vector_take(*vector) == true, ESP_ERR_INVALID_STATE, NULL, "Finding field in structure failed. The vector is being deleted.");
|
||||||
size_t offset = (const uint8_t *)item - (const uint8_t *)sample_struct;
|
ZH_ERROR_CHECK(xSemaphoreTake((*vector)->mutex, portMAX_DELAY) == pdTRUE, ESP_ERR_INVALID_STATE, _zh_vector_give(*vector), "Finding field in structure failed. Mutex acquire failed.");
|
||||||
ZH_ERROR_CHECK((offset + size) <= (*vector)->unit, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex), "Finding field in structure failed. Field exceeds element size.");
|
ZH_ERROR_CHECK(start < (*vector)->size, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Finding field in structure failed. Start index out of bounds.");
|
||||||
|
ZH_ERROR_CHECK((uint32_t)item >= (uint32_t)sample_struct, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Finding field in structure failed. Field pointer is before sample struct.");
|
||||||
|
uint32_t offset = (uint32_t)item - (uint32_t)sample_struct;
|
||||||
|
ZH_ERROR_CHECK(offset < (*vector)->unit, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Finding field in structure failed. Field offset exceeds element size.");
|
||||||
|
ZH_ERROR_CHECK((offset + size) <= (*vector)->unit, ESP_ERR_INVALID_ARG, xSemaphoreGive((*vector)->mutex); _zh_vector_give(*vector), "Finding field in structure failed. Field exceeds element size.");
|
||||||
*index = -1;
|
*index = -1;
|
||||||
for (uint16_t i = start; i < (*vector)->size; ++i)
|
for (uint16_t i = start; i < (*vector)->size; ++i)
|
||||||
{
|
{
|
||||||
const uint8_t *elem = (const uint8_t *)(*vector)->items[i];
|
if ((*vector)->items[i] == NULL)
|
||||||
if (memcmp(elem + offset, value, size) == 0)
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (memcmp((const uint8_t *)(*vector)->items[i] + offset, value, size) == 0)
|
||||||
{
|
{
|
||||||
*index = (int32_t)i;
|
*index = (int32_t)i;
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Finding field in structure success (found).");
|
ZH_LOGI("Finding field in structure success (found).");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xSemaphoreGive((*vector)->mutex);
|
xSemaphoreGive((*vector)->mutex);
|
||||||
|
_zh_vector_give(*vector);
|
||||||
ZH_LOGI("Finding field in structure success (not found).");
|
ZH_LOGI("Finding field in structure success (not found).");
|
||||||
return ESP_ERR_NOT_FOUND;
|
return ESP_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _zh_vector_take(zh_vector_t *vector)
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL(&vector->lock);
|
||||||
|
if (vector->deleting == true)
|
||||||
|
{
|
||||||
|
taskEXIT_CRITICAL(&vector->lock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++vector->refcount;
|
||||||
|
taskEXIT_CRITICAL(&vector->lock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _zh_vector_give(zh_vector_t *vector)
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL(&vector->lock);
|
||||||
|
--vector->refcount;
|
||||||
|
taskEXIT_CRITICAL(&vector->lock);
|
||||||
|
}
|
||||||
|
|
||||||
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity)
|
static esp_err_t _resize(zh_vector_t *vector, uint16_t capacity)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(capacity >= vector->size, ESP_ERR_INVALID_ARG, NULL, "Invalid argument.");
|
ZH_ERROR_CHECK(capacity >= vector->size, ESP_ERR_INVALID_ARG, NULL, "Invalid argument.");
|
||||||
if (capacity == 0)
|
if (capacity == 0)
|
||||||
{
|
{
|
||||||
if (vector->items != NULL)
|
|
||||||
{
|
|
||||||
for (uint16_t i = 0; i < vector->size; ++i)
|
|
||||||
{
|
|
||||||
heap_caps_free(vector->items[i]);
|
|
||||||
vector->items[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
heap_caps_free(vector->items);
|
heap_caps_free(vector->items);
|
||||||
vector->items = NULL;
|
vector->items = NULL;
|
||||||
vector->size = 0;
|
vector->size = 0;
|
||||||
@@ -370,14 +475,25 @@ static esp_err_t _delete(zh_vector_t *vector, uint16_t index)
|
|||||||
heap_caps_free(freed_item);
|
heap_caps_free(freed_item);
|
||||||
freed_item = NULL;
|
freed_item = NULL;
|
||||||
--vector->size;
|
--vector->size;
|
||||||
if (vector->size > 0 && vector->capacity / 2 > vector->size)
|
if (vector->size == 0)
|
||||||
{
|
{
|
||||||
return _resize(vector, vector->size);
|
if (vector->capacity > 0)
|
||||||
}
|
|
||||||
else if (vector->size == 0 && vector->capacity > 0)
|
|
||||||
{
|
{
|
||||||
_resize(vector, 0);
|
_resize(vector, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (vector->capacity > 4 && vector->capacity / 2 >= vector->size * 2)
|
||||||
|
{
|
||||||
|
uint16_t target = (vector->size > UINT16_MAX / 2) ? vector->capacity : vector->size * 2;
|
||||||
|
if (target < 4)
|
||||||
|
{
|
||||||
|
target = 4;
|
||||||
|
}
|
||||||
|
if (target < vector->capacity)
|
||||||
|
{
|
||||||
|
_resize(vector, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user