ref: c0503d48738851ac31cd49ee98afa4f3e431d64a
parent: cdf163953105e37b4c90838227342c4eb2cab670
author: Simon Tatham <anakin@pobox.com>
date: Sun Oct 1 05:50:22 EDT 2017
midend_deserialise: keep deserialised data in a struct. Lots of the local variables in midend_deserialise are now fields of a structure which contains everything that is _going_ to be written into the midend once we finish validating it all. This makes it easy to keep all that data together, and (in future) pass it to other functions all in one go. No functional change.
--- a/midend.c
+++ b/midend.c
@@ -94,6 +94,22 @@
} \
} while (0)
+/*
+ * Structure storing all the decoded data from reading a serialised
+ * game. We keep it in one of these while we check its sanity, and
+ * only once we're completely satisfied do we install it all in the
+ * midend structure proper.
+ */
+struct deserialise_data {
+ char *seed, *parstr, *desc, *privdesc;
+ char *auxinfo, *uistr, *cparstr;
+ float elapsed;
+ game_params *params, *cparams;
+ game_ui *ui;
+ struct midend_state_entry *states;
+ int nstates, statepos;
+};
+
void midend_reset_tilesize(midend *me)
{
me->preferred_tilesize = me->ourgame->preferred_tilesize;
@@ -1754,7 +1770,8 @@
int (*read)(void *ctx, void *buf, int len),
void *rctx)
{
- int nstates = 0, statepos = -1, gotstates = 0;
+ struct deserialise_data data;
+ int gotstates = 0;
int started = FALSE;
int i;
@@ -1762,18 +1779,14 @@
/* Initially all errors give the same report */
char *ret = "Data does not appear to be a saved game file";
- /*
- * We construct all the new state in local variables while we
- * check its sanity. Only once we have finished reading the
- * serialised data and detected no errors at all do we start
- * modifying stuff in the midend passed in.
- */
- char *seed = NULL, *parstr = NULL, *desc = NULL, *privdesc = NULL;
- char *auxinfo = NULL, *uistr = NULL, *cparstr = NULL;
- float elapsed = 0.0F;
- game_params *params = NULL, *cparams = NULL;
- game_ui *ui = NULL;
- struct midend_state_entry *states = NULL;
+ data.seed = data.parstr = data.desc = data.privdesc = NULL;
+ data.auxinfo = data.uistr = data.cparstr = NULL;
+ data.elapsed = 0.0F;
+ data.params = data.cparams = NULL;
+ data.ui = NULL;
+ data.states = NULL;
+ data.nstates = 0;
+ data.statepos = -1;
/*
* Loop round and round reading one key/value pair at a time
@@ -1780,7 +1793,8 @@
* from the serialised stream, until we have enough game states
* to finish.
*/
- while (nstates <= 0 || statepos < 0 || gotstates < nstates-1) {
+ while (data.nstates <= 0 || data.statepos < 0 ||
+ gotstates < data.nstates-1) {
char key[9], c;
int len;
@@ -1852,24 +1866,24 @@
goto cleanup;
}
} else if (!strcmp(key, "PARAMS")) {
- sfree(parstr);
- parstr = val;
+ sfree(data.parstr);
+ data.parstr = val;
val = NULL;
} else if (!strcmp(key, "CPARAMS")) {
- sfree(cparstr);
- cparstr = val;
+ sfree(data.cparstr);
+ data.cparstr = val;
val = NULL;
} else if (!strcmp(key, "SEED")) {
- sfree(seed);
- seed = val;
+ sfree(data.seed);
+ data.seed = val;
val = NULL;
} else if (!strcmp(key, "DESC")) {
- sfree(desc);
- desc = val;
+ sfree(data.desc);
+ data.desc = val;
val = NULL;
} else if (!strcmp(key, "PRIVDESC")) {
- sfree(privdesc);
- privdesc = val;
+ sfree(data.privdesc);
+ data.privdesc = val;
val = NULL;
} else if (!strcmp(key, "AUXINFO")) {
unsigned char *tmp;
@@ -1877,49 +1891,49 @@
tmp = hex2bin(val, len);
obfuscate_bitmap(tmp, len*8, TRUE);
- sfree(auxinfo);
- auxinfo = snewn(len + 1, char);
- memcpy(auxinfo, tmp, len);
- auxinfo[len] = '\0';
+ sfree(data.auxinfo);
+ data.auxinfo = snewn(len + 1, char);
+ memcpy(data.auxinfo, tmp, len);
+ data.auxinfo[len] = '\0';
sfree(tmp);
} else if (!strcmp(key, "UI")) {
- sfree(uistr);
- uistr = val;
+ sfree(data.uistr);
+ data.uistr = val;
val = NULL;
} else if (!strcmp(key, "TIME")) {
- elapsed = (float)atof(val);
+ data.elapsed = (float)atof(val);
} else if (!strcmp(key, "NSTATES")) {
- nstates = atoi(val);
- if (nstates <= 0) {
+ data.nstates = atoi(val);
+ if (data.nstates <= 0) {
ret = "Number of states in save file was negative";
goto cleanup;
}
- if (states) {
+ if (data.states) {
ret = "Two state counts provided in save file";
goto cleanup;
}
- states = snewn(nstates, struct midend_state_entry);
- for (i = 0; i < nstates; i++) {
- states[i].state = NULL;
- states[i].movestr = NULL;
- states[i].movetype = NEWGAME;
+ data.states = snewn(data.nstates, struct midend_state_entry);
+ for (i = 0; i < data.nstates; i++) {
+ data.states[i].state = NULL;
+ data.states[i].movestr = NULL;
+ data.states[i].movetype = NEWGAME;
}
} else if (!strcmp(key, "STATEPOS")) {
- statepos = atoi(val);
+ data.statepos = atoi(val);
} else if (!strcmp(key, "MOVE")) {
gotstates++;
- states[gotstates].movetype = MOVE;
- states[gotstates].movestr = val;
+ data.states[gotstates].movetype = MOVE;
+ data.states[gotstates].movestr = val;
val = NULL;
} else if (!strcmp(key, "SOLVE")) {
gotstates++;
- states[gotstates].movetype = SOLVE;
- states[gotstates].movestr = val;
+ data.states[gotstates].movetype = SOLVE;
+ data.states[gotstates].movestr = val;
val = NULL;
} else if (!strcmp(key, "RESTART")) {
gotstates++;
- states[gotstates].movetype = RESTART;
- states[gotstates].movestr = val;
+ data.states[gotstates].movetype = RESTART;
+ data.states[gotstates].movestr = val;
val = NULL;
}
}
@@ -1928,68 +1942,70 @@
val = NULL;
}
- params = me->ourgame->default_params();
- me->ourgame->decode_params(params, parstr);
- if (me->ourgame->validate_params(params, TRUE)) {
+ data.params = me->ourgame->default_params();
+ me->ourgame->decode_params(data.params, data.parstr);
+ if (me->ourgame->validate_params(data.params, TRUE)) {
ret = "Long-term parameters in save file are invalid";
goto cleanup;
}
- cparams = me->ourgame->default_params();
- me->ourgame->decode_params(cparams, cparstr);
- if (me->ourgame->validate_params(cparams, FALSE)) {
+ data.cparams = me->ourgame->default_params();
+ me->ourgame->decode_params(data.cparams, data.cparstr);
+ if (me->ourgame->validate_params(data.cparams, FALSE)) {
ret = "Short-term parameters in save file are invalid";
goto cleanup;
}
- if (seed && me->ourgame->validate_params(cparams, TRUE)) {
+ if (data.seed && me->ourgame->validate_params(data.cparams, TRUE)) {
/*
* The seed's no use with this version, but we can perfectly
* well use the rest of the data.
*/
- sfree(seed);
- seed = NULL;
+ sfree(data.seed);
+ data.seed = NULL;
}
- if (!desc) {
+ if (!data.desc) {
ret = "Game description in save file is missing";
goto cleanup;
- } else if (me->ourgame->validate_desc(cparams, desc)) {
+ } else if (me->ourgame->validate_desc(data.cparams, data.desc)) {
ret = "Game description in save file is invalid";
goto cleanup;
}
- if (privdesc && me->ourgame->validate_desc(cparams, privdesc)) {
+ if (data.privdesc &&
+ me->ourgame->validate_desc(data.cparams, data.privdesc)) {
ret = "Game private description in save file is invalid";
goto cleanup;
}
- if (statepos < 0 || statepos >= nstates) {
+ if (data.statepos < 0 || data.statepos >= data.nstates) {
ret = "Game position in save file is out of range";
}
- states[0].state = me->ourgame->new_game(me, cparams,
- privdesc ? privdesc : desc);
- for (i = 1; i < nstates; i++) {
- assert(states[i].movetype != NEWGAME);
- switch (states[i].movetype) {
+ data.states[0].state = me->ourgame->new_game(
+ me, data.cparams, data.privdesc ? data.privdesc : data.desc);
+ for (i = 1; i < data.nstates; i++) {
+ assert(data.states[i].movetype != NEWGAME);
+ switch (data.states[i].movetype) {
case MOVE:
case SOLVE:
- states[i].state = me->ourgame->execute_move(states[i-1].state,
- states[i].movestr);
- if (states[i].state == NULL) {
+ data.states[i].state = me->ourgame->execute_move(
+ data.states[i-1].state, data.states[i].movestr);
+ if (data.states[i].state == NULL) {
ret = "Save file contained an invalid move";
goto cleanup;
}
break;
case RESTART:
- if (me->ourgame->validate_desc(cparams, states[i].movestr)) {
+ if (me->ourgame->validate_desc(
+ data.cparams, data.states[i].movestr)) {
ret = "Save file contained an invalid restart move";
goto cleanup;
}
- states[i].state = me->ourgame->new_game(me, cparams,
- states[i].movestr);
+ data.states[i].state = me->ourgame->new_game(
+ me, data.cparams, data.states[i].movestr);
break;
}
}
- ui = me->ourgame->new_ui(states[0].state);
- me->ourgame->decode_ui(ui, uistr);
+ data.ui = me->ourgame->new_ui(data.states[0].state);
+ me->ourgame->decode_ui(data.ui, data.uistr);
/*
* Now we've run out of possible error conditions, so we're
@@ -2002,45 +2018,45 @@
char *tmp;
tmp = me->desc;
- me->desc = desc;
- desc = tmp;
+ me->desc = data.desc;
+ data.desc = tmp;
tmp = me->privdesc;
- me->privdesc = privdesc;
- privdesc = tmp;
+ me->privdesc = data.privdesc;
+ data.privdesc = tmp;
tmp = me->seedstr;
- me->seedstr = seed;
- seed = tmp;
+ me->seedstr = data.seed;
+ data.seed = tmp;
tmp = me->aux_info;
- me->aux_info = auxinfo;
- auxinfo = tmp;
+ me->aux_info = data.auxinfo;
+ data.auxinfo = tmp;
}
me->genmode = GOT_NOTHING;
- me->statesize = nstates;
- nstates = me->nstates;
+ me->statesize = data.nstates;
+ data.nstates = me->nstates;
me->nstates = me->statesize;
{
struct midend_state_entry *tmp;
tmp = me->states;
- me->states = states;
- states = tmp;
+ me->states = data.states;
+ data.states = tmp;
}
- me->statepos = statepos;
+ me->statepos = data.statepos;
{
game_params *tmp;
tmp = me->params;
- me->params = params;
- params = tmp;
+ me->params = data.params;
+ data.params = tmp;
tmp = me->curparams;
- me->curparams = cparams;
- cparams = tmp;
+ me->curparams = data.cparams;
+ data.cparams = tmp;
}
me->oldstate = NULL;
@@ -2051,11 +2067,11 @@
game_ui *tmp;
tmp = me->ui;
- me->ui = ui;
- ui = tmp;
+ me->ui = data.ui;
+ data.ui = tmp;
}
- me->elapsed = elapsed;
+ me->elapsed = data.elapsed;
me->pressed_mouse_button = 0;
midend_set_timer(me);
@@ -2073,28 +2089,28 @@
cleanup:
sfree(val);
- sfree(seed);
- sfree(parstr);
- sfree(cparstr);
- sfree(desc);
- sfree(privdesc);
- sfree(auxinfo);
- sfree(uistr);
- if (params)
- me->ourgame->free_params(params);
- if (cparams)
- me->ourgame->free_params(cparams);
- if (ui)
- me->ourgame->free_ui(ui);
- if (states) {
+ sfree(data.seed);
+ sfree(data.parstr);
+ sfree(data.cparstr);
+ sfree(data.desc);
+ sfree(data.privdesc);
+ sfree(data.auxinfo);
+ sfree(data.uistr);
+ if (data.params)
+ me->ourgame->free_params(data.params);
+ if (data.cparams)
+ me->ourgame->free_params(data.cparams);
+ if (data.ui)
+ me->ourgame->free_ui(data.ui);
+ if (data.states) {
int i;
- for (i = 0; i < nstates; i++) {
- if (states[i].state)
- me->ourgame->free_game(states[i].state);
- sfree(states[i].movestr);
+ for (i = 0; i < data.nstates; i++) {
+ if (data.states[i].state)
+ me->ourgame->free_game(data.states[i].state);
+ sfree(data.states[i].movestr);
}
- sfree(states);
+ sfree(data.states);
}
return ret;