Router-XS
view release on metacpan or search on metacpan
if (matchidx) {
DEBUG_PRINT("capturing %s\n", SPLITBUF[bufidx]);
}
}
}
DEBUG_PRINT("Found %zu matches\n", newmatches);
// if there are no new matches
if (newmatches) {
// keep going if there are more words in the path to match
if (bufidx + 1 < SPLITBUFLEN) {
return NodeSearch(bufidx + 1, matchidx + 1, newmatches);
}
else {
MATCHES:
// we've matched all the words in the path return the first match
for (int i = 0; i < newmatches; i++) {
Node *n = MATCHBUF[matchidx + 1][i];
// only a complete path match will have the coderef set in the leaf node
if (n->coderef)
return n;
}
}
}
ENDNODESEARCH:
DEBUG_PRINT("returning NULL\n");
return NULL;
}
void * NodeTestPath(Node *r, char *path, size_t pathlen, size_t *numcaptures) {
DEBUG_PRINT("\ntesting path: %s\n", path);
pathsplit(path, pathlen, "/", &SPLITBUFLEN);
MATCHBUF[0][0] = r;
Node *n = NodeSearch(0, 0, 1);
if (n) {
DEBUG_PRINT("matched full path\n");
for (int i = 0; i < n->numcaptures; i++) {
memcpy(CAPBUF[i], SPLITBUF[ *(n->captures + i) ], WORDLEN);
}
*numcaptures = n->numcaptures;
return n->coderef;
}
return NULL;
}
MODULE = Router::XS PACKAGE = Router::XS
PROTOTYPES: DISABLED
BOOT:
ROOT = NodeNew("");
void
add_route(path, coderef)
SV *path
SV *coderef
PREINIT:
char *pathstr;
size_t pathlen, numcaptures = 0;
PPCODE:
SvGETMAGIC(path);
/* check for undef, empty string */
if (!SvOK(path) || !SvCUR(path) || !SvROK(coderef))
{
croak("requires path and coderef arguments");
}
pathstr = SvPV_nomg(path, pathlen);
if (NodeTestPath(ROOT, pathstr, pathlen, &numcaptures)) {
croak("Attempted to add duplicate path %s", pathstr);
}
// increment the refcount to stop Perl deleting it
SvREFCNT_inc(coderef);
NodeAddPath(ROOT, pathstr, pathlen, coderef);
// return undef
EXTEND(SP, 1);
PUSHs(sv_newmortal());
void
check_route(path)
SV *path
PREINIT:
char *pathstr;
SV *coderef;
size_t numcaptures = 0, caplen, pathlen;
PPCODE:
SvGETMAGIC(path);
/* check for undef, empty string */
if (!SvOK(path) || !SvCUR(path))
{
croak("requires path");
}
pathstr = SvPV_nomg(path, pathlen);
coderef = NodeTestPath(ROOT, pathstr, pathlen, &numcaptures);
EXTEND(SP, 1);
if (coderef) {
PUSHMARK(SP);
PUSHs(coderef);
if (numcaptures) {
EXTEND(SP, numcaptures);
for (int i = 0; i < numcaptures; i++) {
caplen = strlen(CAPBUF[i]);
PUSHs( sv_2mortal(newSVpvn(CAPBUF[i], caplen)) );
}
}
PUTBACK;
}
else {
// return undef
PUSHs(sv_newmortal());
}
( run in 1.773 second using v1.01-cache-2.11-cpan-5511b514fd6 )