lexlib 2.0.1

library with miscellaneous stuff
Documentation
// Copyright 2023 alexevier <alexevier@proton.me>
// licensed under the zlib license <https://www.zlib.net/zlib_license.html>

#include<lexlib/defines.h>
#include<lexlib/vec.h>
#include<lexlib/mem.h>
#include<stdint.h>
#include<string.h>
#include<stdlib.h>

// the count of elements to expand every time
#define EXTEND 2

struct VecHead {
	size_t len;
	size_t cap;
	size_t tze;
};

void *lexlibVecNew_(size_t len, size_t typeSize){
	size_t size = len * typeSize;
	struct VecHead *head = malloc(size + sizeof(struct VecHead));
	if(!head)
		return NULL;

	head->len = len;
	head->cap = len;
	head->tze = typeSize;

	head++;
	memset(head, 0, size);

	return head;
}

void lexlibVecDelete(void *vec){
	if(!vec)
		return;
	struct VecHead *head = vec;
	head--;
	free(head);
}

void *lexlibVecGet(const void *vec, size_t index){
	const struct VecHead *head = vec;
	head--;

	if(index >= head->len)
		return NULL;

	return (uint8_t*)vec + index * head->tze;
}

int lexlibVecPush_(void **vec, const void *obj){
	struct VecHead *head = *vec;
	head--;

	if(head->len >= head->cap){
		if(lexlibVecResize(vec, head->cap+EXTEND))
			return LEXLIB_OUT_OF_MEMORY;

		head = *vec;
		head--;
	}

	memcpy((uint8_t*)*vec + head->len * head->tze, obj, head->tze);
	head->len++;

	return LEXLIB_OK;
}

void lexlibVecPop(void *vec){
	struct VecHead *head = vec;
	head--;
	if(head->len)
		head->len--;
}

int lexlibVecInsert_(void **vec, size_t index, const void *obj){
	struct VecHead *head = *vec;
	head--;

	if(index > head->len)
		return LEXLIB_INVALID_OPERATION;

	if(head->len >= head->cap){
		if(lexlibVecResize(vec, head->cap+EXTEND))
			return LEXLIB_OUT_OF_MEMORY;

		head = *vec;
		head--;
	}

	size_t size = (head->len - index) * head->tze;
	uint8_t* src = *vec;
	src += index * head->tze;
	uint8_t* dst = src + head->tze;
	memmove(dst, src, size);

	dst -= head->tze;
	memcpy(dst, obj, head->tze);
	head->len++;

	return LEXLIB_OK;
}

int lexlibVecRemove(void *vec, size_t index){
	struct VecHead *head = vec;
	head--;

	if(index >= head->len)
		return LEXLIB_INVALID_OPERATION;

	size_t size = (head->len-1 - index) * head->tze;
	uint8_t* dst = vec;
	dst += index * head->tze;
	uint8_t* src = dst + head->tze;
	memmove(dst, src, size);

	head->len--;

	return LEXLIB_OK;
}

int lexlibVecResize(void **vec, size_t newcap){
	struct VecHead *head = *vec;
	head--;

	if(head->cap == newcap)
		return LEXLIB_OK;

	head = realloc(head, newcap * head->tze + sizeof(struct VecHead));
	if(!head)
		return LEXLIB_OUT_OF_MEMORY;

	head->cap = newcap;
	if(head->len > head->cap)
		head->len = head->cap;

	head++;
	*vec = head;

	return LEXLIB_OK;
}

void *lexlibVecFind(const void *vec, const void *obj){
	const struct VecHead *head = vec;
	head--;

	const uint8_t *bvec = vec;
	for(size_t i = 0; i < head->len; i++){
		if(memcmp(bvec, obj, head->tze) == 0)
			return (void*)bvec;
		bvec += head->tze;
	}

	return NULL;
}

int lexlibVecSwap(void *vec, size_t a, size_t b){
	struct VecHead *head = vec;
	head--;

	if(a >= head->len || b >= head->len)
		return LEXLIB_INVALID_OPERATION;

	uint8_t *pa = vec;
	pa += a * head->tze;
	uint8_t *pb = vec;
	pb += b * head->tze;

	void* tmp = malloc(head->tze);
	if(!tmp)
		return LEXLIB_OUT_OF_MEMORY;

	memcpy(tmp, pa, head->tze);
	memcpy(pa, pb, head->tze);
	memcpy(pb, tmp, head->tze);

	free(tmp);
	return LEXLIB_OK;
}

void lexlibVecClear(void *vec){
	struct VecHead *head = vec;
	head--;

	head->len = 0;
	memset(vec, 0, head->cap * head->tze);
}

size_t lexlibVecLen(const void *vec){
	const struct VecHead *head = vec;
	head--;
	return head->len;
}

size_t lexlibVecCap(const void *vec){
	const struct VecHead *head = vec;
	head--;
	return head->cap;
}