@@ -155,3 +155,128 @@ PyTypeObject PyEnum_Type = {
155
155
enum_new , /* tp_new */
156
156
PyObject_GC_Del , /* tp_free */
157
157
};
158
+
159
+ /* Reversed Object ***************************************************************/
160
+
161
+ typedef struct {
162
+ PyObject_HEAD
163
+ long index ;
164
+ PyObject * seq ;
165
+ } reversedobject ;
166
+
167
+ static PyObject *
168
+ reversed_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
169
+ {
170
+ long n ;
171
+ PyObject * seq ;
172
+ reversedobject * ro ;
173
+
174
+ if (!PyArg_UnpackTuple (args , "reversed" , 1 , 1 , & seq ))
175
+ return NULL ;
176
+
177
+ /* Special case optimization for xrange */
178
+ if (PyRange_Check (seq ))
179
+ return PyObject_CallMethod (seq , "__reversed__" , NULL );
180
+
181
+ if (!PySequence_Check (seq )) {
182
+ PyErr_SetString (PyExc_TypeError ,
183
+ "argument to reversed() must be a sequence" );
184
+ return NULL ;
185
+ }
186
+
187
+ n = PySequence_Size (seq );
188
+ if (n == -1 )
189
+ return NULL ;
190
+
191
+ ro = (reversedobject * )type -> tp_alloc (type , 0 );
192
+ if (ro == NULL )
193
+ return NULL ;
194
+
195
+ ro -> index = n - 1 ;
196
+ Py_INCREF (seq );
197
+ ro -> seq = seq ;
198
+ return (PyObject * )ro ;
199
+ }
200
+
201
+ static void
202
+ reversed_dealloc (reversedobject * ro )
203
+ {
204
+ PyObject_GC_UnTrack (ro );
205
+ Py_XDECREF (ro -> seq );
206
+ ro -> ob_type -> tp_free (ro );
207
+ }
208
+
209
+ static int
210
+ reversed_traverse (reversedobject * ro , visitproc visit , void * arg )
211
+ {
212
+ if (ro -> seq )
213
+ return visit ((PyObject * )(ro -> seq ), arg );
214
+ return 0 ;
215
+ }
216
+
217
+ static PyObject *
218
+ reversed_next (reversedobject * ro )
219
+ {
220
+ PyObject * item ;
221
+
222
+ if (ro -> index < 0 )
223
+ return NULL ;
224
+
225
+ assert (PySequence_Check (ro -> seq ));
226
+ item = PySequence_GetItem (ro -> seq , ro -> index );
227
+ if (item == NULL )
228
+ return NULL ;
229
+
230
+ ro -> index -- ;
231
+ return item ;
232
+ }
233
+
234
+ PyDoc_STRVAR (reversed_doc ,
235
+ "reverse(sequence) -> reverse iterator over values of the sequence\n"
236
+ "\n"
237
+ "Return a reverse iterator" );
238
+
239
+ PyTypeObject PyReversed_Type = {
240
+ PyObject_HEAD_INIT (& PyType_Type )
241
+ 0 , /* ob_size */
242
+ "reversed" , /* tp_name */
243
+ sizeof (reversedobject ), /* tp_basicsize */
244
+ 0 , /* tp_itemsize */
245
+ /* methods */
246
+ (destructor )reversed_dealloc , /* tp_dealloc */
247
+ 0 , /* tp_print */
248
+ 0 , /* tp_getattr */
249
+ 0 , /* tp_setattr */
250
+ 0 , /* tp_compare */
251
+ 0 , /* tp_repr */
252
+ 0 , /* tp_as_number */
253
+ 0 , /* tp_as_sequence */
254
+ 0 , /* tp_as_mapping */
255
+ 0 , /* tp_hash */
256
+ 0 , /* tp_call */
257
+ 0 , /* tp_str */
258
+ PyObject_GenericGetAttr , /* tp_getattro */
259
+ 0 , /* tp_setattro */
260
+ 0 , /* tp_as_buffer */
261
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
262
+ Py_TPFLAGS_BASETYPE , /* tp_flags */
263
+ reversed_doc , /* tp_doc */
264
+ (traverseproc )reversed_traverse ,/* tp_traverse */
265
+ 0 , /* tp_clear */
266
+ 0 , /* tp_richcompare */
267
+ 0 , /* tp_weaklistoffset */
268
+ PyObject_SelfIter , /* tp_iter */
269
+ (iternextfunc )reversed_next , /* tp_iternext */
270
+ 0 , /* tp_methods */
271
+ 0 , /* tp_members */
272
+ 0 , /* tp_getset */
273
+ 0 , /* tp_base */
274
+ 0 , /* tp_dict */
275
+ 0 , /* tp_descr_get */
276
+ 0 , /* tp_descr_set */
277
+ 0 , /* tp_dictoffset */
278
+ 0 , /* tp_init */
279
+ PyType_GenericAlloc , /* tp_alloc */
280
+ reversed_new , /* tp_new */
281
+ PyObject_GC_Del , /* tp_free */
282
+ };
0 commit comments