aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2017-10-01 09:59:50 +0100
committerSimon Tatham <anakin@pobox.com>2017-10-01 10:38:01 +0100
commit9e62c710dfba0596eb355b95c46fd5153f5fe13d (patch)
tree7a097e15c860d5a9b9371da6bc76b6672c0cff2d
parentc0503d48738851ac31cd49ee98afa4f3e431d64a (diff)
downloadpuzzles-9e62c710dfba0596eb355b95c46fd5153f5fe13d.zip
puzzles-9e62c710dfba0596eb355b95c46fd5153f5fe13d.tar.gz
puzzles-9e62c710dfba0596eb355b95c46fd5153f5fe13d.tar.bz2
puzzles-9e62c710dfba0596eb355b95c46fd5153f5fe13d.tar.xz
midend_deserialise: accept an extra validation function.
This will let me do a 'conditional deserialisation' operation, in which we fully decode the serialised data and then (assuming that gave no errors) decide whether or not to actually install it based on some arbitrary condition. I don't think there's any possible use for the extra check function _outside_ midend.c, so I've left the API for front ends as it is; the externally visible midend_deserialise() doesn't have the new parameter, and only midend_deserialise_internal() includes it.
-rw-r--r--midend.c35
1 files changed, 31 insertions, 4 deletions
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;
@@ -2008,6 +2022,13 @@ char *midend_deserialise(midend *me,
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
* midend. We'll do this by swapping things with the local
@@ -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