--- /dev/null
+../../licenses/CC0
\ No newline at end of file
--- /dev/null
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * order - Simple, common value comparison functions
+ *
+ * This implements a number of commonly useful comparison functions in
+ * a form which can be used with qsort() and bsearch() in the standard
+ * library, or asort() and asearch() in ccan amongst other places.
+ *
+ * License: CC0
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/typesafe_cb\n");
+ return 0;
+ }
+ if (strcmp(argv[1], "testdepends") == 0) {
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+/* CC0 license (public domain) - see LICENSE file for details */
+#ifndef CCAN_ORDER_H
+#define CCAN_ORDER_H
+
+#include <stdint.h>
+#include <assert.h>
+
+#include <ccan/typesafe_cb/typesafe_cb.h>
+
+typedef int (*_total_order_cb)(const void *, const void *, void *);
+typedef int (*total_order_noctx_cb)(const void *, const void *);
+
+#define total_order_cb(_name, _item, _ctx) \
+ int (*_name)(const __typeof__(_item) *, \
+ const __typeof__(_item) *, \
+ __typeof__(_ctx))
+
+#define total_order_cast(cmp, item, ctx) \
+ typesafe_cb_cast(_total_order_cb, total_order_cb(, item, ctx), \
+ (cmp))
+
+struct _total_order {
+ _total_order_cb cb;
+ void *ctx;
+};
+
+#define total_order(_name, _item, _ctx) \
+ struct { \
+ total_order_cb(cb, _item, _ctx); \
+ _ctx ctx; \
+ } _name
+
+#endif /* CCAN_ORDER_H */
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <ccan/order/order.h>
+
+#include "fancy_cmp.h"
+
+#ifdef FAIL
+typedef int item_t;
+#else
+typedef struct item item_t;
+#endif
+
+int main(int argc, char *argv[])
+{
+ total_order_cb(cb0, struct item, struct cmp_info *) = fancy_cmp;
+ _total_order_cb cb1 = total_order_cast(fancy_cmp,
+ item_t, struct cmp_info *);
+
+ printf("%p %p\n", cb0, cb1);
+
+ exit(0);
+}
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <ccan/order/order.h>
+
+#include "fancy_cmp.h"
+
+#ifdef FAIL
+typedef int ctx_t;
+#else
+typedef struct cmp_info ctx_t;
+#endif
+
+int main(int argc, char *argv[])
+{
+ total_order_cb(cb0, struct item, struct cmp_info *) = fancy_cmp;
+ _total_order_cb cb1 = total_order_cast(fancy_cmp, struct item,
+ ctx_t *);
+
+ printf("%p %p\n", cb0, cb1);
+
+ exit(0);
+
+}
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <ccan/order/order.h>
+
+#include "fancy_cmp.h"
+
+int main(int argc, char *argv[])
+{
+ total_order_cb(cb0, struct item, struct cmp_info *) = fancy_cmp;
+ _total_order_cb cb1 = total_order_cast(fancy_cmp,
+ struct item, struct cmp_info *);
+ total_order_noctx_cb cb_noctx = fancy_cmp_noctx;
+
+ printf("%p %p %p\n", cb0, cb1, cb_noctx);
+
+ exit(0);
+}
--- /dev/null
+#ifndef _FANCY_CMP_H
+#define _FANCY_CMP_H
+
+struct cmp_info {
+ unsigned xcode;
+ int offset;
+};
+
+struct item {
+ unsigned value;
+ char *str;
+};
+
+static inline int fancy_cmp(const struct item *a, const struct item *b,
+ struct cmp_info *ctx)
+{
+ unsigned vala = a->value ^ ctx->xcode;
+ unsigned valb = b->value ^ ctx->xcode;
+ const char *stra, *strb;
+
+ if (vala < valb)
+ return -1;
+ else if (valb < vala)
+ return 1;
+
+ stra = a->str + ctx->offset;
+ strb = b->str + ctx->offset;
+
+ return strcmp(stra, strb);
+}
+
+static inline int fancy_cmp_noctx(const void *av, const void *bv)
+{
+ const struct item *a = (const struct item *)av;
+ const struct item *b = (const struct item *)bv;
+ struct cmp_info ctx_default = {
+ .xcode = 0x1234,
+ .offset = 3,
+ };
+ total_order(default_order, struct item, struct cmp_info *) = {
+ fancy_cmp, &ctx_default,
+ };
+
+ return default_order.cb(a, b, default_order.ctx);
+}
+
+#endif /* _FANCY_CMP_H */