Commits

Nick Coghlan committed f1560ab

First cut at a subtype - still some test failures

Comments (0)

Files changed (4)

Include/longobject.h

 PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *);
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(int) _PyLong_AsInt(PyObject *);
+
+PyAPI_DATA(PyTypeObject) _PyBytesLong_Type;
 PyAPI_FUNC(PyObject *) _PyBytesLong_FromLong(long);
 #endif
 PyAPI_FUNC(PyObject *) PyLong_GetInfo(void);
 
 del sys, _f, _g, _C,                              # Not for export
 
+# Transition type for binary indexing/iteration
+# TODO: Peephole optimiser constant folds bytes lookups, which confuses
+# marshal. So marshal will need to understand the transition type to avoid
+# breaking backwards compatibility.
+_BytesInt = type(bytes(b"a")[0])
+
 
 # Provide a PEP 3115 compliant mechanism for class creation
 def new_class(name, bases=(), kwds=None, exec_body=None):

Objects/longobject.c

 #endif
 }
 
+/* Custom subclass for objects returned from binary indexing/iteration */
+PyTypeObject _PyBytesLong_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "types._BytesInt",                          /* tp_name */
+    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
+    sizeof(digit),                              /* tp_itemsize */
+    0,                               /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_reserved */
+    0,                     /* tp_repr */
+    0,                            /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                        /* tp_hash */
+    0,                                          /* tp_call */
+    0,                     /* tp_str */
+    0,                    /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+        Py_TPFLAGS_LONG_SUBCLASS,               /* tp_flags */
+    0,                                   /* tp_doc */
+    0,                                          /* tp_traverse */
+    0,                                          /* tp_clear */
+    0,                           /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                               /* tp_methods */
+    0,                                          /* tp_members */
+    0,                                /* tp_getset */
+    &PyLong_Type,                               /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    0,                                          /* tp_alloc */
+    0,                                   /* tp_new */
+    0,                               /* tp_free */
+};
 
 PyObject *
 _PyBytesLong_FromLong(long ival)
 {
-    /*TODO: Return a long subclass instead of a normal long object */
-    return PyLong_FromLong(ival);
+    /* As with long_subtype_new, allocate a normal long, copy contents */
+    PyLongObject *tmp = (PyLongObject *)PyLong_FromLong(ival);
+    PyLongObject *result;
+    Py_ssize_t i, n;
+
+    assert(PyLong_CheckExact(tmp));
+    n = Py_SIZE(tmp);
+    if (n < 0)
+        n = -n;
+    result = (PyLongObject *)_PyBytesLong_Type.tp_alloc(&_PyBytesLong_Type, n);
+    if (result == NULL) {
+        Py_DECREF(tmp);
+        return NULL;
+    }
+    assert(PyLong_Check(result));
+    Py_SIZE(result) = Py_SIZE(tmp);
+    for (i = 0; i < n; i++)
+        result->ob_digit[i] = tmp->ob_digit[i];
+    Py_DECREF(tmp);
+    return (PyObject *)result;
 }
     if (PyType_Ready(&PyLong_Type) < 0)
         Py_FatalError("Can't initialize int type");
 
+    if (PyType_Ready(&_PyBytesLong_Type) < 0)
+        Py_FatalError("Can't initialize types._BytesInt type");
+
     if (PyType_Ready(&PyBool_Type) < 0)
         Py_FatalError("Can't initialize bool type");