Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a5d2d55

Browse files
committed
Patch 1335 by Christian Heimes.
Add a bytes iterator (copied from stringobject.c and reindented :-). I (Guido) added a small change to _abcoll.py to remove the registration of bytes as a virtual subtype of Iterator -- the presence of __iter__ will handle that now.
1 parent 57233cb commit a5d2d55

2 files changed

Lines changed: 121 additions & 3 deletions

File tree

Lib/_abcoll.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ def __subclasshook__(cls, C):
5151
return True
5252
return NotImplemented
5353

54-
Iterable.register(bytes)
55-
5654

5755
class Iterator(metaclass=ABCMeta):
5856

Objects/bytesobject.c

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3023,6 +3023,8 @@ PyDoc_STRVAR(bytes_doc,
30233023
\n\
30243024
If an argument is given it must be an iterable yielding ints in range(256).");
30253025

3026+
static PyObject *bytes_iter(PyObject *seq);
3027+
30263028
PyTypeObject PyBytes_Type = {
30273029
PyVarObject_HEAD_INIT(&PyType_Type, 0)
30283030
"bytes",
@@ -3050,7 +3052,7 @@ PyTypeObject PyBytes_Type = {
30503052
0, /* tp_clear */
30513053
(richcmpfunc)bytes_richcompare, /* tp_richcompare */
30523054
0, /* tp_weaklistoffset */
3053-
0, /* tp_iter */
3055+
bytes_iter, /* tp_iter */
30543056
0, /* tp_iternext */
30553057
bytes_methods, /* tp_methods */
30563058
0, /* tp_members */
@@ -3065,3 +3067,121 @@ PyTypeObject PyBytes_Type = {
30653067
PyType_GenericNew, /* tp_new */
30663068
PyObject_Del, /* tp_free */
30673069
};
3070+
3071+
/*********************** Bytes Iterator ****************************/
3072+
3073+
typedef struct {
3074+
PyObject_HEAD
3075+
Py_ssize_t it_index;
3076+
PyBytesObject *it_seq; /* Set to NULL when iterator is exhausted */
3077+
} bytesiterobject;
3078+
3079+
static void
3080+
bytesiter_dealloc(bytesiterobject *it)
3081+
{
3082+
_PyObject_GC_UNTRACK(it);
3083+
Py_XDECREF(it->it_seq);
3084+
PyObject_GC_Del(it);
3085+
}
3086+
3087+
static int
3088+
bytesiter_traverse(bytesiterobject *it, visitproc visit, void *arg)
3089+
{
3090+
Py_VISIT(it->it_seq);
3091+
return 0;
3092+
}
3093+
3094+
static PyObject *
3095+
bytesiter_next(bytesiterobject *it)
3096+
{
3097+
PyBytesObject *seq;
3098+
PyObject *item;
3099+
3100+
assert(it != NULL);
3101+
seq = it->it_seq;
3102+
if (seq == NULL)
3103+
return NULL;
3104+
assert(PyBytes_Check(seq));
3105+
3106+
if (it->it_index < PyBytes_GET_SIZE(seq)) {
3107+
item = PyInt_FromLong(
3108+
(unsigned char)seq->ob_bytes[it->it_index]);
3109+
if (item != NULL)
3110+
++it->it_index;
3111+
return item;
3112+
}
3113+
3114+
Py_DECREF(seq);
3115+
it->it_seq = NULL;
3116+
return NULL;
3117+
}
3118+
3119+
static PyObject *
3120+
bytesiter_length_hint(bytesiterobject *it)
3121+
{
3122+
Py_ssize_t len = 0;
3123+
if (it->it_seq)
3124+
len = PyBytes_GET_SIZE(it->it_seq) - it->it_index;
3125+
return PyInt_FromSsize_t(len);
3126+
}
3127+
3128+
PyDoc_STRVAR(length_hint_doc,
3129+
"Private method returning an estimate of len(list(it)).");
3130+
3131+
static PyMethodDef bytesiter_methods[] = {
3132+
{"__length_hint__", (PyCFunction)bytesiter_length_hint, METH_NOARGS,
3133+
length_hint_doc},
3134+
{NULL, NULL} /* sentinel */
3135+
};
3136+
3137+
PyTypeObject PyBytesIter_Type = {
3138+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
3139+
"bytesiterator", /* tp_name */
3140+
sizeof(bytesiterobject), /* tp_basicsize */
3141+
0, /* tp_itemsize */
3142+
/* methods */
3143+
(destructor)bytesiter_dealloc, /* tp_dealloc */
3144+
0, /* tp_print */
3145+
0, /* tp_getattr */
3146+
0, /* tp_setattr */
3147+
0, /* tp_compare */
3148+
0, /* tp_repr */
3149+
0, /* tp_as_number */
3150+
0, /* tp_as_sequence */
3151+
0, /* tp_as_mapping */
3152+
0, /* tp_hash */
3153+
0, /* tp_call */
3154+
0, /* tp_str */
3155+
PyObject_GenericGetAttr, /* tp_getattro */
3156+
0, /* tp_setattro */
3157+
0, /* tp_as_buffer */
3158+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3159+
0, /* tp_doc */
3160+
(traverseproc)bytesiter_traverse, /* tp_traverse */
3161+
0, /* tp_clear */
3162+
0, /* tp_richcompare */
3163+
0, /* tp_weaklistoffset */
3164+
PyObject_SelfIter, /* tp_iter */
3165+
(iternextfunc)bytesiter_next, /* tp_iternext */
3166+
bytesiter_methods, /* tp_methods */
3167+
0,
3168+
};
3169+
3170+
static PyObject *
3171+
bytes_iter(PyObject *seq)
3172+
{
3173+
bytesiterobject *it;
3174+
3175+
if (!PyBytes_Check(seq)) {
3176+
PyErr_BadInternalCall();
3177+
return NULL;
3178+
}
3179+
it = PyObject_GC_New(bytesiterobject, &PyBytesIter_Type);
3180+
if (it == NULL)
3181+
return NULL;
3182+
it->it_index = 0;
3183+
Py_INCREF(seq);
3184+
it->it_seq = (PyBytesObject *)seq;
3185+
_PyObject_GC_TRACK(it);
3186+
return (PyObject *)it;
3187+
}

0 commit comments

Comments
 (0)