summaryrefslogtreecommitdiff
path: root/rec.cpp
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-08-14 17:35:13 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-08-14 17:35:13 +0100
commit936104345884610f0af36b3cb5831ad9fafa0892 (patch)
tree6fc052e1c2080825e4de02c520f9700b2995e61a /rec.cpp
parent392ca7209559f030500c13b9ebc9779c58ecbbb2 (diff)
Rewrite output formatHEADmaster
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.cpp177
1 files changed, 122 insertions, 55 deletions
diff --git a/rec.cpp b/rec.cpp
index 70c37cf..7f4fd83 100644
--- a/rec.cpp
+++ b/rec.cpp
@@ -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");
}
-