Created
May 2, 2017 19:26
-
-
Save FergusInLondon/1af13353c9a5b369af22905cbdf1f331 to your computer and use it in GitHub Desktop.
Dynamic array/container implementation in C - includes iterator. (WIP / Brain-Dump)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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