Encode
view release on metacpan or search on metacpan
#if ENCODE_XS_PROFILE >= 2
Perl_warn(aTHX_
"more=%d, sdone=%d, sleft=%d, SvLEN(dst)=%d\n",
more, sdone, sleft, SvLEN(dst));
#endif
if (sdone != 0) { /* has src ever been processed ? */
#if ENCODE_XS_USEFP == 2
more = (1.0*tlen*SvLEN(dst)+sdone-1)/sdone
- SvLEN(dst);
#elif ENCODE_XS_USEFP
more = (STRLEN)((1.0*SvLEN(dst)+1)/sdone * sleft);
#else
/* safe until SvLEN(dst) == MAX_INT/16 */
more = (16*SvLEN(dst)+1)/sdone/16 * sleft;
#endif
}
more += UTF8_MAXLEN; /* insurance policy */
d = (U8 *) SvGROW(dst, SvLEN(dst) + more);
/* dst need to grow need MORE bytes! */
if (ddone >= SvLEN(dst)) {
Perl_croak(aTHX_ "Destination couldn't be grown.");
}
dlen = SvLEN(dst)-ddone-1;
d += ddone;
s += slen;
slen = tlen-sdone;
continue;
}
case ENCODE_NOREP:
/* encoding */
if (dir == enc->f_utf8) {
STRLEN clen;
UV ch =
utf8n_to_uvchr(s+slen, (tlen-sdone-slen),
&clen, UTF8_ALLOW_ANY|UTF8_CHECK_ONLY);
/* if non-representable multibyte prefix at end of current buffer - break*/
if (clen > tlen - sdone - slen) break;
if (check & ENCODE_DIE_ON_ERR) {
Perl_croak(aTHX_ ERR_ENCODE_NOMAP,
(UV)ch, enc->name[0]);
return &PL_sv_undef; /* never reaches but be safe */
}
if (encode_ckWARN(check, WARN_UTF8)) {
Perl_warner(aTHX_ packWARN(WARN_UTF8),
ERR_ENCODE_NOMAP, (UV)ch, enc->name[0]);
}
if (check & ENCODE_RETURN_ON_ERR){
goto ENCODE_SET_SRC;
}
if (check & (ENCODE_PERLQQ|ENCODE_HTMLCREF|ENCODE_XMLCREF)){
STRLEN sublen;
char *substr;
SV* subchar =
(fallback_cb != &PL_sv_undef)
? do_fallback_cb(aTHX_ ch, fallback_cb)
: newSVpvf(check & ENCODE_PERLQQ ? "\\x{%04" UVxf "}" :
check & ENCODE_HTMLCREF ? "&#%" UVuf ";" :
"&#x%" UVxf ";", (UV)ch);
substr = SvPV(subchar, sublen);
if (SvUTF8(subchar) && sublen && !utf8_to_bytes((U8 *)substr, &sublen)) { /* make sure no decoded string gets in */
SvREFCNT_dec(subchar);
croak("Wide character");
}
sdone += slen + clen;
ddone += dlen + sublen;
sv_catpvn(dst, substr, sublen);
SvREFCNT_dec(subchar);
} else {
/* fallback char */
sdone += slen + clen;
ddone += dlen + enc->replen;
sv_catpvn(dst, (char*)enc->rep, enc->replen);
}
}
/* decoding */
else {
if (check & ENCODE_DIE_ON_ERR){
Perl_croak(aTHX_ ERR_DECODE_NOMAP,
enc->name[0], (UV)s[slen]);
return &PL_sv_undef; /* never reaches but be safe */
}
if (encode_ckWARN(check, WARN_UTF8)) {
Perl_warner(
aTHX_ packWARN(WARN_UTF8),
ERR_DECODE_NOMAP,
enc->name[0], (UV)s[slen]);
}
if (check & ENCODE_RETURN_ON_ERR){
goto ENCODE_SET_SRC;
}
if (check &
(ENCODE_PERLQQ|ENCODE_HTMLCREF|ENCODE_XMLCREF)){
STRLEN sublen;
char *substr;
SV* subchar =
(fallback_cb != &PL_sv_undef)
? do_fallback_cb(aTHX_ (UV)s[slen], fallback_cb)
: newSVpvf("\\x%02" UVXf, (UV)s[slen]);
substr = SvPVutf8(subchar, sublen);
sdone += slen + 1;
ddone += dlen + sublen;
sv_catpvn(dst, substr, sublen);
SvREFCNT_dec(subchar);
} else {
sdone += slen + 1;
ddone += dlen + strlen(FBCHAR_UTF8);
sv_catpvn(dst, FBCHAR_UTF8, strlen(FBCHAR_UTF8));
}
}
/* settle variables when fallback */
d = (U8 *)SvEND(dst);
dlen = SvLEN(dst) - ddone - 1;
s = sorig + sdone;
slen = tlen - sdone;
break;
default:
Perl_croak(aTHX_ "Unexpected code %d converting %s %s",
code, (dir == enc->f_utf8) ? "to" : "from",
enc->name[0]);
/* Copy as far as was successful */
Move(s, d, len, U8);
d += len;
s = (U8 *) e_or_where_failed;
/* Are done if it was valid, or we are accepting partial characters and
* the only error is that the final bytes form a partial character */
if ( LIKELY(valid)
|| ( stop_at_partial
&& is_utf8_valid_partial_char_flags(s, e, flags)))
{
break;
}
/* Here, was not valid. If is 'strict', and is legal extended UTF-8,
* we know it is a code point whose value we can calculate, just not
* one accepted under strict. Otherwise, it is malformed in some way.
* In either case, the system function can calculate either the code
* point, or the best substitution for it */
uv = utf8n_to_uvchr(s, e - s, &ulen, UTF8_ALLOW_ANY);
/*
* Here, we are looping through the input and found an error.
* 'uv' is the code point in error if calculable, or the REPLACEMENT
* CHARACTER if not.
* 'ulen' is how many bytes of input this iteration of the loop
* consumes */
if (!encode && (check & (ENCODE_DIE_ON_ERR|ENCODE_WARN_ON_ERR|ENCODE_PERLQQ)))
for (i=0; i<ulen; ++i) sprintf(esc+4*i, "\\x%02X", s[i]);
if (check & ENCODE_DIE_ON_ERR){
if (encode)
Perl_croak(aTHX_ ERR_ENCODE_NOMAP, uv, (strict ? "UTF-8" : "utf8"));
else
Perl_croak(aTHX_ ERR_DECODE_STR_NOMAP, (strict ? "UTF-8" : "utf8"), esc);
}
if (encode_ckWARN(check, WARN_UTF8)) {
if (encode)
Perl_warner(aTHX_ packWARN(WARN_UTF8),
ERR_ENCODE_NOMAP, uv, (strict ? "UTF-8" : "utf8"));
else
Perl_warner(aTHX_ packWARN(WARN_UTF8),
ERR_DECODE_STR_NOMAP, (strict ? "UTF-8" : "utf8"), esc);
}
if (check & ENCODE_RETURN_ON_ERR) {
break;
}
if (check & (ENCODE_PERLQQ|ENCODE_HTMLCREF|ENCODE_XMLCREF)){
STRLEN sublen;
char *substr;
SV* subchar;
if (encode) {
subchar =
(fallback_cb != &PL_sv_undef)
? do_fallback_cb(aTHX_ uv, fallback_cb)
: newSVpvf(check & ENCODE_PERLQQ
? (ulen == 1 ? "\\x%02" UVXf : "\\x{%04" UVXf "}")
: check & ENCODE_HTMLCREF ? "&#%" UVuf ";"
: "&#x%" UVxf ";", uv);
substr = SvPV(subchar, sublen);
if (SvUTF8(subchar) && sublen && !utf8_to_bytes((U8 *)substr, &sublen)) { /* make sure no decoded string gets in */
SvREFCNT_dec(subchar);
croak("Wide character");
}
} else {
if (fallback_cb != &PL_sv_undef) {
/* in decode mode we have sequence of wrong bytes */
subchar = do_bytes_fallback_cb(aTHX_ s, ulen, fallback_cb);
} else {
char *ptr = esc;
/* ENCODE_PERLQQ is already stored in esc */
if (check & (ENCODE_HTMLCREF|ENCODE_XMLCREF))
for (i=0; i<ulen; ++i) ptr += sprintf(ptr, ((check & ENCODE_HTMLCREF) ? "&#%u;" : "&#x%02X;"), s[i]);
subchar = newSVpvn(esc, strlen(esc));
}
substr = SvPVutf8(subchar, sublen);
}
dlen += sublen - ulen;
SvCUR_set(dst, d-(U8 *)SvPVX(dst));
*SvEND(dst) = '\0';
sv_catpvn(dst, substr, sublen);
SvREFCNT_dec(subchar);
d = (U8 *) SvGROW(dst, dlen) + SvCUR(dst);
} else {
STRLEN fbcharlen = strlen(FBCHAR_UTF8);
dlen += fbcharlen - ulen;
if (SvLEN(dst) < dlen) {
SvCUR_set(dst, d-(U8 *)SvPVX(dst));
d = (U8 *) sv_grow(dst, dlen) + SvCUR(dst);
}
memcpy(d, FBCHAR_UTF8, fbcharlen);
d += fbcharlen;
}
s += ulen;
}
SvCUR_set(dst, d-(U8 *)SvPVX(dst));
*SvEND(dst) = '\0';
return s;
}
static SV *
find_encoding(pTHX_ SV *enc)
{
dSP;
I32 count;
SV *m_enc;
SV *obj = &PL_sv_undef;
#ifndef SV_NOSTEAL
U32 tmp;
#endif
ENTER;
SAVETMPS;
PUSHMARK(sp);
m_enc = sv_newmortal();
#ifndef SV_NOSTEAL
tmp = SvFLAGS(enc) & SVs_TEMP;
SvTEMP_off(enc);
sv_setsv_flags(m_enc, enc, 0);
( run in 0.557 second using v1.01-cache-2.11-cpan-3c2a17b8caa )