@@ -155,3 +155,128 @@ PyTypeObject PyEnum_Type = {
155155 enum_new , /* tp_new */
156156 PyObject_GC_Del , /* tp_free */
157157};
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