Add files via upload
This commit is contained in:
236
dynamic_array.c
Normal file
236
dynamic_array.c
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "dynamic_array.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
Reference in New Issue
Block a user