File: sort.h

package info (click to toggle)
graphviz 14.0.5-2
  • links: PTS
  • area: main
  • in suites: forky
  • size: 139,388 kB
  • sloc: ansic: 141,938; cpp: 11,957; python: 7,766; makefile: 4,043; yacc: 3,030; xml: 2,972; tcl: 2,495; sh: 1,388; objc: 1,159; java: 560; lex: 423; perl: 243; awk: 156; pascal: 139; php: 58; ruby: 49; cs: 31; sed: 1
file content (39 lines) | stat: -rw-r--r-- 1,252 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/// @file
/// @brief `qsort` with carried along context
/// @ingroup cgraph_utils
///
/// The non-standard `qsort_r`, Windows’ `qsort_s`, and C11’s `qsort_s` provide
/// a `qsort` alternative with an extra state parameter. Unfortunately none of
/// these are easily usable portably in Graphviz. This header implements an
/// alternative that hopefully is.

#pragma once

#include <assert.h>
#include <stdlib.h>

static _Thread_local int (*gv_sort_compar)(const void *, const void *, void *);
static _Thread_local void *gv_sort_arg;

static inline int gv_sort_compar_wrapper(const void *a, const void *b) {
  assert(gv_sort_compar != NULL && "no comparator set in gv_sort");
  return gv_sort_compar(a, b, gv_sort_arg);
}

/// `qsort` with an extra state parameter, ala `qsort_r`
static inline void gv_sort(void *base, size_t nmemb, size_t size,
                           int (*compar)(const void *, const void *, void *),
                           void *arg) {
  assert(gv_sort_compar == NULL && gv_sort_arg == NULL &&
         "unsupported recursive call to gv_sort");

  gv_sort_compar = compar;
  gv_sort_arg = arg;

  if (nmemb > 1) {
    qsort(base, nmemb, size, gv_sort_compar_wrapper);
  }

  gv_sort_compar = NULL;
  gv_sort_arg = NULL;
}