Files
git/prio-queue.c
Kristofer Karlsson 3c57836988 prio-queue: rename .nr to .nr_ and add accessor helpers
Rename the .nr member to .nr_ so that callers outside prio-queue.c
that directly reference .nr get a compilation error.  This catches
both existing misuse and future in-flight topics.

Add prio_queue_size() for callers that need to know the element count
and prio_queue_for_each() for callers that need to walk all elements.

Convert all external .nr users:
 - Loop conditions: use prio_queue_size(), prio_queue_get(), or
   prio_queue_peek() as the loop condition
 - Array iterations: use prio_queue_for_each()

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-09 11:11:46 -07:00

119 lines
2.6 KiB
C

#include "git-compat-util.h"
#include "prio-queue.h"
static inline int compare(struct prio_queue *queue, size_t i, size_t j)
{
int cmp = queue->compare(queue->array[i].data, queue->array[j].data,
queue->cb_data);
if (!cmp)
cmp = (queue->array[i].ctr > queue->array[j].ctr) -
(queue->array[i].ctr < queue->array[j].ctr);
return cmp;
}
static inline void swap(struct prio_queue *queue, size_t i, size_t j)
{
SWAP(queue->array[i], queue->array[j]);
}
void prio_queue_reverse(struct prio_queue *queue)
{
size_t i, j;
if (queue->compare)
BUG("prio_queue_reverse() on non-LIFO queue");
if (!queue->nr_)
return;
for (i = 0; i < (j = (queue->nr_ - 1) - i); i++)
swap(queue, i, j);
}
void clear_prio_queue(struct prio_queue *queue)
{
FREE_AND_NULL(queue->array);
queue->nr_ = 0;
queue->alloc = 0;
queue->insertion_ctr = 0;
}
void prio_queue_put(struct prio_queue *queue, void *thing)
{
size_t ix, parent;
/* Append at the end */
ALLOC_GROW(queue->array, queue->nr_ + 1, queue->alloc);
queue->array[queue->nr_].ctr = queue->insertion_ctr++;
queue->array[queue->nr_].data = thing;
queue->nr_++;
if (!queue->compare)
return; /* LIFO */
/* Bubble up the new one */
for (ix = queue->nr_ - 1; ix; ix = parent) {
parent = (ix - 1) / 2;
if (compare(queue, parent, ix) <= 0)
break;
swap(queue, parent, ix);
}
}
static void sift_down_root(struct prio_queue *queue)
{
size_t ix, child;
/* Push down the one at the root */
for (ix = 0; ix * 2 + 1 < queue->nr_; ix = child) {
child = ix * 2 + 1; /* left */
if (child + 1 < queue->nr_ &&
compare(queue, child, child + 1) >= 0)
child++; /* use right child */
if (compare(queue, ix, child) <= 0)
break;
swap(queue, child, ix);
}
}
void *prio_queue_get(struct prio_queue *queue)
{
void *result;
if (!queue->nr_)
return NULL;
if (!queue->compare)
return queue->array[--queue->nr_].data; /* LIFO */
result = queue->array[0].data;
if (!--queue->nr_)
return result;
queue->array[0] = queue->array[queue->nr_];
sift_down_root(queue);
return result;
}
void *prio_queue_peek(struct prio_queue *queue)
{
if (!queue->nr_)
return NULL;
if (!queue->compare)
return queue->array[queue->nr_ - 1].data;
return queue->array[0].data;
}
void prio_queue_replace(struct prio_queue *queue, void *thing)
{
if (!queue->nr_) {
prio_queue_put(queue, thing);
} else if (!queue->compare) {
queue->array[queue->nr_ - 1].ctr = queue->insertion_ctr++;
queue->array[queue->nr_ - 1].data = thing;
} else {
queue->array[0].ctr = queue->insertion_ctr++;
queue->array[0].data = thing;
sift_down_root(queue);
}
}