Skip to content

Instantly share code, notes, and snippets.

@basp1
Created September 2, 2019 08:10
Show Gist options
  • Save basp1/0851a5ebea97cbf090ac1b1135412509 to your computer and use it in GitHub Desktop.
Save basp1/0851a5ebea97cbf090ac1b1135412509 to your computer and use it in GitHub Desktop.
array
#include "array.h"
#include <assert.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#define HEADER(P) ((array_header_t*)((char*)P - sizeof(array_header_t)))
void* array_new(int length, int value_size)
{
array_header_t* header = (array_header_t*)malloc(sizeof(array_header_t) + value_size * length);
if (NULL == header)
{
return NULL;
}
header->length = length;
header->capacity = length;
header->value_size = value_size;
return header->values;
}
char* array_new_string(const char* str)
{
char* array = array_new(0, sizeof(char));
while (*str)
{
array_push(&array, str++);
}
return array;
}
void array_delete(void* array)
{
if (NULL == array)
{
return;
}
array_header_t* header = HEADER(array);
header->capacity = 0;
header->length = 0;
free(header);
}
void array_clear(void* array)
{
assert(NULL != array);
HEADER(array)->length = 0;
}
void array_setcap(void** array, int cap)
{
assert(NULL != array);
array_header_t* header = HEADER(*array);
assert(cap >= header->capacity);
if (cap == header->capacity)
{
return;
}
header = xrealloc(header, sizeof(array_header_t) + header->value_size * cap);
header->capacity = cap;
*array = header->values;
}
int array_cap(void* array)
{
assert(NULL != array);
return HEADER(array)->capacity;
}
int array_len(void* array)
{
assert(NULL != array);
return HEADER(array)->length;
}
void array_init(void* array, void* value)
{
assert(NULL != array);
int len = HEADER(array)->length;
for (int i = 0; i < len; i++)
{
array_set(array, i, value);
}
}
void* array_get(void* array, int index)
{
assert(NULL != array);
return (char*)array + (HEADER(array)->value_size * index);
}
void array_set(void* array, int index, void* value)
{
assert(NULL != array);
array_header_t* header = HEADER(array);
assert(index < header->length);
memcpy((char*)array + header->value_size * index, value, header->value_size);
}
void array_push(void** array, void* value)
{
assert(NULL != array);
array_header_t* header = HEADER(*array);
if (header->length == header->capacity)
{
int newcap;
if (0 == header->capacity)
{
newcap = 1;
}
else
{
newcap = 2 * header->capacity;
}
array_setcap(array, newcap);
}
header = HEADER(*array);
header->length += 1;
array_set(*array, header->length - 1, value);
}
bool array_pop(void* array, void* p)
{
assert(NULL != array);
assert(NULL != p);
array_header_t* header = HEADER(array);
if (0 == header->length)
{
return false;
}
void* last = array_get(array, header->length - 1);
memcpy(p, last, header->value_size);
header->length -= 1;
return true;
}
void* array_first(void* array)
{
assert(NULL != array);
assert(array_len(array) > 0);
return array_get(array, 0);
}
void* array_last(void* array)
{
assert(NULL != array);
assert(array_len(array) > 0);
return array_get(array, array_len(array) - 1);
}
void array_remove(void* array, int index)
{
assert(NULL != array);
array_header_t* header = HEADER(array);
assert(index < header->length);
if (index < (header->length - 1))
{
memmove
(
(char*)array + header->value_size * index,
(char*)array + header->value_size * (index + 1),
header->value_size * (header->length - index - 1)
);
}
header->length -= 1;
}
void* array_copy(void* array)
{
assert(NULL != array);
array_header_t* header = HEADER(array);
void* copy = array_new(header->length, header->value_size);
memcpy(copy, array, header->value_size * header->length);
return copy;
}
bool array_contains(void* array, void* value)
{
assert(NULL != array);
array_header_t* header = HEADER(array);
for (int i = 0; i < header->length; i++)
{
if (!memcmp(value, (char*)array + header->value_size * i, header->value_size))
{
return true;
}
}
return false;
}
bool array_equals(void* array1, void* array2)
{
assert(NULL != array1);
assert(NULL != array2);
array_header_t* header1 = HEADER(array1);
array_header_t* header2 = HEADER(array2);
if (header1->length != header2->length)
{
return false;
}
if (header1->value_size != header2->value_size)
{
return false;
}
return !memcmp(array1, array2, header1->value_size * header1->length);
}
#undef HEADER
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct array_header_t {
int capacity;
int length;
int value_size;
char values[0];
} array_header_t;
void* array_new(int length, int value_size);
char* array_new_string(const char*);
void array_delete(void* array);
void array_clear(void* array);
void array_setcap(void** array, int);
int array_cap(void* array);
int array_len(void* array);
void array_init(void* array, void*);
void* array_get(void* array, int);
void array_set(void* array, int, void*);
void array_push(void** array, void*);
bool array_pop(void* array, void* p);
void* array_first(void* array);
void* array_last(void* array);
void array_remove(void* array, int);
void* array_copy(void* array);
bool array_contains(void* array, void*);
bool array_equals(void*, void*);
#ifdef __cplusplus
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment