fix intern() optimisation
authorStefan Behnel <scoder@users.berlios.de>
Thu, 22 Oct 2009 09:24:48 +0000 (11:24 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Thu, 22 Oct 2009 09:24:48 +0000 (11:24 +0200)
Cython/Compiler/Builtin.py
tests/run/intern_T431.pyx [new file with mode: 0644]

index 69f160a1fe312530e76edc4c576adf19c7d42cbc..494057bd484d4dab2b7b0fd19c5f199bdb7733db 100644 (file)
@@ -28,7 +28,7 @@ builtin_function_table = [
     #('hex',       "",     "",      ""),
     #('id',        "",     "",      ""),
     #('input',     "",     "",      ""),
-    #('intern',     "s",    "O",     "__Pyx_InternFromString"), # Doesn't work for Python str objects with null characters.
+    ('intern',     "O",    "O",     "__Pyx_Intern"),
     ('isinstance', "OO",   "b",     "PyObject_IsInstance"),
     ('issubclass', "OO",   "b",     "PyObject_IsSubclass"),
     ('iter',       "O",    "O",     "PyObject_GetIter"),
@@ -237,12 +237,23 @@ bad:
 
 intern_utility_code = UtilityCode(
 proto = """
-#if PY_MAJOR_VERSION >= 3
-#  define __Pyx_InternFromString(s) PyUnicode_InternFromString(s)
-#else
-#  define __Pyx_InternFromString(s) PyString_InternFromString(s)
-#endif
-""")
+static PyObject* __Pyx_Intern(PyObject* s); /* proto */
+""",
+impl = '''
+static PyObject* __Pyx_Intern(PyObject* s) {
+    if (!(likely(PyString_CheckExact(s)))) {
+        PyErr_Format(PyExc_TypeError, "Expected str, got %s", Py_TYPE(s)->tp_name);
+        return 0;
+    }
+    Py_INCREF(s);
+    #if PY_MAJOR_VERSION >= 3
+    PyUnicode_InternInPlace(&s);
+    #else
+    PyString_InternInPlace(&s);
+    #endif
+    return s;
+}
+''')
 
 def put_py23_set_init_utility_code(code, pos):
     code.putln("#if PY_VERSION_HEX < 0x02040000")
diff --git a/tests/run/intern_T431.pyx b/tests/run/intern_T431.pyx
new file mode 100644 (file)
index 0000000..dfdff19
--- /dev/null
@@ -0,0 +1,16 @@
+__doc__ = u"""
+>>> s == s_interned
+True
+>>> intern(s) is s_interned
+True
+>>> intern('abc') is s_interned
+True
+>>> intern('abc') is s_interned_dynamic
+True
+"""
+
+s = 'abc'
+
+s_interned = intern(s)
+
+s_interned_dynamic = intern('a'+'b'+'c')