Last active
October 21, 2020 09:57
-
-
Save mrtrizer/fe8b20a9d9ea7f86ca731fd3f1e68888 to your computer and use it in GitHub Desktop.
The main idea is to make serial components access as fast as possible because this is the most usual way to interact with components.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <limits.h> | |
#include <assert.h> | |
#include <stdbool.h> | |
typedef uint32_t EId; | |
typedef struct | |
{ | |
EId* eIds; | |
uint8_t* data; | |
size_t itemSize; | |
size_t length; | |
size_t reserve; | |
size_t i; | |
size_t removedN; | |
void (*deinit)(void*); | |
void* (*realloc)(void *, size_t); | |
} ECDict; | |
static inline bool getCDataIndex(ECDict* dict, size_t* i, EId eId) | |
{ | |
*i = dict->i + 1; | |
if (*i >= dict->length) | |
{ | |
if (dict->length == 0) | |
return false; | |
i = 0; | |
} | |
if (dict->eIds[*i] == eId) | |
return true; | |
else | |
*i = 0; | |
while (true) | |
{ | |
if (dict->eIds[*i] == eId) | |
return true; | |
*i += 1; | |
if (*i == dict->length) | |
return false; | |
} | |
return false; | |
} | |
static inline void* getCData(ECDict* dict, EId eId) | |
{ | |
size_t i; | |
if (getCDataIndex(dict, &i, eId)) | |
{ | |
dict->i = i; | |
return dict->data + i * dict->itemSize; | |
} | |
else | |
{ | |
return NULL; | |
} | |
} | |
void* addC(ECDict* dict, EId eId) | |
{ | |
if (dict->removedN > 0) | |
{ | |
size_t i; | |
assert(getCDataIndex(dict, &i, 0)); | |
dict->eIds[i] = eId; | |
dict->removedN--; | |
return dict->data + i * dict->itemSize; | |
} | |
else | |
{ | |
if (dict->length == dict->reserve) | |
{ | |
dict->reserve += 1000; | |
dict->data = dict->realloc(dict->data, dict->reserve * dict->itemSize); | |
dict->eIds = dict->realloc(dict->eIds, dict->reserve * sizeof(*dict->eIds)); | |
} | |
dict->eIds[dict->length] = eId; | |
return dict->data + dict->itemSize * dict->length++; | |
} | |
} | |
bool removeC(ECDict* dict, EId eId) | |
{ | |
size_t i; | |
if (getCDataIndex(dict, &i, eId)) | |
{ | |
dict->eIds[i] = 0; | |
if (dict->deinit) | |
dict->deinit(dict->data + dict->itemSize * i); | |
dict->removedN++; | |
return true; | |
} | |
return false; | |
} | |
typedef struct | |
{ | |
int x; | |
int y; | |
} TestComponent; | |
void initTestComponent(void* ref, int x, int y) | |
{ | |
TestComponent* c = ref; | |
c->x = x; | |
c->y = y; | |
} | |
void deinitTestComponent(void* ref) | |
{ | |
TestComponent* c = ref; | |
c->x = c->y = 0; | |
} | |
void testSys(ECDict test) | |
{ | |
for (EId* id = test.eIds; id != test.eIds + test.length; id++) | |
{ | |
TestComponent* c = getCData(&test, *id); | |
printf("%lu ( %u ) %d %d\n", id - test.eIds, *id, c->x, c->y); | |
} | |
} | |
int main(void) | |
{ | |
ECDict test = { .itemSize = sizeof(TestComponent), .realloc = realloc, .deinit = deinitTestComponent }; | |
initTestComponent(addC(&test, 1), 10, 20); | |
initTestComponent(addC(&test, 2), 11, 21); | |
assert(test.length == 2); | |
assert(test.reserve == 1000); | |
removeC(&test, 1); | |
initTestComponent(addC(&test, 3), 12, 22); | |
initTestComponent(addC(&test, 4), 13, 23); | |
assert(test.length == 3); | |
testSys(test); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment