~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Objects/iterobject.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Iterator objects */
 
2
 
 
3
#include "Python.h"
 
4
 
 
5
typedef struct {
 
6
    PyObject_HEAD
 
7
    Py_ssize_t it_index;
 
8
    PyObject *it_seq; /* Set to NULL when iterator is exhausted */
 
9
} seqiterobject;
 
10
 
 
11
PyObject *
 
12
PySeqIter_New(PyObject *seq)
 
13
{
 
14
    seqiterobject *it;
 
15
 
 
16
    if (!PySequence_Check(seq)) {
 
17
        PyErr_BadInternalCall();
 
18
        return NULL;
 
19
    }
 
20
    it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
 
21
    if (it == NULL)
 
22
        return NULL;
 
23
    it->it_index = 0;
 
24
    Py_INCREF(seq);
 
25
    it->it_seq = seq;
 
26
    _PyObject_GC_TRACK(it);
 
27
    return (PyObject *)it;
 
28
}
 
29
 
 
30
static void
 
31
iter_dealloc(seqiterobject *it)
 
32
{
 
33
    _PyObject_GC_UNTRACK(it);
 
34
    Py_XDECREF(it->it_seq);
 
35
    PyObject_GC_Del(it);
 
36
}
 
37
 
 
38
static int
 
39
iter_traverse(seqiterobject *it, visitproc visit, void *arg)
 
40
{
 
41
    Py_VISIT(it->it_seq);
 
42
    return 0;
 
43
}
 
44
 
 
45
static PyObject *
 
46
iter_iternext(PyObject *iterator)
 
47
{
 
48
    seqiterobject *it;
 
49
    PyObject *seq;
 
50
    PyObject *result;
 
51
 
 
52
    assert(PySeqIter_Check(iterator));
 
53
    it = (seqiterobject *)iterator;
 
54
    seq = it->it_seq;
 
55
    if (seq == NULL)
 
56
        return NULL;
 
57
 
 
58
    result = PySequence_GetItem(seq, it->it_index);
 
59
    if (result != NULL) {
 
60
        it->it_index++;
 
61
        return result;
 
62
    }
 
63
    if (PyErr_ExceptionMatches(PyExc_IndexError) ||
 
64
        PyErr_ExceptionMatches(PyExc_StopIteration))
 
65
    {
 
66
        PyErr_Clear();
 
67
        Py_DECREF(seq);
 
68
        it->it_seq = NULL;
 
69
    }
 
70
    return NULL;
 
71
}
 
72
 
 
73
static PyObject *
 
74
iter_len(seqiterobject *it)
 
75
{
 
76
    Py_ssize_t seqsize, len;
 
77
 
 
78
    if (it->it_seq) {
 
79
        if (_PyObject_HasLen(it->it_seq)) {
 
80
            seqsize = PySequence_Size(it->it_seq);
 
81
            if (seqsize == -1)
 
82
                return NULL;
 
83
        }
 
84
        else {
 
85
            Py_RETURN_NOTIMPLEMENTED;
 
86
        }
 
87
        len = seqsize - it->it_index;
 
88
        if (len >= 0)
 
89
            return PyLong_FromSsize_t(len);
 
90
    }
 
91
    return PyLong_FromLong(0);
 
92
}
 
93
 
 
94
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
 
95
 
 
96
static PyObject *
 
97
iter_reduce(seqiterobject *it)
 
98
{
 
99
    if (it->it_seq != NULL)
 
100
        return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
 
101
                             it->it_seq, it->it_index);
 
102
    else
 
103
        return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
 
104
}
 
105
 
 
106
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
 
107
 
 
108
static PyObject *
 
109
iter_setstate(seqiterobject *it, PyObject *state)
 
110
{
 
111
    Py_ssize_t index = PyLong_AsSsize_t(state);
 
112
    if (index == -1 && PyErr_Occurred())
 
113
        return NULL;
 
114
    if (it->it_seq != NULL) {
 
115
        if (index < 0)
 
116
            index = 0;
 
117
        it->it_index = index;
 
118
    }
 
119
    Py_RETURN_NONE;
 
120
}
 
121
 
 
122
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
 
123
 
 
124
static PyMethodDef seqiter_methods[] = {
 
125
    {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
 
126
    {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
 
127
    {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
 
128
    {NULL,              NULL}           /* sentinel */
 
129
};
 
130
 
 
131
PyTypeObject PySeqIter_Type = {
 
132
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
 
133
    "iterator",                                 /* tp_name */
 
134
    sizeof(seqiterobject),                      /* tp_basicsize */
 
135
    0,                                          /* tp_itemsize */
 
136
    /* methods */
 
137
    (destructor)iter_dealloc,                   /* tp_dealloc */
 
138
    0,                                          /* tp_print */
 
139
    0,                                          /* tp_getattr */
 
140
    0,                                          /* tp_setattr */
 
141
    0,                                          /* tp_reserved */
 
142
    0,                                          /* tp_repr */
 
143
    0,                                          /* tp_as_number */
 
144
    0,                                          /* tp_as_sequence */
 
145
    0,                                          /* tp_as_mapping */
 
146
    0,                                          /* tp_hash */
 
147
    0,                                          /* tp_call */
 
148
    0,                                          /* tp_str */
 
149
    PyObject_GenericGetAttr,                    /* tp_getattro */
 
150
    0,                                          /* tp_setattro */
 
151
    0,                                          /* tp_as_buffer */
 
152
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
 
153
    0,                                          /* tp_doc */
 
154
    (traverseproc)iter_traverse,                /* tp_traverse */
 
155
    0,                                          /* tp_clear */
 
156
    0,                                          /* tp_richcompare */
 
157
    0,                                          /* tp_weaklistoffset */
 
158
    PyObject_SelfIter,                          /* tp_iter */
 
159
    iter_iternext,                              /* tp_iternext */
 
160
    seqiter_methods,                            /* tp_methods */
 
161
    0,                                          /* tp_members */
 
162
};
 
163
 
 
164
/* -------------------------------------- */
 
165
 
 
166
typedef struct {
 
167
    PyObject_HEAD
 
168
    PyObject *it_callable; /* Set to NULL when iterator is exhausted */
 
169
    PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
 
170
} calliterobject;
 
171
 
 
172
PyObject *
 
173
PyCallIter_New(PyObject *callable, PyObject *sentinel)
 
174
{
 
175
    calliterobject *it;
 
176
    it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
 
177
    if (it == NULL)
 
178
        return NULL;
 
179
    Py_INCREF(callable);
 
180
    it->it_callable = callable;
 
181
    Py_INCREF(sentinel);
 
182
    it->it_sentinel = sentinel;
 
183
    _PyObject_GC_TRACK(it);
 
184
    return (PyObject *)it;
 
185
}
 
186
static void
 
187
calliter_dealloc(calliterobject *it)
 
188
{
 
189
    _PyObject_GC_UNTRACK(it);
 
190
    Py_XDECREF(it->it_callable);
 
191
    Py_XDECREF(it->it_sentinel);
 
192
    PyObject_GC_Del(it);
 
193
}
 
194
 
 
195
static int
 
196
calliter_traverse(calliterobject *it, visitproc visit, void *arg)
 
197
{
 
198
    Py_VISIT(it->it_callable);
 
199
    Py_VISIT(it->it_sentinel);
 
200
    return 0;
 
201
}
 
202
 
 
203
static PyObject *
 
204
calliter_iternext(calliterobject *it)
 
205
{
 
206
    if (it->it_callable != NULL) {
 
207
        PyObject *args = PyTuple_New(0);
 
208
        PyObject *result;
 
209
        if (args == NULL)
 
210
            return NULL;
 
211
        result = PyObject_Call(it->it_callable, args, NULL);
 
212
        Py_DECREF(args);
 
213
        if (result != NULL) {
 
214
            int ok;
 
215
            ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);               
 
216
            if (ok == 0)
 
217
                return result; /* Common case, fast path */
 
218
            Py_DECREF(result);
 
219
            if (ok > 0) {
 
220
                Py_CLEAR(it->it_callable);
 
221
                Py_CLEAR(it->it_sentinel);
 
222
            }
 
223
        }
 
224
        else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
 
225
            PyErr_Clear();
 
226
            Py_CLEAR(it->it_callable);
 
227
            Py_CLEAR(it->it_sentinel);
 
228
        }
 
229
    }
 
230
    return NULL;
 
231
}
 
232
 
 
233
static PyObject *
 
234
calliter_reduce(calliterobject *it)
 
235
{
 
236
    if (it->it_callable != NULL && it->it_sentinel != NULL)
 
237
        return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"),
 
238
                             it->it_callable, it->it_sentinel);
 
239
    else
 
240
        return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
 
241
}
 
242
 
 
243
static PyMethodDef calliter_methods[] = {
 
244
    {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
 
245
    {NULL,              NULL}           /* sentinel */
 
246
};
 
247
 
 
248
PyTypeObject PyCallIter_Type = {
 
249
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
 
250
    "callable_iterator",                        /* tp_name */
 
251
    sizeof(calliterobject),                     /* tp_basicsize */
 
252
    0,                                          /* tp_itemsize */
 
253
    /* methods */
 
254
    (destructor)calliter_dealloc,               /* tp_dealloc */
 
255
    0,                                          /* tp_print */
 
256
    0,                                          /* tp_getattr */
 
257
    0,                                          /* tp_setattr */
 
258
    0,                                          /* tp_reserved */
 
259
    0,                                          /* tp_repr */
 
260
    0,                                          /* tp_as_number */
 
261
    0,                                          /* tp_as_sequence */
 
262
    0,                                          /* tp_as_mapping */
 
263
    0,                                          /* tp_hash */
 
264
    0,                                          /* tp_call */
 
265
    0,                                          /* tp_str */
 
266
    PyObject_GenericGetAttr,                    /* tp_getattro */
 
267
    0,                                          /* tp_setattro */
 
268
    0,                                          /* tp_as_buffer */
 
269
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
 
270
    0,                                          /* tp_doc */
 
271
    (traverseproc)calliter_traverse,            /* tp_traverse */
 
272
    0,                                          /* tp_clear */
 
273
    0,                                          /* tp_richcompare */
 
274
    0,                                          /* tp_weaklistoffset */
 
275
    PyObject_SelfIter,                          /* tp_iter */
 
276
    (iternextfunc)calliter_iternext,            /* tp_iternext */
 
277
    calliter_methods,                           /* tp_methods */
 
278
};
 
279
 
 
280