develooper Front page | perl.perl5.porters | Postings from May 2013

Re: [perl #116407] SvPVutf8 != SvPVX, and sv_2pvutf8

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
May 17, 2013 14:34
Subject:
Re: [perl #116407] SvPVutf8 != SvPVX, and sv_2pvutf8
Message ID:
20130517141416.GQ2069@iabyn.com
On Fri, May 10, 2013 at 12:13:38PM +0100, Dave Mitchell wrote:
> > The previous sentence might need to be another
> > ticket. perlguts in blead says nothing about SvPV is not SvPVX and says
> > nothing about COW.
> 
> Currently near the top of my things to do prior to 5.18 is to add some
> notes about that issue to perlguts.

It won't be in time for perl 5.18.0 now, but in terms of what we need to add
to perlguts, my feeling is that the general outline should be something
like the following. I'm happy to be corrected however; this isn't an
area I work with much. In particular, I'm not sure whether we need to
mention SV_CHECK_THINKFIRST/SvTHINKFIRST/sv_force_normal_flags(), SvIsCOW
etc?

    Given an arbitrary SV,

    1) if you want to *read* its string value, use SvPV (or one of it's many
    variants such as SvPV_nomg, SvPV_nolen etc, depending on circumstances).
    This will give you a string representation of the SV in a char buffer
    (which may or may not match the SvPVX of the string).

    Note that this preserves the original content of the SV. For example if
    the SV is a reference, then after the call to SvPV(), it's still a
    reference, it's not SvPOK, and the return value points to a temporary
    buffer containing a string like "ARRAY(0x12345678)".

    As a shortcut, if you've already done any get magic processing that was
    required, and if the SV is SvPOK, then its okay to use SvCUR and to
    directly read from the SvPVX buffer.

    2) If you want to *modify* the string value of an SV by writing into its
    string buffer (for example if you wanted to implement an in-place version
    of the ucfirst() function), then you need to first call SvPV_force (or one
    of its variants like SvPV_force_nomg, SvPVutf8_force etc). This will
    coerce the SV into a PV-compatible type regardless of its previous
    contents (or croak with "Can't coerce HASH to string" or similar, if it's
    something not convertible).

    Note that this may destroy the original content of the SV. For example if
    the SV was a reference, then after the call to SvPV(), it's no longer
    a reference, and is instead a plain SvPOK string with a value like
    "ARRAY(0x12345678)"

    After modifying the buffer, you will need to do SvSETMAGIC for the
    changes to potentially take effect (for example if the variable is
    tied).

    As a shortcut, if you've already done any get magic processing that was
    required, and if the SV is SvPOK, then its okay to use SvCUR and to
    directly read from and write to the SvPVX buffer, and to use SvGROW()
    if you want to write beyond the end of the string. You'll still need
    to call SvSETMAGIC afterwards.

    3) if an XS sub is declared as having a 'char *' or similar argument,
    then the standard typemap will do the equivalent of calling SvPV on
    the passed SV to retrieve a string buffer. Note that this means that
    the buffer should be treated as read-only, and not passed to any C
    function which might modify it. If your XS sub needs to modify the
    string, then declare the arg as type 'SV *' and manually perform your
    own SvPV_force and (later SvSETMAGIC) on it.

-- 
Overhead, without any fuss, the stars were going out.
    -- Arthur C Clarke

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About