diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-11-03 20:12:38 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-11-03 20:12:38 +0000 |
commit | c217be996d55560b6fbb2932ab498372306b2379 (patch) | |
tree | fbc188a15cd3d6dbc7cf8505f0bac1ad973d95f5 /src/common | |
parent | d4e339ed879ef60e645a2b2d1fea87aaecc342fe (diff) | |
download | tor-c217be996d55560b6fbb2932ab498372306b2379.tar.gz tor-c217be996d55560b6fbb2932ab498372306b2379.zip |
r14677@tombo: nickm | 2007-11-03 15:16:27 -0400
Add a smartlist_bsearch_idx function that gives more useful output than regular bsearch for the value-not-found case.
svn:r12360
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/container.c | 52 | ||||
-rw-r--r-- | src/common/container.h | 4 |
2 files changed, 54 insertions, 2 deletions
diff --git a/src/common/container.c b/src/common/container.c index 3432bd084b..02e095f359 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -490,21 +490,69 @@ smartlist_uniq(smartlist_t *sl, } /** Assuming the members of <b>sl</b> are in order, return a pointer to the - * member which matches <b>key</b>. Ordering and matching are defined by a - * <b>compare</b> function, which returns 0 on a match; less than 0 if key is + * member that matches <b>key</b>. Ordering and matching are defined by a + * <b>compare</b> function that returns 0 on a match; less than 0 if key is * less than member, and greater than 0 if key is greater then member. */ void * smartlist_bsearch(smartlist_t *sl, const void *key, int (*compare)(const void *key, const void **member)) { +#if 0 void ** r; + if (!sl->num_used) return NULL; r = bsearch(key, sl->list, sl->num_used, sizeof(void*), (int (*)(const void *, const void *))compare); return r ? *r : NULL; +#endif + int found, idx; + idx = smartlist_bsearch_idx(sl, key, compare, &found); + return found ? smartlist_get(sl, idx) : NULL; +} + +/** Assuming the members of <b>sl</b> are in order, return the index of the + * member that matches <b>key</b>. If no member matches, return the index of + * the first member greater than <b>key</b>, or smartlist_len(sl) if no member + * is greater than <b>key</b>. Set <b>found_out</b> to true on a match, to + * false otherwise. Ordering and matching are defined by a <b>compare</b> + * function that returns 0 on a match; less than 0 if key is less than member, + * and greater than 0 if key is greater then member. + */ +int +smartlist_bsearch_idx(const smartlist_t *sl, const void *key, + int (*compare)(const void *key, const void **member), + int *found_out) +{ + int hi = smartlist_len(sl) - 1, lo = 0, cmp, mid; + + while (lo <= hi) { + mid = (lo + hi) / 2; + cmp = compare(key, (const void**) &(sl->list[mid])); + if (cmp>0) { /* key > sl[mid] */ + lo = mid+1; + } else if (cmp<0) { /* key < sl[mid] */ + hi = mid-1; + } else { /* key == sl[mid] */ + *found_out = 1; + return mid; + } + } + /* lo > hi. */ + { + tor_assert(lo >= 0); + if (lo < smartlist_len(sl)) { + cmp = compare(key, (const void**) &(sl->list[lo])); + tor_assert(cmp < 0); + } else if (smartlist_len(sl)) { + cmp = compare(key, (const void**) &(sl->list[smartlist_len(sl)-1])); + tor_assert(cmp > 0); + } + } + *found_out = 0; + return lo; } /** Helper: compare two const char **s. */ diff --git a/src/common/container.h b/src/common/container.h index 35ba743173..bbf654f5f2 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -106,6 +106,10 @@ void smartlist_uniq_digests(smartlist_t *sl); void *smartlist_bsearch(smartlist_t *sl, const void *key, int (*compare)(const void *key, const void **member)) ATTR_PURE; +int smartlist_bsearch_idx(const smartlist_t *sl, const void *key, + int (*compare)(const void *key, const void **member), + int *found_out) + ATTR_PURE; void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), |