chiark / gitweb /
midend_deserialise: accept an extra validation function.
[sgt-puzzles.git] / midend.c
index ddb734e4544c0c47b6436cf14655b0b907f768ac..53ee0a2338e42bfa7c1ce86c12865c5df69dcb26 100644 (file)
--- 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