Acme-Pointer

 view release on metacpan or  search on metacpan

lib/Acme/Pointer.xs  view on Meta::CPAN

#ifdef __cplusplus
extern "C" {
#endif

#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#ifdef __cplusplus
} /* extern "C" */
#endif

#define NEED_newSVpvn_flags
#include "ppport.h"

#define CODE   "CODE"
#define HASH   "HASH"
#define ARRAY  "ARRAY"
#define SCALAR "SCALAR"

#define IsCodeRef(l, str)   (l > 4 && strnNE(str, CODE,   4) == 0 && str[4] == '(' && str[l - 1] == ')')
#define IsHashRef(l, str)   (l > 4 && strnNE(str, HASH,   4) == 0 && str[4] == '(' && str[l - 1] == ')')
#define IsArrayRef(l, str)  (l > 5 && strnNE(str, ARRAY,  5) == 0 && str[5] == '(' && str[l - 1] == ')')
#define IsScalarRef(l, str) (l > 6 && strnNE(str, SCALAR, 6) == 0 && str[6] == '(' && str[l - 1] == ')')

static SV *
_pointer(pTHX_ const char *addr)
{
    SV *p = (SV *)strtoul(addr, NULL, 0);
    if (SvTYPE(p) > 0) {
        return newRV_inc(p);
    }
    return &PL_sv_undef;
}

static SV *
get_address(pTHX_ int idx, int len, const char *ref)
{
    int i = idx;
    while (ref[i++] != ')');
    const char *addr;
    int l = i - (idx + 2);
    Newxz(addr, l, char);  /* same as calloc */
    Move(ref + idx + 1, addr, l, char); /* same as memmove */
    return _pointer(aTHX_ addr);
}

MODULE = Acme::Pointer    PACKAGE = Acme::Pointer

PROTOTYPES: ENABLE

SV *
deref(ref_str)
    SV *ref_str
CODE:
{
    STRLEN len;
    const char *ref = SvPV(ref_str, len);
    if (IsCodeRef(len, ref) || IsHashRef(len, ref)) {
        RETVAL = get_address(aTHX_ 4, len, ref);
    } else if (IsArrayRef(len, ref)) {
        RETVAL = get_address(aTHX_ 5, len, ref);
    } else if (IsScalarRef(len, ref)) {
        RETVAL = get_address(aTHX_ 6, len, ref);
    } else {
        RETVAL = &PL_sv_undef;
    }
}
OUTPUT:
    RETVAL

SV *
pointer(addr_str)



( run in 1.484 second using v1.01-cache-2.11-cpan-140bd7fdf52 )