-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathXS.xs
103 lines (91 loc) · 2.5 KB
/
XS.xs
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define PERL_NO_GET_CONTEXT
#include "locale.h"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "src/nsort.h"
#include "const-c.inc"
static I32
S_sv_ncmp(pTHX_ SV *a, SV *b)
{
const char *ia = (const char *) SvPVutf8_nolen(a);
const char *ib = (const char *) SvPVutf8_nolen(b);
return _ncmp(ia, ib, 0, 0);
}
static I32
S_sv_ncmp_reverse(pTHX_ SV *a, SV *b)
{
const char *ia = (const char *) SvPVutf8_nolen(a);
const char *ib = (const char *) SvPVutf8_nolen(b);
return _ncmp(ia, ib, 1, 0);
}
static I32
S_sv_ncoll(pTHX_ SV *a, SV *b)
{
const char *ia = (const char *) SvPVbyte_nolen(a);
const char *ib = (const char *) SvPVbyte_nolen(b);
return _ncmp(ia, ib, 0, 1);
}
static I32
S_sv_ncoll_reverse(pTHX_ SV *a, SV *b)
{
const char *ia = (const char *) SvPVbyte_nolen(a);
const char *ib = (const char *) SvPVbyte_nolen(b);
return _ncmp(ia, ib, 1, 1);
}
MODULE = Sort::Naturally::XS PACKAGE = Sort::Naturally::XS
INCLUDE: const-xs.inc
int
ncmp(arg_a, arg_b)
const char * arg_a
const char * arg_b
CODE:
RETVAL = _ncmp(arg_a, arg_b, 0, 0);
OUTPUT:
RETVAL
void
nsort(...)
PROTOTYPE: @
CODE:
if (!items) {
XSRETURN(0);
}
AV * array = newAV();
int i;
for (i=0; i<items; i++) {
av_push(array, ST(i));
}
sortsv(AvARRAY(array), items, S_sv_ncmp);
for (i=0; i<items; i++) {
ST(i) = av_shift(array);
}
av_undef(array);
SvREFCNT_dec(array);
XSRETURN(items);
void
_sorted(array_ref, reverse, locale)
SV * array_ref
int reverse
const char * locale
CODE:
if (!SvROK(array_ref) || SvTYPE(SvRV(array_ref)) != SVt_PVAV) {
croak("Not an ARRAY ref");
}
AV * array = (AV *) SvRV(array_ref);
int array_len = av_len(array) + 1;
if (locale != NULL && strlen(locale)) {
const char * old_locale = setlocale(LC_ALL, locale);
if (reverse) {
sortsv(AvARRAY(array), array_len, S_sv_ncoll_reverse);
} else {
sortsv(AvARRAY(array), array_len, S_sv_ncoll);
}
setlocale(LC_ALL, old_locale);
} else {
if (reverse) {
sortsv(AvARRAY(array), array_len, S_sv_ncmp_reverse);
} else {
sortsv(AvARRAY(array), array_len, S_sv_ncmp);
}
}