summaryrefslogtreecommitdiff
path: root/dist/IO/IO.xs
diff options
context:
space:
mode:
authorChristian Hansen <chansen@cpan.org>2013-02-17 14:50:30 -0700
committerKarl Williamson <public@khwilliamson.com>2013-02-18 21:32:41 -0700
commit10e621bc35cb48b15b69b5a57242ff004f7455dc (patch)
tree228ad6b0c4f1f624c787ae8f2f1836119be447a8 /dist/IO/IO.xs
parentf10c05c1d5f850f4bfb45f5d10409f4b2f3cfb2f (diff)
downloadperl-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.xs32
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;