X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FEncode%2FEncode.xs;h=22812ab28adba90f992fa2b16baeac291e681931;hb=3aececdab11e76bf99d892f63f8a9048dedbc74d;hp=c48a5a017351a3996d6a4c109736cdc651e01447;hpb=4cf4f8f871391c98cb64b9c8574ca8e07b0f4a78;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/Encode/Encode.xs b/ext/Encode/Encode.xs index c48a5a0..22812ab 100644 --- a/ext/Encode/Encode.xs +++ b/ext/Encode/Encode.xs @@ -477,18 +477,20 @@ encode_method(pTHX_ encode_t * enc, encpage_t * dir, SV * src, { STRLEN slen; U8 *s = (U8 *) SvPV(src, slen); - STRLEN tlen = slen; + STRLEN tlen = slen; + STRLEN ddone = 0; + STRLEN sdone = 0; SV *dst = sv_2mortal(newSV(slen+1)); if (slen) { U8 *d = (U8 *) SvPVX(dst); STRLEN dlen = SvLEN(dst)-1; int code; while ((code = do_encode(dir, s, &slen, d, dlen, &dlen, !check))) { - SvCUR_set(dst, dlen); + SvCUR_set(dst, dlen+ddone); SvPOK_on(dst); #if 0 - Perl_warn(aTHX_ "code=%d @ s=%d/%d d=%d",code,slen,tlen,dlen); + Perl_warn(aTHX_ "code=%d @ s=%d/%d/%d d=%d/%d/%d",code,slen,sdone,tlen,dlen,ddone,SvLEN(dst)-1); #endif if (code == ENCODE_FALLBACK || code == ENCODE_PARTIAL) @@ -497,23 +499,25 @@ encode_method(pTHX_ encode_t * enc, encpage_t * dir, SV * src, switch (code) { case ENCODE_NOSPACE: { - STRLEN done = tlen-slen; STRLEN need ; - if (done) { - need = (tlen*dlen)/done+1; + sdone += slen; + ddone += dlen; + if (sdone) { + need = (tlen*SvLEN(dst)+sdone-1)/sdone+UTF8_MAXLEN; } else { - need = dlen + UTF8_MAXLEN; + need = SvLEN(dst) + UTF8_MAXLEN; } d = (U8 *) SvGROW(dst, need); - if (dlen >= SvLEN(dst)) { - Perl_croak(aTHX_ - "Destination couldn't be grown (the need may be miscalculated)."); + if (ddone >= SvLEN(dst)) { + Perl_croak(aTHX_ "Destination couldn't be grown."); } - dlen = SvLEN(dst); - slen = tlen; - break; + dlen = SvLEN(dst)-ddone-1; + d += ddone; + s += slen; + slen = tlen-sdone; + continue; } case ENCODE_NOREP: @@ -551,13 +555,14 @@ encode_method(pTHX_ encode_t * enc, encpage_t * dir, SV * src, return &PL_sv_undef; } } - SvCUR_set(dst, dlen); + SvCUR_set(dst, dlen+ddone); SvPOK_on(dst); if (check) { - if (slen < SvCUR(src)) { - Move(s + slen, s, SvCUR(src) - slen, U8); + sdone = SvCUR(src) - (slen+sdone); + if (sdone) { + Move(s + slen, SvPVX(src), sdone , U8); } - SvCUR_set(src, SvCUR(src) - slen); + SvCUR_set(src, sdone); *SvEND(src) = '\0'; } }