Skip to content

Instantly share code, notes, and snippets.

@FergusInLondon
Created May 2, 2017 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FergusInLondon/1af13353c9a5b369af22905cbdf1f331 to your computer and use it in GitHub Desktop.
Save FergusInLondon/1af13353c9a5b369af22905cbdf1f331 to your computer and use it in GitHub Desktop.
Dynamic array/container implementation in C - includes iterator. (WIP / Brain-Dump)
#include <string.h> // memcpy
#include <stdlib.h> //
/**
*
*
*/
typedef struct {
uint8_t object_count, iteration_counter, max_count;
uint8_t *indices_in_use;
size_t object_size;
unsigned char *begin;
} container_t;
/**
*
*
*/
container_t *create_container(size_t object_size, uint8_t len)
{
container_t *container = calloc(sizeof(struct container) + (object_size * len));
container->object_count = 0;
container->max_count = len;
container->object_size = size;
container->begin = (void *) (((char *)container) + sizeof(struct container));
container->indices_in_use = calloc(sizeof(uint8_t) * len);
container->increment_counter = 0;
return container;
}
/**
*
*
*/
void *container_set_element(container_t *container, void *element)
{
if (container->object_count >= container->max_count) return NULL;
unsigned char *ptr = container->begin;
int i = 0;
while (container->indices_in_use[i] == 1 && i <= container->max_count) i++;
ptr += (container->object_size * i);
memcpy(ptr, element, container->object_size);
container->object_count++;
container->indices_in_use[i] = 1;
return (void *)ptr;
}
/**
*
*
*/
void *container_get_element(container_t *container, uint8_t idx)
{
if (idx > object_count)
return NULL;
if (container->indices_in_use[idx] == 0)
return NULL;
char *ptr = container->begin;
ptr += sizeof(struct container);
ptr += container->object_size * idx;
return (void *)ptr;
}
/**
*
*
*/
void *container_remove_element(container_t *container, void *element)
{
unsigned char *target = &element;
uint8_t idx = (target - container->begin) / container->object_size;
container->indices_in_use[idx] = 0;
memset(element, 0, container->object_size);
}
/**
*
*
*/
void *container_reset_iterator(container_t *container)
{
container->iteration_counter = 0;
}
/**
*
*
*/
void *container_get_next_element(container_t *container)
{
if( container->iteration_counter >= container->max_count )
return NULL;
for (; container->iteration_counter <= container->max_count; container->iteration_counter++) {
if (container->indices_in_use[ container->iteration_counter ] > 0){
return container_get_element(container->iteration_counter);
}
}
return NULL;
}
/**
*
* Makes sense to change param 1 to a **, to allow us to modify the ptr.. but yeah.
* I will get around to that at some point.
*
* This destroys current indexes! Do not use if your care about your indexing.
*/
container_t *container_resize(container_t *container, uint8_t new_size)
{
// check current count etc
if (container->object_count > new_size)
return NULL;
// allocate new memory region for
container_t *new = calloc(sizeof(container_t) + (new_size * container->object_size));
memcpy(new, container, sizeof(container_t));
unsigned char *begin = (unsigned char *)new + sizeof(container_t);
// if increasing in size, straight up copy.
if (new_size > container->max_count) {
memcpy(
begin, container->begin, (container->object_size * container->max_count)
);
}
// decreasing in size, copy element by element, skipping blank indexes
else {
void *ptr;
unsigned char *target = &begin;
container_reset_iterator(container);
while(ptr = container_get_element() != NULL) {
memcpy((void *)target, ptr, container->object_size)
target += container->object_size;
}
}
free(container);
container = NULL;
new->begin = begin;
new->max_count = new_size;
return new;
}
/**
*
*
*/
void container_destroy(container_t *container)
{
free(container);
container = NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment