According to perlapi, sv_catpv()
works as follows:
Concatenates the
NUL
-terminated string onto the end of the string which is in the SV. If the SV has the UTF-8 status set, then the bytes appended should be valid UTF-8. Handles 'get' magic, but not 'set' magic.
void sv_catpv(SV *const sv, const char* ptr)
Most of the XS tutorials I've found use sv_catpvs()
, though, which does this:
Like
sv_catpvn
, but takes a literal string instead of a string/length pair.
void sv_catpvs(SV* sv, const char* s)
Well, that's not very helpful, so let's look at sv_catpvn()
:
Concatenates the string onto the end of the string which is in the SV. The
len
indicates number of bytes to copy. If the SV has the UTF-8 status set, then the bytes appended should be valid UTF-8. Handles 'get' magic, but not 'set' magic.
void sv_catpvn(SV *dsv, const char *sstr, STRLEN len)
So, sv_catpvn
does the same thing as sv_catpv
except that it takes the string length as a separate parameter, and sv_catpvs
is the same as sv_catpvn
except it takes the literal string.
Is there some subtle difference between sv_catpv
and sv_catpvs
that I'm missing, or are they just two ways to do the same thing?
As per the passages you quoted, sv_catpvs
only takes a string literal.
const char *str = "foo";
sv_catpvs(sv, "foo"); // ok
sv_catpvs(sv, str); // ERROR
sv_catpv
, on the other hand, accepts any expression that returns a string.
sv_catpv(sv, "foo"); // ok
sv_catpv(sv, str); // ok
So why does sv_catpvs
exist at all? Because it's faster. The reason sv_catpvs
takes only takes a string literal is that it's a macro that expands
sv_catpvs(sv, "foo")
into something similar to
sv_catpvn_flags(sv, "foo", sizeof("foo")-1, SV_GMAGIC)
which resolves to
sv_catpvn_flags(sv, "foo", 3, SV_GMAGIC)
at compile-time. sv_catpv
, on the other hand, is forced to use slower strlen
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With