inline void *operator new(size_t s) { return malloc(s); } inline void operator delete(void *p) { free(p); } class Record { public: enum FieldsType { Nothing, X, Y, State, Detail, Window, Width, Height, Keysym, MAX_FIELD }; static const char *get_field_name(FieldsType type); static FieldsType get_field_type(const char *name); enum RecordType { KeyDown, KeyUp, ButtonDown, ButtonUp, MouseMotion, WindowMove = 256, TargetWindow }; static const char *get_record_name(RecordType type); static RecordType get_record_type(const char *name); Record(RecordType _type, unsigned _time): fields_present(0), type(_type), time(_time) { } ~Record() { } RecordType get_type() const { return type; } unsigned get_time() const { return time; } bool has_field(FieldsType type) const { return ((fields_present >> type) & 1) != 0; } unsigned get_field(FieldsType type) const { if (!has_field(type)) { fprintf(stderr, "record has no field %d\n", type); exit(EXIT_FAILURE); } return fields[type]; } unsigned get_field(FieldsType type, unsigned def) const { if (!has_field(type)) return def; return fields[type]; } void set_field(FieldsType type, unsigned value) { fields_present |= 1u << type; fields[type] = value; } private: RecordType type; unsigned time; unsigned fields_present; unsigned fields[MAX_FIELD]; }; class RecordsFile { protected: RecordsFile(FILE *_f); ~RecordsFile() { fclose(f); } FILE *f; }; class ReadRecordsFile: public RecordsFile { public: ReadRecordsFile(const char *fn); bool at_eof() const { return eof; } Record get(); private: void get_line(); bool eof; char next_line[1024]; }; class WriteRecordsFile: public RecordsFile { public: WriteRecordsFile(const char *fn); void put(const Record &rec); };