builtin: implement array.sort_with_compare_context
parent
eb772cfcf9
commit
17226830c8
|
@ -756,12 +756,22 @@ pub fn (mut a array) sort(callback fn (voidptr, voidptr) int)
|
||||||
// ```
|
// ```
|
||||||
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
pub fn (mut a array) sort_with_compare(callback fn (voidptr, voidptr) int) {
|
||||||
$if freestanding {
|
$if freestanding {
|
||||||
panic('sort does not work with -freestanding')
|
panic('sort_with_compare does not work with -freestanding')
|
||||||
} $else {
|
} $else {
|
||||||
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
unsafe { vqsort(a.data, usize(a.len), usize(a.element_size), callback) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut a array) sort_with_compare_context(callback fn (voidptr, voidptr, voidptr) int, context voidptr) {
|
||||||
|
$if freestanding {
|
||||||
|
panic('sort_with_compare_context does not work with -freestanding')
|
||||||
|
} $else {
|
||||||
|
unsafe {
|
||||||
|
vqsort_context(a.data, usize(a.len), usize(a.element_size), callback, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// contains determines whether an array includes a certain value among its elements
|
// contains determines whether an array includes a certain value among its elements
|
||||||
// It will return `true` if the array contains an element with this value.
|
// It will return `true` if the array contains an element with this value.
|
||||||
// It is similar to `.any` but does not take an `it` expression.
|
// It is similar to `.any` but does not take an `it` expression.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module builtin
|
||||||
|
|
||||||
|
fn C.qsort_r(base voidptr, items usize, item_size usize, context voidptr, cb C.qsort_r_bsd_callback_func_context)
|
||||||
|
fn C.qsort_s(base voidptr, items usize, item_size usize, cb C.qsort_s_iso_callback_func_context, context voidptr)
|
|
@ -0,0 +1,3 @@
|
||||||
|
module builtin
|
||||||
|
|
||||||
|
fn C.qsort_r(base voidptr, items usize, item_size usize, cb C.qsort_r_gnu_callback_func_context, context voidptr)
|
|
@ -0,0 +1,3 @@
|
||||||
|
module builtin
|
||||||
|
|
||||||
|
fn C.qsort_s(base voidptr, items usize, item_size usize, cb C.qsort_s_windows_callback_func_context, context voidptr)
|
|
@ -66,7 +66,41 @@ pub fn vmemset(s voidptr, c int, n int) voidptr {
|
||||||
|
|
||||||
type FnSortCB = fn (const_a voidptr, const_b voidptr) int
|
type FnSortCB = fn (const_a voidptr, const_b voidptr) int
|
||||||
|
|
||||||
|
type FnSortContextCB = fn (const_a voidptr, const_b voidptr, context voidptr) int
|
||||||
|
|
||||||
[inline; unsafe]
|
[inline; unsafe]
|
||||||
fn vqsort(base voidptr, nmemb usize, size usize, sort_cb FnSortCB) {
|
fn vqsort(base voidptr, nmemb usize, size usize, sort_cb FnSortCB) {
|
||||||
C.qsort(base, nmemb, size, voidptr(sort_cb))
|
C.qsort(base, nmemb, size, voidptr(sort_cb))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VIndirectQSortContext {
|
||||||
|
mut:
|
||||||
|
real_context voidptr
|
||||||
|
real_sort_cb FnSortContextCB
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline; unsafe]
|
||||||
|
fn vqsort_context(base voidptr, nmemb usize, size usize, sort_cb FnSortContextCB, context voidptr) {
|
||||||
|
// See https://stackoverflow.com/questions/39560773/different-declarations-of-qsort-r-on-mac-and-linux
|
||||||
|
// ... and https://xkcd.com/927/ :-|
|
||||||
|
$if linux {
|
||||||
|
C.qsort_r(base, nmemb, size, voidptr(sort_cb), context)
|
||||||
|
} $else {
|
||||||
|
ic := VIndirectQSortContext{
|
||||||
|
real_context: context
|
||||||
|
real_sort_cb: sort_cb
|
||||||
|
}
|
||||||
|
$if windows {
|
||||||
|
cb := fn (context &VIndirectQSortContext, const_a voidptr, const_b voidptr) int {
|
||||||
|
return context.real_sort_cb(const_a, const_b, context.real_context)
|
||||||
|
}
|
||||||
|
C.qsort_s(base, nmemb, size, voidptr(cb), &ic)
|
||||||
|
} $else {
|
||||||
|
// macos, BSDs, probably other unixes too:
|
||||||
|
cb := fn (context &VIndirectQSortContext, const_a voidptr, const_b voidptr) int {
|
||||||
|
return context.real_sort_cb(const_a, const_b, context.real_context)
|
||||||
|
}
|
||||||
|
C.qsort_r(base, nmemb, size, &ic, voidptr(cb))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
struct Context {
|
||||||
|
mut:
|
||||||
|
comparisons []string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_sort_with_compare() {
|
||||||
|
mut a := ['hi', '1', '5', '3']
|
||||||
|
mut context := Context{}
|
||||||
|
a.sort_with_compare_context(fn (a &string, b &string, mut context Context) int {
|
||||||
|
context.comparisons << 'a: ${*a} | b: ${*b}'
|
||||||
|
if a < b {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if a > b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}, context)
|
||||||
|
dump(a)
|
||||||
|
dump(context)
|
||||||
|
assert a == ['1', '3', '5', 'hi']
|
||||||
|
assert context.comparisons == [
|
||||||
|
'a: hi | b: 1',
|
||||||
|
'a: 5 | b: 3',
|
||||||
|
'a: 1 | b: 3',
|
||||||
|
'a: hi | b: 3',
|
||||||
|
'a: hi | b: 5',
|
||||||
|
]
|
||||||
|
}
|
|
@ -478,6 +478,10 @@ const c_headers = c_helper_macros + c_unsigned_comparison_functions + c_common_m
|
||||||
r'
|
r'
|
||||||
// c_headers
|
// c_headers
|
||||||
typedef int (*qsort_callback_func)(const void*, const void*);
|
typedef int (*qsort_callback_func)(const void*, const void*);
|
||||||
|
typedef int (*qsort_s_iso_callback_func_context)(const void*, const void*, void*); // ISO C11, *optional* Annex K
|
||||||
|
typedef int (*qsort_s_windows_callback_func_context)(void*, const void*, const void*); // Windows
|
||||||
|
typedef int (*qsort_r_gnu_callback_func_context)(const void*, const void*, void*); // Linux, GNU
|
||||||
|
typedef int (*qsort_r_bsd_callback_func_context)(void*, const void*, const void*); // MacOS, BSD
|
||||||
#include <stdio.h> // TODO remove all these includes, define all function signatures and types manually
|
#include <stdio.h> // TODO remove all these includes, define all function signatures and types manually
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
Loading…
Reference in New Issue