#include<lexlib/defines.h>
#include<lexlib/vec.h>
#include<lexlib/mem.h>
#include<stdint.h>
#include<string.h>
#include<stdlib.h>
#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;
}