Linting and formatting of .c and .h with C/C++ IntelliSence

This commit is contained in:
conc3rned
2024-09-17 16:19:54 +03:00
parent 8c94e3230e
commit c1db09b19e
80 changed files with 9996 additions and 8587 deletions

View File

@@ -27,29 +27,29 @@
#define ALLOC_STEP 16384
// minimum subnet fill percent is PCTMULT/PCTDIV (for example 3/4)
#define DEFAULT_PCTMULT 3
#define DEFAULT_PCTDIV 4
#define DEFAULT_PCTMULT 3
#define DEFAULT_PCTDIV 4
// subnet search range in "zero bit count"
// means search start from /(32-ZCT_MAX) to /(32-ZCT_MIN)
#define DEFAULT_V4_ZCT_MAX 10 // /22
#define DEFAULT_V4_ZCT_MIN 2 // /30
#define DEFAULT_V6_ZCT_MAX 72 // /56
#define DEFAULT_V6_ZCT_MIN 64 // /64
// must be no less than N ipv6 in subnet
#define DEFAULT_V6_THRESHOLD 5
// must be no less than N IPv6 in subnet
#define DEFAULT_V6_THRESHOLD 5
static int ucmp(const void * a, const void * b, void *arg)
static int ucmp(const void *a, const void *b, void *arg)
{
if (*(uint32_t*)a < *(uint32_t*)b)
if (*(uint32_t *)a < *(uint32_t *)b)
return -1;
else if (*(uint32_t*)a > *(uint32_t*)b)
else if (*(uint32_t *)a > *(uint32_t *)b)
return 1;
else
return 0;
}
static uint32_t mask_from_bitcount(uint32_t zct)
{
return zct<32 ? ~((1 << zct) - 1) : 0;
return zct < 32 ? ~((1 << zct) - 1) : 0;
}
// make presorted array unique. return number of unique items.
// 1,1,2,3,3,0,0,0 (ct=8) => 1,2,3,0 (ct=4)
@@ -59,18 +59,18 @@ static uint32_t unique(uint32_t *pu, uint32_t ct)
for (i = j = 0; j < ct; i++)
{
u = pu[j++];
for (; j < ct && pu[j] == u; j++);
for (; j < ct && pu[j] == u; j++)
;
pu[i] = u;
}
return i;
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
__attribute__((optimize("no-strict-aliasing")))
#endif
static int cmp6(const void * a, const void * b, void *arg)
static int
cmp6(const void *a, const void *b, void *arg)
{
// this function is critical for sort performance
// on big endian systems cpu byte order is equal to network byte order
@@ -79,15 +79,15 @@ static int cmp6(const void * a, const void * b, void *arg)
// 64-bit archs often have cpu command to reverse byte order
// assume that a and b are properly aligned
#if defined(__BYTE_ORDER__) && ((__BYTE_ORDER__==__ORDER_BIG_ENDIAN__) || (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))
#if defined(__BYTE_ORDER__) && ((__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
uint64_t aa,bb;
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
aa = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[0]);
bb = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[0]);
uint64_t aa, bb;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
aa = __builtin_bswap64(((uint64_t *)((struct in6_addr *)a)->s6_addr)[0]);
bb = __builtin_bswap64(((uint64_t *)((struct in6_addr *)b)->s6_addr)[0]);
#else
aa = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[0];
bb = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[0];
aa = ((uint64_t *)((struct in6_addr *)a)->s6_addr)[0];
bb = ((uint64_t *)((struct in6_addr *)b)->s6_addr)[0];
#endif
if (aa < bb)
return -1;
@@ -95,16 +95,17 @@ static int cmp6(const void * a, const void * b, void *arg)
return 1;
else
{
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
aa = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[1]);
bb = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[1]);
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
aa = __builtin_bswap64(((uint64_t *)((struct in6_addr *)a)->s6_addr)[1]);
bb = __builtin_bswap64(((uint64_t *)((struct in6_addr *)b)->s6_addr)[1]);
#else
aa = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[1];
bb = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[1];
aa = ((uint64_t *)((struct in6_addr *)a)->s6_addr)[1];
bb = ((uint64_t *)((struct in6_addr *)b)->s6_addr)[1];
#endif
return aa < bb ? -1 : aa > bb ? 1 : 0;
return aa < bb ? -1 : aa > bb ? 1
: 0;
}
#else
// fallback case
for (uint8_t i = 0; i < sizeof(((struct in6_addr *)0)->s6_addr); i++)
@@ -124,7 +125,8 @@ static uint32_t unique6(struct in6_addr *pu, uint32_t ct)
uint32_t i, j, k;
for (i = j = 0; j < ct; i++)
{
for (k = j++; j < ct && !memcmp(pu + j, pu + k, sizeof(struct in6_addr)); j++);
for (k = j++; j < ct && !memcmp(pu + j, pu + k, sizeof(struct in6_addr)); j++)
;
pu[i] = pu[k];
}
return i;
@@ -132,26 +134,26 @@ static uint32_t unique6(struct in6_addr *pu, uint32_t ct)
static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
{
if (zct >= 128)
memset(a->s6_addr,0x00,16);
memset(a->s6_addr, 0x00, 16);
else
{
int32_t n = (127 - zct) >> 3;
memset(a->s6_addr,0xFF,n);
memset(a->s6_addr+n,0x00,16-n);
memset(a->s6_addr, 0xFF, n);
memset(a->s6_addr + n, 0x00, 16 - n);
a->s6_addr[n] = ~((1 << (zct & 7)) - 1);
}
}
static struct in6_addr ip6_mask[129];
static void mask_from_bitcount6_prepare(void)
{
for (int zct=0;zct<=128;zct++) mask_from_bitcount6_make(zct, ip6_mask+zct);
for (int zct = 0; zct <= 128; zct++)
mask_from_bitcount6_make(zct, ip6_mask + zct);
}
static inline const struct in6_addr *mask_from_bitcount6(uint32_t zct)
{
return ip6_mask+zct;
return ip6_mask + zct;
}
/*
// this is "correct" solution for strict aliasing feature
// but I don't like this style of coding
@@ -176,44 +178,43 @@ static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct i
// result = a & b
// assume that a and b are properly aligned
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
__attribute__((optimize("no-strict-aliasing")))
#endif
static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr * restrict b, struct in6_addr * restrict result)
static void
ip6_and(const struct in6_addr *restrict a, const struct in6_addr *restrict b, struct in6_addr *restrict result)
{
#ifdef __SIZEOF_INT128__
// gcc and clang have 128 bit int types on some 64-bit archs. take some advantage
*((unsigned __int128*)result->s6_addr) = *((unsigned __int128*)a->s6_addr) & *((unsigned __int128*)b->s6_addr);
*((unsigned __int128 *)result->s6_addr) = *((unsigned __int128 *)a->s6_addr) & *((unsigned __int128 *)b->s6_addr);
#else
((uint64_t*)result->s6_addr)[0] = ((uint64_t*)a->s6_addr)[0] & ((uint64_t*)b->s6_addr)[0];
((uint64_t*)result->s6_addr)[1] = ((uint64_t*)a->s6_addr)[1] & ((uint64_t*)b->s6_addr)[1];
((uint64_t *)result->s6_addr)[0] = ((uint64_t *)a->s6_addr)[0] & ((uint64_t *)b->s6_addr)[0];
((uint64_t *)result->s6_addr)[1] = ((uint64_t *)a->s6_addr)[1] & ((uint64_t *)b->s6_addr)[1];
#endif
}
static void rtrim(char *s)
{
if (s)
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--)
*p = '\0';
}
static struct params_s
{
bool ipv6;
uint32_t pctmult, pctdiv; // for v4
uint32_t pctmult, pctdiv; // for v4
uint32_t zct_min, zct_max; // for v4 and v6
uint32_t v6_threshold; // for v6
uint32_t v6_threshold; // for v6
} params;
static void exithelp(void)
{
printf(
" -4\t\t\t\t; ipv4 list (default)\n"
" -6\t\t\t\t; ipv6 list\n"
" --prefix-length=min[-max]\t; consider prefix lengths from 'min' to 'max'. examples : 22-30 (ipv4), 56-64 (ipv6)\n"
" --v4-threshold=mul/div\t\t; ipv4 only : include subnets with more than mul/div ips. example : 3/4\n"
" --v6-threshold=N\t\t; ipv6 only : include subnets with more than N v6 ips. example : 5\n"
);
" -4\t\t\t\t; IPv4 list (default)\n"
" -6\t\t\t\t; IPv6 list\n"
" --prefix-length=min[-max]\t; consider prefix lengths from 'min' to 'max'. examples : 22-30 (IPv4), 56-64 (IPv6)\n"
" --v4-threshold=mul/div\t\t; IPv4 only : include subnets with more than mul/div ips. example : 3/4\n"
" --v6-threshold=N\t\t; IPv6 only : include subnets with more than N v6 ips. example : 5\n");
exit(1);
}
@@ -221,7 +222,7 @@ static void parse_params(int argc, char *argv[])
{
int option_index = 0;
int v, i;
uint32_t plen1=-1, plen2=-1;
uint32_t plen1 = -1, plen2 = -1;
memset(&params, 0, sizeof(params));
params.pctmult = DEFAULT_PCTMULT;
@@ -229,18 +230,18 @@ static void parse_params(int argc, char *argv[])
params.v6_threshold = DEFAULT_V6_THRESHOLD;
const struct option long_options[] = {
{ "help",no_argument,0,0 },// optidx=0
{ "h",no_argument,0,0 },// optidx=1
{ "4",no_argument,0,0 },// optidx=2
{ "6",no_argument,0,0 },// optidx=3
{ "prefix-length",required_argument,0,0 },// optidx=4
{ "v4-threshold",required_argument,0,0 },// optidx=5
{ "v6-threshold",required_argument,0,0 },// optidx=6
{ NULL,0,NULL,0 }
};
{"help", no_argument, 0, 0}, // optidx=0
{"h", no_argument, 0, 0}, // optidx=1
{"4", no_argument, 0, 0}, // optidx=2
{"6", no_argument, 0, 0}, // optidx=3
{"prefix-length", required_argument, 0, 0}, // optidx=4
{"v4-threshold", required_argument, 0, 0}, // optidx=5
{"v6-threshold", required_argument, 0, 0}, // optidx=6
{NULL, 0, NULL, 0}};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v)
exithelp();
switch (option_index)
{
case 0:
@@ -254,9 +255,10 @@ static void parse_params(int argc, char *argv[])
params.ipv6 = true;
break;
case 4:
i = sscanf(optarg,"%u-%u",&plen1,&plen2);
if (i == 1) plen2 = plen1;
if (i<=0 || plen2<plen1 || !plen1 || !plen2)
i = sscanf(optarg, "%u-%u", &plen1, &plen2);
if (i == 1)
plen2 = plen1;
if (i <= 0 || plen2 < plen1 || !plen1 || !plen2)
{
fprintf(stderr, "invalid parameter for prefix-length : %s\n", optarg);
exit(1);
@@ -264,7 +266,7 @@ static void parse_params(int argc, char *argv[])
break;
case 5:
i = sscanf(optarg, "%u/%u", &params.pctmult, &params.pctdiv);
if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv)
if (i != 2 || params.pctdiv < 2 || params.pctmult < 1 || params.pctmult >= params.pctdiv)
{
fprintf(stderr, "invalid parameter for v4-threshold : %s\n", optarg);
exit(1);
@@ -272,7 +274,7 @@ static void parse_params(int argc, char *argv[])
break;
case 6:
i = sscanf(optarg, "%u", &params.v6_threshold);
if (i != 1 || params.v6_threshold<1)
if (i != 1 || params.v6_threshold < 1)
{
fprintf(stderr, "invalid parameter for v6-threshold : %s\n", optarg);
exit(1);
@@ -280,19 +282,20 @@ static void parse_params(int argc, char *argv[])
break;
}
}
if (plen1 != -1 && ((!params.ipv6 && (plen1>31 || plen2>31)) || (params.ipv6 && (plen1>127 || plen2>127))))
if (plen1 != -1 && ((!params.ipv6 && (plen1 > 31 || plen2 > 31)) || (params.ipv6 && (plen1 > 127 || plen2 > 127))))
{
fprintf(stderr, "invalid parameter for prefix-length\n");
exit(1);
}
params.zct_min = params.ipv6 ? plen2==-1 ? DEFAULT_V6_ZCT_MIN : 128-plen2 : plen2==-1 ? DEFAULT_V4_ZCT_MIN : 32-plen2;
params.zct_max = params.ipv6 ? plen1==-1 ? DEFAULT_V6_ZCT_MAX : 128-plen1 : plen1==-1 ? DEFAULT_V4_ZCT_MAX : 32-plen1;
params.zct_min = params.ipv6 ? plen2 == -1 ? DEFAULT_V6_ZCT_MIN : 128 - plen2 : plen2 == -1 ? DEFAULT_V4_ZCT_MIN
: 32 - plen2;
params.zct_max = params.ipv6 ? plen1 == -1 ? DEFAULT_V6_ZCT_MAX : 128 - plen1 : plen1 == -1 ? DEFAULT_V4_ZCT_MAX
: 32 - plen1;
}
int main(int argc, char **argv)
{
char str[256],d;
char str[256], d;
uint32_t ipct = 0, iplist_size = 0, pos = 0, p, zct, ip_ct, pos_end;
parse_params(argc, argv);
@@ -313,25 +316,27 @@ int main(int argc, char **argv)
}
if (inet_pton(AF_INET6, str, &a))
{
if (d=='/')
if (d == '/')
{
// we have subnet ip6/y
// output it as is
if (sscanf(s + 1, "%u", &zct)==1 && zct!=128)
if (sscanf(s + 1, "%u", &zct) == 1 && zct != 128)
{
if (zct<128) printf("%s/%u\n", str, zct);
if (zct < 128)
printf("%s/%u\n", str, zct);
continue;
}
}
else if (d=='-')
else if (d == '-')
{
if (inet_pton(AF_INET6, s+1, &a)) printf("%s-%s\n", str, s+1);
if (inet_pton(AF_INET6, s + 1, &a))
printf("%s-%s\n", str, s + 1);
continue;
}
if (ipct >= iplist_size)
{
iplist_size += ALLOC_STEP;
iplist_new = (struct in6_addr*)(iplist ? realloc(iplist, sizeof(*iplist)*iplist_size) : malloc(sizeof(*iplist)*iplist_size));
iplist_new = (struct in6_addr *)(iplist ? realloc(iplist, sizeof(*iplist) * iplist_size) : malloc(sizeof(*iplist) * iplist_size));
if (!iplist_new)
{
free(iplist);
@@ -371,7 +376,8 @@ int main(int argc, char **argv)
if (memcmp(&ip_start, &ip, sizeof(ip)))
break;
}
if (ip_ct == 1) break;
if (ip_ct == 1)
break;
if (ip_ct >= params.v6_threshold)
{
// network found. but is there smaller network with the same ip_ct ? dont do carpet bombing if possible, use smaller subnets
@@ -400,20 +406,19 @@ int main(int argc, char **argv)
}
else // ipv4
{
uint32_t u1,u2,u3,u4, u11,u22,u33,u44, ip;
uint32_t u1, u2, u3, u4, u11, u22, u33, u44, ip;
uint32_t *iplist = NULL, *iplist_new, i;
while (fgets(str, sizeof(str), stdin))
{
if ((i = sscanf(str, "%u.%u.%u.%u-%u.%u.%u.%u", &u1, &u2, &u3, &u4, &u11, &u22, &u33, &u44)) >= 8 &&
if ((i = sscanf(str, "%u.%u.%u.%u-%u.%u.%u.%u", &u1, &u2, &u3, &u4, &u11, &u22, &u33, &u44)) >= 8 &&
!(u1 & 0xFFFFFF00) && !(u2 & 0xFFFFFF00) && !(u3 & 0xFFFFFF00) && !(u4 & 0xFFFFFF00) &&
!(u11 & 0xFFFFFF00) && !(u22 & 0xFFFFFF00) && !(u33 & 0xFFFFFF00) && !(u44 & 0xFFFFFF00))
{
printf("%u.%u.%u.%u-%u.%u.%u.%u\n", u1, u2, u3, u4, u11, u22, u33, u44);
}
else
if ((i = sscanf(str, "%u.%u.%u.%u/%u", &u1, &u2, &u3, &u4, &zct)) >= 4 &&
!(u1 & 0xFFFFFF00) && !(u2 & 0xFFFFFF00) && !(u3 & 0xFFFFFF00) && !(u4 & 0xFFFFFF00))
else if ((i = sscanf(str, "%u.%u.%u.%u/%u", &u1, &u2, &u3, &u4, &zct)) >= 4 &&
!(u1 & 0xFFFFFF00) && !(u2 & 0xFFFFFF00) && !(u3 & 0xFFFFFF00) && !(u4 & 0xFFFFFF00))
{
if (i == 5 && zct != 32)
{
@@ -428,7 +433,7 @@ int main(int argc, char **argv)
if (ipct >= iplist_size)
{
iplist_size += ALLOC_STEP;
iplist_new = (uint32_t*)(iplist ? realloc(iplist, sizeof(*iplist)*iplist_size) : malloc(sizeof(*iplist)*iplist_size));
iplist_new = (uint32_t *)(iplist ? realloc(iplist, sizeof(*iplist) * iplist_size) : malloc(sizeof(*iplist) * iplist_size));
if (!iplist_new)
{
free(iplist);
@@ -456,12 +461,14 @@ int main(int argc, char **argv)
mask = mask_from_bitcount(zct);
ip_start = iplist[pos] & mask;
subnet_ct = ~mask + 1;
if (iplist[pos] > (ip_start + subnet_ct*(params.pctdiv - params.pctmult) / params.pctdiv))
if (iplist[pos] > (ip_start + subnet_ct * (params.pctdiv - params.pctmult) / params.pctdiv))
continue; // ip is higher than (1-PCT). definitely coverage is not enough. skip searching
ip_end = ip_start | ~mask;
for (p=pos+1, ip_ct=1; p < ipct && iplist[p] <= ip_end; p++) ip_ct++; // count ips within subnet range
if (ip_ct == 1) break;
if (ip_ct >= (subnet_ct*params.pctmult / params.pctdiv))
for (p = pos + 1, ip_ct = 1; p < ipct && iplist[p] <= ip_end; p++)
ip_ct++; // count ips within subnet range
if (ip_ct == 1)
break;
if (ip_ct >= (subnet_ct * params.pctmult / params.pctdiv))
{
// network found. but is there smaller network with the same ip_ct ? dont do carpet bombing if possible, use smaller subnets
if (!ip_ct_best || ip_ct == ip_ct_best)

View File

@@ -20,25 +20,25 @@
Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
//#include <alloca.h>
// #include <alloca.h>
#include <limits.h>
#include <stdlib.h>
//#include <string.h>
// #include <string.h>
#include "qsort.h"
/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size) \
do \
{ \
size_t __size = (size); \
char *__a = (a), *__b = (b); \
do \
{ \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0); \
} while (0)
#define SWAP(a, b, size) \
do \
{ \
size_t __size = (size); \
char *__a = (a), *__b = (b); \
do \
{ \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0); \
} while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
@@ -46,21 +46,20 @@
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct
{
char *lo;
char *hi;
} stack_node;
{
char *lo;
char *hi;
} stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
/* The stack needs log (total_elements) entries (we could even subtract
log(MAX_THRESH)). Since total_elements has type size_t, we get as
upper bound for log (total_elements):
bits per byte (CHAR_BIT) * sizeof(size_t). */
#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
#define PUSH(low, high) ((void)((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void)(--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
/* Order size using quicksort. This implementation incorporates
four optimizations discussed in Sedgewick:
@@ -86,11 +85,10 @@ typedef struct
smaller partition. This *guarantees* no more than log (total_elems)
stack size is needed (actually O(1) in this case)! */
void
gnu_quicksort (void *const pbase, size_t total_elems, size_t size,
__gnu_compar_d_fn_t cmp, void *arg)
void gnu_quicksort(void *const pbase, size_t total_elems, size_t size,
__gnu_compar_d_fn_t cmp, void *arg)
{
char *base_ptr = (char *) pbase;
char *base_ptr = (char *)pbase;
const size_t max_thresh = MAX_THRESH * size;
@@ -99,101 +97,100 @@ gnu_quicksort (void *const pbase, size_t total_elems, size_t size,
return;
if (total_elems > MAX_THRESH)
{
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
stack_node stack[STACK_SIZE];
stack_node *top = stack;
PUSH(NULL, NULL);
while (STACK_NOT_EMPTY)
{
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
stack_node stack[STACK_SIZE];
stack_node *top = stack;
char *left_ptr;
char *right_ptr;
PUSH (NULL, NULL);
/* Select median value from among LO, MID, and HI. Rearrange
LO and HI so the three values are sorted. This lowers the
probability of picking a pathological pivot value and
skips a comparison for both the LEFT_PTR and RIGHT_PTR in
the while loops. */
while (STACK_NOT_EMPTY)
char *mid = lo + size * ((hi - lo) / size >> 1);
if ((*cmp)((void *)mid, (void *)lo, arg) < 0)
SWAP(mid, lo, size);
if ((*cmp)((void *)hi, (void *)mid, arg) < 0)
SWAP(mid, hi, size);
else
goto jump_over;
if ((*cmp)((void *)mid, (void *)lo, arg) < 0)
SWAP(mid, lo, size);
jump_over:;
left_ptr = lo + size;
right_ptr = hi - size;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do
{
while ((*cmp)((void *)left_ptr, (void *)mid, arg) < 0)
left_ptr += size;
while ((*cmp)((void *)mid, (void *)right_ptr, arg) < 0)
right_ptr -= size;
if (left_ptr < right_ptr)
{
char *left_ptr;
char *right_ptr;
/* Select median value from among LO, MID, and HI. Rearrange
LO and HI so the three values are sorted. This lowers the
probability of picking a pathological pivot value and
skips a comparison for both the LEFT_PTR and RIGHT_PTR in
the while loops. */
char *mid = lo + size * ((hi - lo) / size >> 1);
if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
SWAP (mid, lo, size);
if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
SWAP (mid, hi, size);
else
goto jump_over;
if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
SWAP (mid, lo, size);
jump_over:;
left_ptr = lo + size;
right_ptr = hi - size;
/* Here's the famous ``collapse the walls'' section of quicksort.
Gotta like those tight inner loops! They are the main reason
that this algorithm runs much faster than others. */
do
{
while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
left_ptr += size;
while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
right_ptr -= size;
if (left_ptr < right_ptr)
{
SWAP (left_ptr, right_ptr, size);
if (mid == left_ptr)
mid = right_ptr;
else if (mid == right_ptr)
mid = left_ptr;
left_ptr += size;
right_ptr -= size;
}
else if (left_ptr == right_ptr)
{
left_ptr += size;
right_ptr -= size;
break;
}
}
while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= max_thresh)
{
if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr))
{
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else
{
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
SWAP(left_ptr, right_ptr, size);
if (mid == left_ptr)
mid = right_ptr;
else if (mid == right_ptr)
mid = left_ptr;
left_ptr += size;
right_ptr -= size;
}
else if (left_ptr == right_ptr)
{
left_ptr += size;
right_ptr -= size;
break;
}
} while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
left and right partitions are below the threshold size. If so,
ignore one or both. Otherwise, push the larger partition's
bounds on the stack and continue sorting the smaller one. */
if ((size_t)(right_ptr - lo) <= max_thresh)
{
if ((size_t)(hi - left_ptr) <= max_thresh)
/* Ignore both small partitions. */
POP(lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t)(hi - left_ptr) <= max_thresh)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr))
{
/* Push larger left partition indices. */
PUSH(lo, right_ptr);
lo = left_ptr;
}
else
{
/* Push larger right partition indices. */
PUSH(left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
is completely sorted using insertion sort, since this is efficient
@@ -214,37 +211,37 @@ gnu_quicksort (void *const pbase, size_t total_elems, size_t size,
and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
if ((*cmp)((void *)run_ptr, (void *)tmp_ptr, arg) < 0)
tmp_ptr = run_ptr;
if (tmp_ptr != base_ptr)
SWAP (tmp_ptr, base_ptr, size);
SWAP(tmp_ptr, base_ptr, size);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = base_ptr + size;
while ((run_ptr += size) <= end_ptr)
{
tmp_ptr = run_ptr - size;
while ((*cmp)((void *)run_ptr, (void *)tmp_ptr, arg) < 0)
tmp_ptr -= size;
tmp_ptr += size;
if (tmp_ptr != run_ptr)
{
tmp_ptr = run_ptr - size;
while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
tmp_ptr -= size;
char *trav;
tmp_ptr += size;
if (tmp_ptr != run_ptr)
{
char *trav;
trav = run_ptr + size;
while (--trav >= run_ptr)
{
char c = *trav;
char *hi, *lo;
trav = run_ptr + size;
while (--trav >= run_ptr)
{
char c = *trav;
char *hi, *lo;
for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
*hi = *lo;
*hi = c;
}
}
for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
*hi = *lo;
*hi = c;
}
}
}
}
}

View File

@@ -2,5 +2,5 @@
// GNU qsort is 2x faster than musl
typedef int (*__gnu_compar_d_fn_t) (const void *, const void *, void *);
void gnu_quicksort (void *const pbase, size_t total_elems, size_t size, __gnu_compar_d_fn_t cmp, void *arg);
typedef int (*__gnu_compar_d_fn_t)(const void *, const void *, void *);
void gnu_quicksort(void *const pbase, size_t total_elems, size_t size, __gnu_compar_d_fn_t cmp, void *arg);