Skip to content

Instantly share code, notes, and snippets.

@Xunnamius
Created May 6, 2020 16:57
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 Xunnamius/2fad5f85ae5012681347dae5659e1167 to your computer and use it in GitHub Desktop.
Save Xunnamius/2fad5f85ae5012681347dae5659e1167 to your computer and use it in GitHub Desktop.
C void* vectors
// vector.h
#ifndef VECTOR_H_
#define VECTOR_H_
#include <stdint.h>
#include "cexception_configured.h"
#define VECTOR_GROWTH_FACTOR 2
/**
* Dynamically allocated "growth on demand" array.
*
* @data The data elements stored in the vector
* @size The bytesize of the vector (as void * pouint32_ters)
* @count Number of elements in the vector
*/
typedef struct vector_t
{
const void ** data;
uint32_t size;
uint32_t count;
} vector_t;
/**
* Create a new vector yielded to the vector pointer parameter.
*
* XXX: It is advisable that you do NOT mix different types in the same vector!
*
* This function is O(1).
*
* @param vector
*/
vector_t * vector_init();
/**
* Destroy a vector (free all components). Note that the elements of the vector
* will not themselves be freed. This must be done manually.
*
* This function is O(1).
*
* @param vector
*/
void vector_fini(vector_t * vector);
/**
* Add element to the end of vector.
*
* This function is O(1).
*
* @param vector
* @param element
*/
void vector_add(vector_t * vector, const void * element);
/**
* Delete the element in vector at index.
*
* Note that while the element at the specified index will be removed, the
* element itself will not be free()'d. You'll have to do that manually.
*
* This function is O(n).
*
* @param vector
* @param index
*/
void vector_delete(vector_t * vector, uint32_t index);
/**
* Get the element in vector at index.
*
* This function is O(1).
*
* @param vector
* @param index
*
* @return Void pointer to the requested element
*/
const void * vector_get(vector_t * vector, uint32_t index);
/**
* Set an index in vector to element.
*
* This function is O(1).
*
* @param vector
* @param index
* @param element
*/
void vector_set(vector_t * vector, uint32_t index, const void * element);
#endif
// vector.c
/*
* Dynamically allocated "boundless" array-type so-called vector implementation.
*
* @author Bernard Dickens
*/
#include <stdlib.h>
#include <string.h>
#include "vector.h"
vector_t * vector_init()
{
vector_t * vector = malloc(sizeof(vector_t));
if(vector == NULL)
Throw(EXCEPTION_ALLOC_FAILURE);
vector->data = NULL;
vector->size = 0;
vector->count = 0;
return vector;
}
void vector_fini(vector_t * vector)
{
free(vector->data);
free(vector);
}
void vector_add(vector_t * vector, const void * element)
{
if(vector->size == 0)
{
vector->size = 10;
vector->data = calloc(vector->size, sizeof(void *));
if(vector->data == NULL)
Throw(EXCEPTION_ALLOC_FAILURE);
}
if(vector->size == vector->count)
{
vector->size *= VECTOR_GROWTH_FACTOR;
vector->data = realloc(vector->data, sizeof(void *) * vector->size);
if(vector->data == NULL)
Throw(EXCEPTION_ALLOC_FAILURE);
}
vector->data[vector->count] = element;
vector->count++;
}
void vector_delete(vector_t * vector, uint32_t index)
{
if(index >= vector->count)
Throw(EXCEPTION_OUT_OF_BOUNDS);
for(uint32_t i = index, j = i + 1; j < vector->count; j++, i++)
vector->data[i] = vector->data[j];
vector->count--;
}
const void * vector_get(vector_t * vector, uint32_t index)
{
if(index >= vector->count)
Throw(EXCEPTION_OUT_OF_BOUNDS);
return vector->data[index];
}
void vector_set(vector_t * vector, uint32_t index, const void * element)
{
if(index >= vector->count)
Throw(EXCEPTION_OUT_OF_BOUNDS);
vector->data[index] = element;
}
// test_vector.c
/*
* @author Bernard Dickens
*/
#include <string.h>
#include "unity.h"
#include "vector.h"
#define TRY_FN_CATCH_EXCEPTION(fn_call) \
e_actual = EXCEPTION_NO_EXCEPTION; \
Try \
{ \
fn_call; \
TEST_FAIL(); \
} \
Catch(e_actual) \
TEST_ASSERT_EQUAL_INT(e_expected, e_actual);
static vector_t * vector;
void setUp(void)
{
vector = vector_init();
}
void tearDown(void)
{
vector_fini(vector);
}
void test_vector_functions_throw_exceptions_as_expected(void)
{
CEXCEPTION_T e_expected = EXCEPTION_OUT_OF_BOUNDS;
CEXCEPTION_T e_actual = EXCEPTION_NO_EXCEPTION;
TRY_FN_CATCH_EXCEPTION(vector_delete(vector, 0));
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 0));
TRY_FN_CATCH_EXCEPTION(vector_set(vector, 0, 0));
TRY_FN_CATCH_EXCEPTION(vector_delete(vector, 1));
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 1));
TRY_FN_CATCH_EXCEPTION(vector_set(vector, 1, (int *) 1));
TEST_ASSERT_EQUAL_INT(0, vector->count);
}
void test_vector_add_and_get_perform_as_expected(void)
{
CEXCEPTION_T e_expected = EXCEPTION_OUT_OF_BOUNDS;
CEXCEPTION_T e_actual = EXCEPTION_NO_EXCEPTION;
int i_expected = 5;
int j_expected = 15;
vector_add(vector, &i_expected);
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 0));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 0));
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 1));
vector_add(vector, &i_expected);
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 1));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 1));
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 2));
vector_add(vector, &j_expected);
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 0));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 1));
TEST_ASSERT_EQUAL_INT(j_expected, *(int *) vector_get(vector, 2));
TEST_ASSERT_EQUAL_INT(3, vector->count);
}
void test_vector_delete_removes_element_as_expected(void)
{
CEXCEPTION_T e_expected = EXCEPTION_OUT_OF_BOUNDS;
CEXCEPTION_T e_actual = EXCEPTION_NO_EXCEPTION;
int i_expected = 5;
int j_expected = -55;
int k_expected = 555;
vector_add(vector, &i_expected);
vector_delete(vector, 0);
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 0));
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 1));
TEST_ASSERT_EQUAL_INT(0, vector->count);
vector_add(vector, &i_expected);
vector_add(vector, &j_expected);
vector_add(vector, &k_expected);
vector_delete(vector, 0);
TRY_FN_CATCH_EXCEPTION(vector_get(vector, 2));
TEST_ASSERT_EQUAL_INT(j_expected, *(int *) vector_get(vector, 0));
TEST_ASSERT_EQUAL_INT(k_expected, *(int *) vector_get(vector, 1));
}
void test_vector_set_sets_element_as_expected(void)
{
int i_expected = 5;
int set_expected = -5;
vector_add(vector, &i_expected);
vector_add(vector, &i_expected);
vector_add(vector, &i_expected);
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 1));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 2));
vector_set(vector, 1, &set_expected);
TEST_ASSERT_EQUAL_INT(set_expected, *(int *) vector_get(vector, 1));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 0));
TEST_ASSERT_EQUAL_INT(i_expected, *(int *) vector_get(vector, 2));
}
void test_vector_add_grows_array_size_as_expected(void)
{
int i_expected = 5;
int j_expected = -55;
int k_expected = 555;
for(size_t i = 0; i < 50; ++i)
{
vector_add(vector, &i_expected);
vector_add(vector, &j_expected);
vector_add(vector, &k_expected);
}
TEST_ASSERT_EQUAL_INT(150, vector->count);
TEST_ASSERT_EQUAL_INT(160, vector->size); // XXX: Assuming 2x growth factor
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment