#include "dynamic_array.h" #include #include #include #define DA_DEFAULT_CAPACITY 4 #define DA_GROWTH_FACTOR 2 #define ELEM_PTR(arr, i) \ ((arr)->data + (i) * (arr)->type->element_size) static bool da_ensure_capacity(DynamicArray *arr, const size_t needed) { if (needed <= arr->capacity) return true; size_t new_cap = arr->capacity; while (new_cap < needed) new_cap *= DA_GROWTH_FACTOR; char *new_data = realloc(arr->data, new_cap * arr->type->element_size); if (!new_data) { fprintf(stderr, "da_ensure_capacity: realloc failed\n"); return false; } arr->data = new_data; arr->capacity = new_cap; return true; } DynamicArray *da_create(const TypeInfo *type, size_t initial_capacity) { if (!type) { fprintf(stderr, "da_create: type is NULL\n"); return NULL; } if (initial_capacity <= 0) initial_capacity = DA_DEFAULT_CAPACITY; DynamicArray *arr = (DynamicArray *) malloc(sizeof(DynamicArray)); if (!arr) { fprintf(stderr, "da_create: malloc failed\n"); return NULL; } arr->data = (char *) malloc(initial_capacity * type->element_size); if (!arr->data) { fprintf(stderr, "da_create: malloc for data failed\n"); free(arr); return NULL; } arr->size = 0; arr->capacity = initial_capacity; arr->type = type; return arr; } void da_destroy(DynamicArray *arr) { if (!arr) return; if (arr->type->destroy) { for (size_t i = 0; i < arr->size; i++) arr->type->destroy(ELEM_PTR(arr, i)); } free(arr->data); free(arr); } void *da_get(const DynamicArray *arr, const size_t index) { if (!arr || index >= arr->size) { fprintf(stderr, "da_get: index %zu out of bounds (size=%zu)\n", index, arr ? arr->size : 0); return NULL; } return ELEM_PTR(arr, index); } bool da_set(DynamicArray *arr, const size_t index, const void *value) { if (!arr || !value || index >= arr->size) { fprintf(stderr, "da_set: incorrect arguments\n"); return false; } void *dest = ELEM_PTR(arr, index); if (arr->type->destroy) arr->type->destroy(dest); arr->type->copy(dest, value); return true; } size_t da_size(const DynamicArray *arr) { return arr ? arr->size : 0; } bool da_push_back(DynamicArray *arr, const void *value) { if (!arr || !value) return false; if (!da_ensure_capacity(arr, arr->size+1)) return false; arr->type->copy(ELEM_PTR(arr, arr->size), value); arr->size++; return true; } bool da_insert(DynamicArray *arr, const size_t index, const void *value) { if (!arr || !value || index > arr->size) { fprintf(stderr, "da_insert: invalid arguments\n"); return false; } if (!da_ensure_capacity(arr, arr->size + 1)) return false; const size_t es = arr->type->element_size; memmove(ELEM_PTR(arr, index + 1), ELEM_PTR(arr, index), (arr->size - index) * es); // arr->type->copy(ELEM_PTR(arr, index), value); arr->size++; return true; } bool da_remove(DynamicArray *arr, const size_t index) { if (!arr || index >= arr->size) { fprintf(stderr, "da_remove: index %zu out of bounds\n", index); return false; } if (arr->type->destroy) arr->type->destroy(ELEM_PTR(arr, index)); const size_t es = arr->type->element_size; memmove(ELEM_PTR(arr, index), ELEM_PTR(arr, index + 1), (arr->size - index - 1) * es); arr->size--; return true; } // Вспомогательные функции сортировки static void swap(void *a, void *b, const TypeInfo *type) { void *temp = malloc(type->element_size); type->copy(temp, a); type->copy(a, b); type->copy(b, temp); if (type->destroy) type->destroy(temp); free(temp); } void da_sort(DynamicArray *arr) { for (size_t i = 0; i < arr->size; i++) { for (size_t j = i + 1; j < arr->size; j++) { if (arr->type->compare(ELEM_PTR(arr, i), ELEM_PTR(arr, j)) > 0) swap(ELEM_PTR(arr, i), ELEM_PTR(arr, j), arr->type); } } } DynamicArray* da_map(const DynamicArray *arr, MapFunc f) { if (!arr || !f) return NULL; DynamicArray *result = da_create(arr->type, arr->size); if (!result) return NULL; void *temp = malloc(arr->type->element_size); // Буффер для хранения результатов map if (!temp) { da_destroy(result); return NULL; } for (size_t i = 0; i < arr->size; i++) { memset(temp, 0, arr->type->element_size); f(temp, ELEM_PTR(arr, i)); da_push_back(result, temp); if (arr->type->destroy) arr->type->destroy(temp); } free(temp); return result; } DynamicArray* da_where(const DynamicArray *arr, Predicate pred) { if (!arr || !pred) return NULL; DynamicArray *result = da_create(arr->type, arr->size); if (!result) return NULL; for (size_t i = 0; i < arr->size; i++) { void *elem = ELEM_PTR(arr, i); if (pred(elem)) da_push_back(result, elem); } return result; } void da_reduce(const DynamicArray *arr, ReduceFunc f, void *initial, void *result) { if (!arr || !f || !result) return; size_t es = arr->type->element_size; memcpy(result, initial, es); for (size_t i = 0; i < arr->size; i++) { f(result, ELEM_PTR(arr, i)); } } DynamicArray* da_concat(const DynamicArray *a, const DynamicArray *b) { if (!a || !b) return NULL; if (!types_equal(a->type, b->type)) { fprintf(stderr, "da_concat: type missmatch (%s vs %s)\n", a->type->type_name, b->type->type_name); return NULL; } DynamicArray *result = da_create(a->type, a->size + b->size); if (!result) return NULL; for (size_t i = 0; i < a->size; i++) da_push_back(result, ELEM_PTR(a, i)); for (size_t i = 0; i < b->size; i++) da_push_back(result, ELEM_PTR(b, i)); return result; } void da_print(const DynamicArray *arr) { if (!arr) { printf("(null)\n"); return; } printf("[%s] size=%zu, capacity=%zu\n", arr->type->type_name, arr->size, arr->capacity); printf("[ "); for (size_t i = 0; i < arr->size; i++) { if (i > 0) printf(", "); arr->type->print(ELEM_PTR(arr, i)); } printf(" ]\n"); }