size_t
ss_table_indirect(ss_table_t *table, /* Table in which IDX exists */
size_t idx, /* Index for the object for which we are searching for an indirect index. This
* is usually a direct index but doesn't necessarily have to be such. */
size_t beyond /* Return an indirect index greater than this value. A value of zero means to
* return the first indirect index. This argument can be used to scan through
* a table looking for all matching indirect indices for a particular direct
* index. If this is a direct index (such as zero) then the first matching
* indirect index is returned. */
)
{
SS_ENTER(ss_table_indirect, size_t);
ss_persobj_t *persobj=NULL;
size_t retval = SS_NOSIZE;
size_t first_subtab, subtabidx, nelmts, i;
SS_ASSERT_TYPE(table, ss_table_t);
SS_ASSERT(SS_TABLE_STATE_READ==table->state || SS_TABLE_STATE_CLOSED==table->state);
if (SS_NOSIZE==beyond) SS_ERROR_FMT(USAGE, ("BEYOND is out of range"));
/* Get the object address and minimum return value */
if (NULL==(persobj=ss_table_lookup(table, idx, SS_STRICT))) SS_ERROR(FAILED);
if (beyond & SS_TABLE_INDIRECT) {
beyond++;
first_subtab = ss_table_localidx(&beyond);
} else {
first_subtab = beyond = 0;
}
/* Scan through the indirect pointers to find the first one that points to persobj */
for (subtabidx=first_subtab; subtabidx<SS_NSUBTABLES; subtabidx++) {
if (NULL==table->maptab[subtabidx]) continue;
nelmts = ss_table_subsize(subtabidx);
for (i=beyond; i<nelmts; i++) {
if (table->maptab[subtabidx][i]==persobj) {
retval = SS_TABLE_INDIRECT | ss_table_globalidx(subtabidx, i);
goto done;
}
}
beyond = 0; /*start at zero in the next subtable*/
}
done:
SS_CLEANUP:
SS_LEAVE(retval);
}