/** * @file array.c * @author CylAlon(ChenYinglong) * @brief * @version 1.0.0 * @date 2022-07-20 */ /* * 完整的API见头文件,头文件提供了一套宏定义扩展array库。 * 本动态数组库支持任意类型的数组(包括自定义的结构体类型), * 本数据结构提供了两种方式初始化数组,一种是自动增长Cap的方式Array_Init,一种是指定数组Array_InitStatic, * 由于malloc可能存在碎片化问题,所以建议使用Array_InitStatic。 * 如果将malloc以及free替换成自己的内存管理函数,那么就可以使用Array_Init。 * */ #include "array.h" #ifdef ARRAY_ENABLE #define Array_Resize_Unit 8 /** * @brief Initialize an array. * * @param array The array to initialize. */ void Array_Init(Array_t *array, int cap, uint8_t elm_bytes) { array->type = true; array->Data = (uint8_t *) malloc(cap * elm_bytes); memset(array->Data, 0, cap * elm_bytes); array->Cap = cap; array->ElemBytes = elm_bytes; array->Size = 0; } void Array_InitStatic(Array_t *array, int cap, uint8_t elm_bytes, uint8_t *buff) { array->type = false; array->Data = buff; array->Cap = cap; array->ElemBytes = elm_bytes; array->Size = 0; } /** * @brief Destruction of the array. * * @param array The array to destroy. */ void Array_Destroy(Array_t *array) { if (array->type) { FreePtr(array->Data); } array->Data = NULL; array->type = false; array->Cap = 0; array->ElemBytes = 0; array->Size = 0; } /** * @brief Expanding the array. * * @param array The array to expand. * @param cap */ static bool Array_Resize(Array_t *array, int size) { if (array->type == false) { return false; } if (array != NULL) { uint8_t len = 0; if (array->ElemBytes < 4) { len = Array_Resize_Unit + size; } else if (array->ElemBytes < 8) { len = Array_Resize_Unit / 2 + size; } else { len = Array_Resize_Unit / 4 + size; } array->Data = (uint8_t *) realloc(array->Data, (array->Cap + len) * array->ElemBytes); array->Cap = array->Cap + len; return true; } return false; } /** * @brief Add an value to the array. * * @param array The array to add to. * @param value This is data to add to the array. * @param size The size of the data to add. */ bool Array_AddArray(Array_t *array, const uint8_t *value, int size) { if (array != NULL) { if (array->Size + size > array->Cap) { if (!Array_Resize(array, size)) { return false; } } for (int i = 0; i < size * array->ElemBytes; i++) { *(array->Data + array->Size * array->ElemBytes + i) = value[i]; } array->Size += size; return true; } return false; } bool Array_AddArrayUint8(Array_t *array, uint8_t value, int index) { if (array != NULL) { *(array->Data + array->Size * array->ElemBytes + index) = value; // array->Size += 1; return true; } return false; } /** * @brief Insert an value to the array. * * @param array The array to add to. * @param value This is data to add to the array. * @param size The size of the data to add. */ bool Array_Insert(Array_t *array, uint8_t *value, int size, int index) { if (array != NULL) { if (array->Size + size > array->Cap) { if (!Array_Resize(array, size)) { return false; } } if (index < 0 || index >= array->Size) { Array_PushArray(array, value, size); return true; } for (int i = array->Size * array->ElemBytes - 1; i >= index; i--) { array->Data[i + size * array->ElemBytes] = array->Data[i]; } for (int i = 0; i < size * array->ElemBytes; i++) { array->Data[index * array->ElemBytes + i] = value[i]; } array->Size += size; return true; } return false; } /** * @brief Remove an value to the array. * * @param array The array to remove to. * @param start The starting index. * @param end The ending index. */ bool Array_Remove(Array_t *array, int start, int end) { if (array != NULL) { if (start < 0 || array->Size <= 0 || end < start || array->Size <= start) { return false; } if (array->Size < end) { end = array->Size; } int len = end - start; for (int i = start * array->ElemBytes; i < (array->Size - len) * array->ElemBytes; i++) { array->Data[i] = array->Data[i + len * array->ElemBytes]; } array->Size = array->Size - len; return true; } return false; } #endif // ARRAY_ENABLE