diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2015-08-14 17:35:13 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2015-08-14 17:35:13 +0100 |
commit | 936104345884610f0af36b3cb5831ad9fafa0892 (patch) | |
tree | 6fc052e1c2080825e4de02c520f9700b2995e61a /rec.cpp | |
parent | 392ca7209559f030500c13b9ebc9779c58ecbbb2 (diff) |
Use text format instead of binary one. Much easier to debug and you can
add comments too.
Do not use XI constants for the record.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Diffstat (limited to 'rec.cpp')
-rw-r--r-- | rec.cpp | 177 |
1 files changed, 122 insertions, 55 deletions
@@ -1,9 +1,67 @@ #include "config.h" #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "rec.h" +#define FIELD_TYPES \ + FIELD(X, "x") \ + FIELD(Y, "y") \ + FIELD(State, "state") \ + FIELD(Detail, "detail") \ + FIELD(Window, "win") \ + FIELD(Width, "w") \ + FIELD(Height, "h") \ + FIELD(Keysym, "keysym") + +const char *Record::get_field_name(FieldsType type) +{ +#define FIELD(t,n) case t: return n; + switch (type) { + FIELD_TYPES + } +#undef FIELD + return ""; +} + +Record::FieldsType Record::get_field_type(const char *name) +{ +#define FIELD(t,n) if (strcmp(name, n) == 0) return t; + FIELD_TYPES +#undef FIELD + fprintf(stderr, "Invalid field type %s\n", name); + exit(EXIT_FAILURE); +} + +#define RECORD_TYPES \ + RECORD(KeyDown, "key_down") \ + RECORD(KeyUp, "key_up") \ + RECORD(ButtonDown, "button_down") \ + RECORD(ButtonUp, "button_up") \ + RECORD(MouseMotion, "mouse_move") \ + RECORD(WindowMove, "window_move") \ + RECORD(TargetWindow, "target_window") + +const char *Record::get_record_name(RecordType type) +{ +#define RECORD(t,n) case t: return n; + switch (type) { + RECORD_TYPES + } +#undef RECORD + return ""; +} + +Record::RecordType Record::get_record_type(const char *name) +{ +#define RECORD(t,n) if (strcmp(name, n) == 0) return t; + RECORD_TYPES +#undef RECORD + fprintf(stderr, "Invalid record type\n"); + exit(EXIT_FAILURE); +} + RecordsFile::RecordsFile(FILE *_f): f(_f) { @@ -14,91 +72,100 @@ RecordsFile::RecordsFile(FILE *_f): } ReadRecordsFile::ReadRecordsFile(const char *fn): - RecordsFile(fopen(fn, "rb")), - eof(false), next(0) + RecordsFile(fopen(fn, "r")), + eof(false) { - get_number(); + get_line(); } -Record ReadRecordsFile::get() -{ - get_number(START_RECORD); - unsigned type = get_number(); - unsigned time = get_number(); - - Record rec(type, time); - for (;;) { - type = get_number(); - if (type == END_RECORD) - return rec; - if (type != FIELD) { - fprintf(stderr, "expected a field!\n"); - exit(EXIT_FAILURE); - } - type = get_number(); - if (type >= Record::MAX_FIELD) { - fprintf(stderr, "invalid field type!\n"); - exit(EXIT_FAILURE); - } - rec.set_field((Record::FieldsType) type, get_number()); - } -} +#define SPACES " \t\v\r\n" -unsigned -ReadRecordsFile::get_number() +void ReadRecordsFile::get_line() { if (eof) { fprintf(stderr, "trying to read past EOF\n"); exit(EXIT_FAILURE); } - unsigned res = next; - if (fread(&next, sizeof(next), 1, f) != 1) { - if (!feof(f)) { - fprintf (stderr, "end of file\n"); - exit(EXIT_FAILURE); - } - eof = true; + while (fgets(next_line, sizeof(next_line), f)) { + const char *p = next_line; + + // skip initial spaces + p += strspn(p, SPACES); + + // detect comments + if (!*p || *p == '#') + continue; + + // got line + return; } - return res; + + if (!feof(f)) { + fprintf (stderr, "error reading input file\n"); + exit(EXIT_FAILURE); + } + eof = true; } -void -ReadRecordsFile::get_number(unsigned n) +Record ReadRecordsFile::get() { - if (get_number() != n) { - fprintf (stderr, "expected %u in file position %lx\n", n, (unsigned long) ftell(f)); + char *line = next_line; + + // skip initial spaces + line += strspn(line, SPACES); + + // read time and command + int got = 0; + unsigned time; + char cmd[64]; + if (sscanf(line, "@%u %60[^" SPACES "]%n", &time, cmd, &got) < 2) { + fprintf (stderr, "error reading time: %s\n", next_line); exit(EXIT_FAILURE); } -} + Record::RecordType type = Record::get_record_type(cmd); + Record rec(type, time); + + char *p = line + got; + for (;;) { + char field[64]; + unsigned value; + + p += strspn(p, SPACES); + if (!*p) + break; + got = 0; + if (sscanf(p, "%60[^:]:%u%n", field, &value, &got) < 2 || got == 0) { + fprintf(stderr, "expected a field: %s\n", next_line); + exit(EXIT_FAILURE); + } + p += got; + + Record::FieldsType type = Record::get_field_type(field); + rec.set_field(type, value); + } + get_line(); + return rec; +} + WriteRecordsFile::WriteRecordsFile(const char *fn): - RecordsFile(fopen(fn, "wb")) + RecordsFile(fopen(fn, "w")) { } void WriteRecordsFile::put(const Record &rec) { - add_number(START_RECORD); - add_number(rec.get_type()); - add_number(rec.get_time()); + fprintf(f, "@%u %s", rec.get_time(), rec.get_record_name(rec.get_type())); for (unsigned n = 0; n < Record::MAX_FIELD; ++n) { Record::FieldsType type = (Record::FieldsType) n; if (!rec.has_field(type)) continue; - add_number(FIELD); - add_number(type); - add_number(rec.get_field(type)); + fprintf(f, " %s:%u", rec.get_field_name(type), rec.get_field(type)); } - add_number(END_RECORD); -} - -void WriteRecordsFile::add_number(unsigned num) -{ - fwrite(&num, sizeof(num), 1, f); + fprintf(f, "\n"); } - |