size_t element_size;
size_t capacity;
size_t count;
- void *data;
+ char *data;
};
Dynarray *create_dynarray(size_t element_size)
{
Lt *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
- Dynarray *dynarray = PUSH_LT(lt, nth_alloc(sizeof(Dynarray)), free);
+ Dynarray *dynarray = PUSH_LT(lt, nth_calloc(1, sizeof(Dynarray)), free);
if (dynarray == NULL) {
RETURN_LT(lt, NULL);
}
RETURN_LT0(dynarray->lt);
}
+void *dynarray_pointer_at(Dynarray *dynarray, size_t index) {
+ trace_assert(index < dynarray->count);
+ return dynarray->data + index * dynarray->element_size;
+}
+
size_t dynarray_count(const Dynarray *dynarray)
{
trace_assert(dynarray);
dynarray->count = 0;
}
+static
+int dynarray_grow(Dynarray *dynarray)
+{
+ if (dynarray->count < dynarray->capacity) {
+ return 0;
+ }
+
+ void *new_data = nth_realloc(
+ dynarray->data,
+ dynarray->capacity * dynarray->element_size * 2);
+ if (new_data == NULL) {
+ return -1;
+ }
+
+ dynarray->data = REPLACE_LT(dynarray->lt, dynarray->data, new_data);
+ if (dynarray->data == NULL) {
+ return -1;
+ }
+
+ dynarray->capacity *= 2;
+
+ return 0;
+}
+
int dynarray_push(Dynarray *dynarray, const void *element)
{
trace_assert(dynarray);
trace_assert(element);
- if (dynarray->count >= dynarray->capacity) {
- void *new_data = nth_realloc(
- dynarray->data,
- dynarray->capacity * dynarray->element_size * 2);
- if (new_data == NULL) {
- return -1;
- }
-
- dynarray->data = REPLACE_LT(dynarray->lt, dynarray->data, new_data);
- if (dynarray->data == NULL) {
- return -1;
- }
-
- dynarray->capacity *= 2;
+ if (dynarray_grow(dynarray) < 0) {
+ return -1;
}
memcpy(
return false;
}
+
+void dynarray_delete_at(Dynarray *dynarray, size_t index)
+{
+ trace_assert(dynarray);
+ trace_assert(index < dynarray->count);
+ memmove(
+ dynarray->data + index * dynarray->element_size,
+ dynarray->data + (index + 1) * dynarray->element_size,
+ dynarray->element_size * (dynarray->count - index - 1));
+ dynarray->count--;
+}
+
+void dynarray_insert_before(Dynarray *dynarray, size_t index, void *element)
+{
+ trace_assert(dynarray);
+ trace_assert(element);
+ trace_assert(index <= dynarray->count);
+
+ dynarray_grow(dynarray);
+
+ memmove(
+ dynarray->data + (index + 1) * dynarray->element_size,
+ dynarray->data + index * dynarray->element_size,
+ dynarray->element_size * (dynarray->count - index));
+
+ memcpy(
+ dynarray->data + index * dynarray->element_size,
+ element,
+ dynarray->element_size);
+
+ dynarray->count++;
+}
+
+int dynarray_push_empty(Dynarray *dynarray)
+{
+ trace_assert(dynarray);
+
+ if (dynarray_grow(dynarray) < 0) {
+ return -1;
+ }
+
+ memset(
+ (char*) dynarray->data + dynarray->count * dynarray->element_size,
+ 0,
+ dynarray->element_size);
+
+ dynarray->count++;
+
+ return 0;
+}
+
+// TODO(#980): dynarray_push and dynarray_push_empty have duplicate codez
+
+void dynarray_pop(Dynarray *dynarray, void *element)
+{
+ trace_assert(dynarray);
+ trace_assert(dynarray->count > 0);
+
+ dynarray->count--;
+
+ if (element) {
+ memcpy(
+ element,
+ dynarray->data + dynarray->count * dynarray->element_size,
+ dynarray->element_size);
+ }
+}
+
+void dynarray_replace_at(Dynarray *dynarray, size_t index, void *element)
+{
+ trace_assert(dynarray);
+ trace_assert(element);
+ trace_assert(index < dynarray->count);
+
+ memcpy(
+ dynarray->data + index * dynarray->element_size,
+ element,
+ dynarray->element_size);
+}
+
+void dynarray_copy_to(Dynarray *dynarray, void *dest, size_t index)
+{
+ trace_assert(dynarray);
+ trace_assert(dest);
+ trace_assert(index < dynarray->count);
+
+ memcpy(dest, dynarray->data + index * dynarray->element_size, dynarray->element_size);
+}
+
+void dynarray_swap(Dynarray *dynarray, size_t i, size_t j)
+{
+ trace_assert(dynarray);
+ trace_assert(i < dynarray->count);
+ trace_assert(j < dynarray->count);
+
+ if (i == j) return;
+
+ char *a = dynarray_pointer_at(dynarray, i);
+ char *b = dynarray_pointer_at(dynarray, j);
+
+ for (size_t k = 0; k < dynarray->element_size; ++k) {
+ char t = a[k];
+ a[k] = b[k];
+ b[k] = t;
+ }
+}