merge
[dcpu16] / common.c
index 9dbadf369983950b2126efc8a5dcde63a307d2f2..43217719ba99144150d997adb32998bb9c3e4833 100644 (file)
--- a/common.c
+++ b/common.c
@@ -7,6 +7,13 @@
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
+#include <time.h>
+#include <sys/time.h>
+
+#ifdef __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif /* __MACH__ */
 
 #include "common.h"
 #include "dcpu16.h"
@@ -58,6 +65,17 @@ struct dynamic_array *dynarray_new(size_t entry_size, size_t grow_size) {
     return da;
 }
 
+void dynarray_empty(struct dynamic_array *da, void (*free_element)(void *)) {
+    while ( da->entries-- ) {
+        void *element = (void *)DYNARRAY_ITEM(*da, da->entries);
+
+        free_element(element);
+    }
+    free(da->a);
+    da->a = NULL;
+    da->allocated = 0;
+}
+
 /* copy item onto end of array */
 void *dynarray_add(struct dynamic_array *da, void *item) {
     void *dst;
@@ -126,7 +144,11 @@ char *strqtok_r(char *str, const char *sep, int esc, const char *quote, char **l
     }
 
     /* next token starts after any leading seps */
-    *lasts += strspn(*lasts, sep);
+    while (**lasts && strchr(sep, **lasts)) {
+        **lasts = '\0';
+        (*lasts)++;
+    }
+
     tok = *lasts;
     if (*tok == '\0')
         return NULL;
@@ -200,3 +222,74 @@ char *strqtok_r(char *str, const char *sep, int esc, const char *quote, char **l
 
     return tok;
 }
+
+/* like gettimeofday, except with nanoseconds */
+inline
+int gettimespecofday(struct timespec *ts) {
+    int retval = 0;
+#ifdef __MACH__
+    clock_serv_t cclock;
+    mach_timespec_t mts;
+
+    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+    clock_get_time(cclock, &mts);
+    mach_port_deallocate(mach_task_self(), cclock);
+    ts->tv_sec = mts.tv_sec;
+    ts->tv_nsec = mts.tv_nsec;
+#else /* __MACH__ */
+    retval = clock_gettime(CLOCK_REALTIME, ts);
+#endif /* __MACH__ */
+
+    return retval;
+}
+
+inline
+int timespec_add(struct timespec *result, const struct timespec *x) {
+    result->tv_sec += x->tv_sec;
+    result->tv_nsec += x->tv_nsec;
+
+    result->tv_sec += result->tv_nsec / 1000000000;
+    result->tv_nsec %= 1000000000;
+
+    return 0;
+}
+
+inline
+int timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) {
+    if (x->tv_nsec < y->tv_nsec) {
+        int z = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
+        y->tv_nsec -= 1000000000 * z;
+        y->tv_sec += z;
+    }
+    if (x->tv_nsec - y->tv_nsec > 1000000000) {
+        int z = (x->tv_nsec - y->tv_nsec) / 1000000000;
+        y->tv_nsec += 1000000000 * z;
+        y->tv_sec -= z;
+    }
+    result->tv_sec = x->tv_sec - y->tv_sec;
+    result->tv_nsec = x->tv_nsec - y->tv_nsec;
+
+    return x->tv_sec < y->tv_sec;
+}
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
+  /* Perform the carry for the later subtraction by updating y. */
+  if (x->tv_usec < y->tv_usec) {
+    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+    y->tv_usec -= 1000000 * nsec;
+    y->tv_sec += nsec;
+  }
+  if (x->tv_usec - y->tv_usec > 1000000) {
+    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+    y->tv_usec += 1000000 * nsec;
+    y->tv_sec -= nsec;
+  }
+
+  /* Compute the time remaining to wait.
+     tv_usec is certainly positive. */
+  result->tv_sec = x->tv_sec - y->tv_sec;
+  result->tv_usec = x->tv_usec - y->tv_usec;
+
+  /* Return 1 if result is negative. */
+  return x->tv_sec < y->tv_sec;
+}