tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

smartlist.c (24870B)


      1 /* Copyright (c) 2003-2004, Roger Dingledine
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 /**
      7 * \file smartlist.c
      8 *
      9 * \brief Higher-level functions for the "smartlist" resizeable array
     10 * abstraction.
     11 *
     12 * The functions declared here use higher-level functionality than those in
     13 * smartlist_core.c, and handle things like smartlists of different types,
     14 * sorting, searching, heap-structured smartlists, and other convenience
     15 * functions.
     16 **/
     17 
     18 #include "lib/container/smartlist.h"
     19 #include "lib/err/torerr.h"
     20 #include "lib/malloc/malloc.h"
     21 #include "lib/defs/digest_sizes.h"
     22 #include "lib/ctime/di_ops.h"
     23 #include "lib/string/compat_ctype.h"
     24 #include "lib/string/compat_string.h"
     25 #include "lib/string/util_string.h"
     26 #include "lib/string/printf.h"
     27 
     28 #include "lib/log/util_bug.h"
     29 
     30 #include <stdlib.h>
     31 #include <string.h>
     32 
     33 /** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
     34 * to <b>sl</b>. */
     35 void
     36 smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
     37 {
     38  va_list ap;
     39  va_start(ap, pattern);
     40  smartlist_add_vasprintf(sl, pattern, ap);
     41  va_end(ap);
     42 }
     43 
     44 /** va_list-based backend of smartlist_add_asprintf. */
     45 void
     46 smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
     47                        va_list args)
     48 {
     49  char *str = NULL;
     50 
     51  tor_vasprintf(&str, pattern, args);
     52  tor_assert(str != NULL);
     53 
     54  smartlist_add(sl, str);
     55 }
     56 
     57 /** Reverse the order of the items in <b>sl</b>. */
     58 void
     59 smartlist_reverse(smartlist_t *sl)
     60 {
     61  int i, j;
     62  void *tmp;
     63  tor_assert(sl);
     64  for (i = 0, j = sl->num_used-1; i < j; ++i, --j) {
     65    tmp = sl->list[i];
     66    sl->list[i] = sl->list[j];
     67    sl->list[j] = tmp;
     68  }
     69 }
     70 
     71 /** If there are any strings in sl equal to element, remove and free them.
     72 * Does not preserve order. */
     73 void
     74 smartlist_string_remove(smartlist_t *sl, const char *element)
     75 {
     76  int i;
     77  tor_assert(sl);
     78  tor_assert(element);
     79  for (i = 0; i < sl->num_used; ++i) {
     80    if (!strcmp(element, sl->list[i])) {
     81      tor_free(sl->list[i]);
     82      sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
     83      i--; /* so we process the new i'th element */
     84      sl->list[sl->num_used] = NULL;
     85    }
     86  }
     87 }
     88 
     89 /** Return true iff <b>sl</b> has some element E such that
     90 * !strcmp(E,<b>element</b>)
     91 */
     92 int
     93 smartlist_contains_string(const smartlist_t *sl, const char *element)
     94 {
     95  int i;
     96  if (!sl) return 0;
     97  for (i=0; i < sl->num_used; i++)
     98    if (strcmp((const char*)sl->list[i],element)==0)
     99      return 1;
    100  return 0;
    101 }
    102 
    103 /** If <b>element</b> is equal to an element of <b>sl</b>, return that
    104 * element's index.  Otherwise, return -1. */
    105 int
    106 smartlist_string_pos(const smartlist_t *sl, const char *element)
    107 {
    108  int i;
    109  if (!sl) return -1;
    110  for (i=0; i < sl->num_used; i++)
    111    if (strcmp((const char*)sl->list[i],element)==0)
    112      return i;
    113  return -1;
    114 }
    115 
    116 /** If <b>element</b> is the same pointer as an element of <b>sl</b>, return
    117 * that element's index.  Otherwise, return -1. */
    118 int
    119 smartlist_pos(const smartlist_t *sl, const void *element)
    120 {
    121  int i;
    122  if (!sl) return -1;
    123  for (i=0; i < sl->num_used; i++)
    124    if (element == sl->list[i])
    125      return i;
    126  return -1;
    127 }
    128 
    129 /** Return true iff <b>sl</b> has some element E such that
    130 * !strcasecmp(E,<b>element</b>)
    131 */
    132 int
    133 smartlist_contains_string_case(const smartlist_t *sl, const char *element)
    134 {
    135  int i;
    136  if (!sl) return 0;
    137  for (i=0; i < sl->num_used; i++)
    138    if (strcasecmp((const char*)sl->list[i],element)==0)
    139      return 1;
    140  return 0;
    141 }
    142 
    143 /** Return true iff <b>sl</b> has some element E such that E is equal
    144 * to the decimal encoding of <b>num</b>.
    145 */
    146 int
    147 smartlist_contains_int_as_string(const smartlist_t *sl, int num)
    148 {
    149  char buf[32]; /* long enough for 64-bit int, and then some. */
    150  tor_snprintf(buf,sizeof(buf),"%d", num);
    151  return smartlist_contains_string(sl, buf);
    152 }
    153 
    154 /** Return true iff the two lists contain the same strings in the same
    155 * order, or if they are both NULL. */
    156 int
    157 smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
    158 {
    159  if (sl1 == NULL)
    160    return sl2 == NULL;
    161  if (sl2 == NULL)
    162    return 0;
    163  if (smartlist_len(sl1) != smartlist_len(sl2))
    164    return 0;
    165  SMARTLIST_FOREACH(sl1, const char *, cp1, {
    166      const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
    167      if (strcmp(cp1, cp2))
    168        return 0;
    169    });
    170  return 1;
    171 }
    172 
    173 /** Return true iff the two lists contain the same int pointer values in
    174 * the same order, or if they are both NULL. */
    175 int
    176 smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
    177 {
    178  if (sl1 == NULL)
    179    return sl2 == NULL;
    180  if (sl2 == NULL)
    181    return 0;
    182  if (smartlist_len(sl1) != smartlist_len(sl2))
    183    return 0;
    184  SMARTLIST_FOREACH(sl1, int *, cp1, {
    185      int *cp2 = smartlist_get(sl2, cp1_sl_idx);
    186      if (*cp1 != *cp2)
    187        return 0;
    188    });
    189  return 1;
    190 }
    191 
    192 /**
    193 * Return true if there is shallow equality between smartlists -
    194 * i.e. all indices correspond to exactly same object (pointer
    195 * values are matching). Otherwise, return false.
    196 */
    197 int
    198 smartlist_ptrs_eq(const smartlist_t *s1, const smartlist_t *s2)
    199 {
    200  if (s1 == s2)
    201    return 1;
    202 
    203  // Note: pointers cannot both be NULL at this point, because
    204  // above check.
    205  if (s1 == NULL || s2 == NULL)
    206    return 0;
    207 
    208  if (smartlist_len(s1) != smartlist_len(s2))
    209    return 0;
    210 
    211  for (int i = 0; i < smartlist_len(s1); i++) {
    212    if (smartlist_get(s1, i) != smartlist_get(s2, i))
    213      return 0;
    214  }
    215 
    216  return 1;
    217 }
    218 
    219 /** Return true iff <b>sl</b> has some element E such that
    220 * tor_memeq(E,<b>element</b>,DIGEST_LEN)
    221 */
    222 int
    223 smartlist_contains_digest(const smartlist_t *sl, const char *element)
    224 {
    225  int i;
    226  if (!sl) return 0;
    227  for (i=0; i < sl->num_used; i++)
    228    if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN))
    229      return 1;
    230  return 0;
    231 }
    232 
    233 /** Return true iff some element E of sl2 has smartlist_contains(sl1,E).
    234 */
    235 int
    236 smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
    237 {
    238  int i;
    239  for (i=0; i < sl2->num_used; i++)
    240    if (smartlist_contains(sl1, sl2->list[i]))
    241      return 1;
    242  return 0;
    243 }
    244 
    245 /** Remove every element E of sl1 such that !smartlist_contains(sl2,E).
    246 * Does not preserve the order of sl1.
    247 */
    248 void
    249 smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
    250 {
    251  int i;
    252  for (i=0; i < sl1->num_used; i++)
    253    if (!smartlist_contains(sl2, sl1->list[i])) {
    254      sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
    255      i--; /* so we process the new i'th element */
    256      sl1->list[sl1->num_used] = NULL;
    257    }
    258 }
    259 
    260 /** Remove every element E of sl1 such that smartlist_contains(sl2,E).
    261 * Does not preserve the order of sl1.
    262 */
    263 void
    264 smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
    265 {
    266  int i;
    267  for (i=0; i < sl2->num_used; i++)
    268    smartlist_remove(sl1, sl2->list[i]);
    269 }
    270 
    271 /** Allocate and return a new string containing the concatenation of
    272 * the elements of <b>sl</b>, in order, separated by <b>join</b>.  If
    273 * <b>terminate</b> is true, also terminate the string with <b>join</b>.
    274 * If <b>len_out</b> is not NULL, set <b>len_out</b> to the length of
    275 * the returned string. Requires that every element of <b>sl</b> is
    276 * NUL-terminated string.
    277 */
    278 char *
    279 smartlist_join_strings(smartlist_t *sl, const char *join,
    280                       int terminate, size_t *len_out)
    281 {
    282  return smartlist_join_strings2(sl,join,strlen(join),terminate,len_out);
    283 }
    284 
    285 /** As smartlist_join_strings, but instead of separating/terminated with a
    286 * NUL-terminated string <b>join</b>, uses the <b>join_len</b>-byte sequence
    287 * at <b>join</b>.  (Useful for generating a sequence of NUL-terminated
    288 * strings.)
    289 */
    290 char *
    291 smartlist_join_strings2(smartlist_t *sl, const char *join,
    292                        size_t join_len, int terminate, size_t *len_out)
    293 {
    294  int i;
    295  size_t n = 0;
    296  char *r = NULL, *dst, *src;
    297 
    298  tor_assert(sl);
    299  tor_assert(join);
    300 
    301  if (terminate)
    302    n = join_len;
    303 
    304  for (i = 0; i < sl->num_used; ++i) {
    305    n += strlen(sl->list[i]);
    306    if (i+1 < sl->num_used) /* avoid double-counting the last one */
    307      n += join_len;
    308  }
    309  dst = r = tor_malloc(n+1);
    310  for (i = 0; i < sl->num_used; ) {
    311    for (src = sl->list[i]; *src; )
    312      *dst++ = *src++;
    313    if (++i < sl->num_used) {
    314      memcpy(dst, join, join_len);
    315      dst += join_len;
    316    }
    317  }
    318  if (terminate) {
    319    memcpy(dst, join, join_len);
    320    dst += join_len;
    321  }
    322  *dst = '\0';
    323 
    324  if (len_out)
    325    *len_out = dst-r;
    326  return r;
    327 }
    328 
    329 /** Sort the members of <b>sl</b> into an order defined by
    330 * the ordering function <b>compare</b>, which returns less then 0 if a
    331 * precedes b, greater than 0 if b precedes a, and 0 if a 'equals' b.
    332 */
    333 void
    334 smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
    335 {
    336  if (!sl->num_used)
    337    return;
    338  qsort(sl->list, sl->num_used, sizeof(void*),
    339        (int (*)(const void *,const void*))compare);
    340 }
    341 
    342 /** Given a smartlist <b>sl</b> sorted with the function <b>compare</b>,
    343 * return the most frequent member in the list.  Break ties in favor of
    344 * later elements.  If the list is empty, return NULL.  If count_out is
    345 * non-null, set it to the count of the most frequent member.
    346 */
    347 void *
    348 smartlist_get_most_frequent_(const smartlist_t *sl,
    349                             int (*compare)(const void **a, const void **b),
    350                             int *count_out)
    351 {
    352  const void *most_frequent = NULL;
    353  int most_frequent_count = 0;
    354 
    355  const void *cur = NULL;
    356  int i, count=0;
    357 
    358  if (!sl->num_used) {
    359    if (count_out)
    360      *count_out = 0;
    361    return NULL;
    362  }
    363  for (i = 0; i < sl->num_used; ++i) {
    364    const void *item = sl->list[i];
    365    if (cur && 0 == compare(&cur, &item)) {
    366      ++count;
    367    } else {
    368      if (cur && count >= most_frequent_count) {
    369        most_frequent = cur;
    370        most_frequent_count = count;
    371      }
    372      cur = item;
    373      count = 1;
    374    }
    375  }
    376  if (cur && count >= most_frequent_count) {
    377    most_frequent = cur;
    378    most_frequent_count = count;
    379  }
    380  if (count_out)
    381    *count_out = most_frequent_count;
    382  return (void*)most_frequent;
    383 }
    384 
    385 /** Given a sorted smartlist <b>sl</b> and the comparison function used to
    386 * sort it, remove all duplicate members.  If free_fn is provided, calls
    387 * free_fn on each duplicate.  Otherwise, just removes them.  Preserves order.
    388 */
    389 void
    390 smartlist_uniq(smartlist_t *sl,
    391               int (*compare)(const void **a, const void **b),
    392               void (*free_fn)(void *a))
    393 {
    394  int i;
    395  for (i=1; i < sl->num_used; ++i) {
    396    if (compare((const void **)&(sl->list[i-1]),
    397                (const void **)&(sl->list[i])) == 0) {
    398      if (free_fn)
    399        free_fn(sl->list[i]);
    400      smartlist_del_keeporder(sl, i--);
    401    }
    402  }
    403 }
    404 
    405 /** Assuming the members of <b>sl</b> are in order, return a pointer to the
    406 * member that matches <b>key</b>.  Ordering and matching are defined by a
    407 * <b>compare</b> function that returns 0 on a match; less than 0 if key is
    408 * less than member, and greater than 0 if key is greater then member.
    409 */
    410 void *
    411 smartlist_bsearch(const smartlist_t *sl, const void *key,
    412                  int (*compare)(const void *key, const void **member))
    413 {
    414  int found, idx;
    415  idx = smartlist_bsearch_idx(sl, key, compare, &found);
    416  return found ? smartlist_get(sl, idx) : NULL;
    417 }
    418 
    419 /** Assuming the members of <b>sl</b> are in order, return the index of the
    420 * member that matches <b>key</b>.  If no member matches, return the index of
    421 * the first member greater than <b>key</b>, or smartlist_len(sl) if no member
    422 * is greater than <b>key</b>.  Set <b>found_out</b> to true on a match, to
    423 * false otherwise.  Ordering and matching are defined by a <b>compare</b>
    424 * function that returns 0 on a match; less than 0 if key is less than member,
    425 * and greater than 0 if key is greater then member.
    426 */
    427 int
    428 smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
    429                      int (*compare)(const void *key, const void **member),
    430                      int *found_out)
    431 {
    432  int hi, lo, cmp, mid, len, diff;
    433 
    434  tor_assert(sl);
    435  tor_assert(compare);
    436  tor_assert(found_out);
    437 
    438  len = smartlist_len(sl);
    439 
    440  /* Check for the trivial case of a zero-length list */
    441  if (len == 0) {
    442    *found_out = 0;
    443    /* We already know smartlist_len(sl) is 0 in this case */
    444    return 0;
    445  }
    446 
    447  /* Okay, we have a real search to do */
    448  tor_assert(len > 0);
    449  lo = 0;
    450  hi = len - 1;
    451 
    452  /*
    453   * These invariants are always true:
    454   *
    455   * For all i such that 0 <= i < lo, sl[i] < key
    456   * For all i such that hi < i <= len, sl[i] > key
    457   */
    458 
    459  while (lo <= hi) {
    460    diff = hi - lo;
    461    /*
    462     * We want mid = (lo + hi) / 2, but that could lead to overflow, so
    463     * instead diff = hi - lo (non-negative because of loop condition), and
    464     * then hi = lo + diff, mid = (lo + lo + diff) / 2 = lo + (diff / 2).
    465     */
    466    mid = lo + (diff / 2);
    467    cmp = compare(key, (const void**) &(sl->list[mid]));
    468    if (cmp == 0) {
    469      /* sl[mid] == key; we found it */
    470      *found_out = 1;
    471      return mid;
    472    } else if (cmp > 0) {
    473      /*
    474       * key > sl[mid] and an index i such that sl[i] == key must
    475       * have i > mid if it exists.
    476       */
    477 
    478      /*
    479       * Since lo <= mid <= hi, hi can only decrease on each iteration (by
    480       * being set to mid - 1) and hi is initially len - 1, mid < len should
    481       * always hold, and this is not symmetric with the left end of list
    482       * mid > 0 test below.  A key greater than the right end of the list
    483       * should eventually lead to lo == hi == mid == len - 1, and then
    484       * we set lo to len below and fall out to the same exit we hit for
    485       * a key in the middle of the list but not matching.  Thus, we just
    486       * assert for consistency here rather than handle a mid == len case.
    487       */
    488      tor_assert(mid < len);
    489      /* Move lo to the element immediately after sl[mid] */
    490      lo = mid + 1;
    491    } else {
    492      /* This should always be true in this case */
    493      tor_assert(cmp < 0);
    494 
    495      /*
    496       * key < sl[mid] and an index i such that sl[i] == key must
    497       * have i < mid if it exists.
    498       */
    499 
    500      if (mid > 0) {
    501        /* Normal case, move hi to the element immediately before sl[mid] */
    502        hi = mid - 1;
    503      } else {
    504        /* These should always be true in this case */
    505        tor_assert(mid == lo);
    506        tor_assert(mid == 0);
    507        /*
    508         * We were at the beginning of the list and concluded that every
    509         * element e compares e > key.
    510         */
    511        *found_out = 0;
    512        return 0;
    513      }
    514    }
    515  }
    516 
    517  /*
    518   * lo > hi; we have no element matching key but we have elements falling
    519   * on both sides of it.  The lo index points to the first element > key.
    520   */
    521  tor_assert(lo == hi + 1); /* All other cases should have been handled */
    522  tor_assert(lo >= 0);
    523  tor_assert(lo <= len);
    524  tor_assert(hi >= 0);
    525  tor_assert(hi <= len);
    526 
    527  if (lo < len) {
    528    cmp = compare(key, (const void **) &(sl->list[lo]));
    529    tor_assert(cmp < 0);
    530  } else {
    531    cmp = compare(key, (const void **) &(sl->list[len-1]));
    532    tor_assert(cmp > 0);
    533  }
    534 
    535  *found_out = 0;
    536  return lo;
    537 }
    538 
    539 /** Helper: compare two const char **s. */
    540 static int
    541 compare_string_ptrs_(const void **_a, const void **_b)
    542 {
    543  return strcmp((const char*)*_a, (const char*)*_b);
    544 }
    545 
    546 /** Sort a smartlist <b>sl</b> containing strings into lexically ascending
    547 * order. */
    548 void
    549 smartlist_sort_strings(smartlist_t *sl)
    550 {
    551  smartlist_sort(sl, compare_string_ptrs_);
    552 }
    553 
    554 /** Return the most frequent string in the sorted list <b>sl</b> */
    555 const char *
    556 smartlist_get_most_frequent_string(smartlist_t *sl)
    557 {
    558  return smartlist_get_most_frequent(sl, compare_string_ptrs_);
    559 }
    560 
    561 /** Return the most frequent string in the sorted list <b>sl</b>.
    562 * If <b>count_out</b> is provided, set <b>count_out</b> to the
    563 * number of times that string appears.
    564 */
    565 const char *
    566 smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out)
    567 {
    568  return smartlist_get_most_frequent_(sl, compare_string_ptrs_, count_out);
    569 }
    570 
    571 /** Remove duplicate strings from a sorted list, and free them with tor_free().
    572 */
    573 void
    574 smartlist_uniq_strings(smartlist_t *sl)
    575 {
    576  smartlist_uniq(sl, compare_string_ptrs_, tor_free_);
    577 }
    578 
    579 /** Helper: compare two pointers. */
    580 static int
    581 compare_ptrs_(const void **_a, const void **_b)
    582 {
    583  const void *a = *_a, *b = *_b;
    584  if (a<b)
    585    return -1;
    586  else if (a==b)
    587    return 0;
    588  else
    589    return 1;
    590 }
    591 
    592 /** Sort <b>sl</b> in ascending order of the pointers it contains. */
    593 void
    594 smartlist_sort_pointers(smartlist_t *sl)
    595 {
    596  smartlist_sort(sl, compare_ptrs_);
    597 }
    598 
    599 /* Heap-based priority queue implementation for O(lg N) insert and remove.
    600 * Recall that the heap property is that, for every index I, h[I] <
    601 * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]].
    602 *
    603 * For us to remove items other than the topmost item, each item must store
    604 * its own index within the heap.  When calling the pqueue functions, tell
    605 * them about the offset of the field that stores the index within the item.
    606 *
    607 * Example:
    608 *
    609 *   typedef struct timer_t {
    610 *     struct timeval tv;
    611 *     int heap_index;
    612 *   } timer_t;
    613 *
    614 *   static int compare(const void *p1, const void *p2) {
    615 *     const timer_t *t1 = p1, *t2 = p2;
    616 *     if (t1->tv.tv_sec < t2->tv.tv_sec) {
    617 *        return -1;
    618 *     } else if (t1->tv.tv_sec > t2->tv.tv_sec) {
    619 *        return 1;
    620 *     } else {
    621 *        return t1->tv.tv_usec - t2->tv_usec;
    622 *     }
    623 *   }
    624 *
    625 *   void timer_heap_insert(smartlist_t *heap, timer_t *timer) {
    626 *      smartlist_pqueue_add(heap, compare, offsetof(timer_t, heap_index),
    627 *         timer);
    628 *   }
    629 *
    630 *   void timer_heap_pop(smartlist_t *heap) {
    631 *      return smartlist_pqueue_pop(heap, compare,
    632 *         offsetof(timer_t, heap_index));
    633 *   }
    634 */
    635 
    636 /** @{ */
    637 /** Functions to manipulate heap indices to find a node's parent and children.
    638 *
    639 * For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x]
    640 *   = 2*x + 1.  But this is C, so we have to adjust a little. */
    641 
    642 /* MAX_PARENT_IDX is the largest IDX in the smartlist which might have
    643 * children whose indices fit inside an int.
    644 * LEFT_CHILD(MAX_PARENT_IDX) == INT_MAX-2;
    645 * RIGHT_CHILD(MAX_PARENT_IDX) == INT_MAX-1;
    646 * LEFT_CHILD(MAX_PARENT_IDX + 1) == INT_MAX // impossible, see max list size.
    647 */
    648 #define MAX_PARENT_IDX ((INT_MAX - 2) / 2)
    649 /* If this is true, then i is small enough to potentially have children
    650 * in the smartlist, and it is save to use LEFT_CHILD/RIGHT_CHILD on it. */
    651 #define IDX_MAY_HAVE_CHILDREN(i) ((i) <= MAX_PARENT_IDX)
    652 #define LEFT_CHILD(i)  ( 2*(i) + 1 )
    653 #define RIGHT_CHILD(i) ( 2*(i) + 2 )
    654 #define PARENT(i)      ( ((i)-1) / 2 )
    655 /** @} */
    656 
    657 /** @{ */
    658 /** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
    659 * set to the offset of an integer index within the heap element structure,
    660 * IDX_OF_ITEM(p) gives you the index of p, and IDXP(p) gives you a pointer to
    661 * where p's index is stored.  Given additionally a local smartlist <b>sl</b>,
    662 * UPDATE_IDX(i) sets the index of the element at <b>i</b> to the correct
    663 * value (that is, to <b>i</b>).
    664 */
    665 #define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset))
    666 
    667 #define UPDATE_IDX(i)  do {                            \
    668    void *updated = sl->list[i];                       \
    669    *IDXP(updated) = i;                                \
    670  } while (0)
    671 
    672 #define IDX_OF_ITEM(p) (*IDXP(p))
    673 /** @} */
    674 
    675 /** Helper. <b>sl</b> may have at most one violation of the heap property:
    676 * the item at <b>idx</b> may be greater than one or both of its children.
    677 * Restore the heap property. */
    678 static inline void
    679 smartlist_heapify(smartlist_t *sl,
    680                  int (*compare)(const void *a, const void *b),
    681                  ptrdiff_t idx_field_offset,
    682                  int idx)
    683 {
    684  while (1) {
    685    if (! IDX_MAY_HAVE_CHILDREN(idx)) {
    686      /* idx is so large that it cannot have any children, since doing so
    687       * would mean the smartlist was over-capacity. Therefore it cannot
    688       * violate the heap property by being greater than a child (since it
    689       * doesn't have any). */
    690      return;
    691    }
    692 
    693    int left_idx = LEFT_CHILD(idx);
    694    int best_idx;
    695 
    696    if (left_idx >= sl->num_used)
    697      return;
    698    if (compare(sl->list[idx],sl->list[left_idx]) < 0)
    699      best_idx = idx;
    700    else
    701      best_idx = left_idx;
    702    if (left_idx+1 < sl->num_used &&
    703        compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
    704      best_idx = left_idx + 1;
    705 
    706    if (best_idx == idx) {
    707      return;
    708    } else {
    709      void *tmp = sl->list[idx];
    710      sl->list[idx] = sl->list[best_idx];
    711      sl->list[best_idx] = tmp;
    712      UPDATE_IDX(idx);
    713      UPDATE_IDX(best_idx);
    714 
    715      idx = best_idx;
    716    }
    717  }
    718 }
    719 
    720 /** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is
    721 * determined by <b>compare</b> and the offset of the item in the heap is
    722 * stored in an int-typed field at position <b>idx_field_offset</b> within
    723 * item.
    724 */
    725 void
    726 smartlist_pqueue_add(smartlist_t *sl,
    727                     int (*compare)(const void *a, const void *b),
    728                     ptrdiff_t idx_field_offset,
    729                     void *item)
    730 {
    731  int idx;
    732  smartlist_add(sl,item);
    733  UPDATE_IDX(sl->num_used-1);
    734 
    735  for (idx = sl->num_used - 1; idx; ) {
    736    int parent = PARENT(idx);
    737    if (compare(sl->list[idx], sl->list[parent]) < 0) {
    738      void *tmp = sl->list[parent];
    739      sl->list[parent] = sl->list[idx];
    740      sl->list[idx] = tmp;
    741      UPDATE_IDX(parent);
    742      UPDATE_IDX(idx);
    743      idx = parent;
    744    } else {
    745      return;
    746    }
    747  }
    748 }
    749 
    750 /** Remove and return the top-priority item from the heap stored in <b>sl</b>,
    751 * where order is determined by <b>compare</b> and the item's position is
    752 * stored at position <b>idx_field_offset</b> within the item.  <b>sl</b> must
    753 * not be empty. */
    754 void *
    755 smartlist_pqueue_pop(smartlist_t *sl,
    756                     int (*compare)(const void *a, const void *b),
    757                     ptrdiff_t idx_field_offset)
    758 {
    759  void *top;
    760  tor_assert(sl->num_used);
    761 
    762  top = sl->list[0];
    763  *IDXP(top)=-1;
    764  if (--sl->num_used) {
    765    sl->list[0] = sl->list[sl->num_used];
    766    sl->list[sl->num_used] = NULL;
    767    UPDATE_IDX(0);
    768    smartlist_heapify(sl, compare, idx_field_offset, 0);
    769  }
    770  sl->list[sl->num_used] = NULL;
    771  return top;
    772 }
    773 
    774 /** Remove the item <b>item</b> from the heap stored in <b>sl</b>,
    775 * where order is determined by <b>compare</b> and the item's position is
    776 * stored at position <b>idx_field_offset</b> within the item.  <b>sl</b> must
    777 * not be empty. */
    778 void
    779 smartlist_pqueue_remove(smartlist_t *sl,
    780                        int (*compare)(const void *a, const void *b),
    781                        ptrdiff_t idx_field_offset,
    782                        void *item)
    783 {
    784  int idx = IDX_OF_ITEM(item);
    785  tor_assert(idx >= 0);
    786  tor_assert(sl->list[idx] == item);
    787  --sl->num_used;
    788  *IDXP(item) = -1;
    789  if (idx == sl->num_used) {
    790    sl->list[sl->num_used] = NULL;
    791    return;
    792  } else {
    793    sl->list[idx] = sl->list[sl->num_used];
    794    sl->list[sl->num_used] = NULL;
    795    UPDATE_IDX(idx);
    796    smartlist_heapify(sl, compare, idx_field_offset, idx);
    797  }
    798 }
    799 
    800 /** Assert that the heap property is correctly maintained by the heap stored
    801 * in <b>sl</b>, where order is determined by <b>compare</b>. */
    802 void
    803 smartlist_pqueue_assert_ok(smartlist_t *sl,
    804                           int (*compare)(const void *a, const void *b),
    805                           ptrdiff_t idx_field_offset)
    806 {
    807  int i;
    808  for (i = sl->num_used - 1; i >= 0; --i) {
    809    if (i>0)
    810      tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
    811    tor_assert(IDX_OF_ITEM(sl->list[i]) == i);
    812  }
    813 }
    814 
    815 /** Helper: compare two DIGEST_LEN digests. */
    816 static int
    817 compare_digests_(const void **_a, const void **_b)
    818 {
    819  return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
    820 }
    821 
    822 /** Sort the list of DIGEST_LEN-byte digests into ascending order. */
    823 void
    824 smartlist_sort_digests(smartlist_t *sl)
    825 {
    826  smartlist_sort(sl, compare_digests_);
    827 }
    828 
    829 /** Remove duplicate digests from a sorted list, and free them with tor_free().
    830 */
    831 void
    832 smartlist_uniq_digests(smartlist_t *sl)
    833 {
    834  smartlist_uniq(sl, compare_digests_, tor_free_);
    835 }
    836 
    837 /** Helper: compare two DIGEST256_LEN digests. */
    838 static int
    839 compare_digests256_(const void **_a, const void **_b)
    840 {
    841  return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN);
    842 }
    843 
    844 /** Sort the list of DIGEST256_LEN-byte digests into ascending order. */
    845 void
    846 smartlist_sort_digests256(smartlist_t *sl)
    847 {
    848  smartlist_sort(sl, compare_digests256_);
    849 }
    850 
    851 /** Return the most frequent member of the sorted list of DIGEST256_LEN
    852 * digests in <b>sl</b> */
    853 const uint8_t *
    854 smartlist_get_most_frequent_digest256(smartlist_t *sl)
    855 {
    856  return smartlist_get_most_frequent(sl, compare_digests256_);
    857 }
    858 
    859 /** Remove duplicate 256-bit digests from a sorted list, and free them with
    860 * tor_free().
    861 */
    862 void
    863 smartlist_uniq_digests256(smartlist_t *sl)
    864 {
    865  smartlist_uniq(sl, compare_digests256_, tor_free_);
    866 }