diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-09-01 02:00:43 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2009-10-15 15:17:13 -0400 |
commit | a8e92ba8fd65e12dbec265ccfcf0c89ac61847f2 (patch) | |
tree | b8a53aca97fda17e44cf74035f8b733a1cf87839 /src/common/container.c | |
parent | a7ba02f3f1dc267be81bf36f16bc1e69b34af050 (diff) | |
download | tor-a8e92ba8fd65e12dbec265ccfcf0c89ac61847f2.tar.gz tor-a8e92ba8fd65e12dbec265ccfcf0c89ac61847f2.zip |
Add a function to get the most frequent member of a list.
Diffstat (limited to 'src/common/container.c')
-rw-r--r-- | src/common/container.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/common/container.c b/src/common/container.c index 12ac2527e9..4fb94d3f7c 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -459,6 +459,42 @@ smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b)) (int (*)(const void *,const void*))compare); } +/** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>, + * return the most frequent member in the list. Break ties in favor of + * later elements. If the list is empty, return NULL. + */ +void * +smartlist_get_most_frequent(const smartlist_t *sl, + int (*compare)(const void **a, const void **b)) +{ + const void *most_frequent = NULL; + int most_frequent_count = 0; + + const void **cur = NULL; + int i, count=0; + + if (!sl->num_used) + return NULL; + for (i = 0; i < sl->num_used; ++i) { + const void *item = sl->list[i]; + if (cur && 0 == compare(cur, &item)) { + ++count; + } else { + if (cur && count >= most_frequent_count) { + most_frequent = *cur; + most_frequent_count = count; + } + cur = &item; + count = 1; + } + } + if (cur && count >= most_frequent_count) { + most_frequent = *cur; + most_frequent_count = count; + } + return (void*)most_frequent; +} + /** Given a sorted smartlist <b>sl</b> and the comparison function used to * sort it, remove all duplicate members. If free_fn is provided, calls * free_fn on each duplicate. Otherwise, just removes them. Preserves order. @@ -550,6 +586,13 @@ smartlist_sort_strings(smartlist_t *sl) smartlist_sort(sl, _compare_string_ptrs); } +/** Return the most frequent string in the sorted list <b>sl</b> */ +char * +smartlist_get_most_frequent_string(smartlist_t *sl) +{ + return smartlist_get_most_frequent(sl, _compare_string_ptrs); +} + /** Remove duplicate strings from a sorted list, and free them with tor_free(). */ void @@ -681,6 +724,37 @@ smartlist_uniq_digests(smartlist_t *sl) smartlist_uniq(sl, _compare_digests, _tor_free); } +/** Helper: compare two DIGEST256_LEN digests. */ +static int +_compare_digests256(const void **_a, const void **_b) +{ + return memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); +} + +/** Sort the list of DIGEST256_LEN-byte digests into ascending order. */ +void +smartlist_sort_digests256(smartlist_t *sl) +{ + smartlist_sort(sl, _compare_digests256); +} + +/** Return the most frequent member of the sorted list of DIGEST256_LEN + * digests in <b>sl</b> */ +char * +smartlist_get_most_frequent_digest256(smartlist_t *sl) +{ + return smartlist_get_most_frequent(sl, _compare_digests256); +} + +/** Remove duplicate 256-bit digests from a sorted list, and free them with + * tor_free(). + */ +void +smartlist_uniq_digests256(smartlist_t *sl) +{ + smartlist_uniq(sl, _compare_digests256, _tor_free); +} + /** Helper: Declare an entry type and a map type to implement a mapping using * ht.h. The map type will be called <b>maptype</b>. The key part of each * entry is declared using the C declaration <b>keydecl</b>. All functions |