#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "ffi_platypus.h"
#include "ffi_platypus_guts.h"
XS(ffi_pl_record_accessor_opaque)
{
ffi_pl_record_member *member;
SV *self;
SV *arg;
char *ptr1;
void **ptr2;
dVAR; dXSARGS;
if(items == 0)
croak("This is a method, you must provide at least the object");
member = (ffi_pl_record_member*) CvXSUBANY(cv).any_ptr;
self = ST(0);
if(SvROK(self))
self = SvRV(self);
if(!SvOK(self))
croak("Null record error");
ptr1 = (char*) SvPV_nolen(self);
ptr2 = (void**) &ptr1[member->offset];
if(items > 1)
{
if(SvREADONLY(self))
{
croak("record is read-only");
}
else
{
arg = ST(1);
*ptr2 = SvOK(arg) ? INT2PTR(void*, SvIV(arg)) : NULL;
}
}
if(GIMME_V == G_VOID)
XSRETURN_EMPTY;
if(*ptr2 != NULL)
XSRETURN_IV( PTR2IV( *ptr2 ));
else
XSRETURN_EMPTY;
}
XS(ffi_pl_record_accessor_opaque_array)
{
ffi_pl_record_member *member;
SV *self;
SV *arg;
SV **item;
AV *av;
char *ptr1;
void **ptr2;
int i;
dVAR; dXSARGS;
if(items == 0)
croak("This is a method, you must provide at least the object");
member = (ffi_pl_record_member*) CvXSUBANY(cv).any_ptr;
self = ST(0);
if(SvROK(self))
self = SvRV(self);
if(!SvOK(self))
croak("Null record error");
ptr1 = (char*) SvPV_nolen(self);
ptr2 = (void**) &ptr1[member->offset];
if(items > 1 && SvREADONLY(self))
{
croak("record is read-only");
}
if(items > 2)
{
i = SvIV(ST(1));
if(i >= 0 && i < member->count)
{
arg = ST(2);
ptr2[i] = SvOK(arg) ? INT2PTR(void*, SvIV(arg)) : NULL;
}
else
{
warn("illegal index %d", i);
}
}
else if(items > 1)
{
arg = ST(1);
if(SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVAV)
{
av = (AV*) SvRV(arg);
for(i=0; i < member->count; i++)
{
item = av_fetch(av, i, 0);
if(item != NULL && SvOK(*item))
{
ptr2[i] = INT2PTR(void*, SvIV(*item));
}
else
{
ptr2[i] = NULL;
}
}
}
else
{
i = SvIV(ST(1));
if(i < 0 && i >= member->count)
{
warn("illegal index %d", i);
XSRETURN_EMPTY;
}
else if(ptr2[i] == NULL)
{
XSRETURN_EMPTY;
}
else
{
XSRETURN_IV(PTR2IV(ptr2[i]));
}
warn("passing non array reference into ffi/platypus array argument type");
}
}
if(GIMME_V == G_VOID)
XSRETURN_EMPTY;
av = newAV();
av_fill(av, member->count-1);
for(i=0; i < member->count; i++)
{
if(ptr2[i] != NULL)
sv_setiv(*av_fetch(av, i, 1), PTR2IV(ptr2[i]));
}
ST(0) = newRV_inc((SV*)av);
XSRETURN(1);
}