Router-XS

 view release on metacpan or  search on metacpan

XS.xs  view on Meta::CPAN

      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 )