diff options
author | Christian Hansen <chansen@cpan.org> | 2013-02-17 14:50:30 -0700 |
---|---|---|
committer | Karl Williamson <public@khwilliamson.com> | 2013-02-18 21:32:41 -0700 |
commit | 10e621bc35cb48b15b69b5a57242ff004f7455dc (patch) | |
tree | 228ad6b0c4f1f624c787ae8f2f1836119be447a8 /dist/IO/IO.xs | |
parent | f10c05c1d5f850f4bfb45f5d10409f4b2f3cfb2f (diff) | |
download | perl-10e621bc35cb48b15b69b5a57242ff004f7455dc.tar.gz |
PATCH: [perl #116322]: getc() and ungetc() with unicode failure
ungetc() had no knowledge of UTF-8. This patch adds it.
The committer fleshed out the author's code to make a patch, making
a few small changes.
Diffstat (limited to 'dist/IO/IO.xs')
-rw-r--r-- | dist/IO/IO.xs | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/dist/IO/IO.xs b/dist/IO/IO.xs index 085db547f7..ac64d17c2b 100644 --- a/dist/IO/IO.xs +++ b/dist/IO/IO.xs @@ -327,14 +327,38 @@ MODULE = IO PACKAGE = IO::Handle PREFIX = f int ungetc(handle, c) InputStream handle - int c + SV * c CODE: - if (handle) + if (handle) { #ifdef PerlIO - RETVAL = PerlIO_ungetc(handle, c); + UV v; + + if ((SvIOK_notUV(c) && SvIV(c) < 0) || (SvNOK(c) && SvNV(c) < 0.0)) + croak("Negative character number in ungetc()"); + + v = SvUV(c); + if (NATIVE_IS_INVARIANT(v) || (v <= 0xFF && !PerlIO_isutf8(handle))) + RETVAL = PerlIO_ungetc(handle, (int)v); + else { + U8 buf[UTF8_MAXBYTES + 1], *end; + Size_t len; + + if (!PerlIO_isutf8(handle)) + croak("Wide character number in ungetc()"); + + /* This doesn't warn for non-chars, surrogate, and + * above-Unicodes */ + end = uvchr_to_utf8_flags(buf, v, 0); + len = end - buf; + if (PerlIO_unread(handle, &buf, len) == len) + XSRETURN_UV(v); + else + RETVAL = EOF; + } #else - RETVAL = ungetc(c, handle); + RETVAL = ungetc((int)SvIV(c), handle); #endif + } else { RETVAL = -1; errno = EINVAL; |