icfp12/ovm/trace.c

83 lines
1.9 KiB
C

#include "trace.h"
static void trace_entry_free(trace_entry_t *te) {
g_slice_free1(te->count*12 + 8, te);
}
static void _trace_entry_free(gpointer p, gpointer x) {
UNUSED(x);
trace_entry_free(p);
}
static trace_entry_t *trace_entry_new(guint32 timestamp, guint32 count) {
trace_entry_t *te = g_slice_alloc(count*12 + 8);
te->timestamp = timestamp;
te->count = count;
return te;
}
trace_t *trace_load(const gchar *filename) {
GError *err = NULL;
guint32 *buf = NULL;
gsize len = 0, i;
trace_t *trace = g_slice_new0(trace_t);
trace->data = g_ptr_array_new();
if (!g_file_get_contents(filename, (gchar**) &buf, &len, &err)) {
fprintf (stderr, "Unable to read file %s: %s\n", filename, err->message);
g_error_free (err);
exit(1);
}
if (len % 4 > 0) {
fprintf (stderr, "Solution: length not aligned\n");
exit(10);
}
len /= 4;
if (len < 10) {
fprintf (stderr, "Solution too short\n");
exit(10);
}
if (buf[0] != 0xCAFEBABE) {
fprintf (stderr, "Wrong magic in solution: 0x%X\n", (guint) buf[0]);
exit(10);
}
trace->magic = buf[0];
trace->team = buf[1];
trace->scenario = buf[2];
for (i = 3; i < len; ) {
guint32 timestamp, count;
trace_entry_t *te;
if (i+1 >= len) {
fprintf(stderr, "Solution: unexpected end of file (%i+1 >= %i)\n", (guint) i, (guint) len);
exit(10);
}
timestamp = buf[i++];
count = buf[i++];
if (i+count*3 > len) {
fprintf(stderr, "Solution: unexpected end of file (%i+%i*3 >= %i\n", (guint) i, (guint) count, (guint) len);
exit(10);
}
te = trace_entry_new(timestamp, count);
if (count > 0) memcpy(te->data, &buf[i], count * 12);
i += 3*count;
g_ptr_array_add(trace->data, te);
if (count == 0 && i < len) {
fprintf (stderr, "Solution: expected end of file (count = 0)\n");
}
}
return trace;
}
void trace_free(trace_t *trace) {
g_ptr_array_foreach(trace->data, _trace_entry_free, NULL);
}