aboutsummaryrefslogtreecommitdiff
path: root/src/common/container.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-09-01 02:00:43 -0400
committerNick Mathewson <nickm@torproject.org>2009-10-15 15:17:13 -0400
commita8e92ba8fd65e12dbec265ccfcf0c89ac61847f2 (patch)
treeb8a53aca97fda17e44cf74035f8b733a1cf87839 /src/common/container.c
parenta7ba02f3f1dc267be81bf36f16bc1e69b34af050 (diff)
downloadtor-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.c74
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