#include "XSUB.h"
#define U8 U8
+#define OUR_DEFAULT_FB "Encode::PERLQQ"
+
#if defined(USE_PERLIO) && !defined(USE_SFIO)
/* Define an encoding "layer" in the perliol.h sense.
"SUPER::flush.
Note that "flush" is _also_ called for read mode - we still do the
- (back)-translate so that the the base class's "flush" sees the
+ (back)-translate so that the base class's "flush" sees the
correct number of encoded chars for positioning the seek
pointer. (This double translation is the worst performance issue -
particularly with all-perl encode engine.)
SV *enc; /* the encoding object */
SV *chk; /* CHECK in Encode methods */
int flags; /* Flags currently just needs lines */
+ int inEncodeCall; /* trap recursive encode calls */
} PerlIOEncode;
#define NEEDS_LINES 1
-#define OUR_DEFAULT_FB "Encode::FB_QUIET"
SV *
PerlIOEncode_getarg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
SV *sv = &PL_sv_undef;
if (e->enc) {
dSP;
+ /* Not 100% sure stack swap is right thing to do during dup ... */
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
ENTER;
SAVETMPS;
PUSHMARK(sp);
sv = newSVsv(POPs);
PUTBACK;
}
+ FREETMPS;
+ LEAVE;
+ POPSTACK;
}
return sv;
}
IV
-PerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg)
+PerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, PerlIO_funcs *tab)
{
PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
dSP;
- IV code = PerlIOBuf_pushed(aTHX_ f, mode, Nullsv);
+ IV code = PerlIOBuf_pushed(aTHX_ f, mode, Nullsv,tab);
SV *result = Nullsv;
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
+
ENTER;
SAVETMPS;
code = -1;
}
else {
-#ifdef USE_NEW_SEQUENCE
+
+ /* $enc->renew */
PUSHMARK(sp);
XPUSHs(result);
PUTBACK;
- if (call_method("new_sequence",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
- Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support new_sequence",
+ if (call_method("renew",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
+ Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support renew method",
arg);
}
else {
result = POPs;
PUTBACK;
}
-#endif
e->enc = newSVsv(result);
PUSHMARK(sp);
XPUSHs(e->enc);
PerlIOBase(f)->flags |= PERLIO_F_UTF8;
}
- e->chk = newSVsv(get_sv("PerlIO::encoding::check", 0));
+ e->chk = newSVsv(get_sv("PerlIO::encoding::fallback", 0));
+ e->inEncodeCall = 0;
FREETMPS;
LEAVE;
+ POPSTACK;
return code;
}
Perl_die(aTHX_ "panic: cannot push :perlio for %p",f);
}
}
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
ENTER;
SAVETMPS;
retry:
STDCHAR *ptr = PerlIO_get_ptr(n);
SSize_t use = (avail >= 0) ? avail : 0;
SV *uni;
- char *s;
+ char *s = Nullch;
STRLEN len = 0;
e->base.ptr = e->base.end = (STDCHAR *) Nullch;
(void) PerlIOEncode_get_base(aTHX_ f);
}
else {
/* Create a "dummy" SV to represent the available data from layer below */
- if (SvLEN(e->dataSV) && SvPVX(e->dataSV)) {
- Safefree(SvPVX(e->dataSV));
+ if (SvLEN(e->dataSV) && SvPVX_const(e->dataSV)) {
+ Safefree(SvPVX_mutable(e->dataSV));
}
if (use > (SSize_t)e->base.bufsiz) {
if (e->flags & NEEDS_LINES) {
use = e->base.bufsiz;
}
}
- SvPVX(e->dataSV) = (char *) ptr;
- SvLEN(e->dataSV) = 0; /* Hands off sv.c - it isn't yours */
+ SvPV_set(e->dataSV, (char *) ptr);
+ SvLEN_set(e->dataSV, 0); /* Hands off sv.c - it isn't yours */
SvCUR_set(e->dataSV,use);
SvPOK_only(e->dataSV);
}
PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
goto retry;
}
- FREETMPS;
- LEAVE;
- return code;
}
else {
end_of_file:
+ code = -1;
if (avail == 0)
PerlIOBase(f)->flags |= PERLIO_F_EOF;
else
PerlIOBase(f)->flags |= PERLIO_F_ERROR;
- return -1;
}
+ FREETMPS;
+ LEAVE;
+ POPSTACK;
+ return code;
}
IV
PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
IV code = 0;
- if (e->bufsv && (e->base.ptr > e->base.buf)) {
+ if (e->bufsv) {
dSP;
SV *str;
char *s;
STRLEN len;
SSize_t count = 0;
- if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
- /* Write case encode the buffer and write() to layer below */
+ if ((PerlIOBase(f)->flags & PERLIO_F_WRBUF) && (e->base.ptr > e->base.buf)) {
+ if (e->inEncodeCall) return 0;
+ /* Write case - encode the buffer and write() to layer below */
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(e->bufsv);
XPUSHs(e->chk);
PUTBACK;
+ e->inEncodeCall = 1;
if (call_method("encode", G_SCALAR) != 1) {
+ e->inEncodeCall = 0;
Perl_die(aTHX_ "panic: encode did not return a value");
}
+ e->inEncodeCall = 0;
SPAGAIN;
str = POPs;
PUTBACK;
}
FREETMPS;
LEAVE;
+ POPSTACK;
if (PerlIO_flush(PerlIONext(f)) != 0) {
code = -1;
}
return code;
}
}
- else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
+ else if ((PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
/* read case */
/* if we have any untranslated stuff then unread that first */
+ /* FIXME - unread is fragile is there a better way ? */
if (e->dataSV && SvCUR(e->dataSV)) {
s = SvPV(e->dataSV, len);
count = PerlIO_unread(PerlIONext(f),s,len);
if ((STRLEN)count != len) {
code = -1;
}
+ SvCUR_set(e->dataSV,0);
}
/* See if there is anything left in the buffer */
if (e->base.ptr < e->base.end) {
+ if (e->inEncodeCall) return 0;
/* Bother - have unread data.
re-encode and unread() to layer below
*/
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
ENTER;
SAVETMPS;
str = sv_newmortal();
sv_upgrade(str, SVt_PV);
- SvPVX(str) = (char*)e->base.ptr;
- SvLEN(str) = 0;
+ SvPV_set(str, (char*)e->base.ptr);
+ SvLEN_set(str, 0);
SvCUR_set(str, e->base.end - e->base.ptr);
SvPOK_only(str);
SvUTF8_on(str);
XPUSHs(str);
XPUSHs(e->chk);
PUTBACK;
+ e->inEncodeCall = 1;
if (call_method("encode", G_SCALAR) != 1) {
- Perl_die(aTHX_ "panic: encode did not return a value");
+ e->inEncodeCall = 0;
+ Perl_die(aTHX_ "panic: encode did not return a value");
}
+ e->inEncodeCall = 0;
SPAGAIN;
str = POPs;
PUTBACK;
}
FREETMPS;
LEAVE;
+ POPSTACK;
}
}
e->base.ptr = e->base.end = e->base.buf;
PerlIOEncode_close(pTHX_ PerlIO * f)
{
PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
- IV code = PerlIOBase_close(aTHX_ f);
-
+ IV code;
+ if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
+ /* Discard partial character */
+ if (e->dataSV) {
+ SvCUR_set(e->dataSV,0);
+ }
+ /* Don't back decode and unread any pending data */
+ e->base.ptr = e->base.end = e->base.buf;
+ }
+ code = PerlIOBase_close(aTHX_ f);
if (e->bufsv) {
+ /* This should only fire for write case */
if (e->base.buf && e->base.ptr > e->base.buf) {
Perl_croak(aTHX_ "Close with partial character");
}
}
PerlIO_funcs PerlIO_encode = {
+ sizeof(PerlIO_funcs),
"encoding",
sizeof(PerlIOEncode),
PERLIO_K_BUFFERED|PERLIO_K_DESTRUCT,
PerlIOEncode_pushed,
PerlIOEncode_popped,
PerlIOBuf_open,
+ NULL, /* binmode - always pop */
PerlIOEncode_getarg,
PerlIOBase_fileno,
PerlIOEncode_dup,
BOOT:
{
- SV *chk = get_sv("PerlIO::encoding::check", GV_ADD|GV_ADDMULTI);
+ SV *chk = get_sv("PerlIO::encoding::fallback", GV_ADD|GV_ADDMULTI);
/*
* we now "use Encode ()" here instead of
* PerlIO/encoding.pm. This avoids SEGV when ":encoding()"
* is invoked without prior "use Encode". -- dankogai
*/
- if (!gv_stashpvn("Encode", 6, FALSE)) {
+ PUSHSTACKi(PERLSI_MAGIC);
+ SPAGAIN;
+ if (!get_cv(OUR_DEFAULT_FB, 0)) {
#if 0
/* This would just be an irritant now loading works */
Perl_warner(aTHX_ packWARN(WARN_IO), ":encoding without 'use Encode'");
#ifdef PERLIO_LAYERS
PerlIO_define_layer(aTHX_ &PerlIO_encode);
#endif
+ POPSTACK;
}