Compare commits

..

7 Commits

7 changed files with 879 additions and 69 deletions

View File

@@ -219,7 +219,7 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
marigold_dynamic_array marigold_vector
Copyright (C) 2026 Emilia Marigold Copyright (C) 2026 Emilia Marigold
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

View File

@@ -0,0 +1,9 @@
#ifndef INTERNAL_MARIGOLD_MACROS_H
#define INTERNAL_MARIGOLD_MACROS_H
#define SINGLE_ELEMENT 1
#define INDEX_ZERO 0
#define BIT_FALSE 0
#define EMPTY 0
#endif /* INTERNAL_MARIGOLD_MACROS_H */

View File

@@ -0,0 +1,62 @@
#include "internal_marigold_vector.h"
vector_struct*
vector_initialize(vector_struct* new_vector,
size_t item_size,
size_t starting_capacity,
vector_growth_rate_enum growth_rate,
int (*comparator)(const void*, const void*),
void (*item_free)(const void *),
bool is_multithread_safe)
{
new_vector->item_size = item_size;
new_vector->current_capacity = starting_capacity;
new_vector->current_occupancy = 0;
new_vector->comparator = comparator;
new_vector->item_free = item_free;
new_vector->growth_strategy = (uint8_t)growth_rate;
new_vector->owner_count = 1;
if (is_multithread_safe)
{
new_vector->flags |= vector_multithread_safe;
}
#ifdef MARIGOLD_DEBUG
new_vector->debug_flags = 0;
new_vector->debug_resize_count = 0;
new_vector->debug_function_call_count = 0;
new_vector->debug_last_error_code = 0;
new_vector->debug_allocation_failures = 0;
#endif
if (starting_capacity > 0)
{
new_vector->data_pointer = calloc(starting_capacity, item_size);
if (!new_vector->data_pointer)
{
return NULL;
}
}
else
{
new_vector->data_pointer = NULL;
}
if (is_multithread_safe)
{
new_vector->mutex_lock = calloc(1, sizeof(pthread_mutex_t));
if (!new_vector->mutex_lock)
{
free(new_vector->data_pointer);
return NULL;
}
pthread_mutex_init(new_vector->mutex_lock, NULL);
}
else
{
new_vector->mutex_lock = NULL;
}
return new_vector;
}

View File

@@ -1,10 +1,75 @@
#ifndef INTERNAL_MARIGOLD_VECTOR_H
#define INTERNAL_MARIGOLD_VECTOR_H
/**
* @brief Destroy a dynamic array and free its memory. #include <pthread.h>
* #include <stdbool.h>
* Frees the memory block and the array structure itself. #include <stdint.h>
* Sets owner_count to 0 before freeing. #include <stdlib.h>
*
* @param array Pointer to the dynamic_array to destroy. typedef enum
*/ vector_flag_enum
void dynamic_array_destroy(dynamic_array* array); {
vector_multithread_safe = 1 << 0,
vector_read_only = 1 << 1,
vector_certainly_sorted = 1 << 2,
vector_marked_for_free = 1 << 3,
vector_debug_has_function_call_rolled_over = 1 << 4,
vector_debug_has_owner_count_rolled_over = 1 << 5,
vector_debug_has_been_resized = 1 << 6,
vector_debug_has_been_resized_rolled_over = 1 << 7
}
vector_flag_enum;
typedef enum
vector_growth_rate_enum
{
vector_growth_none = 0,
vector_growth_linear = 1,
vector_growth_double = 2,
vector_growth_triple = 3,
vector_growth_quadruple = 4,
vector_growth_quintuple = 5
}
vector_growth_rate_enum;
typedef struct
vector_struct
{
size_t item_size;
size_t current_capacity;
size_t current_occupancy;
void* data_pointer;
int (*comparator)(const void *, const void *);
void (*item_free)(const void *);
pthread_mutex_t* mutex_lock;
unsigned short owner_count;
uint8_t growth_strategy;
uint8_t flags;
#ifdef MARIGOLD_DEBUG
uint8_t debug_flags;
uint32_t debug_resize_count;
uint32_t debug_function_call_count;
uint32_t debug_last_error_code;
uint32_t debug_allocation_failures;
#endif /* MARIGOLD_DEBUG. */
}
vector_struct;
vector_struct*
vector_initialize(vector_struct* new_vector,
size_t item_size,
size_t starting_capacity,
vector_growth_rate_enum growth_rate,
int (*comparator)(const void*, const void*),
void (*item_free)(const void *),
bool is_multithread_safe);
void
vector_free_members();
bool
vector_grow(vector_struct* vector);
#endif /* INTERNAL_MARIGOLD_VECTOR_H */

