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:
parent
eae1e590cc
commit
46fcc27c6f
1 changed files with 47 additions and 26 deletions
|
@ -53,7 +53,7 @@
|
|||
static char *fname;
|
||||
static int lineno;
|
||||
static int human;
|
||||
static int cur_type;
|
||||
static int cur_type, cur_id;
|
||||
static void *cur_obj;
|
||||
static int nflds;
|
||||
static struct castr **fldca;
|
||||
|
@ -315,6 +315,30 @@ getfld(int fldno, int *idx)
|
|||
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
|
||||
setnum(int fldno, double dbl)
|
||||
{
|
||||
|
@ -327,8 +351,11 @@ setnum(int fldno, double dbl)
|
|||
if (!ca)
|
||||
return -1;
|
||||
|
||||
memb_ptr = cur_obj;
|
||||
memb_ptr = getobj(ca, (int)dbl);
|
||||
if (!memb_ptr)
|
||||
return -1;
|
||||
memb_ptr += ca->ca_off;
|
||||
|
||||
switch (ca->ca_type) {
|
||||
case NSC_CHAR:
|
||||
case NSC_TYPEID:
|
||||
|
@ -403,8 +430,11 @@ setstr(int fldno, char *str)
|
|||
if (!ca)
|
||||
return -1;
|
||||
|
||||
memb_ptr = cur_obj;
|
||||
memb_ptr = getobj(ca, cur_id);
|
||||
if (!memb_ptr)
|
||||
return -1;
|
||||
memb_ptr += ca->ca_off;
|
||||
|
||||
switch (ca->ca_type) {
|
||||
case NSC_STRING:
|
||||
old = ((char **)memb_ptr)[idx];
|
||||
|
@ -571,8 +601,6 @@ xuheader1(FILE *fp, int type, struct castr ca[])
|
|||
int *fidx;
|
||||
int ch, i, j, n;
|
||||
|
||||
cur_type = type;
|
||||
|
||||
if (human) {
|
||||
while ((ch = skipfs(fp)) == '\n')
|
||||
lineno++;
|
||||
|
@ -648,6 +676,7 @@ xundump(FILE *fp, char *file, int expected_table)
|
|||
fldca = calloc(nflds, sizeof(*fldca));
|
||||
fldidx = calloc(nflds, sizeof(*fldidx));
|
||||
caflds = calloc(nca, sizeof(*caflds));
|
||||
cur_type = type;
|
||||
|
||||
if (xuheader1(fp, type, ca) < 0 || xundump1(fp, type, ca) < 0)
|
||||
type = EF_BAD;
|
||||
|
@ -669,48 +698,40 @@ xundump1(FILE *fp, int type, struct castr *ca)
|
|||
{
|
||||
struct empfile *ep = &empfile[type];
|
||||
int need_sentinel = !EF_IS_GAME_STATE(type);
|
||||
int row, ch;
|
||||
|
||||
cur_type = type;
|
||||
int row, n, ch;
|
||||
|
||||
n = 0;
|
||||
for (row = 0;; ++row) {
|
||||
while ((ch = skipfs(fp)) == '\n')
|
||||
lineno++;
|
||||
if (ch == '/')
|
||||
break;
|
||||
ungetc(ch, fp);
|
||||
/* TODO ability to skip records */
|
||||
if (row >= ep->fids) {
|
||||
/* 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));
|
||||
cur_obj = NULL;
|
||||
cur_id = row;
|
||||
if (xuflds(fp, xufld) < 0)
|
||||
return -1;
|
||||
n = MAX(n, cur_id + 1);
|
||||
}
|
||||
|
||||
if (CANT_HAPPEN(row > ep->fids))
|
||||
row = ep->fids;
|
||||
if (row < ep->fids) {
|
||||
if (EF_IS_GAME_STATE(type) && row != ep->csize)
|
||||
if (CANT_HAPPEN(n > ep->fids))
|
||||
n = ep->fids;
|
||||
if (n < ep->fids) {
|
||||
if (EF_IS_GAME_STATE(type) && n != ep->csize)
|
||||
/* TODO truncate file */
|
||||
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)
|
||||
; /* shrinking these is okay */
|
||||
else
|
||||
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 (CANT_HAPPEN(row >= ep->csize))
|
||||
if (CANT_HAPPEN(n >= ep->csize))
|
||||
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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue