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;
}
/*
- * 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;
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
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