View File

@@ -0,0 +1,697 @@
#include "marigold_vector.h"
#include "internal/internal_marigold_macros.h"
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
vector_struct*
vector_create(size_t item_size,
size_t starting_capacity,
vector_growth_rate_enum growth_rate,
int (*comparator)(const void*, const void*),
void (*item_free)(const void *),
bool is_multithread_safe)
{
vector_struct* new_vector = calloc(SINGLE_ELEMENT,
sizeof(vector_struct));
if (!new_vector)
{
return NULL;
}
return vector_initialize(new_vector,
item_size,
starting_capacity,
growth_rate,
comparator,
item_free,
is_multithread_safe);
}
bool
vector_destroy(vector_struct* vector_to_destroy)
{
bool destroyed_successfully = false;
vector_free_members(); // actually frees all internal stuff
// then free the base container/mutex etc.
return destroyed_successfully;
}
void
vector_set_flag(vector_struct* vector,
vector_flag_enum flag,
bool value)
{
if (value)
{
vector->flags |= flag; // Bitwise or with value.
}
else
{
vector->flags &= ~flag; // Bitwise and with inverted value.
}
}
bool
vector_get_flag_value(const vector_struct* vector,
vector_flag_enum flag)
{
if ((vector->flags & flag) != BIT_FALSE)
{
return true;
}
else
{
return false;
}
}
size_t
vector_get_occupancy(const vector_struct* vector)
{
return vector->current_occupancy;
}
size_t
vector_get_capacity(const vector_struct* vector)
{
return vector->current_capacity;
}
void*
vector_get_pointer_to_index(vector_struct* vector,
size_t index)
{
return (char*)vector->data_pointer + (index * vector->item_size);
}
const void*
vector_get_const_pointer_to_index(const vector_struct* vector,
size_t index)
{
return (const char*)vector->data_pointer + (index * vector->item_size);
}
void*
vector_get_raw_data_pointer(const vector_struct* vector)
{
return vector->data_pointer;
}
bool
vector_append(vector_struct* vector,
const void* element)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (vector->current_occupancy == vector->current_capacity)
{
if (!vector_grow(vector))
{ /* failed to grow vector (probably out of memory)*/
if (is_thread_safe)
{ /* unlocking mutex during fail case (if it is locked.) */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show append failed. */
}
}
char* data = (char*)vector->data_pointer;
size_t offset = vector->current_occupancy * vector->item_size;
memcpy(data + offset, element, vector->item_size);
vector->current_occupancy++;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show append success. */
}
bool
vector_insert_at(vector_struct* vector,
size_t index,
const void* element)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (index > vector->current_occupancy)
{ /* index out of bounds for insertion. */
if (is_thread_safe)
{ /* unlocking mutex during fail case (if it is locked.) */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show insert failed. */
}
if (vector->current_occupancy == vector->current_capacity)
{
if (!vector_grow(vector))
{ /* failed to grow vector (probably out of memory). */
if (is_thread_safe)
{ /* unlocking mutex during fail case (if it is locked.) */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show insert failed. */
}
}
char* data = (char*)vector->data_pointer;
const size_t element_size = vector->item_size;
const size_t bytes_to_shift = (vector->current_occupancy - index) * element_size;
const size_t shift_offset = index * element_size;
if (bytes_to_shift > INDEX_ZERO)
{
memmove(data + shift_offset + element_size,
data + shift_offset,
bytes_to_shift);
}
memcpy(data + shift_offset, element, element_size);
vector->current_occupancy++;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show insert success. */
}
bool
vector_set_item(vector_struct* vector,
size_t index_to_set,
const void* new_element)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (index_to_set >= vector->current_occupancy)
{ /* index out of bounds for setting. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* failed, cannot set a value outside of current values. */
}
char* data = (char*)vector->data_pointer;
const size_t element_size = vector->item_size;
const size_t offset = index_to_set * element_size;
if (vector->item_free != NULL)
{ /* free the old element if item_free callback is set. */
vector->item_free(data + offset);
}
memcpy(data + offset, new_element, element_size);
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show set success. */
}
bool
vector_swap(vector_struct* vector,
size_t index_a,
size_t index_b)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (index_a >= vector->current_occupancy || index_b >= vector->current_occupancy)
{ /* index out of bounds for swapping. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show swap failed. */
}
if (index_a == index_b)
{ /* same index, nothing to swap. */
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show swap success. */
}
char* data = (char*)vector->data_pointer;
const size_t element_size = vector->item_size;
const size_t offset_a = index_a * element_size;
const size_t offset_b = index_b * element_size;
void* temp = malloc(element_size);
if (!temp)
{ /* failed to allocate temporary buffer. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show swap failed. */
}
memcpy(temp, data + offset_a, element_size);
memcpy(data + offset_a, data + offset_b, element_size);
memcpy(data + offset_b, temp, element_size);
free(temp);
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show swap success. */
}
bool
vector_remove(vector_struct* vector,
size_t index)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (index >= vector->current_occupancy)
{ /* index out of bounds for removal. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show remove failed. */
}
char* data = (char*)vector->data_pointer;
const size_t element_size = vector->item_size;
const size_t offset = index * element_size;
const size_t bytes_to_shift = (vector->current_occupancy - index - 1) * element_size;
if (vector->item_free != NULL)
{ /* free the removed element if item_free callback is set. */
vector->item_free(data + offset);
}
if (bytes_to_shift > INDEX_ZERO)
{
memmove(data + offset,
data + offset + element_size,
bytes_to_shift);
}
vector->current_occupancy--;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show remove success. */
}
void
vector_clear(vector_struct* vector)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (vector->item_free != NULL)
{ /* free all elements if item_free callback is set. */
char* data = (char*)vector->data_pointer;
const size_t element_size = vector->item_size;
for (size_t i = 0; i < vector->current_occupancy; i++)
{
vector->item_free(data + (i * element_size));
}
}
vector->current_occupancy = 0;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
}
bool
vector_is_empty(const vector_struct* vector)
{
if (vector->current_occupancy == EMPTY)
{
return true;
}
else
{
return false;
}
}
bool
vector_increase_capacity(vector_struct* vector,
size_t new_capacity)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (new_capacity <= vector->current_capacity)
{ /* new capacity not larger than current, nothing to do. */
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show success (no-op). */
}
void* new_data = calloc(new_capacity, vector->item_size);
if (!new_data)
{ /* failed to allocate new memory. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show capacity increase failed. */
}
if (vector->current_occupancy > 0)
{
memcpy(new_data,
vector->data_pointer,
vector->current_occupancy * vector->item_size);
}
free(vector->data_pointer);
vector->data_pointer = new_data;
vector->current_capacity = new_capacity;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show capacity increase success. */
}
bool
vector_shrink_to_fit(vector_struct* vector)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (vector->current_capacity <= vector->current_occupancy)
{ /* capacity already matches or is smaller than occupancy, nothing to do. */
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show success (no-op). */
}
void* new_data = calloc(vector->current_occupancy, vector->item_size);
if (!new_data)
{ /* failed to allocate new memory. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show shrink failed. */
}
if (vector->current_occupancy > 0)
{
memcpy(new_data,
vector->data_pointer,
vector->current_occupancy * vector->item_size);
}
free(vector->data_pointer);
vector->data_pointer = new_data;
vector->current_capacity = vector->current_occupancy;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show shrink success. */
}
bool
vector_acquire(vector_struct* vector)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (vector->owner_count >= USHRT_MAX)
{ /* owner_count would overflow. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show acquire failed. */
}
vector->owner_count++;
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return true; /* returns true to show acquire success. */
}
bool
vector_release(vector_struct* vector)
{
const bool is_thread_safe = vector_is_thread_safe(vector);
if (is_thread_safe)
{ /* if thread safe enabled, locking before vector modification. */
pthread_mutex_lock(vector->mutex_lock);
}
if (vector->owner_count == 0)
{ /* owner_count already zero, nothing to release. */
if (is_thread_safe)
{ /* unlocking mutex during fail case if it is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return false; /* returns false to show release failed (already released). */
}
vector->owner_count--;
if (vector->owner_count == 0)
{ /* owner_count reached zero, destroy the vector. */
return vector_destroy(vector);
}
if (is_thread_safe)
{ /* unlocking mutex post vector modification if it exists/is locked. */
pthread_mutex_unlock(vector->mutex_lock);
}
return vector->owner_count > 0; /* returns true if owner_count > 0, false if destroyed. */
}
unsigned short
vector_get_owner_count(const vector_struct* vector)
{
return vector->owner_count;
}
bool
vector_is_thread_safe(const vector_struct* vector)
{
if ((vector->flags & vector_multithread_safe) != FALSE)
{
return true;
}
else
{
return false;
}
}
vector_struct*
vector_shallow_copy(const vector_struct* vector_to_copy)
{
}
vector_struct*
vector_deep_copy(const vector_struct* vector_to_copy,
void* (*item_copy)(const void* item))
{
}
vector_struct*
vector_shallow_copy_slice(const vector_struct* vector_to_copy,
size_t starting_point,
size_t ending_point,
bool is_start_inclusive,
bool is_end_inclusive)
{
}
vector_struct*
vector_deep_copy_slice(const vector_struct* vector_to_copy,
void* (*item_copy)(const void* item),
size_t starting_point,
size_t ending_point,
bool is_start_inclusive,
bool is_end_inclusive)
{
}
void
vector_sort_in_place(vector_struct* vector_to_sort,
bool should_reverse_sort)
{
}
void
vector_sort_slice(vector_struct* vector_to_sort,
size_t starting_point,
size_t ending_point,
bool is_start_inclusive,
bool is_end_inclusive,
bool should_reverse_sort)
{
}
vector_struct*
vector_get_sorted_copy(const vector_struct* vector,
bool should_reverse_sort)
{
}
void
vector_reverse(vector_struct* vector_to_reverse)
{
}
bool
vector_contains(const vector_struct* vector_to_search,
const void* pointer_of_value_to_find)
{
}
size_t
vector_find_first_index_of(const vector_struct* vector_to_search,
const void* pointer_of_value_to_find)
{
}
size_t
vector_find_final_index_of(const vector_struct* vector_to_search,
const void* pointer_of_value_to_find)
{
}
void
vector_set_comparator_function(vector_struct *vector,
int (*comparator)(const void*, const void*))
{
vector->comparator = comparator;
}
bool
vector_get_item(const vector_struct* vector,
size_t index,
void* out_buffer)
{
}
void
vector_iterate_over(vector_struct* vector,
void (*callback)(void* element, void* user_data),
size_t starting_index,
size_t ending_index,
bool is_start_inclusive,
bool is_end_inclusive)
{
}
void
vector_foreach(vector_struct* vector,
void (*callback)(void* element, void* user_data))
{
}
size_t
vector_binary_search(const vector_struct* vector,
const void* value)
{
}
#ifdef MARIGOLD_DEBUG
void
vector_debug_print_stats(const vector_struct* vector)
{
}
void
vector_debug_dump_vector(const vector_struct* vector)
{
}
bool
vector_validate_integrity(const vector_struct* vector)
{
}
#endif /* MARIGOLD_DEBUG */

View File

@@ -1,60 +1,7 @@
#ifndef MARIGOLD_VECTOR_H #ifndef MARIGOLD_VECTOR_H
#define MARIGOLD_VECTOR_H #define MARIGOLD_VECTOR_H
#include <pthread.h> #include "internal/internal_marigold_vector.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef enum
vector_flag_enum
{
vector_multithread_safe = 1 << 0,
vector_read_only = 1 << 1,
vector_certainly_sorted = 1 << 2,
vector_marked_for_free = 1 << 3,
vector_debug_has_function_call_rolled_over = 1 << 4,
vector_debug_has_owner_count_rolled_over = 1 << 5,
vector_debug_has_been_resized = 1 << 6,
vector_debug_has_been_resized_rolled_over = 1 << 7
}
vector_flag_enum;
typedef enum
vector_growth_rate_enum
{
vector_growth_none = 0,
vector_growth_linear = 1,
vector_growth_double = 2,
vector_growth_triple = 3,
vector_growth_quadruple = 4,
vector_growth_quintuple = 5
}
vector_growth_rate_enum;
typedef struct
vector_struct
{
size_t item_size;
size_t current_capacity;
size_t current_occupancy;
void* data_pointer;
int (*comparator)(const void *, const void *);
void (*item_free)(const void *);
pthread_mutex_t* mutex_lock;
unsigned short owner_count;
uint8_t growth_strategy;
uint8_t flags;
#ifdef MARIGOLD_DEBUG
uint8_t debug_flags;
uint32_t debug_resize_count;
uint32_t debug_function_call_count;
uint32_t debug_last_error_code;
uint32_t debug_allocation_failures;
#endif /* MARIGOLD_DEBUG. */
}
vector_struct;
/** /**
* @brief Create a new dynamic vector, it then internally does all the * @brief Create a new dynamic vector, it then internally does all the
@@ -206,13 +153,13 @@ vector_insert_at(vector_struct* vector,
* @brief Replace the element at the specified index. * @brief Replace the element at the specified index.
* *
* @param vector Pointer to the vector. * @param vector Pointer to the vector.
* @param index Index of the element to replace. * @param index_to_set Index of the element to replace.
* @param new_element Pointer to the new element data. * @param new_element Pointer to the new element data.
* @return true on success, false if index is out of bounds. * @return true on success, false if index is out of bounds.
*/ */
bool bool
vector_set_item(vector_struct* vector, vector_set_item(vector_struct* vector,
size_t index, size_t index_to_set,
const void* new_element); const void* new_element);
/** /**

View File

@@ -1,12 +1,42 @@
#include "MODULE_marigold_vector/marigold_vector.h"
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include "MODULE_marigold_dynamic_array/marigold_dynamic_array.h" #include <time.h>
/*
_.-''''-..
.-' -_ \
/ -. \ ,_ , ' ,,-.
/ _ \ \ \ '''" /
|(q) ) | / \
\',_/ / | (|) (|) )
\ __' \ == v ==
'--..-' " - ^-'"
'-__ __)
''''''
This codebase has been visited by Snailcat
Snailcat believes that software should move slow and
be stable. He despises constant updates and dreams of
software so finished it stops having to move at all.
All problems are trivial to solve with enough knowledge/people working on it.
Use AGPLv3 license on your project today.
Move slow, snailcat!
*/
int main(void) int main(void)
{ {
printf("Hello, %s!\n", "marigold_dynamic_array"); printf("Hello, %s!\n", "marigold_dynamic_array");
printf("Version: %s\n", "26.136.1101"); printf("Version: %s\n", "26.136.1101");
dynamic_array array = dynamic_array_create(); vector_struct* vector = vector_create(sizeof(int),
500,
vector_growth_double,
NULL,
NULL,
true);
return 0; return EXIT_SUCCESS;
} }