v0.0.1: initial implementation

brnrs 4 years ago
commit b7967a5d5e
  1. 2
      .gitignore
  2. 0
      README.md
  3. 34
      include/barray.h
  4. 1
      include/meson.build
  5. 10
      meson.build
  6. 273
      src/barray.c
  7. 2
      src/meson.build

2
.gitignore vendored

@ -0,0 +1,2 @@
build/
.cache/

@ -0,0 +1,34 @@
#ifndef _BARRAY_H
#define _BARRAY_H
#include <stddef.h>
#include <stdint.h>
typedef struct {
void* ptr;
size_t len;
size_t cap;
size_t elem_size;
} BArray;
typedef enum {
BARRAY_NO_ERR,
BARRAY_ERR_ALLOC_ERR,
BARRAY_ERR_OUT_OF_BOUNDS,
BARRAY_ERR_SIZE_OVERFLOW,
BARRAY_ERR_NULL,
BARRAY_ERR_ELEM_SIZE_ZERO
} BArray_ErrCode;
BArray barray_create(size_t elem_size, size_t initial_cap, BArray_ErrCode* errc);
void barray_grow(BArray* array, BArray_ErrCode* errc);
void barray_grow_to(BArray* array, size_t new_cap, BArray_ErrCode* errc);
void barray_shrink_to_fit(BArray* array, BArray_ErrCode* errc);
void barray_force_shrink(BArray* array, size_t new_cap, BArray_ErrCode* errc);
void* barray_get(BArray* array, size_t ix, BArray_ErrCode* errc);
void barray_set(BArray* array, size_t ix, void* value, BArray_ErrCode* errc);
void barray_put(BArray* array, size_t ix, void* value, BArray_ErrCode* errc);
void barray_append(BArray* array, void* value, BArray_ErrCode* errc);
void barray_remove(BArray* array, size_t ix, BArray_ErrCode* errc);
void barray_clear(BArray* array, BArray_ErrCode* errc);
#endif /* _BARRAY_H */

@ -0,0 +1 @@
include = include_directories('.')

@ -0,0 +1,10 @@
project('barray', 'c',
version: '0.0.1',
meson_version: '>=0.50.0',
default_options: [ 'warning_level=3',
'c_std=c2x',
]
)
subdir('include')
subdir('src')

