this function inserts size bytes in front of the string efficiently and returns a pointer to the start of the new pv.static char * my_sv_unchop(pTHX_ SV *sv, STRLEN size) { STRLEN len; char *pv = SvPV(sv, len); IV off = SvOOK(sv) ? SvIVX(sv) : 0; if (!size) return pv; if (off >= size) { SvLEN_set(sv, SvLEN(sv) + size); SvCUR_set(sv, len + size); SvPV_set(sv, pv - size); if (off == size) SvFLAGS(sv) &= ~SVf_OOK; else SvIV_set(sv, off - size); } else if (len + size <= off + SvLEN(sv)) { if (off) { SvLEN_set(sv, SvLEN(sv) + off); SvFLAGS(sv) &= ~SVf_OOK; } SvCUR_set(sv, len + size); SvPV_set(sv, pv - off); Move(pv, pv + size - off, len, char); } else { SV *tmp = sv_2mortal(newSV(len + size)); STRLEN tmp_len; char *tmp_pv; SvPOK_on(tmp); tmp_pv = SvPV(tmp, tmp_len); Move(pv, tmp_pv + size, len, char); SvCUR_set(tmp, size + len); sv_setsv(sv, tmp); } return SvPVX(sv); }
You would probably want to modify it so that more bytes than requested are reserved on the string to optimize consecutive insertions.
Note that sv_setsv is used to only copy the string contents once as it steals the SV string memory from the source SV when it is a mortal.
In reply to Re: XS Prepending space to an SVs PV
by salva
in thread XS Prepending space to an SVs PV
by BrowserUk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |