5 #define PERL_NO_GET_CONTEXT
11 #if defined(USE_PERLIO) && !defined(USE_SFIO)
13 /* Define an encoding "layer" in the perliol.h sense.
15 The layer defined here "inherits" in an object-oriented sense from
16 the "perlio" layer with its PerlIOBuf_* "methods". The
17 implementation is particularly efficient as until Encode settles
18 down there is no point in tryint to tune it.
20 The layer works by overloading the "fill" and "flush" methods.
22 "fill" calls "SUPER::fill" in perl terms, then calls the encode OO
23 perl API to convert the encoded data to UTF-8 form, then copies it
24 back to the buffer. The "base class's" read methods then see the
27 "flush" transforms the UTF-8 data deposited by the "base class's
28 write method in the buffer back into the encoded form using the
29 encode OO perl API, then copies data back into the buffer and calls
32 Note that "flush" is _also_ called for read mode - we still do the
33 (back)-translate so that the the base class's "flush" sees the
34 correct number of encoded chars for positioning the seek
35 pointer. (This double translation is the worst performance issue -
36 particularly with all-perl encode engine.)
43 PerlIOBuf base; /* PerlIOBuf stuff */
44 SV *bufsv; /* buffer seen by layers above */
45 SV *dataSV; /* data we have read from layer below */
46 SV *enc; /* the encoding object */
47 SV *chk; /* CHECK in Encode methods */
48 int flags; /* Flags currently just needs lines */
54 #define OUR_ENCODE_FB "Encode::FB_DEFAULT"
56 #define OUR_ENCODE_FB "Encode::FB_QUIET"
60 PerlIOEncode_getarg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
62 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
63 SV *sv = &PL_sv_undef;
71 if (call_method("name", G_SCALAR) == 1) {
81 PerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg)
83 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
87 code = PerlIOBuf_pushed(aTHX_ f, mode, Nullsv);
94 if (call_pv("Encode::find_encoding", G_SCALAR) != 1) {
95 /* should never happen */
96 Perl_die(aTHX_ "Encode::find_encoding did not return a value");
103 if (!SvROK(result) || !SvOBJECT(SvRV(result))) {
105 Perl_warner(aTHX_ packWARN(WARN_IO), "Cannot find encoding \"%" SVf "\"",
111 #ifdef USE_NEW_SEQUENCE
115 if (call_method("new_sequence",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
116 Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support new_sequence",
125 e->enc = newSVsv(result);
129 if (call_method("needs_lines",G_SCALAR|G_EVAL) != 1 || SvTRUE(ERRSV)) {
130 Perl_warner(aTHX_ packWARN(WARN_IO), "\"%" SVf "\" does not support needs_lines",
137 if (SvTRUE(result)) {
138 e->flags |= NEEDS_LINES;
141 PerlIOBase(f)->flags |= PERLIO_F_UTF8;
142 if (e->flags & NEEDS_LINES) {
143 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF;
147 e->chk = newSVsv(get_sv("PerlIO::encoding::check",0));
155 PerlIOEncode_popped(pTHX_ PerlIO * f)
157 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
159 SvREFCNT_dec(e->enc);
163 SvREFCNT_dec(e->bufsv);
167 SvREFCNT_dec(e->dataSV);
171 SvREFCNT_dec(e->chk);
178 PerlIOEncode_get_base(pTHX_ PerlIO * f)
180 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
182 e->base.bufsiz = 1024;
184 e->bufsv = newSV(e->base.bufsiz);
185 sv_setpvn(e->bufsv, "", 0);
187 e->base.buf = (STDCHAR *) SvPVX(e->bufsv);
189 e->base.ptr = e->base.buf;
191 e->base.end = e->base.buf;
192 if (e->base.ptr < e->base.buf
193 || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
194 Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
195 e->base.buf + SvLEN(e->bufsv));
198 if (SvLEN(e->bufsv) < e->base.bufsiz) {
199 SSize_t poff = e->base.ptr - e->base.buf;
200 SSize_t eoff = e->base.end - e->base.buf;
201 e->base.buf = (STDCHAR *) SvGROW(e->bufsv, e->base.bufsiz);
202 e->base.ptr = e->base.buf + poff;
203 e->base.end = e->base.buf + eoff;
205 if (e->base.ptr < e->base.buf
206 || e->base.ptr > e->base.buf + SvLEN(e->bufsv)) {
207 Perl_warn(aTHX_ " ptr %p(%p)%p", e->base.buf, e->base.ptr,
208 e->base.buf + SvLEN(e->bufsv));
215 PerlIOEncode_fill(pTHX_ PerlIO * f)
217 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
222 if (PerlIO_flush(f) != 0)
225 if (!PerlIO_fast_gets(n)) {
226 /* Things get too messy if we don't have a buffer layer
227 push a :perlio to do the job */
229 n = PerlIO_push(aTHX_ n, &PerlIO_perlio, PerlIO_modestr(f,mode), Nullsv);
231 Perl_die(aTHX_ "panic: cannot push :perlio for %p",f);
237 avail = PerlIO_get_cnt(n);
239 avail = PerlIO_fill(n);
241 avail = PerlIO_get_cnt(n);
244 if (!PerlIO_error(n) && PerlIO_eof(n))
248 if (avail > 0 || (e->flags & NEEDS_LINES)) {
249 STDCHAR *ptr = PerlIO_get_ptr(n);
250 SSize_t use = (avail >= 0) ? avail : 0;
254 e->base.ptr = e->base.end = (STDCHAR *) Nullch;
255 (void) PerlIOEncode_get_base(aTHX_ f);
257 e->dataSV = newSV(0);
258 if (SvTYPE(e->dataSV) < SVt_PV) {
259 sv_upgrade(e->dataSV,SVt_PV);
261 if (e->flags & NEEDS_LINES) {
262 /* Encoding needs whole lines (e.g. iso-2022-*)
263 search back from end of available data for
266 STDCHAR *nl = ptr+use-1;
273 if (nl >= ptr && *nl == '\n') {
274 /* found a line - take up to and including that */
277 else if (avail > 0) {
278 /* No line, but not EOF - append avail to the pending data */
279 sv_catpvn(e->dataSV, ptr, use);
280 PerlIO_set_ptrcnt(n, ptr+use, 0);
283 else if (!SvCUR(e->dataSV)) {
287 if (SvCUR(e->dataSV)) {
288 /* something left over from last time - create a normal
289 SV with new data appended
291 if (use + SvCUR(e->dataSV) > e->base.bufsiz) {
292 if (e->flags & NEEDS_LINES) {
293 /* Have to grow buffer */
294 e->base.bufsiz = use + SvCUR(e->dataSV);
295 PerlIOEncode_get_base(aTHX_ f);
298 use = e->base.bufsiz - SvCUR(e->dataSV);
301 sv_catpvn(e->dataSV,(char*)ptr,use);
304 /* Create a "dummy" SV to represent the available data from layer below */
305 if (SvLEN(e->dataSV) && SvPVX(e->dataSV)) {
306 Safefree(SvPVX(e->dataSV));
308 if (use > e->base.bufsiz) {
309 if (e->flags & NEEDS_LINES) {
310 /* Have to grow buffer */
311 e->base.bufsiz = use;
312 PerlIOEncode_get_base(aTHX_ f);
315 use = e->base.bufsiz;
318 SvPVX(e->dataSV) = (char *) ptr;
319 SvLEN(e->dataSV) = 0; /* Hands off sv.c - it isn't yours */
320 SvCUR_set(e->dataSV,use);
321 SvPOK_only(e->dataSV);
323 SvUTF8_off(e->dataSV);
329 if (call_method("decode", G_SCALAR) != 1) {
330 Perl_die(aTHX_ "panic: decode did not return a value");
335 /* Now get translated string (forced to UTF-8) and use as buffer */
337 s = SvPVutf8(uni, len);
338 #ifdef PARANOID_ENCODE_CHECKS
339 if (len && !is_utf8_string((U8*)s,len)) {
340 Perl_warn(aTHX_ "panic: decode did not return UTF-8 '%.*s'",(int) len,s);
346 /* if decode gave us back dataSV then data may vanish when
347 we do ptrcnt adjust - so take our copy now.
348 (The copy is a pain - need a put-it-here option for decode.)
350 sv_setpvn(e->bufsv,s,len);
351 e->base.ptr = e->base.buf = (STDCHAR*)SvPVX(e->bufsv);
352 e->base.end = e->base.ptr + SvCUR(e->bufsv);
353 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
356 /* Adjust ptr/cnt not taking anything which
357 did not translate - not clear this is a win */
358 /* compute amount we took */
359 use -= SvCUR(e->dataSV);
360 PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
361 /* and as we did not take it it isn't pending */
362 SvCUR_set(e->dataSV,0);
364 /* Got nothing - assume partial character so we need some more */
365 /* Make sure e->dataSV is a normal SV before re-filling as
366 buffer alias will change under us
368 s = SvPV(e->dataSV,len);
369 sv_setpvn(e->dataSV,s,len);
370 PerlIO_set_ptrcnt(n, ptr+use, (avail-use));
380 PerlIOBase(f)->flags |= PERLIO_F_EOF;
382 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
388 PerlIOEncode_flush(pTHX_ PerlIO * f)
390 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
392 if (e->bufsv && (e->base.ptr > e->base.buf)) {
398 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
399 /* Write case encode the buffer and write() to layer below */
404 SvCUR_set(e->bufsv, e->base.ptr - e->base.buf);
409 if (call_method("encode", G_SCALAR) != 1) {
410 Perl_die(aTHX_ "panic: encode did not return a value");
416 count = PerlIO_write(PerlIONext(f),s,len);
422 if (PerlIO_flush(PerlIONext(f)) != 0) {
425 if (SvCUR(e->bufsv)) {
426 /* Did not all translate */
427 e->base.ptr = e->base.buf+SvCUR(e->bufsv);
431 else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
433 /* if we have any untranslated stuff then unread that first */
434 if (e->dataSV && SvCUR(e->dataSV)) {
435 s = SvPV(e->dataSV, len);
436 count = PerlIO_unread(PerlIONext(f),s,len);
441 /* See if there is anything left in the buffer */
442 if (e->base.ptr < e->base.end) {
443 /* Bother - have unread data.
444 re-encode and unread() to layer below
448 str = sv_newmortal();
449 sv_upgrade(str, SVt_PV);
450 SvPVX(str) = (char*)e->base.ptr;
452 SvCUR_set(str, e->base.end - e->base.ptr);
460 if (call_method("encode", G_SCALAR) != 1) {
461 Perl_die(aTHX_ "panic: encode did not return a value");
467 count = PerlIO_unread(PerlIONext(f),s,len);
475 e->base.ptr = e->base.end = e->base.buf;
476 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
482 PerlIOEncode_close(pTHX_ PerlIO * f)
484 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
485 IV code = PerlIOBase_close(aTHX_ f);
487 if (e->base.buf && e->base.ptr > e->base.buf) {
488 Perl_croak(aTHX_ "Close with partial character");
490 SvREFCNT_dec(e->bufsv);
496 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
501 PerlIOEncode_tell(pTHX_ PerlIO * f)
503 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
504 /* Unfortunately the only way to get a postion is to (re-)translate,
505 the UTF8 we have in bufefr and then ask layer below
508 if (b->buf && b->ptr > b->buf) {
509 Perl_croak(aTHX_ "Cannot tell at partial character");
511 return PerlIO_tell(PerlIONext(f));
515 PerlIOEncode_dup(pTHX_ PerlIO * f, PerlIO * o,
516 CLONE_PARAMS * params, int flags)
518 if ((f = PerlIOBase_dup(aTHX_ f, o, params, flags))) {
519 PerlIOEncode *fe = PerlIOSelf(f, PerlIOEncode);
520 PerlIOEncode *oe = PerlIOSelf(o, PerlIOEncode);
522 fe->enc = PerlIO_sv_dup(aTHX_ oe->enc, params);
529 PerlIOEncode_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
531 SSize_t size = PerlIOBuf_write(aTHX_ f, vbuf, count);
532 PerlIOEncode *e = PerlIOSelf(f, PerlIOEncode);
533 if (e->flags & NEEDS_LINES) {
538 PerlIO_funcs PerlIO_encode = {
540 sizeof(PerlIOEncode),
541 PERLIO_K_BUFFERED|PERLIO_K_DESTRUCT,
559 PerlIOBase_setlinebuf,
560 PerlIOEncode_get_base,
564 PerlIOBuf_set_ptrcnt,
566 #endif /* encode layer */
568 MODULE = PerlIO::encoding PACKAGE = PerlIO::encoding
574 SV *sv = get_sv("PerlIO::encoding::check", GV_ADD|GV_ADDMULTI);
578 if (call_pv(OUR_ENCODE_FB, G_SCALAR) != 1) {
579 Perl_warner(aTHX_ packWARN(WARN_IO),
580 "Call to %s failed!",OUR_ENCODE_FB);
588 PerlIO_define_layer(aTHX_ &PerlIO_encode);