Commit 2fe537c5 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

r6958@Kushana: nickm | 2006-07-29 18:54:15 -0400

 Looks like we might need a priority queue.


svn:r6953
parent 8ba913c6
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -461,6 +461,87 @@ smartlist_sort_strings(smartlist_t *sl)
  smartlist_sort(sl, _compare_string_ptrs);
}

#define LEFT_CHILD(i)  ( ((i)+1)*2 - 1)
#define RIGHT_CHILD(i) ( ((i)+1)*2 )
#define PARENT(i)      ( ((i)+1)/2 - 1)

static INLINE void
smartlist_heapify(smartlist_t *sl,
                  int (*compare)(const void *a, const void *b),
                  int idx)
{
  while (1) {
    int left_idx = LEFT_CHILD(idx);
    int best_idx;

    if (left_idx >= sl->num_used)
      return;
    if (compare(sl->list[idx],sl->list[left_idx]) < 0)
      best_idx = idx;
    else
      best_idx = left_idx;
    if (left_idx+1 < sl->num_used &&
        compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
      best_idx = left_idx + 1;

    if (best_idx == idx) {
      return;
    } else {
      void *tmp = sl->list[idx];
      sl->list[idx] = sl->list[best_idx];
      sl->list[best_idx] = tmp;

      idx = best_idx;
    }
  }
}

void
smartlist_pqueue_add(smartlist_t *sl,
                     int (*compare)(const void *a, const void *b),
                     void *item)
{
  int idx;
  smartlist_add(sl,item);

  for (idx = sl->num_used - 1; idx; ) {
    int parent = PARENT(idx);
    if (compare(sl->list[idx], sl->list[parent]) < 0) {
      void *tmp = sl->list[parent];
      sl->list[parent] = sl->list[idx];
      sl->list[idx] = tmp;
      idx = parent;
    } else {
      return;
    }
  }
}

void *
smartlist_pqueue_pop(smartlist_t *sl,
                     int (*compare)(const void *a, const void *b))
{
  void *top;
  tor_assert(sl->num_used);

  top = sl->list[0];
  if (--sl->num_used) {
    sl->list[0] = sl->list[sl->num_used];
    smartlist_heapify(sl, compare, 0);
  }
  return top;
}

void
smartlist_pqueue_assert_ok(smartlist_t *sl,
                           int (*compare)(const void *a, const void *b))
{
  int i;
  for (i = sl->num_used - 1; i > 0; --i) {
    tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
  }
}

/** Helper: compare two DIGEST_LEN digests. */
static int
_compare_digests(const void **_a, const void **_b)
+9 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ int smartlist_string_num_isin(const smartlist_t *sl, int num);
int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);

/* smartlist_choose() is defined in crypto.[ch] */
#ifdef DEBUG_SMARTLIST
/** Return the number of items in sl.
@@ -76,6 +77,14 @@ void smartlist_sort_digests(smartlist_t *sl);
void *smartlist_bsearch(smartlist_t *sl, const void *key,
                        int (*compare)(const void *key, const void **member));

void smartlist_pqueue_add(smartlist_t *sl,
                          int (*compare)(const void *a, const void *b),
                          void *item);
void *smartlist_pqueue_pop(smartlist_t *sl,
                           int (*compare)(const void *a, const void *b));
void smartlist_pqueue_assert_ok(smartlist_t *sl,
                                int (*compare)(const void *a, const void *b));

#define SPLIT_SKIP_SPACE   0x01
#define SPLIT_IGNORE_BLANK 0x02
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
+61 −0
Original line number Diff line number Diff line
@@ -921,6 +921,66 @@ test_util(void)
  smartlist_free(sl);
}

static int
_compare_strings_for_pqueue(const void *s1, const void *s2)
{
  return strcmp((const char*)s1, (const char*)s2);
}

static void
test_pqueue(void)
{
  smartlist_t *sl;
  int (*cmp)(const void *, const void*);
#define OK() smartlist_pqueue_assert_ok(sl, cmp)

  cmp = _compare_strings_for_pqueue;

  sl = smartlist_create();
  smartlist_pqueue_add(sl, cmp, "cows");
  smartlist_pqueue_add(sl, cmp, "zebras");
  smartlist_pqueue_add(sl, cmp, "fish");
  smartlist_pqueue_add(sl, cmp, "frogs");
  smartlist_pqueue_add(sl, cmp, "apples");
  smartlist_pqueue_add(sl, cmp, "squid");//
  smartlist_pqueue_add(sl, cmp, "daschunds");
  smartlist_pqueue_add(sl, cmp, "eggplants");
  smartlist_pqueue_add(sl, cmp, "weissbier");//
  smartlist_pqueue_add(sl, cmp, "lobsters");
  smartlist_pqueue_add(sl, cmp, "roquefort");//

  OK();

  test_eq(smartlist_len(sl), 11);
  test_streq(smartlist_get(sl, 0), "apples");
  test_streq(smartlist_pqueue_pop(sl, cmp), "apples");
  test_eq(smartlist_len(sl), 10);
  OK();
  test_streq(smartlist_pqueue_pop(sl, cmp), "cows");
  test_streq(smartlist_pqueue_pop(sl, cmp), "daschunds");
  smartlist_pqueue_add(sl, cmp, "chinchillas");
  OK();
  smartlist_pqueue_add(sl, cmp, "fireflies");
  OK();
  test_streq(smartlist_pqueue_pop(sl, cmp), "chinchillas");
  test_streq(smartlist_pqueue_pop(sl, cmp), "eggplants");
  test_streq(smartlist_pqueue_pop(sl, cmp), "fireflies");
  OK();
  test_streq(smartlist_pqueue_pop(sl, cmp), "fish");
  test_streq(smartlist_pqueue_pop(sl, cmp), "frogs");
  test_streq(smartlist_pqueue_pop(sl, cmp), "lobsters");
  test_streq(smartlist_pqueue_pop(sl, cmp), "roquefort");
  OK();
  test_eq(smartlist_len(sl), 3);
  test_streq(smartlist_pqueue_pop(sl, cmp), "squid");
  test_streq(smartlist_pqueue_pop(sl, cmp), "weissbier");
  test_streq(smartlist_pqueue_pop(sl, cmp), "zebras");
  test_eq(smartlist_len(sl), 0);
  OK();
#undef OK
  smartlist_free(sl);
}

static void
test_gzip(void)
{
@@ -1675,6 +1735,7 @@ main(int c, char**v)
  test_util();
  test_strmap();
  test_control_formats();
  test_pqueue();
  puts("\n========================= Onion Skins =====================");
  test_onion();
  test_onion_handshake();