93 lines
2.0 KiB
C
93 lines
2.0 KiB
C
|
#ifndef TURBO_LIST_H
|
||
|
#define TURBO_LIST_H
|
||
|
// TODO: malloclike and freelike refactor
|
||
|
|
||
|
#include<stdint.h>
|
||
|
#include<stdlib.h>
|
||
|
#include<assert.h>
|
||
|
|
||
|
#ifndef TL_NOINLINE
|
||
|
#define TL_NOINLINE __attribute__((noinline))
|
||
|
#endif /* TL_NOINLINE */
|
||
|
|
||
|
#ifndef TL_LIKELY
|
||
|
#define TL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||
|
#endif /* TL_LIKELY */
|
||
|
#ifndef TL_UNLIKELY
|
||
|
#define TL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||
|
#endif /* TL_UNLIKELY */
|
||
|
|
||
|
struct turbolist{
|
||
|
int *old;
|
||
|
int *nex;
|
||
|
|
||
|
uint32_t mid; // non-inclusive . . . m
|
||
|
uint32_t end; // non-inclusive e . . . .
|
||
|
|
||
|
uint32_t capacity;
|
||
|
};
|
||
|
typedef struct turbolist turbolist;
|
||
|
|
||
|
static inline void turbolist_insert(turbolist *tl, int elem);
|
||
|
|
||
|
static TL_NOINLINE void __turbolist_grow_and_insert(turbolist *tl, int elem) {
|
||
|
// assert(mid == 0);
|
||
|
if(tl->old) free(tl->old);
|
||
|
tl->old = tl->nex;
|
||
|
tl->mid = tl->end;
|
||
|
tl->capacity *= 2;
|
||
|
tl->nex = (int *) malloc(tl->capacity * sizeof(int));
|
||
|
|
||
|
// Will go into the INSERT code path here
|
||
|
turbolist_insert(tl, elem);
|
||
|
}
|
||
|
|
||
|
static inline turbolist turbolist_create(uint32_t initial_size = 0, uint32_t initial_cap = 16) {
|
||
|
assert(initial_size <= initial_cap);
|
||
|
|
||
|
turbolist tl;
|
||
|
tl.old = NULL;
|
||
|
tl.mid = 0;
|
||
|
tl.end = initial_size;
|
||
|
tl.capacity = initial_cap;
|
||
|
tl.nex = (int *) malloc(tl.capacity * sizeof(int));
|
||
|
return tl;
|
||
|
}
|
||
|
|
||
|
static inline void turbolist_delete(turbolist *tl) {
|
||
|
if(tl->nex) free(tl->nex);
|
||
|
if(tl->old) free(tl->old);
|
||
|
}
|
||
|
|
||
|
static inline int turbolist_get(turbolist *tl, uint32_t i) {
|
||
|
return (i < tl->mid) ? tl->old[i] : tl->nex[i];
|
||
|
}
|
||
|
|
||
|
static inline void turbolist_insert(turbolist *tl, int elem) {
|
||
|
if(TL_LIKELY(tl->end < tl->capacity)) {
|
||
|
|
||
|
// INSERT
|
||
|
|
||
|
/* Same as this:
|
||
|
if(mid > 0) {
|
||
|
nex[mid - 1] = old[mid - 1];
|
||
|
--mid;
|
||
|
}
|
||
|
*/
|
||
|
bool hasmid = (tl->mid > 0);
|
||
|
tl->mid -= hasmid;
|
||
|
tl->nex[tl->mid] = hasmid ? tl->old[tl->mid] : tl->nex[tl->mid];
|
||
|
|
||
|
tl->nex[tl->end++] = elem;
|
||
|
} else {
|
||
|
// GROW
|
||
|
__turbolist_grow_and_insert(tl, elem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline uint32_t turbolist_size(turbolist *tl) {
|
||
|
return tl->mid + (tl->capacity - tl->end - 1);
|
||
|
}
|
||
|
|
||
|
#endif /* TURBO_LIST_H */
|