Make all timestamps use UInt64.

This commit is contained in:
Jordan Bancino 2023-08-12 23:02:06 +00:00
parent e9af54e4c7
commit 2c715c6e72
14 changed files with 265 additions and 181 deletions

View file

@ -23,6 +23,7 @@
*/ */
#include <Cron.h> #include <Cron.h>
#include <UInt64.h>
#include <Array.h> #include <Array.h>
#include <Memory.h> #include <Memory.h>
#include <Util.h> #include <Util.h>
@ -31,7 +32,7 @@
struct Cron struct Cron
{ {
unsigned long tick; UInt64 tick;
Array *jobs; Array *jobs;
pthread_mutex_t lock; pthread_mutex_t lock;
volatile unsigned int stop:1; volatile unsigned int stop:1;
@ -40,14 +41,14 @@ struct Cron
typedef struct Job typedef struct Job
{ {
unsigned long interval; UInt64 interval;
unsigned long lastExec; UInt64 lastExec;
JobFunc *func; JobFunc *func;
void *args; void *args;
} Job; } Job;
static Job * static Job *
JobCreate(long interval, JobFunc * func, void *args) JobCreate(UInt32 interval, JobFunc * func, void *args)
{ {
Job *job; Job *job;
@ -62,8 +63,8 @@ JobCreate(long interval, JobFunc * func, void *args)
return NULL; return NULL;
} }
job->interval = interval; job->interval = UInt64Create(0, interval);
job->lastExec = 0; job->lastExec = UInt64Create(0, 0);
job->func = func; job->func = func;
job->args = args; job->args = args;
@ -78,8 +79,8 @@ CronThread(void *args)
while (!cron->stop) while (!cron->stop)
{ {
size_t i; size_t i;
unsigned long ts; /* tick start */ UInt64 ts; /* tick start */
unsigned long te; /* tick end */ UInt64 te; /* tick end */
pthread_mutex_lock(&cron->lock); pthread_mutex_lock(&cron->lock);
@ -89,13 +90,13 @@ CronThread(void *args)
{ {
Job *job = ArrayGet(cron->jobs, i); Job *job = ArrayGet(cron->jobs, i);
if (ts - job->lastExec > job->interval) if (UInt64Gt(UInt64Sub(ts, job->lastExec), job->interval))
{ {
job->func(job->args); job->func(job->args);
job->lastExec = ts; job->lastExec = ts;
} }
if (!job->interval) if (UInt64Eq(job->interval, UInt64Create(0, 0)))
{ {
ArrayDelete(cron->jobs, i); ArrayDelete(cron->jobs, i);
Free(job); Free(job);
@ -106,21 +107,23 @@ CronThread(void *args)
pthread_mutex_unlock(&cron->lock); pthread_mutex_unlock(&cron->lock);
/* Only sleep if the jobs didn't overrun the tick */ /* Only sleep if the jobs didn't overrun the tick */
if (cron->tick > (te - ts)) if (UInt64Gt(cron->tick, UInt64Sub(te, ts)))
{ {
const unsigned long microTick = 100; const UInt64 microTick = UInt64Create(0, 100);
unsigned long remainingTick = cron->tick - (te - ts);
UInt64 remainingTick = UInt64Sub(cron->tick, UInt64Sub(te, ts));
/* Only sleep for microTick ms at a time because if the job /* Only sleep for microTick ms at a time because if the job
* scheduler is supposed to stop before the tick is up, we * scheduler is supposed to stop before the tick is up, we
* don't want to be stuck in a long sleep */ * don't want to be stuck in a long sleep */
while (remainingTick >= microTick && !cron->stop) while (UInt64Geq(remainingTick, microTick) && !cron->stop)
{ {
UtilSleepMillis(microTick); UtilSleepMillis(microTick);
remainingTick -= microTick;
remainingTick = UInt64Sub(remainingTick, microTick);
} }
if (remainingTick && !cron->stop) if (UInt64Neq(remainingTick, UInt64Create(0, 0)) && !cron->stop)
{ {
UtilSleepMillis(remainingTick); UtilSleepMillis(remainingTick);
} }
@ -131,7 +134,7 @@ CronThread(void *args)
} }
Cron * Cron *
CronCreate(unsigned long tick) CronCreate(UInt32 tick)
{ {
Cron *cron = Malloc(sizeof(Cron)); Cron *cron = Malloc(sizeof(Cron));
@ -147,7 +150,7 @@ CronCreate(unsigned long tick)
return NULL; return NULL;
} }
cron->tick = tick; cron->tick = UInt64Create(0, tick);
cron->stop = 1; cron->stop = 1;
pthread_mutex_init(&cron->lock, NULL); pthread_mutex_init(&cron->lock, NULL);

View file

@ -23,6 +23,7 @@
*/ */
#include <Db.h> #include <Db.h>
#include <UInt64.h>
#include <Memory.h> #include <Memory.h>
#include <Json.h> #include <Json.h>
#include <Util.h> #include <Util.h>
@ -76,7 +77,7 @@ struct DbRef
{ {
HashMap *json; HashMap *json;
unsigned long ts; UInt64 ts;
size_t size; size_t size;
Array *name; Array *name;
@ -494,12 +495,12 @@ DbLockFromArr(Db * db, Array * args)
if (ref) /* In cache */ if (ref) /* In cache */
{ {
unsigned long diskTs = UtilLastModified(file); UInt64 diskTs = UtilLastModified(file);
ref->fd = fd; ref->fd = fd;
ref->stream = stream; ref->stream = stream;
if (diskTs > ref->ts) if (UInt64Gt(diskTs, ref->ts))
{ {
/* File was modified on disk since it was cached */ /* File was modified on disk since it was cached */
HashMap *json = JsonDecode(ref->stream); HashMap *json = JsonDecode(ref->stream);
@ -651,7 +652,7 @@ DbCreate(Db * db, size_t nArgs,...)
file = DbFileName(db, args); file = DbFileName(db, args);
if (UtilLastModified(file)) if (UInt64Neq(UtilLastModified(file), UInt64Create(0, 0)))
{ {
Free(file); Free(file);
ArrayFree(args); ArrayFree(args);
@ -754,7 +755,7 @@ DbDelete(Db * db, size_t nArgs,...)
Free(hash); Free(hash);
if (UtilLastModified(file)) if (UInt64Neq(UtilLastModified(file), UInt64Create(0, 0)))
{ {
ret = remove(file) == 0; ret = remove(file) == 0;
} }
@ -872,7 +873,7 @@ DbExists(Db * db, size_t nArgs,...)
pthread_mutex_lock(&db->lock); pthread_mutex_lock(&db->lock);
file = DbFileName(db, args); file = DbFileName(db, args);
ret = UtilLastModified(file); ret = UInt64Neq(UtilLastModified(file), UInt64Create(0, 0));
pthread_mutex_unlock(&db->lock); pthread_mutex_unlock(&db->lock);

View file

@ -465,7 +465,7 @@ HttpServerWorkerThread(void *args)
ssize_t i = 0; ssize_t i = 0;
HttpRequestMethod requestMethod; HttpRequestMethod requestMethod;
long firstRead; UInt64 firstRead;
fp = DequeueConnection(server); fp = DequeueConnection(server);
@ -473,7 +473,7 @@ HttpServerWorkerThread(void *args)
{ {
/* Block for 1 millisecond before continuing so we don't /* Block for 1 millisecond before continuing so we don't
* murder the CPU if the queue is empty. */ * murder the CPU if the queue is empty. */
UtilSleepMillis(1); UtilSleepMillis(UInt64Create(0, 1));
continue; continue;
} }
@ -492,12 +492,12 @@ HttpServerWorkerThread(void *args)
/* If the server is stopped, or it's been a while, just /* If the server is stopped, or it's been a while, just
* give up so we aren't wasting a thread on this client. */ * give up so we aren't wasting a thread on this client. */
if (server->stop || (UtilServerTs() - firstRead) > 1000 * 30) if (server->stop || UInt64Gt(UInt64Sub(UtilServerTs(), firstRead), UInt64Create(0, 1000 * 30)))
{ {
goto finish; goto finish;
} }
UtilSleepMillis(5); UtilSleepMillis(UInt64Create(0, 5));
} }
if (lineLen == -1) if (lineLen == -1)

View file

@ -40,14 +40,14 @@ Int64Str(Int64 x, int base, char *out, size_t len)
size_t i = len - 1; size_t i = len - 1;
size_t j = 0; size_t j = 0;
int neg = Int64Sign(x); int neg = Int64Sign(x);
Int64 base64 = Int64Create(0, base); Int64 base64 = Int64Create(0, base);
if (neg) if (neg)
{ {
x = Int64Neg(x); x = Int64Neg(x);
} }
/* We only have symbols up to base 16 */ /* We only have symbols up to base 16 */
if (base < 2 || base > 16) if (base < 2 || base > 16)
@ -65,19 +65,19 @@ Int64Str(Int64 x, int base, char *out, size_t len)
x = Int64Div(x, base64); x = Int64Div(x, base64);
} while (Int64Gt(x, Int64Create(0, 0))); } while (Int64Gt(x, Int64Create(0, 0)));
/* /*
* Binary, octal, and hexadecimal are known to * Binary, octal, and hexadecimal are known to
* be bit representations. Everything else (notably * be bit representations. Everything else (notably
* decimal) should include the negative sign. * decimal) should include the negative sign.
*/ */
if (base != 2 && base != 8 && base != 16) if (base != 2 && base != 8 && base != 16)
{ {
if (neg) if (neg)
{ {
out[i] = '-'; out[i] = '-';
i--; i--;
} }
} }
while (++i < len) while (++i < len)
{ {
@ -128,18 +128,18 @@ Int64Mul(Int64 x, Int64 y)
{ {
Int64 z = Int64Create(0, 0); Int64 z = Int64Create(0, 0);
int xneg = Int64Sign(x); int xneg = Int64Sign(x);
int yneg = Int64Sign(y); int yneg = Int64Sign(y);
if (xneg) if (xneg)
{ {
x = Int64Neg(x); x = Int64Neg(x);
} }
if (yneg) if (yneg)
{ {
y = Int64Neg(y); y = Int64Neg(y);
} }
/* while (y > 0) */ /* while (y > 0) */
while (Int64Gt(y, Int64Create(0, 0))) while (Int64Gt(y, Int64Create(0, 0)))
@ -154,10 +154,10 @@ Int64Mul(Int64 x, Int64 y)
y = Int64Sra(y, 1); y = Int64Sra(y, 1);
} }
if (xneg != yneg) if (xneg != yneg)
{ {
z = Int64Neg(z); z = Int64Neg(z);
} }
return z; return z;
} }
@ -175,8 +175,8 @@ Int64LongDivision(Int64 n, Int64 d)
int i; int i;
int nneg = Int64Sign(n); int nneg = Int64Sign(n);
int dneg = Int64Sign(d); int dneg = Int64Sign(d);
o.q = Int64Create(0, 0); o.q = Int64Create(0, 0);
o.r = Int64Create(0, 0); o.r = Int64Create(0, 0);
@ -187,19 +187,20 @@ Int64LongDivision(Int64 n, Int64 d)
return o; return o;
} }
if (nneg) if (nneg)
{ {
n = Int64Neg(n); n = Int64Neg(n);
} }
if (dneg) if (dneg)
{ {
d = Int64Neg(d); d = Int64Neg(d);
} }
for (i = 63; i >= 0; i--) for (i = 63; i >= 0; i--)
{ {
Int64 bit = Int64And(Int64Sra(n, i), Int64Create(0, 1)); Int64 bit = Int64And(Int64Sra(n, i), Int64Create(0, 1));
o.r = Int64Sll(o.r, 1); o.r = Int64Sll(o.r, 1);
o.r = Int64Or(o.r, bit); o.r = Int64Or(o.r, bit);
@ -210,11 +211,11 @@ Int64LongDivision(Int64 n, Int64 d)
} }
} }
if (nneg != dneg) if (nneg != dneg)
{ {
o.r = Int64Neg(o.r); o.r = Int64Neg(o.r);
o.q = Int64Neg(o.q); o.q = Int64Neg(o.q);
} }
return o; return o;
} }
@ -261,7 +262,7 @@ Int64Sra(Int64 x, int y)
{ {
Int64 z; Int64 z;
int neg = Int64Sign(x); int neg = Int64Sign(x);
if (!y) if (!y)
{ {
@ -280,11 +281,12 @@ Int64Sra(Int64 x, int y)
z.i[0] = x.i[1] >> (y - 32); z.i[0] = x.i[1] >> (y - 32);
} }
if (neg) if (neg)
{ {
Int64 mask = Int64Create(0xFFFFFFFF, 0xFFFFFFFF); Int64 mask = Int64Create(0xFFFFFFFF, 0xFFFFFFFF);
z = Int64Or(Int64Sll(mask, (64 - y)), z);
} z = Int64Or(Int64Sll(mask, (64 - y)), z);
}
return z; return z;
} }
@ -322,47 +324,51 @@ Int64Eq(Int64 x, Int64 y)
int int
Int64Lt(Int64 x, Int64 y) Int64Lt(Int64 x, Int64 y)
{ {
int xneg = Int64Sign(x); int xneg = Int64Sign(x);
int yneg = Int64Sign(y); int yneg = Int64Sign(y);
if (xneg != yneg) if (xneg != yneg)
{ {
return xneg > yneg; return xneg > yneg;
} }
else else
{ {
if (xneg) /* Both negative */ if (xneg)
{ {
return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]); /* Both negative */
} return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]);
else /* Both positive */ }
{ else
return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]); {
} /* Both positive */
} return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]);
}
}
} }
int int
Int64Gt(Int64 x, Int64 y) Int64Gt(Int64 x, Int64 y)
{ {
int xneg = Int64Sign(x); int xneg = Int64Sign(x);
int yneg = Int64Sign(y); int yneg = Int64Sign(y);
if (xneg != yneg) if (xneg != yneg)
{ {
return xneg < yneg; return xneg < yneg;
} }
else else
{ {
if (xneg) /* Both negative */ if (xneg)
{ {
return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]); /* Both negative */
} return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]);
else /* Both positive */ }
{ else
return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]); {
} /* Both positive */
} return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]);
}
}
} }

