diff --git a/midend.c b/midend.c index ddb734e..53ee0a2 100644 --- a/midend.c +++ b/midend.c @@ -110,6 +110,14 @@ struct deserialise_data { int nstates, statepos; }; +/* + * Forward reference. + */ +static char *midend_deserialise_internal( + midend *me, int (*read)(void *ctx, void *buf, int len), void *rctx, + char *(*check)(void *ctx, midend *, const struct deserialise_data *), + void *cctx); + void midend_reset_tilesize(midend *me) { me->preferred_tilesize = me->ourgame->preferred_tilesize; @@ -1764,11 +1772,17 @@ void midend_serialise(midend *me, } /* - * This function returns NULL on success, or an error message. + * Internal version of midend_deserialise, taking an extra check + * function to be called just before beginning to install things in + * the midend. + * + * Like midend_deserialise proper, this function returns NULL on + * success, or an error message. */ -char *midend_deserialise(midend *me, - int (*read)(void *ctx, void *buf, int len), - void *rctx) +static char *midend_deserialise_internal( + midend *me, int (*read)(void *ctx, void *buf, int len), void *rctx, + char *(*check)(void *ctx, midend *, const struct deserialise_data *data), + void *cctx) { struct deserialise_data data; int gotstates = 0; @@ -2007,6 +2021,13 @@ char *midend_deserialise(midend *me, data.ui = me->ourgame->new_ui(data.states[0].state); me->ourgame->decode_ui(data.ui, data.uistr); + /* + * Run the externally provided check function, and abort if it + * returns an error message. + */ + if (check && (ret = check(cctx, me, &data)) != NULL) + goto cleanup; /* error message is already in ret */ + /* * Now we've run out of possible error conditions, so we're * ready to start overwriting the real data in the current @@ -2116,6 +2137,12 @@ char *midend_deserialise(midend *me, return ret; } +char *midend_deserialise( + midend *me, int (*read)(void *ctx, void *buf, int len), void *rctx) +{ + return midend_deserialise_internal(me, read, rctx, NULL, NULL); +} + /* * This function examines a saved game file just far enough to * determine which game type it contains. It returns NULL on success