in reply to Re: XS: SvPVLV examples?
in thread XS: SvPVLV examples?

And here's a sample getter and setter:
typedef enum { ENDIAN_NATIVE, ENDIAN_NETWORK, ENDIAN_LITTLE, ENDIAN_BIG = ENDIAN_NETWORK } ENDIANNESS; int magic_get_uint16(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; SV* const src_sv = LvTARG(sv); const char* const src_mem = SvPV_const(src_sv, len); STRLEN ofs = LvTARGOFF(sv); ENDIANNESS endianness = (ENDIANNESS)LvTARGLEN(sv); U16 dst; /* We use a PVLV instead of storing an SV in the magic */ PERL_UNUSED_ARG(mg); if (ofs >= len/2) croak("Index outside of mmap"); ofs *= 2; if (endianness == ENDIAN_LITTLE) dst = (src_mem[ofs+1] << 8) | src_mem[ofs+0]; else if (sizeof(U16) != 2 || endianness == ENDIAN_NETWORK) dst = (src_mem[ofs+0] << 8) | src_mem[ofs+1]; else { *(((char*)&dst)+0) = src_mem[ofs+0]; *(((char*)&dst)+1) = src_mem[ofs+1]; } sv_setuv(sv, dst); return 0; } int magic_set_uint16(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; SV* const dst_sv = LvTARG(sv); char* const dst_mem = SvPV(dst_sv, len); STRLEN ofs = LvTARGOFF(sv); ENDIANNESS endianness = (ENDIANNESS)LvTARGLEN(sv); UV num U16 src; /* We use a PVLV instead of storing an SV in the magic */ PERL_UNUSED_ARG(mg); SvUV(sv); if (!SvIOK(sv)) croak("Invalid value: Not a integer"); num = SvUVX(sv); if (num > 65535) croak("Invalid value: Not a 16-bit integer"); src = (U16)num; if (ofs >= len/2) croak("Index outside of mmap"); ofs *= 2; if (endianness == ENDIAN_LITTLE) { dst_mem[ofs+0] = src & 0xFF; dst_mem[ofs+1] = src >> 8; } else if (sizeof(U16) != 2 || endianness == ENDIAN_NETWORK) { dst_mem[ofs+0] = src >> 8; dst_mem[ofs+1] = src & 0xFF; } else { dst_mem[ofs+0] = *(((const char*)&src)+0); dst_mem[ofs+1] = *(((const char*)&src)+1); } return 0; }

It would simplify things to case src_mem/dst_mem to *U16, but U16 can be more than 16 bits and it introduces alignment issues.

I made the native byte ordering big endian on systems where there is no 16-bit unsigned int.

Replies are listed 'Best First'.
Re^3: XS: SvPVLV examples?
by BrowserUk (Patriarch) on Sep 26, 2009 at 03:41 UTC
    const char* const src_mem = SvPV_const(lsv, len);
    1. Where is SvPV_const() documented?
    2. And where does lsv come from?

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      1. Doesn't appear to be. It surely isn't necessary in the getter to do so much consting in the getter, and it's wrong to use SvPV_const in the setter. Fixed setter.
      2. Should be src_sv and dst_sv. Fixed.