@ -0,0 +1,273 @@
#include "barray.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static BArray BARRAY_INVALID = { NULL, 0, 0, 0 };
BArray barray_create(size_t elem_size, size_t initial_cap, BArray_ErrCode* errc) {
assert(errc != NULL);
if (elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return BARRAY_INVALID;
}
if (initial_cap == 0) {
*errc = BARRAY_NO_ERR;
return (BArray) { NULL, 0, 0, elem_size };
}
void* ptr = malloc(elem_size * initial_cap);
if (ptr == NULL) {
*errc = BARRAY_ERR_ALLOC_ERR;
return BARRAY_INVALID;
}
*errc = BARRAY_NO_ERR;
return (BArray) { ptr, 0, initial_cap, elem_size };
}
void barray_grow(BArray* array, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
size_t cap = array->cap;
size_t new_cap;
if (cap <= 8) {
new_cap = 16;
} else if (cap <= 16) {
new_cap = 32;
} else if (cap <= 32) {
new_cap = 64;
} else if (cap <= 64) {
new_cap = 128;
} else if (cap <= 128) {
new_cap = 256;
} else if (cap <= 256) {
new_cap = 512;
} else if (cap <= 512) {
new_cap = 1024;
} else {
new_cap = (cap / 512) + (cap % 512 == 0 ? 1 : 2);
if (new_cap < cap) {
*errc = BARRAY_ERR_SIZE_OVERFLOW;
return;
}
}
void* new_ptr = realloc(array->ptr, new_cap * array->elem_size);
if (new_ptr == NULL) {
*errc = BARRAY_ERR_ALLOC_ERR;
return;
}
*errc = BARRAY_NO_ERR;
array->ptr = new_ptr;
array->cap = new_cap;
}
void barray_grow_to(BArray* array, size_t new_cap, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
if (new_cap < array->cap) {
*errc = BARRAY_NO_ERR;
return;
}
void* new_ptr = realloc(array->ptr, new_cap * array->elem_size);
if (new_ptr == NULL) {
*errc = BARRAY_ERR_ALLOC_ERR;
return;
}
*errc = BARRAY_NO_ERR;
array->ptr = new_ptr;
array->cap = new_cap;
}
void barray_shrink_to_fit(BArray* array, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
assert(array->cap >= array->len);
if (array->cap == array->len) {
*errc = BARRAY_NO_ERR;
return;
}
size_t new_cap = array->len;
void* new_ptr = realloc(array->ptr, new_cap * array->elem_size);
if (new_ptr == NULL) {
*errc = BARRAY_ERR_ALLOC_ERR;
return;
}
*errc = BARRAY_NO_ERR;
array->ptr = new_ptr;
array->cap = new_cap;
}
void barray_force_shrink(BArray* array, size_t new_cap, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
if (new_cap >= array->cap) {
*errc = BARRAY_NO_ERR;
return;
}
void* new_ptr = realloc(array->ptr, new_cap * array->elem_size);
if (new_ptr == NULL) {
*errc = BARRAY_ERR_ALLOC_ERR;
return;
}
*errc = BARRAY_NO_ERR;
array->ptr = new_ptr;
array->cap = new_cap;
array->len = new_cap;
}
void* barray_get(BArray* array, size_t ix, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return NULL;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return NULL;
}
if (ix >= array->len) {
*errc = BARRAY_ERR_OUT_OF_BOUNDS;
return NULL;
}
*errc = BARRAY_NO_ERR;
unsigned char* ptr = array->ptr;
return (void*) &ptr[(ix * array->elem_size)];
}
void barray_set(BArray* array, size_t ix, void* value, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
if (ix >= array->len) {
*errc = BARRAY_ERR_OUT_OF_BOUNDS;
return;
}
if (value == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
*errc = BARRAY_NO_ERR;
unsigned char* ptr = array->ptr;
void* elem_ptr = (void*) &ptr[(ix * array->elem_size)];
memcpy(elem_ptr, value, array->elem_size);
}
void barray_put(BArray* array, size_t ix, void* value, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
if (ix > array->len) {
*errc = BARRAY_ERR_OUT_OF_BOUNDS;
return;
}
if (value == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->cap > (array->len + 1)) {
barray_grow(array, errc);
if (*errc != BARRAY_NO_ERR) {
return;
}
}
unsigned char* ptr = array->ptr;
if (ix == array->len) {
goto nomove;
}
void* src = (void*) &ptr[(ix * array->elem_size)];
void* dest = (void*) &ptr[((ix + 1) * array->elem_size)];
memmove(dest, src, array->elem_size * (array->len - ix));
nomove:
*errc = BARRAY_NO_ERR;
void* elem_ptr = (void*) &ptr[(ix * array->elem_size)];
memcpy(elem_ptr, value, array->elem_size);
array->len = array->len + 1;
}
void barray_append(BArray* array, void* value, BArray_ErrCode* errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
barray_put(array, array->len, value, errc);
}
void barray_remove(BArray *array, size_t ix, BArray_ErrCode *errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
if (array->elem_size == 0) {
*errc = BARRAY_ERR_ELEM_SIZE_ZERO;
return;
}
if (ix >= array->len) {
*errc = BARRAY_ERR_OUT_OF_BOUNDS;
return;
}
unsigned char* ptr = array->ptr;
if (ix == array->len) {
goto nomove;
}
void* src = (void*) &ptr[(ix * array->elem_size)];
void* dest = (void*) &ptr[((ix - 1) * array->elem_size)];
memmove(dest, src, array->elem_size * (array->len - ix));
nomove:
*errc = BARRAY_NO_ERR;
array->len = array->len - 1;
}
void barray_clear(BArray *array, BArray_ErrCode *errc) {
assert(errc != NULL);
if (array == NULL) {
*errc = BARRAY_ERR_NULL;
return;
}
*errc = BARRAY_NO_ERR;
array->len = 0;
}

@ -0,0 +1,2 @@
src = ['barray.c']
library('barray', src, include_directories: include)
Loading…
Cancel
Save