Xdumps don't contain records not in use, cope with that:

(xundump1, setnum, setstr, getobj, cur_id): Delay table lookup until
first field is about to be assigned.
(xundump1): Record largest ID, because it's no longer given by final
value of row.

(xuheader1, xundump1, xundump): Move initialization of cur_type to
xundump().
This commit is contained in:
Markus Armbruster 2006-02-13 21:22:05 +00:00
parent eae1e590cc
commit 46fcc27c6f

View file

@ -53,7 +53,7 @@
static char *fname; static char *fname;
static int lineno; static int lineno;
static int human; static int human;
static int cur_type; static int cur_type, cur_id;
static void *cur_obj; static void *cur_obj;
static int nflds; static int nflds;
static struct castr **fldca; static struct castr **fldca;
@ -315,6 +315,30 @@ getfld(int fldno, int *idx)
return fldca[fldno]; return fldca[fldno];
} }
static void *
getobj(struct castr *ca, int altid)
{
struct empfile *ep = &empfile[cur_type];
int need_sentinel = !EF_IS_GAME_STATE(cur_type);
if (!cur_obj) {
if (ca->ca_table == cur_type)
cur_id = altid;
if (cur_id >= ep->fids) {
/* TODO grow cache (and posssibly file) unless EFF_STATIC */
if (cur_id < ep->csize - !!need_sentinel)
ep->cids = ep->fids = cur_id + 1;
/* else: ef_ptr() will fail */
}
cur_obj = ef_ptr(cur_type, cur_id);
if (!cur_obj)
gripe("Can't put ID %d into table %s, it holds only 0..%d.",
cur_id, ep->name, ep->fids - 1);
}
return cur_obj;
}
static int static int
setnum(int fldno, double dbl) setnum(int fldno, double dbl)
{ {
@ -327,8 +351,11 @@ setnum(int fldno, double dbl)
if (!ca) if (!ca)
return -1; return -1;
memb_ptr = cur_obj; memb_ptr = getobj(ca, (int)dbl);
if (!memb_ptr)
return -1;
memb_ptr += ca->ca_off; memb_ptr += ca->ca_off;
switch (ca->ca_type) { switch (ca->ca_type) {
case NSC_CHAR: case NSC_CHAR:
case NSC_TYPEID: case NSC_TYPEID:
@ -403,8 +430,11 @@ setstr(int fldno, char *str)
if (!ca) if (!ca)
return -1; return -1;
memb_ptr = cur_obj; memb_ptr = getobj(ca, cur_id);
if (!memb_ptr)
return -1;
memb_ptr += ca->ca_off; memb_ptr += ca->ca_off;
switch (ca->ca_type) { switch (ca->ca_type) {
case NSC_STRING: case NSC_STRING:
old = ((char **)memb_ptr)[idx]; old = ((char **)memb_ptr)[idx];
@ -571,8 +601,6 @@ xuheader1(FILE *fp, int type, struct castr ca[])
int *fidx; int *fidx;
int ch, i, j, n; int ch, i, j, n;
cur_type = type;
if (human) { if (human) {
while ((ch = skipfs(fp)) == '\n') while ((ch = skipfs(fp)) == '\n')
lineno++; lineno++;
@ -648,6 +676,7 @@ xundump(FILE *fp, char *file, int expected_table)
fldca = calloc(nflds, sizeof(*fldca)); fldca = calloc(nflds, sizeof(*fldca));
fldidx = calloc(nflds, sizeof(*fldidx)); fldidx = calloc(nflds, sizeof(*fldidx));
caflds = calloc(nca, sizeof(*caflds)); caflds = calloc(nca, sizeof(*caflds));
cur_type = type;
if (xuheader1(fp, type, ca) < 0 || xundump1(fp, type, ca) < 0) if (xuheader1(fp, type, ca) < 0 || xundump1(fp, type, ca) < 0)
type = EF_BAD; type = EF_BAD;
@ -669,48 +698,40 @@ xundump1(FILE *fp, int type, struct castr *ca)
{ {
struct empfile *ep = &empfile[type]; struct empfile *ep = &empfile[type];
int need_sentinel = !EF_IS_GAME_STATE(type); int need_sentinel = !EF_IS_GAME_STATE(type);
int row, ch; int row, n, ch;
cur_type = type;
n = 0;
for (row = 0;; ++row) { for (row = 0;; ++row) {
while ((ch = skipfs(fp)) == '\n') while ((ch = skipfs(fp)) == '\n')
lineno++; lineno++;
if (ch == '/') if (ch == '/')
break; break;
ungetc(ch, fp); ungetc(ch, fp);
/* TODO ability to skip records */ cur_obj = NULL;
if (row >= ep->fids) { cur_id = row;
/* TODO grow cache (and posssibly file) unless EFF_STATIC */
if (row < ep->csize - !!need_sentinel)
ep->cids = ep->fids = row + 1;
/* else: ef_ptr() will fail */
}
cur_obj = ef_ptr(type, row);
if (!cur_obj)
return gripe("Too many rows for table %s", ef_nameof(type));
if (xuflds(fp, xufld) < 0) if (xuflds(fp, xufld) < 0)
return -1; return -1;
n = MAX(n, cur_id + 1);
} }
if (CANT_HAPPEN(row > ep->fids)) if (CANT_HAPPEN(n > ep->fids))
row = ep->fids; n = ep->fids;
if (row < ep->fids) { if (n < ep->fids) {
if (EF_IS_GAME_STATE(type) && row != ep->csize) if (EF_IS_GAME_STATE(type) && n != ep->csize)
/* TODO truncate file */ /* TODO truncate file */
gripe("Warning: should resize table %s from %d to %d, not implemented", gripe("Warning: should resize table %s from %d to %d, not implemented",
ef_nameof(type), ep->csize, row); ef_nameof(type), ep->csize, n);
else if (type >= EF_SHIP_CHR && type <= EF_NUKE_CHR) else if (type >= EF_SHIP_CHR && type <= EF_NUKE_CHR)
; /* shrinking these is okay */ ; /* shrinking these is okay */
else else
return gripe("Table %s requires %d rows, got %d", return gripe("Table %s requires %d rows, got %d",
ef_nameof(type), ep->fids, row); ef_nameof(type), ep->fids, n);
} }
if (need_sentinel) { if (need_sentinel) {
if (CANT_HAPPEN(row >= ep->csize)) if (CANT_HAPPEN(n >= ep->csize))
return gripe("No space for sentinel"); return gripe("No space for sentinel");
memset(ep->cache + ep->size * row, 0, ep->size); memset(ep->cache + ep->size * n, 0, ep->size);
} }
if (xutrailer(fp, type, row) < 0) if (xutrailer(fp, type, row) < 0)