/* * Copyright (C) Dmitry Volyntsev * Copyright (C) NGINX, Inc. */ #include typedef void (*njs_swap_t) (void *a, void *b, size_t size); njs_inline void njs_swap_u128(void *a, void *b, size_t size) { uint64_t u, v, *au, *bu; au = (uint64_t *) a; bu = (uint64_t *) b; u = au[0]; v = au[1]; au[0] = bu[0]; au[1] = bu[1]; bu[0] = u; bu[1] = v; } njs_inline void njs_swap_u128x(void *a, void *b, size_t size) { uint64_t u, v, *au, *bu; au = (uint64_t *) a; bu = (uint64_t *) b; do { u = au[0]; v = au[1]; au[0] = bu[0]; au[1] = bu[1]; bu[0] = u; bu[1] = v; size -= sizeof(uint64_t) * 2; au += 2; bu += 2; } while (size != 0); } njs_inline void njs_swap_bytes(void *a, void *b, size_t size) { uint8_t u, *au, *bu; au = (uint8_t *) a; bu = (uint8_t *) b; while (size-- != 0) { u = *au; *au++ = *bu; *bu++ = u; } } njs_inline njs_swap_t njs_choose_swap(size_t size) { switch (size) { case 2: return njs_swap_u16; case 4: return njs_swap_u32; case 8: return njs_swap_u64; case 16: return njs_swap_u128; default: if ((size % 16) == 0) { return njs_swap_u128x; } if (size == 1) { return njs_swap_u8; } } return njs_swap_bytes; } njs_inline void njs_sift_down(u_char *base, njs_sort_cmp_t cmp, njs_swap_t swap, size_t n, size_t esize, void *ctx, njs_uint_t i) { njs_uint_t c, m; m = i; while (1) { c = 2 * i + esize; if (c < n && cmp(base + m, base + c, ctx) < 0) { m = c; } c += esize; if (c < n && cmp(base + m, base + c, ctx) < 0) { m = c; } if (m == i) { break; } swap(base + i, base + m, esize); i = m; } } static void njs_heapsort(u_char *base, size_t n, size_t esize, njs_swap_t swap, njs_sort_cmp_t cmp, void *ctx) { njs_uint_t i; i = (n / 2) * esize; n = n * esize; for ( ;; ) { njs_sift_down(base, cmp, swap, n, esize, ctx, i); if (i == 0) { break; } i -= esize; } while (n > esize) { swap(base, base + n - esize, esize); n -= esize; njs_sift_down(base, cmp, swap, n, esize, ctx, 0); } } njs_inline void * njs_pivot(void *a, void *b, void *c, njs_sort_cmp_t cmp, void *ctx) { if (cmp(a, c, ctx) < 0) { if (cmp(b, c, ctx) < 0) { return (cmp(a, b, ctx) < 0) ? b : a; } return c; } if (cmp(b, a, ctx) < 0) { return (cmp(b, c, ctx) < 0) ? c : b; } return a; } typedef struct { u_char *base; njs_uint_t elems; } njs_qsort_state_t; #define NJS_MAX_DEPTH 16 void njs_qsort(void *arr, size_t n, size_t esize, njs_sort_cmp_t cmp, void *ctx) { int r; u_char *base, *lt, *gt, *c, *p, *end; njs_uint_t m4; njs_swap_t swap; njs_qsort_state_t stack[NJS_MAX_DEPTH], *sp; if (n < 2) { return; } swap = njs_choose_swap(esize); sp = stack; sp->base = arr; sp->elems = n; sp++; while (sp-- > stack) { base = sp->base; n = sp->elems; end = base + n * esize; while (n > 6) { if (njs_slow_path(sp == &stack[NJS_MAX_DEPTH - 1])) { njs_heapsort(base, n, esize, swap, cmp, ctx); end = base; break; } m4 = (n / 4) * esize; p = njs_pivot(base + m4, base + 2 * m4, base + 3 * m4, cmp, ctx); swap(base, p, esize); /** * Partition * < mid | == mid | unprocessed | mid > * lt p gt */ lt = base; gt = end; p = lt + esize; while (p < gt) { r = cmp(p, lt, ctx); if (r <= 0) { if (r < 0) { swap(lt, p, esize); lt += esize; } p += esize; continue; } swap(gt - esize, p, esize); gt -= esize; } if (lt - base > end - gt) { sp->base = base; sp->elems = (lt - base) / esize; base = gt; n = (end - gt) / esize; } else { sp->base = gt; sp->elems = (end - gt) / esize; n = (lt - base) / esize; } end = base + n * esize; sp++; } /* Insertion sort. */ for (p = base + esize; p < end; p += esize) { for (c = p; c > base && cmp(c, c - esize, ctx) < 0; c -= esize) { swap(c, c - esize, esize); } } } } #define njs_errno_case(e) \ case e: \ return #e; const char* njs_errno_string(int errnum) { switch (errnum) { #ifdef EACCES njs_errno_case(EACCES); #endif #ifdef EADDRINUSE njs_errno_case(EADDRINUSE); #endif #ifdef EADDRNOTAVAIL njs_errno_case(EADDRNOTAVAIL); #endif #ifdef EAFNOSUPPORT njs_errno_case(EAFNOSUPPORT); #endif #ifdef EAGAIN njs_errno_case(EAGAIN); #endif #ifdef EWOULDBLOCK #if EAGAIN != EWOULDBLOCK njs_errno_case(EWOULDBLOCK); #endif #endif #ifdef EALREADY njs_errno_case(EALREADY); #endif #ifdef EBADF njs_errno_case(EBADF); #endif #ifdef EBADMSG njs_errno_case(EBADMSG); #endif #ifdef EBUSY njs_errno_case(EBUSY); #endif #ifdef ECANCELED njs_errno_case(ECANCELED); #endif #ifdef ECHILD njs_errno_case(ECHILD); #endif #ifdef ECONNABORTED njs_errno_case(ECONNABORTED); #endif #ifdef ECONNREFUSED njs_errno_case(ECONNREFUSED); #endif #ifdef ECONNRESET njs_errno_case(ECONNRESET); #endif #ifdef EDEADLK njs_errno_case(EDEADLK); #endif #ifdef EDESTADDRREQ njs_errno_case(EDESTADDRREQ); #endif #ifdef EDOM njs_errno_case(EDOM); #endif #ifdef EDQUOT njs_errno_case(EDQUOT); #endif #ifdef EEXIST njs_errno_case(EEXIST); #endif #ifdef EFAULT njs_errno_case(EFAULT); #endif #ifdef EFBIG njs_errno_case(EFBIG); #endif #ifdef EHOSTUNREACH njs_errno_case(EHOSTUNREACH); #endif #ifdef EIDRM njs_errno_case(EIDRM); #endif #ifdef EILSEQ njs_errno_case(EILSEQ); #endif #ifdef EINPROGRESS njs_errno_case(EINPROGRESS); #endif #ifdef EINTR njs_errno_case(EINTR); #endif #ifdef EINVAL njs_errno_case(EINVAL); #endif #ifdef EIO njs_errno_case(EIO); #endif #ifdef EISCONN njs_errno_case(EISCONN); #endif #ifdef EISDIR njs_errno_case(EISDIR); #endif #ifdef ELOOP njs_errno_case(ELOOP); #endif #ifdef EMFILE njs_errno_case(EMFILE); #endif #ifdef EMLINK njs_errno_case(EMLINK); #endif #ifdef EMSGSIZE njs_errno_case(EMSGSIZE); #endif #ifdef EMULTIHOP njs_errno_case(EMULTIHOP); #endif #ifdef ENAMETOOLONG njs_errno_case(ENAMETOOLONG); #endif #ifdef ENETDOWN njs_errno_case(ENETDOWN); #endif #ifdef ENETRESET njs_errno_case(ENETRESET); #endif #ifdef ENETUNREACH njs_errno_case(ENETUNREACH); #endif #ifdef ENFILE njs_errno_case(ENFILE); #endif #ifdef ENOBUFS njs_errno_case(ENOBUFS); #endif #ifdef ENODATA njs_errno_case(ENODATA); #endif #ifdef ENODEV njs_errno_case(ENODEV); #endif #ifdef ENOENT njs_errno_case(ENOENT); #endif #ifdef ENOEXEC njs_errno_case(ENOEXEC); #endif #ifdef ENOLINK njs_errno_case(ENOLINK); #endif #ifdef ENOLCK #if ENOLINK != ENOLCK njs_errno_case(ENOLCK); #endif #endif #ifdef ENOMEM njs_errno_case(ENOMEM); #endif #ifdef ENOMSG njs_errno_case(ENOMSG); #endif #ifdef ENOPROTOOPT njs_errno_case(ENOPROTOOPT); #endif #ifdef ENOSPC njs_errno_case(ENOSPC); #endif #ifdef ENOSR njs_errno_case(ENOSR); #endif #ifdef ENOSTR njs_errno_case(ENOSTR); #endif #ifdef ENOSYS njs_errno_case(ENOSYS); #endif #ifdef ENOTCONN njs_errno_case(ENOTCONN); #endif #ifdef ENOTDIR njs_errno_case(ENOTDIR); #endif #ifdef ENOTEMPTY #if ENOTEMPTY != EEXIST njs_errno_case(ENOTEMPTY); #endif #endif #ifdef ENOTSOCK njs_errno_case(ENOTSOCK); #endif #ifdef ENOTSUP njs_errno_case(ENOTSUP); #else #ifdef EOPNOTSUPP njs_errno_case(EOPNOTSUPP); #endif #endif #ifdef ENOTTY njs_errno_case(ENOTTY); #endif #ifdef ENXIO njs_errno_case(ENXIO); #endif #ifdef EOVERFLOW njs_errno_case(EOVERFLOW); #endif #ifdef EPERM njs_errno_case(EPERM); #endif #ifdef EPIPE njs_errno_case(EPIPE); #endif #ifdef EPROTO njs_errno_case(EPROTO); #endif #ifdef EPROTONOSUPPORT njs_errno_case(EPROTONOSUPPORT); #endif #ifdef EPROTOTYPE njs_errno_case(EPROTOTYPE); #endif #ifdef ERANGE njs_errno_case(ERANGE); #endif #ifdef EROFS njs_errno_case(EROFS); #endif #ifdef ESPIPE njs_errno_case(ESPIPE); #endif #ifdef ESRCH njs_errno_case(ESRCH); #endif #ifdef ESTALE njs_errno_case(ESTALE); #endif #ifdef ETIME njs_errno_case(ETIME); #endif #ifdef ETIMEDOUT njs_errno_case(ETIMEDOUT); #endif #ifdef ETXTBSY njs_errno_case(ETXTBSY); #endif #ifdef EXDEV njs_errno_case(EXDEV); #endif default: break; } return "UNKNOWN CODE"; }