From: Victor Stinner Date: Wed, 23 Feb 2011 12:14:22 +0000 (+0000) Subject: Merged revisions 88481 via svnmerge from X-Git-Tag: v3.2.1b1~382 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=659eb8445735337650c97fff41118b7a6d8b913e;p=python Merged revisions 88481 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r88481 | victor.stinner | 2011-02-21 22:13:44 +0100 (lun., 21 févr. 2011) | 4 lines Fix PyUnicode_FromFormatV("%c") for non-BMP char Issue #10830: Fix PyUnicode_FromFormatV("%c") for non-BMP characters on narrow build. ........ --- diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index e2d67cd949..9ad9eed6ac 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1427,7 +1427,7 @@ class UnicodeTest(string_tests.CommonTest, # Test PyUnicode_FromFormat() def test_from_format(self): support.import_module('ctypes') - from ctypes import pythonapi, py_object + from ctypes import pythonapi, py_object, c_int if sys.maxunicode == 65535: name = "PyUnicodeUCS2_FromFormat" else: @@ -1452,6 +1452,9 @@ class UnicodeTest(string_tests.CommonTest, 'string, got a non-ASCII byte: 0xe9$', PyUnicode_FromFormat, b'unicode\xe9=%s', 'ascii') + self.assertEqual(PyUnicode_FromFormat(b'%c', c_int(0xabcd)), '\uabcd') + self.assertEqual(PyUnicode_FromFormat(b'%c', c_int(0x10ffff)), '\U0010ffff') + # other tests text = PyUnicode_FromFormat(b'%%A:%A', 'abc\xe9\uabcd\U0010ffff') self.assertEqual(text, r"%A:'abc\xe9\uabcd\U0010ffff'") diff --git a/Misc/NEWS b/Misc/NEWS index b4cff7ff4e..a7f9ba5a56 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins - Issue #11272: On Windows, input() strips '\r' (and not only '\n'), and sys.stdin uses universal newline (replace '\r\n' by '\n'). +- Issue #10830: Fix PyUnicode_FromFormatV("%c") for non-BMP characters on + narrow build. + - Check for NULL result in PyType_FromSpec. Library diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 456719685d..423a53383a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -813,8 +813,19 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) switch (*f) { case 'c': + { +#ifndef Py_UNICODE_WIDE + int ordinal = va_arg(count, int); + if (ordinal > 0xffff) + n += 2; + else + n++; +#else (void)va_arg(count, int); - /* fall through... */ + n++; +#endif + break; + } case '%': n++; break; @@ -992,8 +1003,18 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) switch (*f) { case 'c': - *s++ = va_arg(vargs, int); + { + int ordinal = va_arg(vargs, int); +#ifndef Py_UNICODE_WIDE + if (ordinal > 0xffff) { + ordinal -= 0x10000; + *s++ = 0xD800 | (ordinal >> 10); + *s++ = 0xDC00 | (ordinal & 0x3FF); + } else +#endif + *s++ = ordinal; break; + } case 'd': makefmt(fmt, longflag, longlongflag, size_tflag, zeropad, width, precision, 'd');