83 lines
1.9 KiB
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);
|
|
}
|