/* * Exact matches can use bsearch. */ int blist_match(BLIST * data, const char *name) { int rc = -1; int last = blist_count(data); void *check; ToFind dummy; dummy.name = name; check = bsearch(&dummy, data->theList, (size_t) last, data->itemSize, exact_match); if (check != 0) { rc = (int) ItemToInx(data, check); } COUNTER(total_linear, rc + 1); COUNTER(total_limits, last); COUNTER(total_calls, 1); return rc; }
/* * Given what may be part of the name (length in 'len'), look for a match. * If the result is ambiguous, do not match unless the given name exactly * matches one item. */ int blist_pmatch(BLIST * data, const char *name, int len) { int actual = (int) strlen(name); int rc = -1; int hi, lo, x0, x1, cmp; int last = blist_count(data); const char *item; const char *test; if (len < 0 || len > actual) len = actual; x1 = -1; hi = last - 1; lo = 0; do { x0 = x1; x1 = lo + (hi - lo) / 2; if (x0 == x1) { if (++x1 > hi) break; } item = ItemOf(data, x1); cmp = strncmp(item, name, (size_t) len); if (cmp < 0) { lo = (x1 == lo) ? (x1 + 1) : x1; } else if (cmp > 0) { hi = (x1 == hi) ? (x1 - 1) : x1; } else { rc = x1; /* * Check for an exact match... */ COUNTER(total_compares, 1); if (strcmp(item, name)) { if (x1 > lo) { ToFind dummy; dummy.name = name; test = (const char *) bsearch(&dummy, &ItemOf(data, lo), (size_t) (x1 + 1 - lo), (size_t) data->itemSize, exact_match); if (test) { rc = (int) ItemToInx(data, test); break; } } } /* * Now - if we have not found an exact match, check for ambiguity. */ if (rc >= 0) { if (len > (int) strlen(item)) { rc = -1; } else if (x1 < last - 1) { COUNTER(total_compares, 2); if (strcmp(item, name) && !strncmp(ItemOf(data, x1 + 1), name, (size_t) len)) { rc = -1; } } } break; } } while (hi >= lo); COUNTER(total_linear, rc + 2); COUNTER(total_limits, last); COUNTER(total_calls, 1); return rc; }