]> git.pond.sub.org Git - empserver/commitdiff
Xdumps don't contain records not in use, cope with that:
authorMarkus Armbruster <armbru@pond.sub.org>
Mon, 13 Feb 2006 21:22:05 +0000 (21:22 +0000)
committerMarkus Armbruster <armbru@pond.sub.org>
Mon, 13 Feb 2006 21:22:05 +0000 (21:22 +0000)
(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().

src/lib/common/xundump.c

index 08ea4a9c54d58283a9546efde2354954fad026dc..c0edf93ea4619ec7198329aa0f100c23ac94d6af 100644 (file)
@@ -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)