View file

@ -872,7 +872,7 @@ JsonConsumeWhitespace(JsonParserState * state)
} }
else else
{ {
UtilSleepMillis(delay); UtilSleepMillis(UInt64Create(0, delay));
continue; continue;
} }
} }

View file

@ -24,6 +24,7 @@
#include <Rand.h> #include <Rand.h>
#include <Int.h> #include <Int.h>
#include <UInt64.h>
#include <Util.h> #include <Util.h>
#include <Memory.h> #include <Memory.h>
@ -140,7 +141,8 @@ RandIntN(int *buf, size_t size, unsigned int max)
if (!state) if (!state)
{ {
/* Generate a seed from the system time, PID, and TID */ /* Generate a seed from the system time, PID, and TID */
UInt32 seed = UtilServerTs() ^ getpid() ^ (unsigned long) pthread_self(); UInt64 ts = UtilServerTs();
UInt32 seed = UInt64Low(ts) ^ getpid() ^ (unsigned long) pthread_self();
state = Malloc(sizeof(RandState)); state = Malloc(sizeof(RandState));
RandSeed(state, seed); RandSeed(state, seed);

View file

@ -626,7 +626,7 @@ StreamCopy(Stream * in, Stream * out)
} }
else else
{ {
UtilSleepMillis(STREAM_DELAY); UtilSleepMillis(UInt64Create(0, STREAM_DELAY));
continue; continue;
} }
} }

