diff Objects/unicodeobject.c @ 25638:29d40eae8736 2.2

Backport: 2002/08/11 12:23:04 lemburg Python/bltinmodule.c 2.262 2002/08/11 12:23:04 lemburg Objects/unicodeobject.c 2.162 2002/08/11 12:23:03 lemburg Misc/NEWS 1.461 2002/08/11 12:23:03 lemburg Lib/test/test_unicode.py 1.65 2002/08/11 12:23:03 lemburg Include/unicodeobject.h 2.39 Add C API PyUnicode_FromOrdinal() which exposes unichr() at C level. u'%c' will now raise a ValueError in case the argument is an integer outside the valid range of Unicode code point ordinals. Closes SF bug #593581.
author Michael W. Hudson <mwh@python.net>
date Mon, 07 Oct 2002 12:32:57 +0000
parents bb2033c8b92f
children 3c26ae61e952
line wrap: on
line diff
--- a/Objects/unicodeobject.c	Mon Oct 07 12:21:09 2002 +0000
+++ b/Objects/unicodeobject.c	Mon Oct 07 12:32:57 2002 +0000
@@ -390,6 +390,45 @@
 
 #endif
 
+PyObject *PyUnicode_FromOrdinal(int ordinal)
+{
+    Py_UNICODE s[2];
+
+#ifdef Py_UNICODE_WIDE
+    if (ordinal < 0 || ordinal > 0x10ffff) {
+	PyErr_SetString(PyExc_ValueError,
+			"unichr() arg not in range(0x110000) "
+			"(wide Python build)");
+	return NULL;
+    }
+#else
+    if (ordinal < 0 || ordinal > 0xffff) {
+	PyErr_SetString(PyExc_ValueError,
+			"unichr() arg not in range(0x10000) "
+			"(narrow Python build)");
+	return NULL;
+    }
+#endif
+
+    if (ordinal <= 0xffff) {
+	/* UCS-2 character */
+	s[0] = (Py_UNICODE) ordinal;
+	return PyUnicode_FromUnicode(s, 1);
+    }
+    else {
+#ifndef Py_UNICODE_WIDE
+	/* UCS-4 character.  store as two surrogate characters */
+	ordinal -= 0x10000L;
+	s[0] = 0xD800 + (Py_UNICODE) (ordinal >> 10);
+	s[1] = 0xDC00 + (Py_UNICODE) (ordinal & 0x03FF);
+	return PyUnicode_FromUnicode(s, 2);
+#else
+	s[0] = (Py_UNICODE)ordinal;
+	return PyUnicode_FromUnicode(s, 1);
+#endif
+    }
+}
+
 PyObject *PyUnicode_FromObject(register PyObject *obj)
 {
     /* XXX Perhaps we should make this API an alias of
@@ -5322,7 +5361,22 @@
 	x = PyInt_AsLong(v);
 	if (x == -1 && PyErr_Occurred())
 	    goto onError;
-	buf[0] = (char) x;
+#ifdef Py_UNICODE_WIDE
+	if (x < 0 || x > 0x10ffff) {
+	    PyErr_SetString(PyExc_ValueError,
+			    "%c arg not in range(0x110000) "
+			    "(wide Python build)");
+	    return -1;
+	}
+#else
+	if (x < 0 || x > 0xffff) {
+	    PyErr_SetString(PyExc_ValueError,
+			    "%c arg not in range(0x10000) "
+			    "(narrow Python build)");
+	    return -1;
+	}
+#endif
+	buf[0] = (Py_UNICODE) x;
     }
     buf[1] = '\0';
     return 1;