introducing new callback system

This commit is contained in:
Enno Rehling 2014-07-03 05:10:53 -07:00
parent ee1d97df19
commit 162375842b
5 changed files with 124 additions and 0 deletions

View file

@ -59,6 +59,7 @@ ENDIF()
set (ERESSEA_SRC set (ERESSEA_SRC
eressea.c eressea.c
callback.c
direction.c direction.c
keyword.c keyword.c
skill.c skill.c
@ -146,6 +147,7 @@ set(TESTS_SRC
test_eressea.c test_eressea.c
tests.c tests.c
tests.test.c tests.test.c
callback.test.c
direction.test.c direction.test.c
keyword.test.c keyword.test.c
skill.test.c skill.test.c

54
src/callback.c Normal file
View file

@ -0,0 +1,54 @@
#include "callback.h"
#include <stdlib.h>
#include <string.h>
static struct reg {
struct reg * next;
CALLBACK cb;
const char *name;
} *registry;
CALLBACK create_callback(void (*cbv)(va_list va)) {
CALLBACK cb;
cb.cbv = cbv;
return cb;
}
void reset_callbacks(void) {
registry = 0;
}
CALLBACK register_callback(const char *name, void (*cbv)(va_list va))
{
struct reg * r = (struct reg *)malloc(sizeof(struct reg));
r->next = registry;
r->name = name;
r->cb.cbv = cbv;
registry = r;
return r->cb;
}
int find_callback(const char *name, CALLBACK *result) {
if (result && name) {
struct reg *r;
for (r=registry;r;r=r->next) {
if (strcmp(r->name, name)==0) {
*result = r->cb;
return 0;
}
}
}
return -1;
}
int call_callback(CALLBACK cb, const char *name, ... ) {
va_list ap;
if (name) {
int err = find_callback(name, &cb);
if (err) return err;
}
va_start(ap, name);
cb.cbv(ap);
va_end(ap);
return 0;
}

16
src/callback.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef H_CALLBACK_H
#define H_CALLBACK_H
#include <stdarg.h>
typedef struct {
void (*cbv)(va_list va);
} CALLBACK;
CALLBACK register_callback(const char *name, void (*cbv)(va_list va));
CALLBACK create_callback(void (*cbv)(va_list va));
int find_callback(const char *name, CALLBACK *result);
int call_callback(CALLBACK cb, const char *name, ...);
void reset_callbacks(void);
#endif

50
src/callback.test.c Normal file
View file

@ -0,0 +1,50 @@
#include "callback.h"
#include <stdlib.h>
#include <CuTest.h>
void callback(va_list ap) {
int i = (int)va_arg(ap, int);
int *p = va_arg(ap, int *);
*p += i;
}
static void test_find_callback(CuTest *tc) {
CALLBACK cb;
reset_callbacks();
CuAssertIntEquals(tc, -1, find_callback("test", &cb));
cb = register_callback("test", callback);
CuAssertIntEquals(tc, 0, find_callback("test", &cb));
reset_callbacks();
}
static void test_call_by_handle(CuTest *tc) {
CALLBACK cb;
int x = 0;
reset_callbacks();
cb = create_callback(callback);
CuAssertIntEquals(tc, 0, call_callback(cb, 0, 42, &x));
CuAssertIntEquals(tc, 42, x);
reset_callbacks();
}
static void test_call_by_name(CuTest *tc) {
CALLBACK cb, ca;
int x = 0;
reset_callbacks();
CuAssertIntEquals(tc, -1, call_callback(cb, "test", 42, &x));
cb = register_callback("test", callback);
CuAssertIntEquals(tc, 0, call_callback(cb, "test", 42, &x));
CuAssertIntEquals(tc, 42, x);
CuAssertIntEquals(tc, 0, call_callback(ca, "test", 42, &x));
CuAssertIntEquals(tc, 84, x);
reset_callbacks();
}
CuSuite *get_callback_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_find_callback);
SUITE_ADD_TEST(suite, test_call_by_name);
SUITE_ADD_TEST(suite, test_call_by_handle);
return suite;
}

View file

@ -3,6 +3,7 @@
#include <util/log.h> #include <util/log.h>
CuSuite *get_tests_suite(void); CuSuite *get_tests_suite(void);
CuSuite *get_callback_suite(void);
CuSuite *get_jsonconf_suite(void); CuSuite *get_jsonconf_suite(void);
CuSuite *get_json_suite(void); CuSuite *get_json_suite(void);
CuSuite *get_economy_suite(void); CuSuite *get_economy_suite(void);
@ -41,6 +42,7 @@ int RunAllTests(void)
/* self-test */ /* self-test */
CuSuiteAddSuite(suite, get_tests_suite()); CuSuiteAddSuite(suite, get_tests_suite());
CuSuiteAddSuite(suite, get_callback_suite());
CuSuiteAddSuite(suite, get_json_suite()); CuSuiteAddSuite(suite, get_json_suite());
CuSuiteAddSuite(suite, get_jsonconf_suite()); CuSuiteAddSuite(suite, get_jsonconf_suite());
CuSuiteAddSuite(suite, get_direction_suite()); CuSuiteAddSuite(suite, get_direction_suite());