Basic-Coercion-XS
view release on metacpan or search on metacpan
lib/Basic/Coercion/XS.xs view on Meta::CPAN
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
static SV * new_coerce (SV * type, CV * coerce) {
dTHX;
HV * hash = newHV();
hv_store(hash, "name", 4, type, 0);
hv_store(hash, "coerce", 6, (SV*)coerce, 0);
return sv_bless(newRV_noinc((SV*)hash), gv_stashsv(newSVpv("Basic::Coercion::XS", 19), 0));
}
char *get_caller(void) {
dTHX;
char *callr = HvNAME((HV*)CopSTASH(PL_curcop));
return callr;
}
AV* split_by_regex(char *input, SV **pattern_sv) {
dTHX;
REGEXP *rx;
AV *result = newAV();
if (!pattern_sv || !SvROK(*pattern_sv)) {
char *pattern = (pattern_sv && SvOK(*pattern_sv)) ? SvPV_nolen(*pattern_sv) : "\\s+";
STRLEN patlen = strlen(pattern);
SV *pat_sv = newSVpvn(pattern, patlen);
rx = pregcomp(pat_sv, 0);
SvREFCNT_dec(pat_sv);
} else {
SvREFCNT_inc(*pattern_sv);
rx = (REGEXP *)SvRV(*pattern_sv);
}
if (!rx) {
return result;
}
STRLEN input_len = strlen(input);
STRLEN pos = 0;
STRLEN last = 0;
SV *input_sv = newSVpvn(input, input_len);
while (pos <= input_len) {
I32 nmatch;
nmatch = pregexec(rx, input + pos, input + input_len, input, 0, input_sv, 0);
if (nmatch > 0) {
STRLEN match_start = ((regexp *)SvANY(rx))->offs[0].start;
STRLEN match_end = ((regexp *)SvANY(rx))->offs[0].end;
SV *token = newSVpvn(input + last, match_start - last);
av_push(result, token);
if (match_end == match_start) {
pos = match_end + 1;
} else {
pos = match_end;
}
last = pos;
} else {
SV *token = newSVpvn(input + last, input_len - last);
av_push(result, token);
break;
}
}
SvREFCNT_dec(input_sv);
SvREFCNT_dec(rx);
return result;
}
MODULE = Basic::Coercion::XS::Definition PACKAGE = Basic::Coercion::XS::Definition
PROTOTYPES: DISABLE
SV *
_StrToArray(...)
CODE:
SV * self = CvXSUBANY(cv).any_ptr;
if (!self || !SvOK(self)) {
lib/Basic/Coercion/XS.xs view on Meta::CPAN
hv_store(self, "coerce", 6, newRV_noinc((SV*)type), 0);
if (items % 2 != 0) {
croak("StrToHash type constraint requires an even number of arguments");
}
int i = 0;
for (i = 0; i < items; i += 2) {
SV * key = ST(i);
SV * value = ST(i + 1);
if (!SvOK(key) || SvTYPE(key) != SVt_PV) {
croak("key must be a string");
}
if (!SvOK(value)) {
croak("value must be defined");
}
STRLEN keylen;
char * keystr = SvPV(key, keylen);
hv_store(self, keystr, keylen, newSVsv(value), 0);
}
OUTPUT:
RETVAL
MODULE = Basic::Coercion::XS PACKAGE = Basic::Coercion::XS
PROTOTYPES: ENABLE
FALLBACK: TRUE
SV *
by(self, pattern)
SV *self
SV *pattern
CODE:
if (!self || !SvROK(self)) {
croak("constraint not initialized");
}
if (SvTYPE(pattern) != SVt_PV && !SvROK(pattern)) {
croak("pattern must be a string or a regex object");
}
SvREFCNT_inc(self);
HV * self_hv = (HV*)SvRV(self);
hv_store(self_hv, "by", 2, newSVsv(pattern), 0);
RETVAL = self;
OUTPUT:
RETVAL
CV *
coerce(...)
OVERLOAD: &{}
CODE:
SV * self = ST(0);
if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVHV) {
croak("first argument must be a Basic::Coercion::XS object");
}
SV * cb = *hv_fetch((HV*)SvRV(self), "coerce", 6, 0);
RETVAL = (CV*)SvRV(cb);
OUTPUT:
RETVAL
void
import( ...)
CODE:
char *pkg = get_caller();
STRLEN retlen;
int i = 1;
for (i = 1; i < items; i++) {
char * ex = SvPV(ST(i), retlen);
int name_len = strlen(pkg) + retlen + 3;
char *name = (char *)malloc(name_len);
if (!name) croak("Out of memory");
snprintf(name, name_len, "%s::%s", pkg, ex);
if (strcmp(ex, "StrToArray") == 0) {
newXS(name, XS_Basic__Coercion__XS__Definition_StrToArray, __FILE__);
} else if (strcmp(ex, "StrToHash") == 0) {
newXS(name, XS_Basic__Coercion__XS__Definition_StrToHash, __FILE__);
} else {
croak("Unknown import: %s", ex);
}
safefree(name);
}
( run in 0.671 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )