diff --git a/src/computer.c b/src/computer.c index fd39f71..577d21e 100644 --- a/src/computer.c +++ b/src/computer.c @@ -14,13 +14,78 @@ nn_architecture *nn_getArchitecture(nn_computer *computer); nn_architecture *nn_getNextArchitecture(nn_computer *computer); void nn_setNextArchitecture(nn_computer *computer, nn_architecture *arch); void nn_deleteComputer(nn_computer *computer); -void nn_pushSignal(nn_computer *computer, nn_value *values, size_t len); -nn_value nn_fetchSignalValue(nn_computer *computer, size_t index); -void nn_popSignal(nn_computer *computer); -void nn_addUser(nn_computer *computer, const char *name); -void nn_deleteUser(nn_computer *computer, const char *name); -const char *nn_indexUser(nn_computer *computer, size_t idx); -bool nn_isUser(nn_computer *computer, const char *name); + +const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len) { + if(len > NN_MAX_SIGNAL_VALS) return "too many values"; + if(len == 0) return "missing event"; + // no OOM for you hehe + if(nn_measurePacketSize(values, len) > NN_MAX_SIGNAL_SIZE) { + return "too big"; + } + if(computer->signalCount == NN_MAX_SIGNALS) return "too many signals"; + computer->signals[computer->signalCount].len = len; + for(size_t i = 0; i < len; i++) { + computer->signals[computer->signalCount].values[i] = values[i]; + } + computer->signalCount++; + return NULL; +} + +nn_value nn_fetchSignalValue(nn_computer *computer, size_t index) { + nn_signal *p = computer->signals + computer->signalCount - 1; + if(index >= p->len) return nn_values_nil(); + return p->values[index]; +} + +size_t nn_signalSize(nn_computer *computer) { + if(computer->signalCount == 0) return 0; + return computer->signals[computer->signalCount-1].len; +} + +void nn_popSignal(nn_computer *computer) { + if(computer->signalCount == 0) return; + nn_signal *p = computer->signals + computer->signalCount - 1; + for(size_t i = 0; i < p->len; i++) { + nn_values_drop(p->values[i]); + } + computer->signalCount--; +} + +const char *nn_addUser(nn_computer *computer, const char *name) { + if(computer->userCount == NN_MAX_USERS) return "too many users"; + char *user = nn_strdup(name); + if(user == NULL) return "out of memory"; + computer->users[computer->userCount] = user; + computer->userCount++; + return NULL; +} + +void nn_deleteUser(nn_computer *computer, const char *name) { + size_t j = 0; + for(size_t i = 0; i < computer->userCount; i++) { + char *user = computer->users[i]; + if(strcmp(user, name) == 0) { + nn_free(user); + } else { + computer->users[j] = user; + j++; + } + } + computer->userCount = j; +} + +const char *nn_indexUser(nn_computer *computer, size_t idx) { + if(idx >= computer->userCount) return NULL; + return computer->users[idx]; +} + +bool nn_isUser(nn_computer *computer, const char *name) { + if(computer->userCount == 0) return true; + for(size_t i = 0; i < computer->userCount; i++) { + if(strcmp(computer->users[i], name) == 0) return true; + } + return false; +} int nn_getState(nn_computer *computer) { return computer->state; diff --git a/src/computer.h b/src/computer.h index 2405097..af11856 100644 --- a/src/computer.h +++ b/src/computer.h @@ -3,6 +3,11 @@ #include "neonucleus.h" +typedef struct nn_signal { + size_t len; + nn_value values[NN_MAX_SIGNAL_VALS]; +} nn_signal; + typedef struct nn_computer { char state; bool allocatedError; @@ -25,6 +30,8 @@ typedef struct nn_computer { size_t userCount; size_t energy; size_t maxEnergy; + nn_signal signals[NN_MAX_SIGNALS]; + size_t signalCount; } nn_computer; #endif diff --git a/src/neonucleus.h b/src/neonucleus.h index 0fa6c50..f903ba2 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -55,6 +55,8 @@ #define NN_MAX_SIGNALS 32 #define NN_MAX_SIGNAL_VALS 32 #define NN_MAX_USERDATA 1024 +#define NN_MAX_USER_SIZE 128 +#define NN_MAX_SIGNAL_SIZE 8192 typedef struct nn_guard nn_guard; typedef struct nn_universe nn_universe; @@ -158,10 +160,11 @@ nn_architecture *nn_getArchitecture(nn_computer *computer); nn_architecture *nn_getNextArchitecture(nn_computer *computer); void nn_setNextArchitecture(nn_computer *computer, nn_architecture *arch); void nn_deleteComputer(nn_computer *computer); -void nn_pushSignal(nn_computer *computer, nn_value *values, size_t len); +const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len); nn_value nn_fetchSignalValue(nn_computer *computer, size_t index); +size_t nn_signalSize(nn_computer *computer); void nn_popSignal(nn_computer *computer); -void nn_addUser(nn_computer *computer, const char *name); +const char *nn_addUser(nn_computer *computer, const char *name); void nn_deleteUser(nn_computer *computer, const char *name); const char *nn_indexUser(nn_computer *computer, size_t idx); bool nn_isUser(nn_computer *computer, const char *name); @@ -282,4 +285,10 @@ bool nn_toBoolean(nn_value val); const char *nn_toCString(nn_value val); const char *nn_toString(nn_value val, size_t *len); +/* + * Computes the "packet size" of the values, using the same algorithm as OC. + * This is used by pushSignal to check the size + */ +size_t nn_measurePacketSize(nn_value *vals, size_t len); + #endif diff --git a/src/value.c b/src/value.c index b0b1ec3..d10da19 100644 --- a/src/value.c +++ b/src/value.c @@ -154,3 +154,28 @@ nn_pair nn_values_getPair(nn_value obj, size_t idx) { if(idx >= obj.table->len) return badPair; return obj.table->pairs[idx]; } + +size_t nn_measurePacketSize(nn_value *vals, size_t len) { + size_t size = 0; + for(size_t i = 0; i < len; i++) { + nn_value val = vals[i]; + size += 2; + if(val.tag == NN_VALUE_INT || val.tag == NN_VALUE_NUMBER) { + size += 8; + } else if(val.tag == NN_VALUE_STR) { + size_t len = val.string->len; + if(len == 0) len = 1; // ask OC + size += len; + } else if(val.tag == NN_VALUE_CSTR) { + size_t len = strlen(val.cstring); + if(len == 0) len = 1; // ask OC + size += len; + } else if(val.tag == NN_VALUE_BOOL || val.tag == NN_VALUE_NIL) { + size += 4; + } else { + // yeah no fuck off + return SIZE_MAX; + } + } + return size; +}