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