1N/A/*
1N/A * $Id: encoding.xs,v 0.3 2002/04/21 22:14:41 dankogai Exp $
1N/A */
1N/A
1N/A#define PERL_NO_GET_CONTEXT
1N/A#include "EXTERN.h"
1N/A#include "perl.h"
1N/A#include "XSUB.h"
1N/A#define U8 U8
1N/A
1N/A#define OUR_DEFAULT_FB "Encode::PERLQQ"
1N/A
1N/A#if defined(USE_PERLIO) && !defined(USE_SFIO)
1N/A
1N/A/* Define an encoding "layer" in the perliol.h sense.
1N/A
1N/A The layer defined here "inherits" in an object-oriented sense from
1N/A the "perlio" layer with its PerlIOBuf_* "methods". The
1N/A implementation is particularly efficient as until Encode settles
1N/A down there is no point in tryint to tune it.
1N/A
1N/A The layer works by overloading the "fill" and "flush" methods.
1N/A
1N/A "fill" calls "SUPER::fill" in perl terms, then calls the encode OO
1N/A perl API to convert the encoded data to UTF-8 form, then copies it
1N/A back to the buffer. The "base class's" read methods then see the
1N/A UTF-8 data.
1N/A
1N/A "flush" transforms the UTF-8 data deposited by the "base class's
1N/A write method in the buffer back into the encoded form using the
1N/A encode OO perl API, then copies data back into the buffer and calls
1N/A "SUPER::flush.
1N/A
1N/A Note that "flush" is _also_ called for read mode - we still do the
1N/A (back)-translate so that the base class's "flush" sees the
1N/A correct number of encoded chars for positioning the seek
1N/A pointer. (This double translation is the worst performance issue -
1N/A particularly with all-perl encode engine.)
1N/A
1N/A*/
1N/A
1N/A#include "perliol.h"
1N/A
1N/Atypedef struct {
1N/A PerlIOBuf base; /* PerlIOBuf stuff */
1N/A SV *bufsv; /* buffer seen by layers above */
1N/A SV *dataSV; /* data we have read from layer below */
1N/A SV *enc; /* the encoding object */
1N/A SV *chk; /* CHECK in Encode methods */
1N/A int flags; /* Flags currently just needs lines */
1N/A} PerlIOEncode;
1N/A
1N/A#define NEEDS_LINES 1
1N/A
1N/ASV *
1N/APerlIOEncode_getarg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A SV *sv = &PL_sv_undef;
1N/A if (e->enc) {
1N/A dSP;
1N/A /* Not 100% sure stack swap is right thing to do during dup ... */
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A ENTER;
1N/A SAVETMPS;
1N/A PUSHMARK(sp);
1N/A XPUSHs(e->enc);
1N/A PUTBACK;
1N/A if (call_method("name", G_SCALAR) == 1) {
1N/A SPAGAIN;
1N/A sv = newSVsv(POPs);
1N/A PUTBACK;
1N/A }
1N/A FREETMPS;
1N/A LEAVE;
1N/A POPSTACK;
1N/A }
1N/A return sv;
1N/A}
1N/A
1N/AIV
1N/APerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, PerlIO_funcs *tab)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A dSP;
1N/A IV code = PerlIOBuf_pushed(aTHX_ f, mode, Nullsv,tab);
1N/A SV *result = Nullsv;
1N/A
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A
1N/A ENTER;
1N/A SAVETMPS;
1N/A
1N/A PUSHMARK(sp);
1N/A XPUSHs(arg);
1N/A PUTBACK;
1N/A if (call_pv("Encode::find_encoding", G_SCALAR) != 1) {
1N/A /* should never happen */
1N/A Perl_die(aTHX_ "Encode::find_encoding did not return a value");
1N/A return -1;
1N/A }
1N/A SPAGAIN;
1N/A result = POPs;
1N/A PUTBACK;
1N/A
1N/A if (!SvROK(result) || !SvOBJECT(SvRV(result))) {
1N/A e->enc = Nullsv;
1N/A Perl_warner(aTHX_ packWARN(WARN_IO), "Cannot find encoding \"%" SVf "\"",
1N/A arg);
1N/A errno = EINVAL;
1N/A code = -1;
1N/A }
1N/A else {
1N/A
1N/A /* $enc->renew */
1N/A PUSHMARK(sp);
1N/A XPUSHs(result);
1N/A PUTBACK;
1N/A if (call_method("renew",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
1N/A Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support renew method",
1N/A arg);
1N/A }
1N/A else {
1N/A SPAGAIN;
1N/A result = POPs;
1N/A PUTBACK;
1N/A }
1N/A e->enc = newSVsv(result);
1N/A PUSHMARK(sp);
1N/A XPUSHs(e->enc);
1N/A PUTBACK;
1N/A if (call_method("needs_lines",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
1N/A Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support needs_lines",
1N/A arg);
1N/A }
1N/A else {
1N/A SPAGAIN;
1N/A result = POPs;
1N/A PUTBACK;
1N/A if (SvTRUE(result)) {
1N/A e->flags |= NEEDS_LINES;
1N/A }
1N/A }
1N/A PerlIOBase(f)->flags |= PERLIO_F_UTF8;
1N/A }
1N/A
1N/A e->chk = newSVsv(get_sv("PerlIO::encoding::fallback", 0));
1N/A
1N/A FREETMPS;
1N/A LEAVE;
1N/A POPSTACK;
1N/A return code;
1N/A}
1N/A
1N/AIV
1N/APerlIOEncode_popped(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A if (e->enc) {
1N/A SvREFCNT_dec(e->enc);
1N/A e->enc = Nullsv;
1N/A }
1N/A if (e->bufsv) {
1N/A SvREFCNT_dec(e->bufsv);
1N/A e->bufsv = Nullsv;
1N/A }
1N/A if (e->dataSV) {
1N/A SvREFCNT_dec(e->dataSV);
1N/A e->dataSV = Nullsv;
1N/A }
1N/A if (e->chk) {
1N/A SvREFCNT_dec(e->chk);
1N/A e->chk = Nullsv;
1N/A }
1N/A return 0;
1N/A}
1N/A
1N/ASTDCHAR *
1N/APerlIOEncode_get_base(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A if (!e->base.bufsiz)
1N/A e->base.bufsiz = 1024;
1N/A if (!e->bufsv) {
1N/A e->bufsv = newSV(e->base.bufsiz);
1N/A sv_setpvn(e->bufsv, "", 0);
1N/A }
1N/A e->base.buf = (STDCHAR *) SvPVX(e->bufsv);
1N/A if (!e->base.ptr)
1N/A e->base.ptr = e->base.buf;
1N/A if (!e->base.end)
1N/A e->base.end = e->base.buf;
1N/A if (e->base.ptr < e->base.buf
1N/A || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
1N/A Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
1N/A e->base.buf + SvLEN(e->bufsv));
1N/A abort();
1N/A }
1N/A if (SvLEN(e->bufsv) < e->base.bufsiz) {
1N/A SSize_t poff = e->base.ptr - e->base.buf;
1N/A SSize_t eoff = e->base.end - e->base.buf;
1N/A e->base.buf = (STDCHAR *) SvGROW(e->bufsv, e->base.bufsiz);
1N/A e->base.ptr = e->base.buf + poff;
1N/A e->base.end = e->base.buf + eoff;
1N/A }
1N/A if (e->base.ptr < e->base.buf
1N/A || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
1N/A Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
1N/A e->base.buf + SvLEN(e->bufsv));
1N/A abort();
1N/A }
1N/A return e->base.buf;
1N/A}
1N/A
1N/AIV
1N/APerlIOEncode_fill(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A dSP;
1N/A IV code = 0;
1N/A PerlIO *n;
1N/A SSize_t avail;
1N/A
1N/A if (PerlIO_flush(f) != 0)
1N/A return -1;
1N/A n = PerlIONext(f);
1N/A if (!PerlIO_fast_gets(n)) {
1N/A /* Things get too messy if we don't have a buffer layer
1N/A push a :perlio to do the job */
1N/A char mode[8];
1N/A n = PerlIO_push(aTHX_ n, &PerlIO_perlio, PerlIO_modestr(f,mode), Nullsv);
1N/A if (!n) {
1N/A Perl_die(aTHX_ "panic: cannot push :perlio for %p",f);
1N/A }
1N/A }
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A ENTER;
1N/A SAVETMPS;
1N/A retry:
1N/A avail = PerlIO_get_cnt(n);
1N/A if (avail <= 0) {
1N/A avail = PerlIO_fill(n);
1N/A if (avail == 0) {
1N/A avail = PerlIO_get_cnt(n);
1N/A }
1N/A else {
1N/A if (!PerlIO_error(n) && PerlIO_eof(n))
1N/A avail = 0;
1N/A }
1N/A }
1N/A if (avail > 0 || (e->flags & NEEDS_LINES)) {
1N/A STDCHAR *ptr = PerlIO_get_ptr(n);
1N/A SSize_t use = (avail >= 0) ? avail : 0;
1N/A SV *uni;
1N/A char *s;
1N/A STRLEN len = 0;
1N/A e->base.ptr = e->base.end = (STDCHAR *) Nullch;
1N/A (void) PerlIOEncode_get_base(aTHX_ f);
1N/A if (!e->dataSV)
1N/A e->dataSV = newSV(0);
1N/A if (SvTYPE(e->dataSV) < SVt_PV) {
1N/A sv_upgrade(e->dataSV,SVt_PV);
1N/A }
1N/A if (e->flags & NEEDS_LINES) {
1N/A /* Encoding needs whole lines (e.g. iso-2022-*)
1N/A search back from end of available data for
1N/A and line marker
1N/A */
1N/A STDCHAR *nl = ptr+use-1;
1N/A while (nl >= ptr) {
1N/A if (*nl == '\n') {
1N/A break;
1N/A }
1N/A nl--;
1N/A }
1N/A if (nl >= ptr && *nl == '\n') {
1N/A /* found a line - take up to and including that */
1N/A use = (nl+1)-ptr;
1N/A }
1N/A else if (avail > 0) {
1N/A /* No line, but not EOF - append avail to the pending data */
1N/A sv_catpvn(e->dataSV, (char*)ptr, use);
1N/A PerlIO_set_ptrcnt(n, ptr+use, 0);
1N/A goto retry;
1N/A }
1N/A else if (!SvCUR(e->dataSV)) {
1N/A goto end_of_file;
1N/A }
1N/A }
1N/A if (SvCUR(e->dataSV)) {
1N/A /* something left over from last time - create a normal
1N/A SV with new data appended
1N/A */
1N/A if (use + SvCUR(e->dataSV) > e->base.bufsiz) {
1N/A if (e->flags & NEEDS_LINES) {
1N/A /* Have to grow buffer */
1N/A e->base.bufsiz = use + SvCUR(e->dataSV);
1N/A PerlIOEncode_get_base(aTHX_ f);
1N/A }
1N/A else {
1N/A use = e->base.bufsiz - SvCUR(e->dataSV);
1N/A }
1N/A }
1N/A sv_catpvn(e->dataSV,(char*)ptr,use);
1N/A }
1N/A else {
1N/A /* Create a "dummy" SV to represent the available data from layer below */
1N/A if (SvLEN(e->dataSV) && SvPVX(e->dataSV)) {
1N/A Safefree(SvPVX(e->dataSV));
1N/A }
1N/A if (use > (SSize_t)e->base.bufsiz) {
1N/A if (e->flags & NEEDS_LINES) {
1N/A /* Have to grow buffer */
1N/A e->base.bufsiz = use;
1N/A PerlIOEncode_get_base(aTHX_ f);
1N/A }
1N/A else {
1N/A use = e->base.bufsiz;
1N/A }
1N/A }
1N/A SvPVX(e->dataSV) = (char *) ptr;
1N/A SvLEN(e->dataSV) = 0; /* Hands off sv.c - it isn't yours */
1N/A SvCUR_set(e->dataSV,use);
1N/A SvPOK_only(e->dataSV);
1N/A }
1N/A SvUTF8_off(e->dataSV);
1N/A PUSHMARK(sp);
1N/A XPUSHs(e->enc);
1N/A XPUSHs(e->dataSV);
1N/A XPUSHs(e->chk);
1N/A PUTBACK;
1N/A if (call_method("decode", G_SCALAR) != 1) {
1N/A Perl_die(aTHX_ "panic: decode did not return a value");
1N/A }
1N/A SPAGAIN;
1N/A uni = POPs;
1N/A PUTBACK;
1N/A /* Now get translated string (forced to UTF-8) and use as buffer */
1N/A if (SvPOK(uni)) {
1N/A s = SvPVutf8(uni, len);
1N/A#ifdef PARANOID_ENCODE_CHECKS
1N/A if (len && !is_utf8_string((U8*)s,len)) {
1N/A Perl_warn(aTHX_ "panic: decode did not return UTF-8 '%.*s'",(int) len,s);
1N/A }
1N/A#endif
1N/A }
1N/A if (len > 0) {
1N/A /* Got _something */
1N/A /* if decode gave us back dataSV then data may vanish when
1N/A we do ptrcnt adjust - so take our copy now.
1N/A (The copy is a pain - need a put-it-here option for decode.)
1N/A */
1N/A sv_setpvn(e->bufsv,s,len);
1N/A e->base.ptr = e->base.buf = (STDCHAR*)SvPVX(e->bufsv);
1N/A e->base.end = e->base.ptr + SvCUR(e->bufsv);
1N/A PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
1N/A SvUTF8_on(e->bufsv);
1N/A
1N/A /* Adjust ptr/cnt not taking anything which
1N/A did not translate - not clear this is a win */
1N/A /* compute amount we took */
1N/A use -= SvCUR(e->dataSV);
1N/A PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
1N/A /* and as we did not take it it isn't pending */
1N/A SvCUR_set(e->dataSV,0);
1N/A } else {
1N/A /* Got nothing - assume partial character so we need some more */
1N/A /* Make sure e->dataSV is a normal SV before re-filling as
1N/A buffer alias will change under us
1N/A */
1N/A s = SvPV(e->dataSV,len);
1N/A sv_setpvn(e->dataSV,s,len);
1N/A PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
1N/A goto retry;
1N/A }
1N/A }
1N/A else {
1N/A end_of_file:
1N/A code = -1;
1N/A if (avail == 0)
1N/A PerlIOBase(f)->flags |= PERLIO_F_EOF;
1N/A else
1N/A PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1N/A }
1N/A FREETMPS;
1N/A LEAVE;
1N/A POPSTACK;
1N/A return code;
1N/A}
1N/A
1N/AIV
1N/APerlIOEncode_flush(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A IV code = 0;
1N/A
1N/A if (e->bufsv) {
1N/A dSP;
1N/A SV *str;
1N/A char *s;
1N/A STRLEN len;
1N/A SSize_t count = 0;
1N/A if ((PerlIOBase(f)->flags & PERLIO_F_WRBUF) && (e->base.ptr > e->base.buf)) {
1N/A /* Write case - encode the buffer and write() to layer below */
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A ENTER;
1N/A SAVETMPS;
1N/A PUSHMARK(sp);
1N/A XPUSHs(e->enc);
1N/A SvCUR_set(e->bufsv, e->base.ptr - e->base.buf);
1N/A SvUTF8_on(e->bufsv);
1N/A XPUSHs(e->bufsv);
1N/A XPUSHs(e->chk);
1N/A PUTBACK;
1N/A if (call_method("encode", G_SCALAR) != 1) {
1N/A Perl_die(aTHX_ "panic: encode did not return a value");
1N/A }
1N/A SPAGAIN;
1N/A str = POPs;
1N/A PUTBACK;
1N/A s = SvPV(str, len);
1N/A count = PerlIO_write(PerlIONext(f),s,len);
1N/A if ((STRLEN)count != len) {
1N/A code = -1;
1N/A }
1N/A FREETMPS;
1N/A LEAVE;
1N/A POPSTACK;
1N/A if (PerlIO_flush(PerlIONext(f)) != 0) {
1N/A code = -1;
1N/A }
1N/A if (SvCUR(e->bufsv)) {
1N/A /* Did not all translate */
1N/A e->base.ptr = e->base.buf+SvCUR(e->bufsv);
1N/A return code;
1N/A }
1N/A }
1N/A else if ((PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
1N/A /* read case */
1N/A /* if we have any untranslated stuff then unread that first */
1N/A /* FIXME - unread is fragile is there a better way ? */
1N/A if (e->dataSV && SvCUR(e->dataSV)) {
1N/A s = SvPV(e->dataSV, len);
1N/A count = PerlIO_unread(PerlIONext(f),s,len);
1N/A if ((STRLEN)count != len) {
1N/A code = -1;
1N/A }
1N/A SvCUR_set(e->dataSV,0);
1N/A }
1N/A /* See if there is anything left in the buffer */
1N/A if (e->base.ptr < e->base.end) {
1N/A /* Bother - have unread data.
1N/A re-encode and unread() to layer below
1N/A */
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A ENTER;
1N/A SAVETMPS;
1N/A str = sv_newmortal();
1N/A sv_upgrade(str, SVt_PV);
1N/A SvPVX(str) = (char*)e->base.ptr;
1N/A SvLEN(str) = 0;
1N/A SvCUR_set(str, e->base.end - e->base.ptr);
1N/A SvPOK_only(str);
1N/A SvUTF8_on(str);
1N/A PUSHMARK(sp);
1N/A XPUSHs(e->enc);
1N/A XPUSHs(str);
1N/A XPUSHs(e->chk);
1N/A PUTBACK;
1N/A if (call_method("encode", G_SCALAR) != 1) {
1N/A Perl_die(aTHX_ "panic: encode did not return a value");
1N/A }
1N/A SPAGAIN;
1N/A str = POPs;
1N/A PUTBACK;
1N/A s = SvPV(str, len);
1N/A count = PerlIO_unread(PerlIONext(f),s,len);
1N/A if ((STRLEN)count != len) {
1N/A code = -1;
1N/A }
1N/A FREETMPS;
1N/A LEAVE;
1N/A POPSTACK;
1N/A }
1N/A }
1N/A e->base.ptr = e->base.end = e->base.buf;
1N/A PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
1N/A }
1N/A return code;
1N/A}
1N/A
1N/AIV
1N/APerlIOEncode_close(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A IV code;
1N/A if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
1N/A /* Discard partial character */
1N/A if (e->dataSV) {
1N/A SvCUR_set(e->dataSV,0);
1N/A }
1N/A /* Don't back decode and unread any pending data */
1N/A e->base.ptr = e->base.end = e->base.buf;
1N/A }
1N/A code = PerlIOBase_close(aTHX_ f);
1N/A if (e->bufsv) {
1N/A /* This should only fire for write case */
1N/A if (e->base.buf && e->base.ptr > e->base.buf) {
1N/A Perl_croak(aTHX_ "Close with partial character");
1N/A }
1N/A SvREFCNT_dec(e->bufsv);
1N/A e->bufsv = Nullsv;
1N/A }
1N/A e->base.buf = NULL;
1N/A e->base.ptr = NULL;
1N/A e->base.end = NULL;
1N/A PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
1N/A return code;
1N/A}
1N/A
1N/AOff_t
1N/APerlIOEncode_tell(pTHX_ PerlIO * f)
1N/A{
1N/A PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
1N/A /* Unfortunately the only way to get a postion is to (re-)translate,
1N/A the UTF8 we have in bufefr and then ask layer below
1N/A */
1N/A PerlIO_flush(f);
1N/A if (b->buf && b->ptr > b->buf) {
1N/A Perl_croak(aTHX_ "Cannot tell at partial character");
1N/A }
1N/A return PerlIO_tell(PerlIONext(f));
1N/A}
1N/A
1N/APerlIO *
1N/APerlIOEncode_dup(pTHX_ PerlIO * f, PerlIO * o,
1N/A CLONE_PARAMS * params, int flags)
1N/A{
1N/A if ((f = PerlIOBase_dup(aTHX_ f, o, params, flags))) {
1N/A PerlIOEncode *fe = PerlIOSelf(f, PerlIOEncode);
1N/A PerlIOEncode *oe = PerlIOSelf(o, PerlIOEncode);
1N/A if (oe->enc) {
1N/A fe->enc = PerlIO_sv_dup(aTHX_ oe->enc, params);
1N/A }
1N/A }
1N/A return f;
1N/A}
1N/A
1N/ASSize_t
1N/APerlIOEncode_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
1N/A{
1N/A PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
1N/A if (e->flags & NEEDS_LINES) {
1N/A SSize_t done = 0;
1N/A const char *ptr = (const char *) vbuf;
1N/A const char *end = ptr+count;
1N/A while (ptr < end) {
1N/A const char *nl = ptr;
1N/A while (nl < end && *nl++ != '\n') /* empty body */;
1N/A done = PerlIOBuf_write(aTHX_ f, ptr, nl-ptr);
1N/A if (done != nl-ptr) {
1N/A if (done > 0) {
1N/A ptr += done;
1N/A }
1N/A break;
1N/A }
1N/A ptr += done;
1N/A if (ptr[-1] == '\n') {
1N/A if (PerlIOEncode_flush(aTHX_ f) != 0) {
1N/A break;
1N/A }
1N/A }
1N/A }
1N/A return (SSize_t) (ptr - (const char *) vbuf);
1N/A }
1N/A else {
1N/A return PerlIOBuf_write(aTHX_ f, vbuf, count);
1N/A }
1N/A}
1N/A
1N/APerlIO_funcs PerlIO_encode = {
1N/A sizeof(PerlIO_funcs),
1N/A "encoding",
1N/A sizeof(PerlIOEncode),
1N/A PERLIO_K_BUFFERED|PERLIO_K_DESTRUCT,
1N/A PerlIOEncode_pushed,
1N/A PerlIOEncode_popped,
1N/A PerlIOBuf_open,
1N/A NULL, /* binmode - always pop */
1N/A PerlIOEncode_getarg,
1N/A PerlIOBase_fileno,
1N/A PerlIOEncode_dup,
1N/A PerlIOBuf_read,
1N/A PerlIOBuf_unread,
1N/A PerlIOEncode_write,
1N/A PerlIOBuf_seek,
1N/A PerlIOEncode_tell,
1N/A PerlIOEncode_close,
1N/A PerlIOEncode_flush,
1N/A PerlIOEncode_fill,
1N/A PerlIOBase_eof,
1N/A PerlIOBase_error,
1N/A PerlIOBase_clearerr,
1N/A PerlIOBase_setlinebuf,
1N/A PerlIOEncode_get_base,
1N/A PerlIOBuf_bufsiz,
1N/A PerlIOBuf_get_ptr,
1N/A PerlIOBuf_get_cnt,
1N/A PerlIOBuf_set_ptrcnt,
1N/A};
1N/A#endif /* encode layer */
1N/A
1N/AMODULE = PerlIO::encoding PACKAGE = PerlIO::encoding
1N/A
1N/APROTOTYPES: ENABLE
1N/A
1N/ABOOT:
1N/A{
1N/A SV *chk = get_sv("PerlIO::encoding::fallback", GV_ADD|GV_ADDMULTI);
1N/A /*
1N/A * we now "use Encode ()" here instead of
1N/A * PerlIO/encoding.pm. This avoids SEGV when ":encoding()"
1N/A * is invoked without prior "use Encode". -- dankogai
1N/A */
1N/A PUSHSTACKi(PERLSI_MAGIC);
1N/A SPAGAIN;
1N/A if (!get_cv(OUR_DEFAULT_FB, 0)) {
1N/A#if 0
1N/A /* This would just be an irritant now loading works */
1N/A Perl_warner(aTHX_ packWARN(WARN_IO), ":encoding without 'use Encode'");
1N/A#endif
1N/A ENTER;
1N/A /* Encode needs a lot of stack - it is likely to move ... */
1N/A PUTBACK;
1N/A /* The SV is magically freed by load_module */
1N/A load_module(PERL_LOADMOD_NOIMPORT, newSVpvn("Encode", 6), Nullsv, Nullsv);
1N/A SPAGAIN;
1N/A LEAVE;
1N/A }
1N/A PUSHMARK(sp);
1N/A PUTBACK;
1N/A if (call_pv(OUR_DEFAULT_FB, G_SCALAR) != 1) {
1N/A /* should never happen */
1N/A Perl_die(aTHX_ "%s did not return a value",OUR_DEFAULT_FB);
1N/A }
1N/A SPAGAIN;
1N/A sv_setsv(chk, POPs);
1N/A PUTBACK;
1N/A#ifdef PERLIO_LAYERS
1N/A PerlIO_define_layer(aTHX_ &PerlIO_encode);
1N/A#endif
1N/A POPSTACK;
1N/A}