diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index ba475ec..0ebccc1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,88 @@ -# zh_avr_vector +# AVR library for vector (dynamic array) -AVR library for vector (dynamic array). \ No newline at end of file +## Features + +1. Support of any data types. +2. The maximum size of the veсtor is 65535 elements. + +## Using + +In an existing project, run the following command to install the component: + +```text +cd ../your_project/lib +git clone http://git.zh.com.ru/alexey.zholtikov/zh_avr_vector +``` + +In the application, add the component: + +```c +#include "zh_avr_vector.h" +``` + +## Example + +Create, add, read, modify and delete items: + +```c +#include "avr/io.h" +#include "stdio.h" +#include "zh_avr_vector.h" + +#define BAUD_RATE 9600 +#define BAUD_PRESCALE (F_CPU / 16 / BAUD_RATE - 1) + +void _uart(char byte, FILE *stream) +{ + while ((UCSR0A & (1 << UDRE0)) == 0) + { + } + UDR0 = byte; +} +FILE uart = FDEV_SETUP_STREAM(_uart, NULL, _FDEV_SETUP_WRITE); + +zh_avr_vector_t vector = {0}; + +char example[10] = {0}; + +int main(void) +{ + UBRR0H = (BAUD_PRESCALE >> 8); + UBRR0L = BAUD_PRESCALE; + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); + stdout = &uart; + zh_avr_vector_init(&vector, sizeof(example)); + printf("Initial vector size is: %d\n", zh_avr_vector_get_size(&vector)); + strcpy(example, "Item 1"); + zh_avr_vector_push_back(&vector, &example); + strcpy(example, "Item 2"); + zh_avr_vector_push_back(&vector, &example); + strcpy(example, "Item 3"); + zh_avr_vector_push_back(&vector, &example); + strcpy(example, "Item 4"); + zh_avr_vector_push_back(&vector, &example); + strcpy(example, "Item 5"); + zh_avr_vector_push_back(&vector, &example); + printf("Add 5 items. New vector size is: %d\n", zh_avr_vector_get_size(&vector)); + for (uint16_t i = 0; i < zh_avr_vector_get_size(&vector); ++i) + { + printf("Item position %d is: %s\n", i, (char *)zh_avr_vector_get_item(&vector, i)); + } + strcpy(example, "Item 6"); + zh_avr_vector_change_item(&vector, 3, &example); + printf("Change item on 3 position.\n"); + for (uint16_t i = 0; i < zh_avr_vector_get_size(&vector); ++i) + { + printf("Item position %d is: %s\n", i, (char *)zh_avr_vector_get_item(&vector, i)); + } + zh_avr_vector_delete_item(&vector, 2); + printf("Delete item on 2 position. New vector size is: %d\n", zh_avr_vector_get_size(&vector)); + for (uint16_t i = 0; i < zh_avr_vector_get_size(&vector); ++i) + { + printf("Item position %d is: %s\n", i, (char *)zh_avr_vector_get_item(&vector, i)); + } + zh_avr_vector_free(&vector); + return 0; +} +``` diff --git a/include/zh_avr_vector.h b/include/zh_avr_vector.h new file mode 100755 index 0000000..f3a07ff --- /dev/null +++ b/include/zh_avr_vector.h @@ -0,0 +1,133 @@ +#pragma once + +#include "stdlib.h" +#include "stdint.h" +#include "string.h" +#include "stdbool.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef enum + { + AVR_FAIL = -1, + AVR_OK, + AVR_ERR_NO_MEM, + AVR_ERR_INVALID_ARG, + AVR_ERR_INVALID_STATE, + AVR_ERR_INVALID_SIZE, + AVR_ERR_NOT_FOUND, + AVR_ERR_NOT_SUPPORTED, + AVR_ERR_TIMEOUT, + AVR_ERR_INVALID_RESPONSE, + AVR_ERR_INVALID_CRC, + AVR_ERR_INVALID_VERSION, + AVR_ERR_NOT_FINISHED, + AVR_ERR_NOT_ALLOWED + } avr_err_t; + + typedef struct // Main structure of vector data. + { + void **items; // Array of pointers of vector items. + uint16_t capacity; // Maximum capacity of the vector. @note Used to control the size of allocated memory for array of pointers of vector items. Usually equal to the current number of items in the vector. Automatically changes when items are added or deleted. + uint16_t size; // Number of items in the vector. @note Can be read with zh_avr_vector_get_size(). + uint16_t unit; // Vector item size. @note Possible values from 1 to 65535. + bool status; // Vector initialization status flag. @note Used to prevent execution of vector functions without prior vector initialization. + } zh_avr_vector_t; + + /** + * @brief Initialize vector. + * + * @param[in] vector Pointer to main structure of vector data. + * @param[in] unit Size of vector item. + * + * @return + * - AVR_OK if initialization was success + * - AVR_ERR_INVALID_ARG if parameter error + * - AVR_ERR_INVALID_STATE if vector already initialized + */ + avr_err_t zh_avr_vector_init(zh_avr_vector_t *vector, uint16_t unit); + + /** + * @brief Deinitialize vector. Free all allocated memory. + * + * @param[in] vector Pointer to main structure of vector data. + * + * @return + * - AVR_OK if deinitialization was success + * - AVR_ERR_INVALID_ARG if parameter error + * - AVR_ERR_INVALID_STATE if vector not initialized + */ + avr_err_t zh_avr_vector_free(zh_avr_vector_t *vector); + + /** + * @brief Get current vector size. + * + * @param[in] vector Pointer to main structure of vector data. + * + * @return + * - Vector size + * - AVR_FAIL if parameter error or vector not initialized + */ + avr_err_t zh_avr_vector_get_size(zh_avr_vector_t *vector); + + /** + * @brief Add item at end of vector. + * + * @param[in] vector Pointer to main structure of vector data. + * @param[in] item Pointer to item for add. + * + * @return + * - AVR_OK if add was success + * - AVR_ERR_INVALID_ARG if parameter error + * - AVR_ERR_NO_MEM if memory allocation fail or no free memory in the heap + * - AVR_ERR_INVALID_STATE if vector not initialized + */ + avr_err_t zh_avr_vector_push_back(zh_avr_vector_t *vector, void *item); + + /** + * @brief Change item by index. + * + * @param[in] vector Pointer to main structure of vector data. + * @param[in] index Index of item for change. + * @param[in] item Pointer to new data of item. + * + * @return + * - AVR_OK if change was success + * - AVR_ERR_INVALID_ARG if parameter error + * - AVR_ERR_INVALID_STATE if vector not initialized + * - AVR_FAIL if index does not exist + */ + avr_err_t zh_avr_vector_change_item(zh_avr_vector_t *vector, uint16_t index, void *item); + + /** + * @brief Get item by index. + * + * @param[in] vector Pointer to main structure of vector data. + * @param[in] index Index of item for get. + * + * @return + * - Pointer to item + * - NULL if parameter error or vector not initialized or if index does not exist + */ + void *zh_avr_vector_get_item(zh_avr_vector_t *vector, uint16_t index); + + /** + * @brief Delete item by index and shifts all elements in vector. + * + * @param[in] vector Pointer to main structure of vector data. + * @param[in] index Index of item for delete. + * + * @return + * - AVR_OK if delete was success + * - AVR_ERR_INVALID_ARG if parameter error + * - AVR_ERR_INVALID_STATE if vector not initialized + * - AVR_FAIL if index does not exist + */ + avr_err_t zh_avr_vector_delete_item(zh_avr_vector_t *vector, uint16_t index); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..afaf360 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file diff --git a/zh_avr_vector.c b/zh_avr_vector.c new file mode 100755 index 0000000..2262bcd --- /dev/null +++ b/zh_avr_vector.c @@ -0,0 +1,151 @@ +#include "zh_avr_vector.h" + +static avr_err_t _resize(zh_avr_vector_t *vector, uint16_t capacity); + +avr_err_t zh_avr_vector_init(zh_avr_vector_t *vector, uint16_t unit) +{ + if (vector == NULL || unit == 0) + { + return AVR_ERR_INVALID_ARG; + } + if (vector->status == true) + { + return AVR_ERR_INVALID_STATE; + } + vector->capacity = 0; + vector->size = 0; + vector->unit = unit; + vector->status = true; + return AVR_OK; +} + +avr_err_t zh_avr_vector_free(zh_avr_vector_t *vector) +{ + if (vector == NULL) + { + return AVR_ERR_INVALID_ARG; + } + if (vector->status == false) + { + return AVR_ERR_INVALID_STATE; + } + for (uint16_t i = 0; i < vector->size; ++i) + { + free(vector->items[i]); + } + vector->status = false; + return AVR_OK; +} + +avr_err_t zh_avr_vector_get_size(zh_avr_vector_t *vector) +{ + if (vector == NULL || vector->status == false) + { + return AVR_FAIL; + } + return vector->size; +} + +avr_err_t zh_avr_vector_push_back(zh_avr_vector_t *vector, void *item) +{ + if (vector == NULL || item == NULL) + { + return AVR_ERR_INVALID_ARG; + } + if (vector->status == false) + { + return AVR_ERR_INVALID_STATE; + } + if (vector->capacity == vector->size) + { + if (_resize(vector, vector->capacity + 1) == AVR_ERR_NO_MEM) + { + return AVR_ERR_NO_MEM; + } + } + vector->items[vector->size] = calloc(1, vector->unit); + if (vector->items[vector->size] == NULL) + { + return AVR_ERR_NO_MEM; + } + memcpy(vector->items[vector->size++], item, vector->unit); + return AVR_OK; +} + +avr_err_t zh_avr_vector_change_item(zh_avr_vector_t *vector, uint16_t index, void *item) +{ + if (vector == NULL || item == NULL) + { + return AVR_ERR_INVALID_ARG; + } + if (vector->status == false) + { + return AVR_ERR_INVALID_STATE; + } + if (index < vector->size) + { + memcpy(vector->items[index], item, vector->unit); + return AVR_OK; + } + return AVR_FAIL; +} + +void *zh_avr_vector_get_item(zh_avr_vector_t *vector, uint16_t index) +{ + if (vector == NULL) + { + return NULL; + } + if (vector->status == false) + { + return NULL; + } + if (index < vector->size) + { + void *item = vector->items[index]; + return item; + } + else + { + return NULL; + } +} + +avr_err_t zh_avr_vector_delete_item(zh_avr_vector_t *vector, uint16_t index) +{ + if (vector == NULL) + { + return AVR_ERR_INVALID_ARG; + } + if (vector->status == false) + { + return AVR_ERR_INVALID_STATE; + } + if (index < vector->size) + { + free(vector->items[index]); + for (uint8_t i = index; i < (vector->size - 1); ++i) + { + vector->items[i] = vector->items[i + 1]; + vector->items[i + 1] = NULL; + } + --vector->size; + _resize(vector, vector->capacity - 1); + return AVR_OK; + } + return AVR_FAIL; +} + +static avr_err_t _resize(zh_avr_vector_t *vector, uint16_t capacity) +{ + if (capacity != 0) + { + vector->items = realloc(vector->items, sizeof(void *) * capacity); + if (vector->items == NULL) + { + return AVR_ERR_NO_MEM; + } + } + vector->capacity = capacity; + return AVR_OK; +} \ No newline at end of file