View file

@ -144,6 +144,7 @@ UInt64LongDivision(UInt64 n, UInt64 d)
for (i = 63; i >= 0; i--) for (i = 63; i >= 0; i--)
{ {
UInt64 bit = UInt64And(UInt64Srl(n, i), UInt64Create(0, 1)); UInt64 bit = UInt64And(UInt64Srl(n, i), UInt64Create(0, 1));
o.r = UInt64Sll(o.r, 1); o.r = UInt64Sll(o.r, 1);
o.r = UInt64Or(o.r, bit); o.r = UInt64Or(o.r, bit);

View file

@ -40,6 +40,8 @@
#include <limits.h> #include <limits.h>
#include <pthread.h> #include <pthread.h>
#include <UInt64.h>
#ifndef PATH_MAX #ifndef PATH_MAX
#define PATH_MAX 256 #define PATH_MAX 256
#endif #endif
@ -48,33 +50,84 @@
#define SSIZE_MAX LONG_MAX #define SSIZE_MAX LONG_MAX
#endif #endif
unsigned long UInt64
UtilServerTs(void) UtilServerTs(void)
{ {
struct timeval tv; struct timeval tv;
unsigned long ts;
UInt64 ts;
UInt64 sec;
UInt64 usec;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
ts = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
/*
* POSIX defines struct timeval to be:
*
* struct timeval {
* time_t tv_sec;
* suseconds_t tv_usec;
* };
*
* Note: Although the C standard does not require that
* time_t be an integer type (it may be floating point),
* according to POSIX, time_t shall be an integer type.
* As we are targeting POSIX, not ANSI/ISO C, we can
* rely on this.
*
* The same goes for suseconds_t.
*/
if (sizeof(time_t) == sizeof(UInt64))
{
/* 64 bit time_t: convert it to a 64 bit integer */
time_t ms = tv.tv_sec * 1000;
UInt32 high = (UInt32) (ms >> 32);
UInt32 low = (UInt32) ms;
sec = UInt64Create(high, low);
}
else
{
/* Assume 32 bit time_t: promote to 64 bit, then multiply, in
* case multiplication overflows 32 bits. */
sec = UInt64Create(0, tv.tv_sec);
sec = UInt64Mul(sec, UInt64Create(0, 1000));
}
usec = UInt64Create(0, tv.tv_usec / 1000);
ts = UInt64Add(sec, usec);
return ts; return ts;
} }
unsigned long UInt64
UtilLastModified(char *path) UtilLastModified(char *path)
{ {
struct stat st; struct stat st;
unsigned long ts; UInt64 ts = UInt64Create(0, 0);
if (stat(path, &st) == 0) if (stat(path, &st) == 0)
{ {
ts = (st.st_mtim.tv_sec * 1000) + (st.st_mtim.tv_nsec / 1000000); if (sizeof(time_t) == sizeof(UInt64))
return ts; {
} /* 64 bit time_t: convert it to a 64 bit integer */
else time_t ms = st.st_mtim.tv_sec * 1000;
{ UInt32 high = (UInt32) (ms >> 32);
return 0; UInt32 low = (UInt32) ms;
ts = UInt64Create(high, low);
}
else
{
ts = UInt64Create(0, st.st_mtim.tv_sec);
ts = UInt64Mul(ts, UInt64Create(0, 1000));
}
/* nsec gauanteed to fit in 32 bits */
ts = UInt64Add(ts, UInt64Create(0, st.st_mtim.tv_nsec / 1000000));
} }
return ts;
} }
int int
@ -149,13 +202,21 @@ UtilMkdir(const char *dir, const mode_t mode)
} }
int int
UtilSleepMillis(long ms) UtilSleepMillis(UInt64 ms)
{ {
struct timespec ts; struct timespec ts;
int res; int res;
ts.tv_sec = ms / 1000; if (sizeof(time_t) == sizeof(UInt64))
ts.tv_nsec = (ms % 1000) * 1000000; {
ts.tv_sec = ((time_t) UInt64High(ms) << 32 | UInt64Low(ms)) / 1000;
}
else
{
ts.tv_sec = UInt64Low(ms) / 1000;
}
ts.tv_nsec = UInt64Low(UInt64Rem(ms, UInt64Create(0, 1000))) * 1000000;
res = nanosleep(&ts, &ts); res = nanosleep(&ts, &ts);
@ -251,14 +312,14 @@ ThreadNoDestructor(void *p)
free(p); free(p);
} }
unsigned long UInt32
UtilThreadNo(void) UtilThreadNo(void)
{ {
static pthread_key_t key; static pthread_key_t key;
static int createdKey = 0; static int createdKey = 0;
static unsigned long count = 0; static unsigned long count = 0;
unsigned long *no; UInt32 *no;
if (!createdKey) if (!createdKey)
{ {
@ -269,7 +330,7 @@ UtilThreadNo(void)
no = pthread_getspecific(key); no = pthread_getspecific(key);
if (!no) if (!no)
{ {
no = malloc(sizeof(unsigned long)); no = malloc(sizeof(UInt32));
*no = count++; *no = count++;
pthread_setspecific(key, no); pthread_setspecific(key, no);
} }

View file

@ -56,6 +56,8 @@
* by any means. * by any means.
*/ */
#include <Int.h>
/** /**
* All functions defined here operate on a structure opaque to the * All functions defined here operate on a structure opaque to the
* caller. * caller.
@ -80,8 +82,7 @@ typedef void (JobFunc) (void *);
* .Pp * .Pp
* This function takes the tick interval in milliseconds. * This function takes the tick interval in milliseconds.
*/ */
extern Cron * extern Cron * CronCreate(UInt32);
CronCreate(unsigned long);
/** /**
* Schedule a one-off job to be executed only at the next tick, and * Schedule a one-off job to be executed only at the next tick, and

View file

@ -43,6 +43,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <Stream.h> #include <Stream.h>
#include <UInt64.h>
/** /**
* Get the current timestamp in milliseconds since the Unix epoch. This * Get the current timestamp in milliseconds since the Unix epoch. This
@ -60,7 +61,7 @@
* numbers than the architecture supports. But we can always * numbers than the architecture supports. But we can always
* re-evaluate over the next few years. * re-evaluate over the next few years.
*/ */
extern unsigned long UtilServerTs(void); extern UInt64 UtilServerTs(void);
/** /**
* Use * Use
@ -69,7 +70,7 @@ extern unsigned long UtilServerTs(void);
* was an error getting the last modified time of a file. This is * was an error getting the last modified time of a file. This is
* primarily useful for caching file data. * primarily useful for caching file data.
*/ */
extern unsigned long UtilLastModified(char *); extern UInt64 UtilLastModified(char *);
/** /**
* This function behaves just like the system call * This function behaves just like the system call
@ -85,7 +86,7 @@ extern int UtilMkdir(const char *, const mode_t);
* .Xr nanosleep 2 * .Xr nanosleep 2
* to make its usage much, much simpler. * to make its usage much, much simpler.
*/ */
extern int UtilSleepMillis(long); extern int UtilSleepMillis(UInt64);
/** /**
* This function works identically to the POSIX * This function works identically to the POSIX
@ -111,6 +112,6 @@ extern ssize_t UtilGetLine(char **, size_t *, Stream *);
* .Fn pthread_self * .Fn pthread_self
* to a number. * to a number.
*/ */
extern unsigned long UtilThreadNo(void); extern UInt32 UtilThreadNo(void);
#endif /* CYTOPLASM_UTIL_H */ #endif /* CYTOPLASM_UTIL_H */

View file

@ -3,7 +3,8 @@
#include <Log.h> #include <Log.h>
/* AssertEquals(actual, expected) */ /* AssertEquals(actual, expected) */
int AssertEquals(char *msg, Int64 x, Int64 y) int
AssertEquals(char *msg, Int64 x, Int64 y)
{ {
if (!Int64Eq(x, y)) if (!Int64Eq(x, y))
{ {
@ -17,9 +18,10 @@ int AssertEquals(char *msg, Int64 x, Int64 y)
return 1; return 1;
} }
int Main(void) int
Main(void)
{ {
Int64 x, y; Int64 x, y;
Log(LOG_INFO, "sizeof(Int64) = %lu", sizeof(Int64)); Log(LOG_INFO, "sizeof(Int64) = %lu", sizeof(Int64));
@ -31,9 +33,9 @@ int Main(void)
/* BSR Tests */ /* BSR Tests */
x = Int64Create(0x000000FF, 0x00000000); x = Int64Create(0x000000FF, 0x00000000);
y = Int64Sra(x, 4); y = Int64Sra(x, 4);
AssertEquals("x >> 4", y, Int64Create(0x0000000F, 0xF0000000)); AssertEquals("x >> 4", y, Int64Create(0x0000000F, 0xF0000000));
y = Int64Sra(x, 8); y = Int64Sra(x, 8);
@ -42,15 +44,15 @@ int Main(void)
y = Int64Sra(x, 36); y = Int64Sra(x, 36);
AssertEquals("x >> 36", y, Int64Create(0x00000000, 0x0000000F)); AssertEquals("x >> 36", y, Int64Create(0x00000000, 0x0000000F));
x = Int64Create(0xFF000000, 0x00000000); x = Int64Create(0xFF000000, 0x00000000);
y = Int64Sra(x, 4); y = Int64Sra(x, 4);
AssertEquals("x >> 4", y, Int64Create(0xFFF00000, 0x00000000)); AssertEquals("x >> 4", y, Int64Create(0xFFF00000, 0x00000000));
y = Int64Sra(x, 8); y = Int64Sra(x, 8);
AssertEquals("x >> 8", y, Int64Create(0xFFFF0000, 0x00000000)); AssertEquals("x >> 8", y, Int64Create(0xFFFF0000, 0x00000000));
y = Int64Sra(x, 63); y = Int64Sra(x, 63);
AssertEquals("x >> 63", y, Int64Create(0xFFFFFFFF, 0xFFFFFFFF)); AssertEquals("x >> 63", y, Int64Create(0xFFFFFFFF, 0xFFFFFFFF));
/* BSL Tests */ /* BSL Tests */
@ -76,9 +78,9 @@ int Main(void)
y = Int64Create(0x00000000, 0x10000000); y = Int64Create(0x00000000, 0x10000000);
AssertEquals("0xF0000000 + 0x10000000", Int64Add(x, y), Int64Create(0x00000001, 0x00000000)); AssertEquals("0xF0000000 + 0x10000000", Int64Add(x, y), Int64Create(0x00000001, 0x00000000));
x = Int64Create(0, 5); x = Int64Create(0, 5);
y = Int64Neg(Int64Create(0, 10)); y = Int64Neg(Int64Create(0, 10));
AssertEquals("5 + (-10)", Int64Add(x, y), Int64Neg(Int64Create(0, 5))); AssertEquals("5 + (-10)", Int64Add(x, y), Int64Neg(Int64Create(0, 5)));
/* SUB Tests */ /* SUB Tests */
x = Int64Create(0x00000000, 0x00000005); x = Int64Create(0x00000000, 0x00000005);
@ -89,13 +91,13 @@ int Main(void)
y = Int64Create(0x00000000, 0x00000001); y = Int64Create(0x00000000, 0x00000001);
AssertEquals("0x00000001 0x00000000 - 0x00000001", Int64Sub(x, y), Int64Create(0x00000000, 0xFFFFFFFF)); AssertEquals("0x00000001 0x00000000 - 0x00000001", Int64Sub(x, y), Int64Create(0x00000000, 0xFFFFFFFF));
x = Int64Create(0, 5); x = Int64Create(0, 5);
y = Int64Create(0, 10); y = Int64Create(0, 10);
AssertEquals("5 - 10", Int64Sub(x, y), Int64Neg(Int64Create(0, 5))); AssertEquals("5 - 10", Int64Sub(x, y), Int64Neg(Int64Create(0, 5)));
x = Int64Create(0, 5); x = Int64Create(0, 5);
y = Int64Neg(Int64Create(0, 10)); y = Int64Neg(Int64Create(0, 10));
AssertEquals("5 - (-10)", Int64Sub(x, y), Int64Create(0, 15)); AssertEquals("5 - (-10)", Int64Sub(x, y), Int64Create(0, 15));
/* MUL Tests */ /* MUL Tests */
x = Int64Create(0, 18); x = Int64Create(0, 18);
@ -136,7 +138,8 @@ int Main(void)
y = Int64Create(0x00000000, 0x00000010); y = Int64Create(0x00000000, 0x00000010);
AssertEquals("0x00000000 0x000000F0 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0)); AssertEquals("0x00000000 0x000000F0 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0));
/* TODO: Add more tests for negative multiplication, division, and mod */ /* TODO: Add more tests for negative multiplication, division, and
* mod */
return 0; return 0;
} }

View file

@ -40,7 +40,8 @@
static char * static char *
Trim(char c, char *str) Trim(char c, char *str)
{ {
while (*str == c) str++; while (*str == c)
str++;
return str; return str;
} }
@ -89,7 +90,7 @@ JsonTypeToStr(JsonType type)
{ {
switch (type) switch (type)
{ {
case JSON_OBJECT: case JSON_OBJECT:
return "JSON_OBJECT"; return "JSON_OBJECT";
case JSON_ARRAY: case JSON_ARRAY:
return "JSON_ARRAY"; return "JSON_ARRAY";
@ -355,6 +356,7 @@ Main(Array * args)
!StrEquals(fieldType, "boolean")) !StrEquals(fieldType, "boolean"))
{ {
Node *node = HashMapGet(typeToNode, fieldType); Node *node = HashMapGet(typeToNode, fieldType);
if (!node) if (!node)
{ {
node = Malloc(sizeof(Node)); node = Malloc(sizeof(Node));
@ -603,11 +605,11 @@ Main(Array * args)
StreamPrintf(implFile, " (void) enumParseRes;\n"); StreamPrintf(implFile, " (void) enumParseRes;\n");
StreamPrintf(implFile, "\n"); StreamPrintf(implFile, "\n");
StreamPrintf(implFile, " if (!json | !out)\n" StreamPrintf(implFile, " if (!json | !out)\n"
" {\n" " {\n"
" *errp = \"Invalid pointers passed to %sFromJson()\";\n" " *errp = \"Invalid pointers passed to %sFromJson()\";\n"
" return 0;\n" " return 0;\n"
" }\n\n" " }\n\n"
, type); ,type);
for (i = 0; i < ArraySize(keys); i++) for (i = 0; i < ArraySize(keys); i++)
{ {
char *key = ArrayGet(keys, i); char *key = ArrayGet(keys, i);
@ -875,8 +877,8 @@ Main(Array * args)
fieldType[strlen(fieldType) - 1] = '\0'; fieldType[strlen(fieldType) - 1] = '\0';
isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum"); isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum");
isPrimitive = StrEquals(fieldType, "integer") || isPrimitive = StrEquals(fieldType, "integer") ||
StrEquals(fieldType, "boolean") || StrEquals(fieldType, "boolean") ||
StrEquals(fieldType, "float"); StrEquals(fieldType, "float");
StreamPrintf(implFile, " if (val->%s)\n", key); StreamPrintf(implFile, " if (val->%s)\n", key);
@ -996,9 +998,9 @@ Main(Array * args)
fieldType[strlen(fieldType) - 1] = '\0'; fieldType[strlen(fieldType) - 1] = '\0';
isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum"); isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum");
isPrimitive = StrEquals(fieldType, "boolean") || isPrimitive = StrEquals(fieldType, "boolean") ||
StrEquals(fieldType, "float") || StrEquals(fieldType, "float") ||
StrEquals(fieldType, "integer") || StrEquals(fieldType, "integer") ||
StrEquals(fieldType, "string"); StrEquals(fieldType, "string");
StreamPrintf(implFile, " if (val->%s)\n", key); StreamPrintf(implFile, " if (val->%s)\n", key);
StreamPrintf(implFile, " {\n"); StreamPrintf(implFile, " {\n");
@ -1014,7 +1016,8 @@ Main(Array * args)
} }
else else
{ {
/* Ignore primitives but call the appropriate free method on declared types */ /* Ignore primitives but call the appropriate free
* method on declared types */
if (!isEnum && HashMapGet(types, fieldType)) if (!isEnum && HashMapGet(types, fieldType))
{ {
StreamPrintf(implFile, " %sFree(&val->%s);\n", fieldType, key); StreamPrintf(implFile, " %sFree(&val->%s);\n", fieldType, key);

View file

@ -3,7 +3,8 @@
#include <Log.h> #include <Log.h>
/* AssertEquals(actual, expected) */ /* AssertEquals(actual, expected) */
int AssertEquals(char *msg, UInt64 x, UInt64 y) int
AssertEquals(char *msg, UInt64 x, UInt64 y)
{ {
if (!UInt64Eq(x, y)) if (!UInt64Eq(x, y))
{ {
@ -17,9 +18,10 @@ int AssertEquals(char *msg, UInt64 x, UInt64 y)
return 1; return 1;
} }
int Main(void) int
Main(void)
{ {
UInt64 x, y; UInt64 x, y;
Log(LOG_INFO, "sizeof(UInt64) = %lu", sizeof(UInt64)); Log(LOG_INFO, "sizeof(UInt64) = %lu", sizeof(UInt64));
@ -31,9 +33,9 @@ int Main(void)
/* BSR Tests */ /* BSR Tests */
x = UInt64Create(0x000000FF, 0x00000000); x = UInt64Create(0x000000FF, 0x00000000);
y = UInt64Srl(x, 4); y = UInt64Srl(x, 4);
AssertEquals("x >> 4", y, UInt64Create(0x0000000F, 0xF0000000)); AssertEquals("x >> 4", y, UInt64Create(0x0000000F, 0xF0000000));
y = UInt64Srl(x, 8); y = UInt64Srl(x, 8);
@ -113,5 +115,5 @@ int Main(void)
y = UInt64Create(0x00000000, 0x00000010); y = UInt64Create(0x00000000, 0x00000010);
AssertEquals("0x00000000 0x000000F0 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0)); AssertEquals("0x00000000 0x000000F0 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0));
return 0; return 0;
} }