server/src/kernel/event.c
2019-09-13 21:35:44 +02:00

260 lines
5.6 KiB
C

#include <platform.h>
#include "event.h"
#include "attrib.h"
/* util includes */
#include <kernel/gamedata.h>
#include <util/log.h>
#include <util/strings.h>
#include <storage.h>
/* libc includes */
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
void write_triggers(struct storage *store, const trigger * t)
{
while (t) {
if (t->type->write) {
WRITE_TOK(store, t->type->name);
t->type->write(t, store);
}
t = t->next;
}
WRITE_TOK(store, "end");
}
int read_triggers(struct gamedata *data, trigger ** tp)
{
for (;;) {
trigger_type *ttype;
char zText[128];
READ_TOK(data->store, zText, sizeof(zText));
if (!strcmp(zText, "end"))
break;
ttype = tt_find(zText);
assert(ttype || !"unknown trigger-type");
*tp = t_new(ttype);
if (ttype->read) {
int i = ttype->read(*tp, data);
switch (i) {
case AT_READ_OK:
tp = &(*tp)->next;
break;
case AT_READ_FAIL:
t_free(*tp);
free(*tp);
*tp = NULL;
break;
default:
assert(!"invalid return value");
break;
}
}
}
return 0;
}
trigger *t_new(trigger_type * ttype)
{
trigger *t = calloc(1, sizeof(trigger));
if (!t) abort();
t->type = ttype;
if (ttype->initialize)
ttype->initialize(t);
return t;
}
void t_free(trigger * t)
{
if (t->type->finalize)
t->type->finalize(t);
}
void free_triggers(trigger * triggers)
{
while (triggers) {
trigger *t = triggers;
triggers = t->next;
t_free(t);
free(t);
}
}
int handle_triggers(trigger ** triggers, void *param)
{
trigger **tp = triggers;
while (*tp) {
trigger *t = *tp;
if (t->type->handle(t, param) != 0) {
*tp = t->next;
t_free(t);
free(t);
}
else
tp = &t->next;
}
return (*triggers != NULL);
}
/***
** at_eventhandler
**/
typedef struct handler_info {
char *event;
trigger *triggers;
} handler_info;
static void init_handler(variant *var)
{
var->v = calloc(1, sizeof(handler_info));
}
static void free_handler(variant *var)
{
handler_info *hi = (handler_info *)var->v;
free_triggers(hi->triggers);
free(hi->event);
free(hi);
}
static void
write_handler(const variant *var, const void *owner, struct storage *store)
{
handler_info *hi = (handler_info *)var->v;
WRITE_TOK(store, hi->event);
write_triggers(store, hi->triggers);
}
static int read_handler(variant *var, void *owner, gamedata *data)
{
struct storage *store = data->store;
char zText[128];
handler_info *hi = (handler_info *)var->v;
READ_TOK(store, zText, sizeof(zText));
hi->event = str_strdup(zText);
read_triggers(data, &hi->triggers);
if (hi->triggers != NULL) {
return AT_READ_OK;
}
return AT_READ_FAIL;
}
attrib_type at_eventhandler = {
"eventhandler",
init_handler,
free_handler,
NULL,
write_handler,
read_handler
};
struct trigger **get_triggers(struct attrib *ap, const char *eventname)
{
handler_info *td = NULL;
attrib *a = a_find(ap, &at_eventhandler);
while (a != NULL && a->type == &at_eventhandler) {
td = (handler_info *)a->data.v;
if (strcmp(td->event, eventname) == 0) {
return &td->triggers;
}
a = a->next;
}
return NULL;
}
void add_trigger(struct attrib **ap, const char *eventname, struct trigger *t)
{
trigger **tp;
handler_info *td = NULL;
attrib *a = a_find(*ap, &at_eventhandler);
assert(t->next == NULL);
while (a != NULL && a->type == &at_eventhandler) {
td = (handler_info *)a->data.v;
if (!strcmp(td->event, eventname)) {
break;
}
a = a->next;
}
if (a == NULL || a->type != &at_eventhandler) {
a = a_add(ap, a_new(&at_eventhandler));
td = (handler_info *)a->data.v;
td->event = str_strdup(eventname);
}
assert(td);
tp = &td->triggers;
while (*tp)
tp = &(*tp)->next;
*tp = t;
}
void handle_event(attrib * attribs, const char *eventname, void *data)
{
while (attribs) {
if (attribs->type == &at_eventhandler)
break;
attribs = attribs->nexttype;
}
while (attribs && attribs->type == &at_eventhandler) {
handler_info *tl = (handler_info *)attribs->data.v;
if (!strcmp(tl->event, eventname)) {
handler_info *tl = (handler_info *)attribs->data.v;
handle_triggers(&tl->triggers, data);
break;
}
attribs = attribs->next;
}
}
void t_add(struct trigger **tlist, struct trigger *t)
{
while (*tlist)
tlist = &(*tlist)->next;
*tlist = t;
}
static trigger_type *triggertypes;
void tt_register(trigger_type * tt)
{
tt->next = triggertypes;
triggertypes = tt;
}
trigger_type *tt_find(const char *name)
{
trigger_type *tt = triggertypes;
while (tt && strcmp(tt->name, name)!=0)
tt = tt->next;
return tt;
}
void
remove_triggers(struct attrib **ap, const char *eventname,
const trigger_type * tt)
{
trigger **tp = get_triggers(*ap, eventname);
if (tp == NULL)
return;
while (*tp) {
/* first, remove all gate-triggers */
trigger *t = *tp;
if (t->type == tt) {
*tp = t->next;
t_free(t);
free(t);
}
else
tp = &t->next;
}
}
/***
** default events
**/