merge(third_party/git): Merge squashed git subtree at v2.23.0
Merge commit '1b593e1ea4' as 'third_party/git'
This commit is contained in:
commit
7ef0d62730
3629 changed files with 1139935 additions and 0 deletions
73
third_party/git/mergesort.c
vendored
Normal file
73
third_party/git/mergesort.c
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "cache.h"
|
||||
#include "mergesort.h"
|
||||
|
||||
struct mergesort_sublist {
|
||||
void *ptr;
|
||||
unsigned long len;
|
||||
};
|
||||
|
||||
static void *get_nth_next(void *list, unsigned long n,
|
||||
void *(*get_next_fn)(const void *))
|
||||
{
|
||||
while (n-- && list)
|
||||
list = get_next_fn(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static void *pop_item(struct mergesort_sublist *l,
|
||||
void *(*get_next_fn)(const void *))
|
||||
{
|
||||
void *p = l->ptr;
|
||||
l->ptr = get_next_fn(l->ptr);
|
||||
l->len = l->ptr ? (l->len - 1) : 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
void *llist_mergesort(void *list,
|
||||
void *(*get_next_fn)(const void *),
|
||||
void (*set_next_fn)(void *, void *),
|
||||
int (*compare_fn)(const void *, const void *))
|
||||
{
|
||||
unsigned long l;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
for (l = 1; ; l *= 2) {
|
||||
void *curr;
|
||||
struct mergesort_sublist p, q;
|
||||
|
||||
p.ptr = list;
|
||||
q.ptr = get_nth_next(p.ptr, l, get_next_fn);
|
||||
if (!q.ptr)
|
||||
break;
|
||||
p.len = q.len = l;
|
||||
|
||||
if (compare_fn(p.ptr, q.ptr) > 0)
|
||||
list = curr = pop_item(&q, get_next_fn);
|
||||
else
|
||||
list = curr = pop_item(&p, get_next_fn);
|
||||
|
||||
while (p.ptr) {
|
||||
while (p.len || q.len) {
|
||||
void *prev = curr;
|
||||
|
||||
if (!p.len)
|
||||
curr = pop_item(&q, get_next_fn);
|
||||
else if (!q.len)
|
||||
curr = pop_item(&p, get_next_fn);
|
||||
else if (compare_fn(p.ptr, q.ptr) > 0)
|
||||
curr = pop_item(&q, get_next_fn);
|
||||
else
|
||||
curr = pop_item(&p, get_next_fn);
|
||||
set_next_fn(prev, curr);
|
||||
}
|
||||
p.ptr = q.ptr;
|
||||
p.len = l;
|
||||
q.ptr = get_nth_next(p.ptr, l, get_next_fn);
|
||||
q.len = q.ptr ? l : 0;
|
||||
|
||||
}
|
||||
set_next_fn(curr, NULL);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue