* - Normalize terminology: table/rows/columns or file/records/fields
* - Loading tables with NSC_STRING elements more than once leaks memory
* TODO:
- * - Check EFF_CFG tables are dense
* - Symbolic array indexes
* - Option to treat missing and unknown fields as warning, not error
* TODO, but hardly worth the effort:
static int partno; /* Counts from 0..#parts-1 */
static void *cur_obj; /* The object being read into */
static int cur_id; /* and its index in the table */
-static int cur_obj_is_blank;
+static int old_nelem;
static unsigned char *idgap; /* idgap && idgap[ID] iff part#0 lacks ID */
-static int idgap_max; /* FIXME */
+static int idgap_len; /* #elements in idgap[] */
static int human; /* Reading human-readable syntax? */
static int ellipsis; /* Header ended with ...? */
partno = 0;
cur_id = -1;
cur_obj = NULL;
+ old_nelem = type == EF_BAD ? 0 : ef_nelem(type);
idgap = NULL;
- idgap_max = 0;
+ idgap_len = 0;
}
/* End the current table. */
/*
* Seek to current table's ID-th record.
* ID must be acceptable.
- * Store it in cur_obj, and set cur_id and cur_obj_is_blank accordingly.
+ * Store it in cur_obj, and set cur_id accordingly.
* Return 0 on success, -1 on failure.
*/
static int
{
struct empfile *ep = &empfile[cur_type];
- cur_obj_is_blank = id >= ep->fids;
-
if (id >= ef_nelem(cur_type)) {
if (!ef_ensure_space(cur_type, id, 1))
return gripe("Can't put ID %d into table %s", id, ep->name);
/*
* Get the next object.
* Must not have a record index.
- * Store it in cur_obj, and set cur_id and cur_obj_is_blank accordingly.
+ * Store it in cur_obj, and set cur_id accordingly.
* Return 0 on success, -1 on failure.
*/
static int
/*
* Omit ID1..ID2-1.
+ * Reset the omitted objects to default state.
*/
static void
omit_ids(int id1, int id2)
if (id1 >= id2)
return;
- idgap = realloc(idgap, (id2 + 1) * sizeof(*idgap));
- for (i = idgap_max; i < id1; i++)
+ idgap = realloc(idgap, id2 * sizeof(*idgap));
+ for (i = idgap_len; i < id1; i++)
idgap[i] = 0;
- for (i = id1; i < id2; i++)
+ for (i = id1; i < id2; i++) {
+ ef_blank(cur_type, i, ef_ptr(cur_type, i));
idgap[i] = 1;
- idgap[id2] = 0;
- idgap_max = id2;
+ }
+ idgap_len = id2;
}
/*
int i;
for (i = id1; i < id2; i++) {
- if (i >= idgap_max || !idgap[i])
+ if (i >= idgap_len || !idgap[i])
return i;
}
return -1;
/*
* Get the next object, it has record index ID.
- * Store it in cur_obj, and set cur_id and cur_obj_is_blank accordingly.
+ * Store it in cur_obj, and set cur_id accordingly.
* Ensure we're omitting the same objects as the previous parts.
+ * Reset any omitted objects to default state.
* Return 0 on success, -1 on failure.
*/
static int
* Finish table part.
* If the table has variable length, truncate it.
* Else ensure we're omitting the same objects as the previous parts.
+ * Reset any omitted objects to default state.
* Return 0 on success, -1 on failure.
*/
static int
if (!ef_truncate(cur_type, cur_id + 1))
return -1;
} else {
- return gripe("Expected %d more rows",
- ep->fids - (cur_id + 1));
+ if (!may_omit_id)
+ return gripe("Expected %d more rows",
+ ep->fids - (cur_id + 1));
+ omit_ids(cur_id + 1, ep->fids);
}
} else {
exp_id = expected_id(cur_id + 1, ep->fids);
* it's for a const selector, unless the object is still blank, or
* it was already given in a previous part of a split table.
*/
- return (!cur_obj_is_blank && (fldca[fldno]->ca_flags & NSC_CONST))
+ return (cur_id < old_nelem && (fldca[fldno]->ca_flags & NSC_CONST))
|| fldidx[fldno] < cafldspp[i];
}