big ahh recession

This commit is contained in:
IonutParau 2025-07-02 21:29:59 +02:00
parent 5c3ec01a5a
commit 0961fc0ceb
20 changed files with 399 additions and 204 deletions

View File

@ -0,0 +1,18 @@
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')
boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth')

View File

@ -2,36 +2,45 @@
#include <string.h> #include <string.h>
#include "component.h" #include "component.h"
nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor) { nn_componentTable *nn_newComponentTable(nn_Alloc *alloc, const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor) {
nn_componentTable *table = nn_malloc(sizeof(nn_componentTable)); nn_componentTable *table = nn_alloc(alloc, sizeof(nn_componentTable));
table->name = nn_strdup(typeName); if(table == NULL) {
return NULL;
}
table->name = nn_strdup(alloc, typeName);
if(table->name == NULL) {
nn_dealloc(alloc, table, sizeof(nn_componentTable));
return NULL;
}
table->userdata = userdata; table->userdata = userdata;
table->constructor = constructor; table->constructor = constructor;
table->destructor = destructor; table->destructor = destructor;
table->methodCount = 0; table->methodCount = 0;
table->alloc = *alloc;
return table; return table;
} }
void nn_destroyComponentTable(nn_componentTable *table) { void nn_destroyComponentTable(nn_componentTable *table) {
nn_free(table->name); nn_Alloc alloc = table->alloc;
nn_deallocStr(&alloc, table->name);
for(size_t i = 0; i < table->methodCount; i++) { for(size_t i = 0; i < table->methodCount; i++) {
nn_method method = table->methods[i]; nn_method method = table->methods[i];
nn_free(method.name); nn_deallocStr(&alloc, method.name);
nn_free(method.doc); nn_deallocStr(&alloc, method.doc);
} }
nn_free(table); nn_dealloc(&alloc, table, sizeof(nn_componentTable));
} }
void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc) { void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc) {
if(table->methodCount == NN_MAX_METHODS) return; if(table->methodCount == NN_MAX_METHODS) return;
nn_method method; nn_method method;
method.method = methodFunc; method.method = methodFunc;
method.name = nn_strdup(methodName); method.name = nn_strdup(&table->alloc, methodName);
if(method.name == NULL) return; if(method.name == NULL) return;
method.direct = direct; method.direct = direct;
method.doc = nn_strdup(methodDoc); method.doc = nn_strdup(&table->alloc, methodDoc);
if(method.doc == NULL) { if(method.doc == NULL) {
nn_free(method.name); nn_deallocStr(&table->alloc, method.name);
return; return;
} }
method.userdata = methodUserdata; method.userdata = methodUserdata;

View File

@ -14,6 +14,7 @@ typedef struct nn_method {
typedef struct nn_componentTable { typedef struct nn_componentTable {
char *name; char *name;
nn_Alloc alloc;
void *userdata; void *userdata;
nn_componentConstructor *constructor; nn_componentConstructor *constructor;
nn_componentDestructor *destructor; nn_componentDestructor *destructor;

View File

@ -21,7 +21,7 @@ void nn_drive_getLabel(nn_drive *drive, void *_, nn_component *component, nn_com
if(l == 0) { if(l == 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
} }
} }
void nn_drive_setLabel(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { void nn_drive_setLabel(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) {
@ -33,7 +33,7 @@ void nn_drive_setLabel(nn_drive *drive, void *_, nn_component *component, nn_com
return; return;
} }
l = drive->setLabel(component, drive->userdata, buf, l); l = drive->setLabel(component, drive->userdata, buf, l);
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
} }
void nn_drive_getSectorSize(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { void nn_drive_getSectorSize(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) {
size_t sector_size = drive->getSectorSize(component, drive->userdata); size_t sector_size = drive->getSectorSize(component, drive->userdata);
@ -53,7 +53,7 @@ void nn_drive_readSector(nn_drive *drive, void *_, nn_component *component, nn_c
size_t sector_size = drive->getSectorSize(component, drive->userdata); size_t sector_size = drive->getSectorSize(component, drive->userdata);
char buf[sector_size]; char buf[sector_size];
drive->readSector(component, drive->userdata, sector, buf); drive->readSector(component, drive->userdata, sector, buf);
nn_return(computer, nn_values_string(buf, sector_size)); nn_return_string(computer, buf, sector_size);
} }
void nn_drive_writeSector(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { void nn_drive_writeSector(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) {
nn_value sectorValue = nn_getArgument(computer, 0); nn_value sectorValue = nn_getArgument(computer, 0);
@ -93,7 +93,7 @@ void nn_drive_writeByte(nn_drive *drive, void *_, nn_component *component, nn_co
} }
void nn_loadDriveTable(nn_universe *universe) { void nn_loadDriveTable(nn_universe *universe) {
nn_componentTable *driveTable = nn_newComponentTable("drive", NULL, NULL, (void *)nn_drive_destroy); nn_componentTable *driveTable = nn_newComponentTable(nn_getAllocator(universe), "drive", NULL, NULL, (void *)nn_drive_destroy);
nn_storeUserdata(universe, "NN:DRIVE", driveTable); nn_storeUserdata(universe, "NN:DRIVE", driveTable);
nn_defineMethod(driveTable, "getLabel", false, (void *)nn_drive_getLabel, NULL, "getLabel():string - Get the current label of the drive."); nn_defineMethod(driveTable, "getLabel", false, (void *)nn_drive_getLabel, NULL, "getLabel():string - Get the current label of the drive.");

View File

@ -41,7 +41,7 @@ void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
if(l == 0) { if(l == 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
} }
// Latency, energy costs and stuff // Latency, energy costs and stuff
@ -61,7 +61,7 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
return; return;
} }
l = eeprom->setLabel(component, eeprom->userdata, buf, l); l = eeprom->setLabel(component, eeprom->userdata, buf, l);
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
// Latency, energy costs and stuff // Latency, energy costs and stuff
nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_eepromControl control = nn_eeprom_getControl(component, eeprom);
@ -74,14 +74,15 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_
void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
size_t cap = eeprom->getSize(component, eeprom->userdata); size_t cap = eeprom->getSize(component, eeprom->userdata);
char *buf = nn_malloc(cap); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
} }
size_t len = eeprom->get(component, eeprom->userdata, buf); size_t len = eeprom->get(component, eeprom->userdata, buf);
nn_return(computer, nn_values_string(buf, len)); nn_return_string(computer, buf, len);
nn_free(buf); nn_dealloc(alloc, buf, cap);
nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_eepromControl control = nn_eeprom_getControl(component, eeprom);
nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax);
@ -119,7 +120,8 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
size_t cap = eeprom->getDataSize(component, eeprom->userdata); size_t cap = eeprom->getDataSize(component, eeprom->userdata);
char *buf = nn_malloc(cap); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
@ -128,9 +130,9 @@ void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c
if(len < 0) { if(len < 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
nn_return(computer, nn_values_string(buf, len)); nn_return_string(computer, buf, len);
} }
nn_free(buf); nn_dealloc(alloc, buf, cap);
nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_eepromControl control = nn_eeprom_getControl(component, eeprom);
nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax);
@ -178,7 +180,8 @@ void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component,
// TODO: make good // TODO: make good
void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) {
size_t cap = eeprom->getDataSize(component, eeprom->userdata); size_t cap = eeprom->getDataSize(component, eeprom->userdata);
char *buf = nn_malloc(cap); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, cap);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
@ -188,9 +191,9 @@ void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component,
for(size_t i = 0; i < len; i++) { for(size_t i = 0; i < len; i++) {
sum += buf[i]; sum += buf[i];
} }
nn_free(buf); nn_dealloc(alloc, buf, cap);
nn_return(computer, nn_values_string((void *)&sum, sizeof(sum))); nn_return_string(computer, (void *)&sum, sizeof(sum));
nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_eepromControl control = nn_eeprom_getControl(component, eeprom);
nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax);
@ -200,7 +203,7 @@ void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component,
} }
void nn_loadEepromTable(nn_universe *universe) { void nn_loadEepromTable(nn_universe *universe) {
nn_componentTable *eepromTable = nn_newComponentTable("eeprom", NULL, NULL, (void *)nn_eeprom_destroy); nn_componentTable *eepromTable = nn_newComponentTable(nn_getAllocator(universe), "eeprom", NULL, NULL, (void *)nn_eeprom_destroy);
nn_storeUserdata(universe, "NN:EEPROM", eepromTable); nn_storeUserdata(universe, "NN:EEPROM", eepromTable);
nn_defineMethod(eepromTable, "getSize", true, (void *)nn_eeprom_getSize, NULL, "getSize(): integer - Returns the maximum code capacity of the EEPROM."); nn_defineMethod(eepromTable, "getSize", true, (void *)nn_eeprom_getSize, NULL, "getSize(): integer - Returns the maximum code capacity of the EEPROM.");

View File

@ -69,7 +69,7 @@ void nn_fs_getLabel(nn_filesystem *fs, void *_, nn_component *component, nn_comp
if(l == 0) { if(l == 0) {
nn_return(computer, nn_values_nil()); nn_return(computer, nn_values_nil());
} else { } else {
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
} }
// Latency, energy costs and stuff // Latency, energy costs and stuff
@ -89,7 +89,7 @@ void nn_fs_setLabel(nn_filesystem *fs, void *_, nn_component *component, nn_comp
return; return;
} }
l = fs->setLabel(component, fs->userdata, buf, l); l = fs->setLabel(component, fs->userdata, buf, l);
nn_return(computer, nn_values_string(buf, l)); nn_return_string(computer, buf, l);
nn_fs_readCost(fs, 1, component, computer); nn_fs_readCost(fs, 1, component, computer);
} }
@ -270,18 +270,20 @@ void nn_fs_list(nn_filesystem *fs, void *_, nn_component *component, nn_computer
nn_setCError(computer, "bad path (illegal path)"); nn_setCError(computer, "bad path (illegal path)");
return; return;
} }
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
size_t fileCount = 0; size_t fileCount = 0;
char **files = fs->list(component, fs->userdata, path, &fileCount); char **files = fs->list(alloc, component, fs->userdata, path, &fileCount);
if(files != NULL) { if(files != NULL) {
// operation succeeded // operation succeeded
nn_value arr = nn_values_array(fileCount); nn_value arr = nn_values_array(alloc, fileCount);
for(size_t i = 0; i < fileCount; i++) { for(size_t i = 0; i < fileCount; i++) {
nn_values_set(arr, i, nn_values_string(files[i], strlen(files[i]))); nn_values_set(arr, i, nn_values_string(alloc, files[i], strlen(files[i])));
nn_free(files[i]); nn_deallocStr(alloc, files[i]);
} }
nn_free(files); nn_dealloc(alloc, files, sizeof(char *) * fileCount);
nn_return(computer, arr); nn_return(computer, arr);
} }
@ -356,7 +358,8 @@ void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer
if(len > capacity) len = capacity; if(len > capacity) len = capacity;
size_t byteLen = len; size_t byteLen = len;
char *buf = nn_malloc(byteLen); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
char *buf = nn_alloc(alloc, byteLen);
if(buf == NULL) { if(buf == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
@ -365,9 +368,9 @@ void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer
size_t readLen = fs->read(component, fs->userdata, fd, buf, byteLen); size_t readLen = fs->read(component, fs->userdata, fd, buf, byteLen);
if(readLen > 0) { if(readLen > 0) {
// Nothing read means EoF. // Nothing read means EoF.
nn_return(computer, nn_values_string(buf, readLen)); nn_return_string(computer, buf, readLen);
} }
nn_free(buf); nn_dealloc(alloc, buf, byteLen);
// do not ask where it comes from, balance is hard // do not ask where it comes from, balance is hard
nn_fs_readCost(fs, nn_fs_countChunks(fs, readLen, component), component, computer); nn_fs_readCost(fs, nn_fs_countChunks(fs, readLen, component), component, computer);
@ -410,7 +413,7 @@ void nn_fs_seek(nn_filesystem *fs, void *_, nn_component *component, nn_computer
} }
void nn_loadFilesystemTable(nn_universe *universe) { void nn_loadFilesystemTable(nn_universe *universe) {
nn_componentTable *fsTable = nn_newComponentTable("filesystem", NULL, NULL, (void *)nn_fs_destroy); nn_componentTable *fsTable = nn_newComponentTable(nn_getAllocator(universe), "filesystem", NULL, NULL, (void *)nn_fs_destroy);
nn_storeUserdata(universe, "NN:FILESYSTEM", fsTable); nn_storeUserdata(universe, "NN:FILESYSTEM", fsTable);
nn_defineMethod(fsTable, "getLabel", false, (void *)nn_fs_getLabel, NULL, "getLabel(): string - Returns the label of the filesystem."); nn_defineMethod(fsTable, "getLabel", false, (void *)nn_fs_getLabel, NULL, "getLabel(): string - Returns the label of the filesystem.");

View File

@ -4,6 +4,7 @@
#include <string.h> #include <string.h>
typedef struct nni_gpu { typedef struct nni_gpu {
nn_Alloc alloc;
nn_screen *currentScreen; nn_screen *currentScreen;
nn_address screenAddress; nn_address screenAddress;
nn_gpuControl ctrl; nn_gpuControl ctrl;
@ -34,8 +35,10 @@ bool nni_inBounds(nni_gpu *gpu, int x, int y) {
true; true;
} }
nni_gpu *nni_newGPU(nn_gpuControl *ctrl) { nni_gpu *nni_newGPU(nn_Alloc *alloc, nn_gpuControl *ctrl) {
nni_gpu *gpu = nn_malloc(sizeof(nni_gpu)); nni_gpu *gpu = nn_alloc(alloc, sizeof(nni_gpu));
if(gpu == NULL) return NULL;
gpu->alloc = *alloc;
gpu->currentScreen = NULL; gpu->currentScreen = NULL;
gpu->screenAddress = NULL; gpu->screenAddress = NULL;
gpu->ctrl = *ctrl; gpu->ctrl = *ctrl;
@ -50,10 +53,11 @@ void nni_gpuDeinit(nni_gpu *gpu) {
if(gpu->currentScreen != NULL) { if(gpu->currentScreen != NULL) {
nn_destroyScreen(gpu->currentScreen); nn_destroyScreen(gpu->currentScreen);
} }
nn_Alloc a = gpu->alloc;
if(gpu->screenAddress != NULL) { if(gpu->screenAddress != NULL) {
nn_free(gpu->screenAddress); nn_deallocStr(&a, gpu->screenAddress);
} }
nn_free(gpu); nn_dealloc(&a, gpu, sizeof(nni_gpu));
} }
nn_scrchr_t nni_gpu_makePixel(nni_gpu *gpu, const char *s) { nn_scrchr_t nni_gpu_makePixel(nni_gpu *gpu, const char *s) {
@ -111,9 +115,9 @@ void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
gpu->currentScreen = screen; gpu->currentScreen = screen;
if(gpu->screenAddress != NULL) { if(gpu->screenAddress != NULL) {
nn_free(gpu->screenAddress); nn_deallocStr(&gpu->alloc, gpu->screenAddress);
} }
gpu->screenAddress = nn_strdup(addr); gpu->screenAddress = nn_strdup(&gpu->alloc, addr);
nn_addHeat(computer, gpu->ctrl.bindHeat); nn_addHeat(computer, gpu->ctrl.bindHeat);
nn_callCost(computer, gpu->ctrl.bindCost); nn_callCost(computer, gpu->ctrl.bindCost);
@ -170,7 +174,7 @@ void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co
void nni_gpu_getScreen(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_getScreen(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
if(gpu->screenAddress == NULL) return; if(gpu->screenAddress == NULL) return;
nn_return(computer, nn_values_string(gpu->screenAddress, 0)); nn_return_string(computer, gpu->screenAddress, 0);
} }
void nni_gpu_maxResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { void nni_gpu_maxResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) {
@ -360,7 +364,7 @@ void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
int changes = 0, clears = 0; int changes = 0, clears = 0;
nn_scrchr_t *tmpBuffer = nn_malloc(sizeof(nn_scrchr_t) * w * h); nn_scrchr_t *tmpBuffer = nn_alloc(&gpu->alloc, sizeof(nn_scrchr_t) * w * h);
if(tmpBuffer == NULL) { if(tmpBuffer == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
@ -388,7 +392,7 @@ void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c
} }
} }
nn_free(tmpBuffer); nn_dealloc(&gpu->alloc, tmpBuffer, sizeof(nn_scrchr_t) * w * h);
nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes); nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes);
nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes); nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes);
@ -411,7 +415,7 @@ void nni_gpu_getViewport(nni_gpu *gpu, void *_, nn_component *component, nn_comp
} }
void nn_loadGraphicsCardTable(nn_universe *universe) { void nn_loadGraphicsCardTable(nn_universe *universe) {
nn_componentTable *gpuTable = nn_newComponentTable("gpu", NULL, NULL, (void *)nni_gpuDeinit); nn_componentTable *gpuTable = nn_newComponentTable(nn_getAllocator(universe), "gpu", NULL, NULL, (void *)nni_gpuDeinit);
nn_storeUserdata(universe, "NN:GPU", gpuTable); nn_storeUserdata(universe, "NN:GPU", gpuTable);
nn_defineMethod(gpuTable, "bind", false, (void *)nni_gpu_bind, NULL, "bind(addr: string[, reset: boolean = false]): boolean - Bind a GPU to a screen. Very expensive. If reset is true, it will clear the screen."); nn_defineMethod(gpuTable, "bind", false, (void *)nni_gpu_bind, NULL, "bind(addr: string[, reset: boolean = false]): boolean - Bind a GPU to a screen. Very expensive. If reset is true, it will clear the screen.");
@ -432,7 +436,7 @@ void nn_loadGraphicsCardTable(nn_universe *universe) {
nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) { nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) {
nn_componentTable *gpuTable = nn_queryUserdata(nn_getUniverse(computer), "NN:GPU"); nn_componentTable *gpuTable = nn_queryUserdata(nn_getUniverse(computer), "NN:GPU");
nni_gpu *gpu = nni_newGPU(control); nni_gpu *gpu = nni_newGPU(nn_getAllocator(nn_getUniverse(computer)), control);
if(gpu == NULL) { if(gpu == NULL) {
return NULL; return NULL;
} }

View File

@ -1,7 +1,7 @@
#include "../neonucleus.h" #include "../neonucleus.h"
void nn_loadKeyboardTable(nn_universe *universe) { void nn_loadKeyboardTable(nn_universe *universe) {
nn_componentTable *keyboardTable = nn_newComponentTable("keyboard", NULL, NULL, NULL); nn_componentTable *keyboardTable = nn_newComponentTable(nn_getAllocator(universe), "keyboard", NULL, NULL, NULL);
nn_storeUserdata(universe, "NN:KEYBOARD", keyboardTable); nn_storeUserdata(universe, "NN:KEYBOARD", keyboardTable);
} }

View File

@ -1,10 +1,11 @@
#include "screen.h" #include "screen.h"
#include <string.h> #include <string.h>
nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) { nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) {
nn_screen *screen = nn_malloc(sizeof(nn_screen)); nn_screen *screen = nn_alloc(alloc, sizeof(nn_screen));
screen->buffer = nn_malloc(sizeof(nn_scrchr_t) * maxWidth * maxHeight); screen->alloc = *alloc;
screen->lock = nn_newGuard(); screen->buffer = nn_alloc(alloc, sizeof(nn_scrchr_t) * maxWidth * maxHeight);
screen->lock = nn_newGuard(alloc);
screen->refc = 1; screen->refc = 1;
screen->width = maxWidth; screen->width = maxWidth;
screen->height = maxHeight; screen->height = maxHeight;
@ -16,7 +17,7 @@ nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableC
screen->depth = maxDepth; screen->depth = maxDepth;
screen->editableColors = editableColors; screen->editableColors = editableColors;
screen->paletteColors = paletteColors; screen->paletteColors = paletteColors;
screen->palette = nn_malloc(sizeof(int) * screen->paletteColors); screen->palette = nn_alloc(alloc, sizeof(int) * screen->paletteColors);
memset(screen->palette, 0, sizeof(int) * screen->paletteColors); memset(screen->palette, 0, sizeof(int) * screen->paletteColors);
screen->aspectRatioWidth = 1; screen->aspectRatioWidth = 1;
screen->aspectRatioHeight = 1; screen->aspectRatioHeight = 1;
@ -34,10 +35,11 @@ void nn_retainScreen(nn_screen *screen) {
void nn_destroyScreen(nn_screen *screen) { void nn_destroyScreen(nn_screen *screen) {
if(!nn_decRef(&screen->refc)) return; if(!nn_decRef(&screen->refc)) return;
nn_deleteGuard(screen->lock); nn_Alloc a = screen->alloc;
nn_free(screen->buffer); nn_deleteGuard(&a, screen->lock);
nn_free(screen->palette); nn_dealloc(&a, screen->buffer, sizeof(nn_scrchr_t) * screen->maxWidth * screen->maxHeight);
nn_free(screen); nn_dealloc(&a, screen->palette, sizeof(int) * screen->paletteColors);
nn_dealloc(&a, screen, sizeof(nn_screen));
} }
void nn_lockScreen(nn_screen *screen) { void nn_lockScreen(nn_screen *screen) {
@ -85,14 +87,14 @@ void nn_setAspectRatio(nn_screen *screen, int width, int height) {
void nn_addKeyboard(nn_screen *screen, nn_address address) { void nn_addKeyboard(nn_screen *screen, nn_address address) {
if(screen->keyboardCount == NN_MAX_SCREEN_KEYBOARDS) return; if(screen->keyboardCount == NN_MAX_SCREEN_KEYBOARDS) return;
screen->keyboards[screen->keyboardCount++] = nn_strdup(address); screen->keyboards[screen->keyboardCount++] = nn_strdup(&screen->alloc, address);
} }
void nn_removeKeyboard(nn_screen *screen, nn_address address) { void nn_removeKeyboard(nn_screen *screen, nn_address address) {
size_t j = 0; size_t j = 0;
for(size_t i = 0; i < screen->keyboardCount; i++) { for(size_t i = 0; i < screen->keyboardCount; i++) {
if(strcmp(screen->keyboards[i], address) == 0) { if(strcmp(screen->keyboards[i], address) == 0) {
nn_free(screen->keyboards[i]); nn_deallocStr(&screen->alloc, screen->keyboards[i]);
} else { } else {
screen->keyboards[j] = screen->keyboards[i]; screen->keyboards[j] = screen->keyboards[i];
j++; j++;
@ -206,12 +208,12 @@ void nn_screenComp_destroy(void *_, nn_component *component, nn_screen *screen)
void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *component, nn_computer *computer) { void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *component, nn_computer *computer) {
nn_lockScreen(screen); nn_lockScreen(screen);
nn_value arr = nn_values_array(nn_getKeyboardCount(screen)); nn_value arr = nn_values_array(&screen->alloc, nn_getKeyboardCount(screen));
size_t len = arr.array->len; size_t len = arr.array->len;
for(size_t i = 0; i < len; i++) { for(size_t i = 0; i < len; i++) {
size_t addrlen = strlen(nn_getKeyboard(screen, i)); size_t addrlen = strlen(nn_getKeyboard(screen, i));
nn_value addr = nn_values_string(nn_getKeyboard(screen, i), addrlen); nn_value addr = nn_values_string(&screen->alloc, nn_getKeyboard(screen, i), addrlen);
nn_values_set(arr, i, addr); nn_values_set(arr, i, addr);
} }
@ -220,7 +222,7 @@ void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *compon
} }
void nn_loadScreenTable(nn_universe *universe) { void nn_loadScreenTable(nn_universe *universe) {
nn_componentTable *screenTable = nn_newComponentTable("screen", NULL, NULL, (void *)nn_screenComp_destroy); nn_componentTable *screenTable = nn_newComponentTable(nn_getAllocator(universe), "screen", NULL, NULL, (void *)nn_screenComp_destroy);
nn_storeUserdata(universe, "NN:SCREEN", screenTable); nn_storeUserdata(universe, "NN:SCREEN", screenTable);
nn_defineMethod(screenTable, "getKeyboards", false, (void *)nn_screenComp_getKeyboards, NULL, "getKeyboards(): string[] - Returns the keyboards registered to this screen."); nn_defineMethod(screenTable, "getKeyboards", false, (void *)nn_screenComp_getKeyboards, NULL, "getKeyboards(): string[] - Returns the keyboards registered to this screen.");

View File

@ -4,6 +4,7 @@
#include "../neonucleus.h" #include "../neonucleus.h"
typedef struct nn_screen { typedef struct nn_screen {
nn_Alloc alloc;
nn_scrchr_t *buffer; nn_scrchr_t *buffer;
nn_guard *lock; nn_guard *lock;
nn_refc refc; nn_refc refc;

View File

@ -1,26 +1,27 @@
#include "computer.h" #include "computer.h"
#include "component.h" #include "component.h"
#include "universe.h"
#include "neonucleus.h" #include "neonucleus.h"
#include <string.h> #include <string.h>
nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit) { nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit) {
nn_computer *c = nn_malloc(sizeof(nn_computer)); nn_computer *c = nn_alloc(&universe->alloc, sizeof(nn_computer));
c->components = nn_malloc(sizeof(nn_component) * componentLimit); c->components = nn_alloc(&universe->alloc, sizeof(nn_component) * componentLimit);
if(c->components == NULL) { if(c->components == NULL) {
nn_free(c); nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
return NULL; return NULL;
} }
c->address = nn_strdup(address); c->address = nn_strdup(&universe->alloc, address);
if(c->address == NULL) { if(c->address == NULL) {
nn_free(c->components); nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
nn_free(c); nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
return NULL; return NULL;
} }
c->lock = nn_newGuard(); c->lock = nn_newGuard(&universe->alloc);
if(c->lock == NULL) { if(c->lock == NULL) {
nn_free(c->address); nn_deallocStr(&universe->alloc, c->address);
nn_free(c->components); nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
nn_free(c); nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
return NULL; return NULL;
} }
c->timeOffset = nn_getTime(universe); c->timeOffset = nn_getTime(universe);
@ -50,10 +51,10 @@ nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_archit
// Setup Architecture // Setup Architecture
c->archState = c->arch->setup(c, c->arch->userdata); c->archState = c->arch->setup(c, c->arch->userdata);
if(c->archState == NULL) { if(c->archState == NULL) {
nn_deleteGuard(c->lock); nn_deleteGuard(&universe->alloc, c->lock);
nn_free(c->address); nn_deallocStr(&universe->alloc, c->address);
nn_free(c->components); nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit);
nn_free(c); nn_dealloc(&universe->alloc, c, sizeof(nn_computer));
return NULL; return NULL;
} }
@ -65,8 +66,8 @@ nn_universe *nn_getUniverse(nn_computer *computer) {
} }
void nn_setTmpAddress(nn_computer *computer, nn_address tmp) { void nn_setTmpAddress(nn_computer *computer, nn_address tmp) {
nn_free(computer->tmpAddress); nn_deallocStr(&computer->universe->alloc, computer->tmpAddress);
computer->tmpAddress = nn_strdup(tmp); computer->tmpAddress = nn_strdup(&computer->universe->alloc, tmp);
} }
nn_address nn_getComputerAddress(nn_computer *computer) { nn_address nn_getComputerAddress(nn_computer *computer) {
@ -130,15 +131,15 @@ void nn_deleteComputer(nn_computer *computer) {
while(computer->signalCount > 0) { while(computer->signalCount > 0) {
nn_popSignal(computer); nn_popSignal(computer);
} }
nn_Alloc *a = &computer->universe->alloc;
for(size_t i = 0; i < computer->userCount; i++) { for(size_t i = 0; i < computer->userCount; i++) {
nn_free(computer->users[i]); nn_deallocStr(a, computer->users[i]);
} }
computer->arch->teardown(computer, computer->archState, computer->arch->userdata); computer->arch->teardown(computer, computer->archState, computer->arch->userdata);
nn_deleteGuard(computer->lock); nn_deleteGuard(a, computer->lock);
nn_free(computer->components); nn_deallocStr(a, computer->address);
nn_free(computer->address); nn_dealloc(a, computer->components, sizeof(nn_component) * computer->componentCap);
nn_free(computer->tmpAddress); nn_dealloc(a, computer->components, sizeof(nn_computer));
nn_free(computer);
} }
const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len) { const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len) {
@ -183,7 +184,7 @@ void nn_popSignal(nn_computer *computer) {
const char *nn_addUser(nn_computer *computer, const char *name) { const char *nn_addUser(nn_computer *computer, const char *name) {
if(computer->userCount == NN_MAX_USERS) return "too many users"; if(computer->userCount == NN_MAX_USERS) return "too many users";
char *user = nn_strdup(name); char *user = nn_strdup(&computer->universe->alloc, name);
if(user == NULL) return "out of memory"; if(user == NULL) return "out of memory";
computer->users[computer->userCount] = user; computer->users[computer->userCount] = user;
computer->userCount++; computer->userCount++;
@ -195,7 +196,7 @@ void nn_deleteUser(nn_computer *computer, const char *name) {
for(size_t i = 0; i < computer->userCount; i++) { for(size_t i = 0; i < computer->userCount; i++) {
char *user = computer->users[i]; char *user = computer->users[i];
if(strcmp(user, name) == 0) { if(strcmp(user, name) == 0) {
nn_free(user); nn_deallocStr(&computer->universe->alloc, user);
} else { } else {
computer->users[j] = user; computer->users[j] = user;
j++; j++;
@ -322,7 +323,7 @@ const char *nn_getError(nn_computer *computer) {
void nn_clearError(nn_computer *computer) { void nn_clearError(nn_computer *computer) {
if(computer->allocatedError) { if(computer->allocatedError) {
nn_free(computer->err); nn_deallocStr(&computer->universe->alloc, computer->err);
} }
computer->err = NULL; computer->err = NULL;
computer->allocatedError = false; computer->allocatedError = false;
@ -330,7 +331,7 @@ void nn_clearError(nn_computer *computer) {
void nn_setError(nn_computer *computer, const char *err) { void nn_setError(nn_computer *computer, const char *err) {
nn_clearError(computer); nn_clearError(computer);
char *copy = nn_strdup(err); char *copy = nn_strdup(&computer->universe->alloc, err);
if(copy == NULL) { if(copy == NULL) {
nn_setCError(computer, "out of memory"); nn_setCError(computer, "out of memory");
return; return;
@ -360,7 +361,7 @@ nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slo
computer->componentLen++; computer->componentLen++;
} }
c->address = nn_strdup(address); c->address = nn_strdup(&computer->universe->alloc, address);
if(c->address == NULL) return NULL; if(c->address == NULL) return NULL;
c->table = table; c->table = table;
c->slot = slot; c->slot = slot;
@ -382,7 +383,7 @@ void nn_removeComponent(nn_computer *computer, nn_address address) {
} }
void nn_destroyComponent(nn_component *component) { void nn_destroyComponent(nn_component *component) {
nn_free(component->address); nn_deallocStr(&component->computer->universe->alloc, component->address);
if(component->table->destructor != NULL) { if(component->table->destructor != NULL) {
component->table->destructor(component->table->userdata, component, component->statePtr); component->table->destructor(component->table->userdata, component, component->statePtr);
} }
@ -391,6 +392,7 @@ void nn_destroyComponent(nn_component *component) {
nn_component *nn_findComponent(nn_computer *computer, nn_address address) { nn_component *nn_findComponent(nn_computer *computer, nn_address address) {
for(size_t i = 0; i < computer->componentLen; i++) { for(size_t i = 0; i < computer->componentLen; i++) {
if(computer->components[i].address == NULL) continue; // empty slot
if(strcmp(computer->components[i].address, address) == 0) { if(strcmp(computer->components[i].address, address) == 0) {
return computer->components + i; return computer->components + i;
} }
@ -398,19 +400,13 @@ nn_component *nn_findComponent(nn_computer *computer, nn_address address) {
return NULL; return NULL;
} }
nn_component **nn_listComponent(nn_computer *computer, size_t *len) { nn_component *nn_iterComponent(nn_computer *computer, size_t *internalIndex) {
nn_component **c = nn_malloc(sizeof(nn_component *) * computer->componentLen); for(size_t i = *internalIndex; i < computer->componentLen; i++) {
if(c == NULL) return NULL; if(computer->components[i].address == NULL) continue;
size_t j = 0; *internalIndex = i+1;
for(size_t i = 0; i < computer->componentLen; i++) { return computer->components + i;
nn_component *component = computer->components + i;
if(component->address != NULL) {
c[j] = component;
j++;
}
} }
*len = j; return NULL;
return c;
} }
void nn_resetCall(nn_computer *computer) { void nn_resetCall(nn_computer *computer) {
@ -471,3 +467,49 @@ void nn_lockComputer(nn_computer *computer) {
void nn_unlockComputer(nn_computer *computer) { void nn_unlockComputer(nn_computer *computer) {
nn_unlock(computer->lock); nn_unlock(computer->lock);
} }
void nn_return_nil(nn_computer *computer) {
nn_return(computer, nn_values_nil());
}
void nn_return_integer(nn_computer *computer, intptr_t integer) {
nn_return(computer, nn_values_integer(integer));
}
void nn_return_number(nn_computer *computer, double number) {
nn_return(computer, nn_values_number(number));
}
void nn_return_boolean(nn_computer *computer, bool boolean) {
nn_return(computer, nn_values_boolean(boolean));
}
void nn_return_cstring(nn_computer *computer, const char *cstr) {
nn_return(computer, nn_values_cstring(cstr));
}
void nn_return_string(nn_computer *computer, const char *str, size_t len) {
nn_value val = nn_values_string(&computer->universe->alloc, str, len);
if(val.tag == NN_VALUE_NIL) {
nn_setCError(computer, "out of memory");
}
nn_return(computer, val);
}
nn_value nn_return_array(nn_computer *computer, size_t len) {
nn_value val = nn_values_array(&computer->universe->alloc, len);
if(val.tag == NN_VALUE_NIL) {
nn_setCError(computer, "out of memory");
}
nn_return(computer, val);
return val;
}
nn_value nn_return_table(nn_computer *computer, size_t len) {
nn_value val = nn_values_table(&computer->universe->alloc, len);
if(val.tag == NN_VALUE_NIL) {
nn_setCError(computer, "out of memory");
}
nn_return(computer, val);
return val;
}

View File

@ -184,16 +184,16 @@ size_t ne_fs_read(nn_component *component, ne_fs *fs, int fd, char *buf, size_t
return fread(buf, sizeof(char), required, f); return fread(buf, sizeof(char), required, f);
} }
char **ne_fs_list(nn_component *component, ne_fs *fs, const char *path, size_t *len) { char **ne_fs_list(nn_Alloc *alloc, nn_component *component, ne_fs *fs, const char *path, size_t *len) {
const char *p = ne_fs_diskPath(component, path); const char *p = ne_fs_diskPath(component, path);
if(p[0] == '/') p++; if(p[0] == '/') p++;
FilePathList files = LoadDirectoryFiles(p); FilePathList files = LoadDirectoryFiles(p);
*len = files.count; *len = files.count;
char **buf = nn_malloc(sizeof(char *) * files.count); char **buf = nn_alloc(alloc, sizeof(char *) * files.count);
for(size_t i = 0; i < files.count; i++) { for(size_t i = 0; i < files.count; i++) {
buf[i] = nn_strdup(GetFileName(files.paths[i])); buf[i] = nn_strdup(alloc, GetFileName(files.paths[i]));
} }
UnloadDirectoryFiles(files); UnloadDirectoryFiles(files);
@ -466,7 +466,12 @@ int keycode_to_oc(int keycode) {
int main() { int main() {
printf("Setting up universe\n"); printf("Setting up universe\n");
nn_universe *universe = nn_newUniverse(); nn_Alloc alloc = nn_libcAllocator();
nn_universe *universe = nn_newUniverse(alloc);
if(universe == NULL) {
printf("Failed to create universe\n");
return 1;
}
nn_loadCoreComponentTables(universe); nn_loadCoreComponentTables(universe);
nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua"); nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua");
@ -528,7 +533,7 @@ int main() {
}; };
nn_addFileSystem(computer, "OpenOS", 1, &genericFS); nn_addFileSystem(computer, "OpenOS", 1, &genericFS);
nn_screen *s = nn_newScreen(80, 32, 16, 16, 256); nn_screen *s = nn_newScreen(&alloc, 80, 32, 16, 16, 256);
nn_addKeyboard(s, "shitty keyboard"); nn_addKeyboard(s, "shitty keyboard");
nn_mountKeyboard(computer, "shitty keyboard", 2); nn_mountKeyboard(computer, "shitty keyboard", 2);
nn_addScreen(computer, "Main Screen", 2, s); nn_addScreen(computer, "Main Screen", 2, s);

View File

@ -5,8 +5,8 @@ typedef struct nn_guard {
mtx_t m; mtx_t m;
} nn_guard; } nn_guard;
nn_guard *nn_newGuard() { nn_guard *nn_newGuard(nn_Alloc *alloc) {
nn_guard *g = nn_malloc(sizeof(nn_guard)); nn_guard *g = nn_alloc(alloc, sizeof(nn_guard));
if(g == NULL) return NULL; if(g == NULL) return NULL;
mtx_init(&g->m, mtx_recursive); mtx_init(&g->m, mtx_recursive);
return g; return g;
@ -22,9 +22,10 @@ void nn_unlock(nn_guard *guard) {
mtx_unlock(&guard->m); mtx_unlock(&guard->m);
} }
void nn_deleteGuard(nn_guard *guard) { void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard) {
if(guard == NULL) return; if(guard == NULL) return;
mtx_destroy(&guard->m); mtx_destroy(&guard->m);
nn_dealloc(alloc, guard, sizeof(nn_guard));
} }
void nn_addRef(nn_refc *refc, size_t count) { void nn_addRef(nn_refc *refc, size_t count) {

View File

@ -90,6 +90,23 @@ typedef struct nn_architecture {
} nn_architecture; } nn_architecture;
typedef char *nn_address; typedef char *nn_address;
// A non-zero malloc is a null ptr, with a 0 oldSize, but a non-0 newSize.
// A zero malloc is never called, the proc address itself is returned, which is ignored when freeing.
// A free is a non-null ptr, with a non-zero oldSize, but a newSize of 0.
// A realloc is a non-null ptr, with a non-zero oldSize, and a non-zero newSize.
typedef void *nn_AllocProc(void *userdata, void *ptr, size_t oldSize, size_t newSize, void *extra);
typedef struct nn_Alloc {
void *userdata;
nn_AllocProc *proc;
} nn_Alloc;
// TODO: write a bunch of utils so this *can* work on baremetal.
#ifndef NN_BAREMETAL
nn_Alloc nn_libcAllocator();
#endif
// Values for architectures // Values for architectures
#define NN_VALUE_INT 0 #define NN_VALUE_INT 0
@ -105,18 +122,21 @@ typedef struct nn_string {
char *data; char *data;
size_t len; size_t len;
size_t refc; size_t refc;
nn_Alloc alloc;
} nn_string; } nn_string;
typedef struct nn_array { typedef struct nn_array {
struct nn_value *values; struct nn_value *values;
size_t len; size_t len;
size_t refc; size_t refc;
nn_Alloc alloc;
} nn_array; } nn_array;
typedef struct nn_object { typedef struct nn_object {
struct nn_pair *pairs; struct nn_pair *pairs;
size_t len; size_t len;
size_t refc; size_t refc;
nn_Alloc alloc;
} nn_table; } nn_table;
typedef struct nn_value { typedef struct nn_value {
@ -138,18 +158,19 @@ typedef struct nn_pair {
} nn_pair; } nn_pair;
// we expose the allocator because of some utilities // we expose the allocator because of some utilities
void *nn_malloc(size_t size); void *nn_alloc(nn_Alloc *alloc, size_t size);
void *nn_realloc(void *memory, size_t newSize); void *nn_resize(nn_Alloc *alloc, void *memory, size_t oldSize, size_t newSize);
void nn_free(void *memory); void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size);
// Utilities, both internal and external // Utilities, both internal and external
char *nn_strdup(const char *s); char *nn_strdup(nn_Alloc *alloc, const char *s);
void *nn_memdup(const void *buf, size_t len); void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len);
void nn_deallocStr(nn_Alloc *alloc, char *s);
nn_guard *nn_newGuard(); nn_guard *nn_newGuard(nn_Alloc *alloc);
void nn_lock(nn_guard *guard); void nn_lock(nn_guard *guard);
void nn_unlock(nn_guard *guard); void nn_unlock(nn_guard *guard);
void nn_deleteGuard(nn_guard *guard); void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard);
void nn_addRef(nn_refc *refc, size_t count); void nn_addRef(nn_refc *refc, size_t count);
void nn_incRef(nn_refc *refc); void nn_incRef(nn_refc *refc);
@ -159,10 +180,10 @@ bool nn_removeRef(nn_refc *refc, size_t count);
bool nn_decRef(nn_refc *refc); bool nn_decRef(nn_refc *refc);
bool nn_unicode_validate(const char *s); bool nn_unicode_validate(const char *s);
// returned string must be nn_free()'d // returned string must be nn_deallocStr()'d
char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount); char *nn_unicode_char(nn_Alloc *alloc, unsigned int *codepoints, size_t codepointCount);
// returned array must be nn_free()'d // returned array must be nn_dealloc()'d
unsigned int *nn_unicode_codepoints(const char *s); unsigned int *nn_unicode_codepoints(nn_Alloc *alloc, const char *s, size_t *len);
size_t nn_unicode_len(const char *s); size_t nn_unicode_len(const char *s);
unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset); unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset);
size_t nn_unicode_codepointSize(unsigned int codepoint); size_t nn_unicode_codepointSize(unsigned int codepoint);
@ -170,9 +191,11 @@ const char *nn_unicode_codepointToChar(unsigned int codepoint, size_t *len);
size_t nn_unicode_charWidth(unsigned int codepoint); size_t nn_unicode_charWidth(unsigned int codepoint);
size_t nn_unicode_wlen(const char *s); size_t nn_unicode_wlen(const char *s);
unsigned int nn_unicode_upperCodepoint(unsigned int codepoint); unsigned int nn_unicode_upperCodepoint(unsigned int codepoint);
char *nn_unicode_upper(const char *s); // returned string must be nn_deallocStr()'d
char *nn_unicode_upper(nn_Alloc *alloc, const char *s);
unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint); unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint);
char *nn_unicode_lower(const char *s); // returned string must be nn_deallocStr()'d
char *nn_unicode_lower(nn_Alloc *alloc, const char *s);
double nn_realTime(); double nn_realTime();
double nn_realTimeClock(void *_); double nn_realTimeClock(void *_);
@ -183,7 +206,8 @@ void nn_randomLatency(double min, double max);
typedef double nn_clock_t(void *_); typedef double nn_clock_t(void *_);
nn_universe *nn_newUniverse(); nn_universe *nn_newUniverse(nn_Alloc alloc);
nn_Alloc *nn_getAllocator(nn_universe *universe);
void nn_unsafeDeleteUniverse(nn_universe *universe); void nn_unsafeDeleteUniverse(nn_universe *universe);
void *nn_queryUserdata(nn_universe *universe, const char *name); void *nn_queryUserdata(nn_universe *universe, const char *name);
void nn_storeUserdata(nn_universe *universe, const char *name, void *data); void nn_storeUserdata(nn_universe *universe, const char *name, void *data);
@ -300,8 +324,11 @@ nn_componentTable *nn_getComponentTable(nn_component *component);
const char *nn_getComponentType(nn_componentTable *table); const char *nn_getComponentType(nn_componentTable *table);
void *nn_getComponentUserdata(nn_component *component); void *nn_getComponentUserdata(nn_component *component);
nn_component *nn_findComponent(nn_computer *computer, nn_address address); nn_component *nn_findComponent(nn_computer *computer, nn_address address);
/* RESULT SHOULD BE NN_FREE()'D OR ELSE MEMORY IS LEAKED */ // the internal index is not the array index, but rather an index into
nn_component **nn_listComponent(nn_computer *computer, size_t *len); // an internal structure. YOU SHOULD NOT ADD OR REMOVE COMPONENTS WHILE ITERATING.
// the internalIndex SHOULD BE INITIALIZED TO 0.
// Returns NULL at the end
nn_component *nn_iterComponent(nn_computer *computer, size_t *internalIndex);
// Component VTable stuff // Component VTable stuff
@ -309,7 +336,7 @@ typedef void *nn_componentConstructor(void *tableUserdata, void *componentUserda
typedef void *nn_componentDestructor(void *tableUserdata, nn_component *component, void *componentUserdata); typedef void *nn_componentDestructor(void *tableUserdata, nn_component *component, void *componentUserdata);
typedef void nn_componentMethod(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer); typedef void nn_componentMethod(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer);
nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor); nn_componentTable *nn_newComponentTable(nn_Alloc *alloc, const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor);
void nn_destroyComponentTable(nn_componentTable *table); void nn_destroyComponentTable(nn_componentTable *table);
void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc); void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc);
const char *nn_getTableMethod(nn_componentTable *table, size_t idx, bool *outDirect); const char *nn_getTableMethod(nn_componentTable *table, size_t idx, bool *outDirect);
@ -334,9 +361,18 @@ nn_value nn_values_integer(intptr_t integer);
nn_value nn_values_number(double num); nn_value nn_values_number(double num);
nn_value nn_values_boolean(bool boolean); nn_value nn_values_boolean(bool boolean);
nn_value nn_values_cstring(const char *string); nn_value nn_values_cstring(const char *string);
nn_value nn_values_string(const char *string, size_t len); nn_value nn_values_string(nn_Alloc *alloc, const char *string, size_t len);
nn_value nn_values_array(size_t len); nn_value nn_values_array(nn_Alloc *alloc, size_t len);
nn_value nn_values_table(size_t pairCount); nn_value nn_values_table(nn_Alloc *alloc, size_t pairCount);
void nn_return_nil(nn_computer *computer);
void nn_return_integer(nn_computer *computer, intptr_t integer);
void nn_return_number(nn_computer *computer, double number);
void nn_return_boolean(nn_computer *computer, bool boolean);
void nn_return_cstring(nn_computer *computer, const char *cstr);
void nn_return_string(nn_computer *computer, const char *str, size_t len);
nn_value nn_return_array(nn_computer *computer, size_t len);
nn_value nn_return_table(nn_computer *computer, size_t len);
size_t nn_values_getType(nn_value val); size_t nn_values_getType(nn_value val);
nn_value nn_values_retain(nn_value val); nn_value nn_values_retain(nn_value val);
@ -471,10 +507,13 @@ typedef struct nn_filesystem {
// directory operations // directory operations
bool (*isDirectory)(nn_component *component, void *userdata, const char *path); bool (*isDirectory)(nn_component *component, void *userdata, const char *path);
bool (*makeDirectory)(nn_component *component, void *userdata, const char *path); bool (*makeDirectory)(nn_component *component, void *userdata, const char *path);
// the length and array must be nn_alloc'd. // The returned array should be allocated with the supplied allocator.
// The strings must be NULL-terminated and also nn_alloc'd. // The strings should be null terminated. Use nn_strdup for the allocation to guarantee nn_deallocStr deallocates it correctly.
// See nn_strdup(). // For the array, the *exact* size of the allocation should be sizeof(char *) * (*len),
char **(*list)(nn_component *component, void *userdata, const char *path, size_t *len); // If it is not, the behavior is undefined.
// We recommend first computing len then allocating, though if that is not doable or practical,
// consider nn_resize()ing it to the correct size to guarantee a correct deallocation.
char **(*list)(nn_Alloc *alloc, nn_component *component, void *userdata, const char *path, size_t *len);
// file operations // file operations
size_t (*open)(nn_component *component, void *userdata, const char *path, const char *mode); size_t (*open)(nn_component *component, void *userdata, const char *path, const char *mode);
@ -549,7 +588,7 @@ typedef struct nn_scrchr_t {
bool isBgPalette; bool isBgPalette;
} nn_scrchr_t; } nn_scrchr_t;
nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors); nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors);
nn_componentTable *nn_getScreenTable(nn_universe *universe); nn_componentTable *nn_getScreenTable(nn_universe *universe);
void nn_retainScreen(nn_screen *screen); void nn_retainScreen(nn_screen *screen);

View File

@ -2,6 +2,7 @@
#include <lualib.h> #include <lualib.h>
#include <lauxlib.h> #include <lauxlib.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "neonucleus.h" #include "neonucleus.h"
@ -40,6 +41,13 @@ testLuaArch *testLuaArch_get(lua_State *L) {
return arch; return arch;
} }
nn_Alloc *testLuaArch_getAlloc(lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, "archPtr");
testLuaArch *arch = lua_touserdata(L, -1);
lua_pop(L, 1);
return nn_getAllocator(nn_getUniverse(arch->computer));
}
const char *testLuaArch_pushlstring(lua_State *L, const char *s, size_t len) { const char *testLuaArch_pushlstring(lua_State *L, const char *s, size_t len) {
if (lua_checkstack(L, 1) == 0) { if (lua_checkstack(L, 1) == 0) {
return NULL; return NULL;
@ -58,9 +66,10 @@ const char *testLuaArch_pushstring(lua_State *L, const char *s) {
void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize) { void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize) {
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(arch->computer));
if(nsize == 0) { if(nsize == 0) {
arch->memoryUsed -= osize; arch->memoryUsed -= osize;
nn_free(ptr); free(ptr);
return NULL; return NULL;
} else { } else {
size_t actualOldSize = osize; size_t actualOldSize = osize;
@ -70,7 +79,7 @@ void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize
} }
arch->memoryUsed -= actualOldSize; arch->memoryUsed -= actualOldSize;
arch->memoryUsed += nsize; arch->memoryUsed += nsize;
return nn_realloc(ptr, nsize); return realloc(ptr, nsize);
} }
} }
@ -80,6 +89,7 @@ nn_computer *testLuaArch_getComputer(lua_State *L) {
static nn_value testLuaArch_getValue(lua_State *L, int index) { static nn_value testLuaArch_getValue(lua_State *L, int index) {
int type = lua_type(L, index); int type = lua_type(L, index);
nn_Alloc *alloc = testLuaArch_getAlloc(L);
if(type == LUA_TBOOLEAN) { if(type == LUA_TBOOLEAN) {
return nn_values_boolean(lua_toboolean(L, index)); return nn_values_boolean(lua_toboolean(L, index));
@ -90,7 +100,7 @@ static nn_value testLuaArch_getValue(lua_State *L, int index) {
if(type == LUA_TSTRING) { if(type == LUA_TSTRING) {
size_t l = 0; size_t l = 0;
const char *s = lua_tolstring(L, index, &l); const char *s = lua_tolstring(L, index, &l);
return nn_values_string(s, l); return nn_values_string(alloc, s, l);
} }
if(type == LUA_TNUMBER && lua_isinteger(L, index)) { if(type == LUA_TNUMBER && lua_isinteger(L, index)) {
return nn_values_integer(lua_tointeger(L, index)); return nn_values_integer(lua_tointeger(L, index));
@ -330,17 +340,12 @@ static int testLuaArch_computer_setState(lua_State *L) {
static int testLuaArch_component_list(lua_State *L) { static int testLuaArch_component_list(lua_State *L) {
nn_computer *c = testLuaArch_getComputer(L); nn_computer *c = testLuaArch_getComputer(L);
size_t len = 0; lua_createtable(L, 0, 10);
nn_component **components = nn_listComponent(c, &len); size_t iter = 0;
if(components == NULL) {
lua_pushnil(L);
lua_pushstring(L, "out of memory");
return 2;
}
lua_createtable(L, 0, len);
int list = lua_gettop(L); int list = lua_gettop(L);
for(size_t i = 0; i < len; i++) { while(true) {
nn_component *component = components[i]; nn_component *component = nn_iterComponent(c, &iter);
if(component == NULL) break;
nn_componentTable *table = nn_getComponentTable(component); nn_componentTable *table = nn_getComponentTable(component);
nn_address addr = nn_getComponentAddress(component); nn_address addr = nn_getComponentAddress(component);
const char *type = nn_getComponentType(table); const char *type = nn_getComponentType(table);
@ -348,7 +353,6 @@ static int testLuaArch_component_list(lua_State *L) {
lua_pushstring(L, type); lua_pushstring(L, type);
lua_setfield(L, list, addr); lua_setfield(L, list, addr);
} }
nn_free(components);
return 1; return 1;
} }
@ -463,6 +467,7 @@ static int testLuaArch_component_invoke(lua_State *L) {
int testLuaArch_unicode_sub(lua_State *L) { int testLuaArch_unicode_sub(lua_State *L) {
const char *s = luaL_checkstring(L, 1); const char *s = luaL_checkstring(L, 1);
nn_Alloc *alloc = testLuaArch_getAlloc(L);
int start = luaL_checkinteger(L, 2); int start = luaL_checkinteger(L, 2);
if(!nn_unicode_validate(s)) { if(!nn_unicode_validate(s)) {
luaL_error(L, "invalid utf-8"); luaL_error(L, "invalid utf-8");
@ -500,15 +505,20 @@ int testLuaArch_unicode_sub(lua_State *L) {
// there is a way to do it without an allocation // there is a way to do it without an allocation
// however, I'm lazy // however, I'm lazy
unsigned int *points = nn_unicode_codepoints(s); size_t pointLen;
unsigned int *points = nn_unicode_codepoints(alloc, s, &pointLen);
if(points == NULL) { if(points == NULL) {
luaL_error(L, "out of memory"); luaL_error(L, "out of memory");
} }
char *sub = nn_unicode_char(points + start - 1, stop - start + 1); char *sub = nn_unicode_char(alloc, points + start - 1, stop - start + 1);
if(sub == NULL) {
nn_dealloc(alloc, points, sizeof(unsigned int) * pointLen);
luaL_error(L, "out of memory");
}
const char *res = testLuaArch_pushstring(L, sub); const char *res = testLuaArch_pushstring(L, sub);
nn_free(sub); nn_deallocStr(alloc, sub);
nn_free(points); nn_dealloc(alloc, points, sizeof(unsigned int) * pointLen);
if (!res) { if (!res) {
luaL_error(L, "out of memory"); luaL_error(L, "out of memory");
} }
@ -518,23 +528,24 @@ int testLuaArch_unicode_sub(lua_State *L) {
int testLuaArch_unicode_char(lua_State *L) { int testLuaArch_unicode_char(lua_State *L) {
int argc = lua_gettop(L); int argc = lua_gettop(L);
unsigned int *codepoints = nn_malloc(sizeof(unsigned int) * argc); nn_Alloc *alloc = testLuaArch_getAlloc(L);
unsigned int *codepoints = nn_alloc(alloc, sizeof(unsigned int) * argc);
if(codepoints == NULL) { if(codepoints == NULL) {
luaL_error(L, "out of memory"); luaL_error(L, "out of memory");
} }
for(int i = 0; i < argc; i++) { for(int i = 0; i < argc; i++) {
int idx = i + 1; int idx = i + 1;
if(!lua_isinteger(L, idx)) { if(!lua_isinteger(L, idx)) {
nn_free(codepoints); nn_dealloc(alloc, codepoints, sizeof(unsigned int) * argc);
luaL_argerror(L, idx, "integer expected"); luaL_argerror(L, idx, "integer expected");
return 0; return 0;
} }
codepoints[i] = lua_tointeger(L, idx); codepoints[i] = lua_tointeger(L, idx);
} }
char *s = nn_unicode_char(codepoints, argc); char *s = nn_unicode_char(alloc, codepoints, argc);
const char *res = testLuaArch_pushstring(L, s); const char *res = testLuaArch_pushstring(L, s);
nn_free(s); nn_deallocStr(alloc, s);
nn_free(codepoints); nn_dealloc(alloc, codepoints, sizeof(unsigned int) * argc);
if (!res) { if (!res) {
luaL_error(L, "out of memory"); luaL_error(L, "out of memory");
} }
@ -649,7 +660,8 @@ void testLuaArch_loadEnv(lua_State *L) {
} }
testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) { testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) {
testLuaArch *s = nn_malloc(sizeof(testLuaArch)); nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
testLuaArch *s = nn_alloc(alloc, sizeof(testLuaArch));
if(s == NULL) return NULL; if(s == NULL) return NULL;
s->memoryUsed = 0; s->memoryUsed = 0;
s->computer = computer; s->computer = computer;
@ -665,8 +677,9 @@ testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) {
} }
void testLuaArch_teardown(nn_computer *computer, testLuaArch *arch, void *_) { void testLuaArch_teardown(nn_computer *computer, testLuaArch *arch, void *_) {
nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer));
lua_close(arch->L); lua_close(arch->L);
nn_free(arch); nn_dealloc(alloc, arch, sizeof(testLuaArch));
} }
void testLuaArch_tick(nn_computer *computer, testLuaArch *arch, void *_) { void testLuaArch_tick(nn_computer *computer, testLuaArch *arch, void *_) {
@ -719,7 +732,7 @@ nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath) {
if(f == NULL) return NULL; if(f == NULL) return NULL;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
size_t l = ftell(f); size_t l = ftell(f);
testLuaSandbox = nn_malloc(l+1); testLuaSandbox = malloc(l+1);
if(testLuaSandbox == NULL) { if(testLuaSandbox == NULL) {
fclose(f); fclose(f);
return NULL; return NULL;

View File

@ -205,14 +205,14 @@ bool nn_unicode_validate(const char *b) {
// It is used to power the Lua architecture's Unicode API re-implementation. // It is used to power the Lua architecture's Unicode API re-implementation.
// It can also just be used to deal with unicode. // It can also just be used to deal with unicode.
char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount) { char *nn_unicode_char(nn_Alloc *alloc, unsigned int *codepoints, size_t codepointCount) {
size_t len = 0; size_t len = 0;
for (size_t i = 0; i < codepointCount; i++) { for (size_t i = 0; i < codepointCount; i++) {
unsigned int codepoint = codepoints[i]; unsigned int codepoint = codepoints[i];
len += nn_unicode_codepointSize(codepoint); len += nn_unicode_codepointSize(codepoint);
} }
char *buf = nn_malloc(len+1); char *buf = nn_alloc(alloc, len+1);
if (buf == NULL) return buf; if (buf == NULL) return buf;
size_t j = 0; size_t j = 0;
@ -224,15 +224,18 @@ char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount) {
j += codepointLen; j += codepointLen;
} }
buf[j] = '\0'; buf[j] = '\0';
assert(j == len); // better safe than sorry // this can only fail if size_t is smaller than a pointer and overflowed.
// IF THIS HAPPENS, THE SYSTEM HEADERS ARE BUGGED.
assert(j == len);
return buf; return buf;
} }
unsigned int *nn_unicode_codepoints(const char *s) { unsigned int *nn_unicode_codepoints(nn_Alloc *alloc, const char *s, size_t *len) {
size_t l = nn_unicode_len(s); size_t l = nn_unicode_len(s);
unsigned int *buf = nn_malloc(sizeof(unsigned int) * l); unsigned int *buf = nn_alloc(alloc, sizeof(unsigned int) * l);
if(buf == NULL) return NULL; if(buf == NULL) return NULL;
if(len != NULL) *len = l;
size_t cur = 0; size_t cur = 0;
size_t bufidx = 0; size_t bufidx = 0;
while(s[cur] != 0) { while(s[cur] != 0) {
@ -363,6 +366,6 @@ size_t nn_unicode_wlen(const char *s) {
// NOT IMPLEMENTED YET // NOT IMPLEMENTED YET
unsigned int nn_unicode_upperCodepoint(unsigned int codepoint); unsigned int nn_unicode_upperCodepoint(unsigned int codepoint);
char *nn_unicode_upper(const char *s); char *nn_unicode_upper(nn_Alloc *alloc, const char *s);
unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint); unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint);
char *nn_unicode_lower(const char *s); char *nn_unicode_lower(nn_Alloc *alloc, const char *s);

View File

@ -2,9 +2,10 @@
#include "universe.h" #include "universe.h"
#include <string.h> #include <string.h>
nn_universe *nn_newUniverse() { nn_universe *nn_newUniverse(nn_Alloc alloc) {
nn_universe *u = nn_malloc(sizeof(nn_universe)); nn_universe *u = nn_alloc(&alloc, sizeof(nn_universe));
if(u == NULL) return u; if(u == NULL) return u;
u->alloc = alloc;
// we leave udata uninitialized because it does not matter // we leave udata uninitialized because it does not matter
u->udataLen = 0; u->udataLen = 0;
u->clockUserdata = NULL; u->clockUserdata = NULL;
@ -12,11 +13,15 @@ nn_universe *nn_newUniverse() {
return u; return u;
} }
nn_Alloc *nn_getAllocator(nn_universe *universe) {
return &universe->alloc;
}
void nn_unsafeDeleteUniverse(nn_universe *universe) { void nn_unsafeDeleteUniverse(nn_universe *universe) {
for(size_t i = 0; i < universe->udataLen; i++) { for(size_t i = 0; i < universe->udataLen; i++) {
nn_free(universe->udata[i].name); nn_deallocStr(&universe->alloc, universe->udata[i].name);
} }
nn_free(universe); nn_dealloc(&universe->alloc, universe, sizeof(nn_universe));
} }
void *nn_queryUserdata(nn_universe *universe, const char *name) { void *nn_queryUserdata(nn_universe *universe, const char *name) {
@ -32,7 +37,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) {
if(universe->udataLen == NN_MAX_USERDATA) return; // prevent overflow if(universe->udataLen == NN_MAX_USERDATA) return; // prevent overflow
size_t idx = universe->udataLen; size_t idx = universe->udataLen;
char *allocName = nn_strdup(name); char *allocName = nn_strdup(&universe->alloc, name);
if(allocName == NULL) return; if(allocName == NULL) return;
universe->udata[idx].name = allocName; universe->udata[idx].name = allocName;

View File

@ -9,6 +9,7 @@ typedef struct nn_universe_udata {
} nn_universe_udata; } nn_universe_udata;
typedef struct nn_universe { typedef struct nn_universe {
nn_Alloc alloc;
nn_universe_udata udata[NN_MAX_USERDATA]; nn_universe_udata udata[NN_MAX_USERDATA];
size_t udataLen; size_t udataLen;
nn_clock_t *currentClock; nn_clock_t *currentClock;

View File

@ -1,4 +1,5 @@
#include "neonucleus.h" #include "neonucleus.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -8,32 +9,71 @@
#include <windows.h> #include <windows.h>
#endif #endif
void *nn_malloc(size_t size) { void *nn_alloc(nn_Alloc *alloc, size_t size) {
return malloc(size); if(size == 0) return alloc->proc;
return alloc->proc(alloc->userdata, NULL, 0, size, NULL);
} }
void *nn_realloc(void *memory, size_t newSize) { void *nn_resize(nn_Alloc *alloc, void *memory, size_t oldSize, size_t newSize) {
return realloc(memory, newSize); if(oldSize == newSize) return memory;
if(newSize == 0) {
nn_dealloc(alloc, memory, oldSize);
return alloc->proc;
}
if(memory == NULL) {
return nn_alloc(alloc, newSize);
}
if(memory == alloc->proc) {
if(newSize == 0) return memory;
return nn_alloc(alloc, newSize);
}
return alloc->proc(alloc->userdata, memory, oldSize, newSize, NULL);
} }
void nn_free(void *memory) { void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size) {
free(memory); if(memory == NULL) return; // matches free()
if(memory == alloc->proc) return; // 0-sized memory
alloc->proc(alloc->userdata, memory, size, 0, NULL);
}
static void *nn_libcAllocProc(void *_, void *ptr, size_t oldSize, size_t newSize, void *__) {
if(newSize == 0) {
//printf("Freed %lu bytes from %p\n", oldSize, ptr);
free(ptr);
return NULL;
} else {
void *rptr = realloc(ptr, newSize);
//printf("Allocated %lu bytes for %p\n", newSize - oldSize, rptr);
return rptr;
}
}
nn_Alloc nn_libcAllocator() {
return (nn_Alloc) {
.userdata = NULL,
.proc = nn_libcAllocProc,
};
} }
// Utilities, both internal and external // Utilities, both internal and external
char *nn_strdup(const char *s) { char *nn_strdup(nn_Alloc *alloc, const char *s) {
size_t l = strlen(s); size_t l = strlen(s);
char *m = nn_malloc(l+1); char *m = nn_alloc(alloc, l+1);
if(m == NULL) return m; if(m == NULL) return m;
return strcpy(m, s); return strcpy(m, s);
} }
void *nn_memdup(const void *buf, size_t len) { void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len) {
char *m = malloc(len); char *m = nn_alloc(alloc, len);
if(m == NULL) return m; if(m == NULL) return m;
return memcpy(m, buf, len); return memcpy(m, buf, len);
} }
void nn_deallocStr(nn_Alloc *alloc, char *s) {
if(s == NULL) return;
nn_dealloc(alloc, s, strlen(s)+1);
}
#ifdef NN_POSIX #ifdef NN_POSIX
double nn_realTime() { double nn_realTime() {
@ -71,3 +111,4 @@ void nn_randomLatency(double min, double max) {
double latency = min + t * (max - min); double latency = min + t * (max - min);
nn_busySleep(latency); nn_busySleep(latency);
} }

View File

@ -21,38 +21,38 @@ nn_value nn_values_cstring(const char *string) {
return (nn_value) {.tag = NN_VALUE_CSTR, .cstring = string}; return (nn_value) {.tag = NN_VALUE_CSTR, .cstring = string};
} }
nn_value nn_values_string(const char *string, size_t len) { nn_value nn_values_string(nn_Alloc *alloc, const char *string, size_t len) {
if(len == 0) len = strlen(string); char *buf = nn_alloc(alloc, len+1);
char *buf = nn_malloc(len+1);
if(buf == NULL) { if(buf == NULL) {
return nn_values_nil(); return nn_values_nil();
} }
memcpy(buf, string, len); memcpy(buf, string, len);
buf[len] = '\0'; buf[len] = '\0';
nn_string *s = nn_malloc(sizeof(nn_string)); nn_string *s = nn_alloc(alloc, sizeof(nn_string));
if(s == NULL) { if(s == NULL) {
nn_free(buf); nn_dealloc(alloc, buf, len+1);
return nn_values_nil(); return nn_values_nil();
} }
s->data = buf; s->data = buf;
s->len = len; s->len = len;
s->refc = 1; s->refc = 1;
s->alloc = *alloc;
return (nn_value) {.tag = NN_VALUE_STR, .string = s}; return (nn_value) {.tag = NN_VALUE_STR, .string = s};
} }
nn_value nn_values_array(size_t len) { nn_value nn_values_array(nn_Alloc *alloc, size_t len) {
nn_array *arr = nn_malloc(sizeof(nn_array)); nn_array *arr = nn_alloc(alloc, sizeof(nn_array));
if(arr == NULL) { if(arr == NULL) {
return nn_values_nil(); return nn_values_nil();
} }
arr->alloc = *alloc;
arr->refc = 1; arr->refc = 1;
arr->len = len; arr->len = len;
nn_value *values = nn_malloc(sizeof(nn_value) * len); nn_value *values = nn_alloc(alloc, sizeof(nn_value) * len);
if(values == NULL) { if(values == NULL) {
nn_free(arr); nn_dealloc(alloc, arr, sizeof(nn_array));
return nn_values_nil(); return nn_values_nil();
} }
for(size_t i = 0; i < len; i++) { for(size_t i = 0; i < len; i++) {
@ -62,16 +62,17 @@ nn_value nn_values_array(size_t len) {
return (nn_value) {.tag = NN_VALUE_ARRAY, .array = arr}; return (nn_value) {.tag = NN_VALUE_ARRAY, .array = arr};
} }
nn_value nn_values_table(size_t pairCount) { nn_value nn_values_table(nn_Alloc *alloc, size_t pairCount) {
nn_table *table = nn_malloc(sizeof(nn_table)); nn_table *table = nn_alloc(alloc, sizeof(nn_table));
if(table == NULL) { if(table == NULL) {
return nn_values_nil(); return nn_values_nil();
} }
table->alloc = *alloc;
table->refc = 1; table->refc = 1;
table->len = pairCount; table->len = pairCount;
nn_pair *pairs = nn_malloc(sizeof(nn_pair) * pairCount); nn_pair *pairs = nn_alloc(alloc, sizeof(nn_pair) * pairCount);
if(pairs == NULL) { if(pairs == NULL) {
nn_free(table); nn_dealloc(alloc, table, sizeof(nn_table));
return nn_values_nil(); return nn_values_nil();
} }
for(size_t i = 0; i < pairCount; i++) { for(size_t i = 0; i < pairCount; i++) {
@ -101,8 +102,9 @@ void nn_values_drop(nn_value val) {
if(val.tag == NN_VALUE_STR) { if(val.tag == NN_VALUE_STR) {
val.string->refc--; val.string->refc--;
if(val.string->refc == 0) { if(val.string->refc == 0) {
nn_free(val.string->data); nn_Alloc *a = &val.string->alloc;
nn_free(val.string); nn_dealloc(a, val.string->data, val.string->len + 1);
nn_dealloc(a, val.string, sizeof(nn_string));
} }
} else if(val.tag == NN_VALUE_ARRAY) { } else if(val.tag == NN_VALUE_ARRAY) {
val.array->refc--; val.array->refc--;
@ -110,8 +112,9 @@ void nn_values_drop(nn_value val) {
for(size_t i = 0; i < val.array->len; i++) { for(size_t i = 0; i < val.array->len; i++) {
nn_values_drop(val.array->values[i]); nn_values_drop(val.array->values[i]);
} }
nn_free(val.array->values); nn_Alloc *a = &val.array->alloc;
nn_free(val.array); nn_dealloc(a, val.array->values, sizeof(nn_value) * val.array->len);
nn_dealloc(a, val.array, sizeof(nn_array));
} }
} else if(val.tag == NN_VALUE_TABLE) { } else if(val.tag == NN_VALUE_TABLE) {
val.table->refc--; val.table->refc--;
@ -120,8 +123,9 @@ void nn_values_drop(nn_value val) {
nn_values_drop(val.table->pairs[i].key); nn_values_drop(val.table->pairs[i].key);
nn_values_drop(val.table->pairs[i].val); nn_values_drop(val.table->pairs[i].val);
} }
nn_free(val.table->pairs); nn_Alloc *a = &val.table->alloc;
nn_free(val.table); nn_dealloc(a, val.table->pairs, sizeof(nn_pair) * val.table->len);
nn_dealloc(a, val.table, sizeof(nn_table));
} }
} }
} }