|
|
|
@@ -5,21 +5,43 @@
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
//GOD DAMN IT: https://stackoverflow.com/questions/15846762/timeval-subtract-explanation
|
|
|
|
|
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
|
|
|
|
|
//normallize
|
|
|
|
|
if (x->tv_usec > 999999) {
|
|
|
|
|
x->tv_sec += x->tv_usec / 1000000;
|
|
|
|
|
x->tv_usec %= 1000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (y->tv_usec > 999999) {
|
|
|
|
|
y->tv_sec += y->tv_usec / 1000000;
|
|
|
|
|
y->tv_usec %= 1000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//calc
|
|
|
|
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
|
|
|
|
|
|
|
|
|
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0) {
|
|
|
|
|
if (result->tv_sec != 0) { //only works far from 0
|
|
|
|
|
result->tv_usec += 1000000;
|
|
|
|
|
result->tv_sec--; // borrow
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result->tv_sec < 0 || (result->tv_sec == 0 && result->tv_usec < 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//god damn it
|
|
|
|
|
static struct timeval* diff(struct timeval* lhs, struct timeval* rhs) {
|
|
|
|
|
struct timeval* d = ALLOCATE(struct timeval, 1);
|
|
|
|
|
|
|
|
|
|
d->tv_sec = rhs->tv_sec - lhs->tv_sec;
|
|
|
|
|
d->tv_usec = rhs->tv_usec - lhs->tv_usec;
|
|
|
|
|
|
|
|
|
|
if (d->tv_usec < 0) {
|
|
|
|
|
d->tv_sec--;
|
|
|
|
|
d->tv_usec += 1000 * 1000;
|
|
|
|
|
}
|
|
|
|
|
//I gave up, copied from SO
|
|
|
|
|
timeval_subtract(d, rhs, lhs);
|
|
|
|
|
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//callbacks
|
|
|
|
|
static int nativeStartTimer(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
//no arguments
|
|
|
|
|
if (arguments->count != 0) {
|
|
|
|
@@ -60,6 +82,7 @@ static int nativeStopTimer(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(timeLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _stopTimer\n");
|
|
|
|
|
freeLiteral(timeLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@@ -100,6 +123,14 @@ static int nativeCreateTimer(Interpreter* interpreter, LiteralArray* arguments)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_INTEGER(secondLiteral) || !IS_INTEGER(microsecondLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to createTimer\n");
|
|
|
|
|
freeLiteral(secondLiteral);
|
|
|
|
|
freeLiteral(microsecondLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (AS_INTEGER(microsecondLiteral) <= -1000 * 1000 || AS_INTEGER(microsecondLiteral) >= 1000 * 1000 || (AS_INTEGER(secondLiteral) != 0 && AS_INTEGER(microsecondLiteral) < 0) ) {
|
|
|
|
|
interpreter->errorOutput("Microseconds out of range in createTimer\n");
|
|
|
|
|
freeLiteral(secondLiteral);
|
|
|
|
|
freeLiteral(microsecondLiteral);
|
|
|
|
|
return -1;
|
|
|
|
@@ -124,7 +155,7 @@ static int nativeCreateTimer(Interpreter* interpreter, LiteralArray* arguments)
|
|
|
|
|
static int nativeGetTimerSeconds(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
//no arguments
|
|
|
|
|
if (arguments->count != 1) {
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to getTimerSeconds\n");
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _getTimerSeconds\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -137,6 +168,7 @@ static int nativeGetTimerSeconds(Interpreter* interpreter, LiteralArray* argumen
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(timeLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _getTimerSeconds\n");
|
|
|
|
|
freeLiteral(timeLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@@ -157,7 +189,7 @@ static int nativeGetTimerSeconds(Interpreter* interpreter, LiteralArray* argumen
|
|
|
|
|
static int nativeGetTimerMicroseconds(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
//no arguments
|
|
|
|
|
if (arguments->count != 1) {
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to getTimerSeconds\n");
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _getTimerMicroseconds\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -170,6 +202,7 @@ static int nativeGetTimerMicroseconds(Interpreter* interpreter, LiteralArray* ar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(timeLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _getTimerMicroseconds\n");
|
|
|
|
|
freeLiteral(timeLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@@ -190,7 +223,7 @@ static int nativeGetTimerMicroseconds(Interpreter* interpreter, LiteralArray* ar
|
|
|
|
|
static int nativeCompareTimer(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
//no arguments
|
|
|
|
|
if (arguments->count != 2) {
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _stopTimer\n");
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _compareTimer\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -209,6 +242,7 @@ static int nativeCompareTimer(Interpreter* interpreter, LiteralArray* arguments)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(lhsLiteral) || !IS_OPAQUE(rhsLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _compareTimer\n");
|
|
|
|
|
freeLiteral(lhsLiteral);
|
|
|
|
|
freeLiteral(rhsLiteral);
|
|
|
|
|
return -1;
|
|
|
|
@@ -246,6 +280,7 @@ static int nativeTimerToString(Interpreter* interpreter, LiteralArray* arguments
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(timeLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _timerToString\n");
|
|
|
|
|
freeLiteral(timeLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@@ -253,9 +288,17 @@ static int nativeTimerToString(Interpreter* interpreter, LiteralArray* arguments
|
|
|
|
|
struct timeval* timer = AS_OPAQUE(timeLiteral);
|
|
|
|
|
|
|
|
|
|
//create the string literal
|
|
|
|
|
char buffer[128];
|
|
|
|
|
snprintf(buffer, 128, "%ld.%06ld", timer->tv_sec, timer->tv_usec);
|
|
|
|
|
Literal resultLiteral = TO_STRING_LITERAL( copyString(buffer, strlen(buffer)), strlen(buffer));
|
|
|
|
|
Literal resultLiteral = TO_NULL_LITERAL;
|
|
|
|
|
if (timer->tv_sec == 0 && timer->tv_usec < 0) { //special case, for when the negative sign is encoded in the usec
|
|
|
|
|
char buffer[128];
|
|
|
|
|
snprintf(buffer, 128, "-%ld.%06ld", timer->tv_sec, -timer->tv_usec);
|
|
|
|
|
resultLiteral = TO_STRING_LITERAL( copyString(buffer, strlen(buffer)), strlen(buffer));
|
|
|
|
|
}
|
|
|
|
|
else { //normal case
|
|
|
|
|
char buffer[128];
|
|
|
|
|
snprintf(buffer, 128, "%ld.%06ld", timer->tv_sec, timer->tv_usec);
|
|
|
|
|
resultLiteral = TO_STRING_LITERAL( copyString(buffer, strlen(buffer)), strlen(buffer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pushLiteralArray(&interpreter->stack, resultLiteral);
|
|
|
|
|
|
|
|
|
@@ -269,7 +312,7 @@ static int nativeTimerToString(Interpreter* interpreter, LiteralArray* arguments
|
|
|
|
|
static int nativeDestroyTimer(Interpreter* interpreter, LiteralArray* arguments) {
|
|
|
|
|
//no arguments
|
|
|
|
|
if (arguments->count != 1) {
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _desroyTimer\n");
|
|
|
|
|
interpreter->errorOutput("Incorrect number of arguments to _destroyTimer\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -282,6 +325,7 @@ static int nativeDestroyTimer(Interpreter* interpreter, LiteralArray* arguments)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_OPAQUE(timeLiteral)) {
|
|
|
|
|
interpreter->errorOutput("Incorrect argument type passed to _destroyTimer\n");
|
|
|
|
|
freeLiteral(timeLiteral);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|