]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Objects/rangeobject.c
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Objects / rangeobject.c
CommitLineData
4710c53d 1/* Range object implementation */\r
2\r
3#include "Python.h"\r
4\r
5typedef struct {\r
6 PyObject_HEAD\r
7 long start;\r
8 long step;\r
9 long len;\r
10} rangeobject;\r
11\r
12/* Return number of items in range (lo, hi, step). step != 0\r
13 * required. The result always fits in an unsigned long.\r
14 */\r
15static unsigned long\r
16get_len_of_range(long lo, long hi, long step)\r
17{\r
18 /* -------------------------------------------------------------\r
19 If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.\r
20 Else for step > 0, if n values are in the range, the last one is\r
21 lo + (n-1)*step, which must be <= hi-1. Rearranging,\r
22 n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives\r
23 the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so\r
24 the RHS is non-negative and so truncation is the same as the\r
25 floor. Letting M be the largest positive long, the worst case\r
26 for the RHS numerator is hi=M, lo=-M-1, and then\r
27 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough\r
28 precision to compute the RHS exactly. The analysis for step < 0\r
29 is similar.\r
30 ---------------------------------------------------------------*/\r
31 assert(step != 0);\r
32 if (step > 0 && lo < hi)\r
33 return 1UL + (hi - 1UL - lo) / step;\r
34 else if (step < 0 && lo > hi)\r
35 return 1UL + (lo - 1UL - hi) / (0UL - step);\r
36 else\r
37 return 0UL;\r
38}\r
39\r
40static PyObject *\r
41range_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
42{\r
43 rangeobject *obj;\r
44 long ilow = 0, ihigh = 0, istep = 1;\r
45 unsigned long n;\r
46\r
47 if (!_PyArg_NoKeywords("xrange()", kw))\r
48 return NULL;\r
49\r
50 if (PyTuple_Size(args) <= 1) {\r
51 if (!PyArg_ParseTuple(args,\r
52 "l;xrange() requires 1-3 int arguments",\r
53 &ihigh))\r
54 return NULL;\r
55 }\r
56 else {\r
57 if (!PyArg_ParseTuple(args,\r
58 "ll|l;xrange() requires 1-3 int arguments",\r
59 &ilow, &ihigh, &istep))\r
60 return NULL;\r
61 }\r
62 if (istep == 0) {\r
63 PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero");\r
64 return NULL;\r
65 }\r
66 n = get_len_of_range(ilow, ihigh, istep);\r
67 if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) {\r
68 PyErr_SetString(PyExc_OverflowError,\r
69 "xrange() result has too many items");\r
70 return NULL;\r
71 }\r
72\r
73 obj = PyObject_New(rangeobject, &PyRange_Type);\r
74 if (obj == NULL)\r
75 return NULL;\r
76 obj->start = ilow;\r
77 obj->len = (long)n;\r
78 obj->step = istep;\r
79 return (PyObject *) obj;\r
80}\r
81\r
82PyDoc_STRVAR(range_doc,\r
83"xrange([start,] stop[, step]) -> xrange object\n\\r
84\n\\r
85Like range(), but instead of returning a list, returns an object that\n\\r
86generates the numbers in the range on demand. For looping, this is \n\\r
87slightly faster than range() and more memory efficient.");\r
88\r
89static PyObject *\r
90range_item(rangeobject *r, Py_ssize_t i)\r
91{\r
92 if (i < 0 || i >= r->len) {\r
93 PyErr_SetString(PyExc_IndexError,\r
94 "xrange object index out of range");\r
95 return NULL;\r
96 }\r
97 /* do calculation entirely using unsigned longs, to avoid\r
98 undefined behaviour due to signed overflow. */\r
99 return PyInt_FromLong((long)(r->start + (unsigned long)i * r->step));\r
100}\r
101\r
102static Py_ssize_t\r
103range_length(rangeobject *r)\r
104{\r
105 return (Py_ssize_t)(r->len);\r
106}\r
107\r
108static PyObject *\r
109range_repr(rangeobject *r)\r
110{\r
111 PyObject *rtn;\r
112\r
113 if (r->start == 0 && r->step == 1)\r
114 rtn = PyString_FromFormat("xrange(%ld)",\r
115 r->start + r->len * r->step);\r
116\r
117 else if (r->step == 1)\r
118 rtn = PyString_FromFormat("xrange(%ld, %ld)",\r
119 r->start,\r
120 r->start + r->len * r->step);\r
121\r
122 else\r
123 rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",\r
124 r->start,\r
125 r->start + r->len * r->step,\r
126 r->step);\r
127 return rtn;\r
128}\r
129\r
130/* Pickling support */\r
131static PyObject *\r
132range_reduce(rangeobject *r, PyObject *args)\r
133{\r
134 return Py_BuildValue("(O(iii))", Py_TYPE(r),\r
135 r->start,\r
136 r->start + r->len * r->step,\r
137 r->step);\r
138}\r
139\r
140static PySequenceMethods range_as_sequence = {\r
141 (lenfunc)range_length, /* sq_length */\r
142 0, /* sq_concat */\r
143 0, /* sq_repeat */\r
144 (ssizeargfunc)range_item, /* sq_item */\r
145 0, /* sq_slice */\r
146};\r
147\r
148static PyObject * range_iter(PyObject *seq);\r
149static PyObject * range_reverse(PyObject *seq);\r
150\r
151PyDoc_STRVAR(reverse_doc,\r
152"Returns a reverse iterator.");\r
153\r
154static PyMethodDef range_methods[] = {\r
155 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc},\r
156 {"__reduce__", (PyCFunction)range_reduce, METH_VARARGS},\r
157 {NULL, NULL} /* sentinel */\r
158};\r
159\r
160PyTypeObject PyRange_Type = {\r
161 PyObject_HEAD_INIT(&PyType_Type)\r
162 0, /* Number of items for varobject */\r
163 "xrange", /* Name of this type */\r
164 sizeof(rangeobject), /* Basic object size */\r
165 0, /* Item size for varobject */\r
166 (destructor)PyObject_Del, /* tp_dealloc */\r
167 0, /* tp_print */\r
168 0, /* tp_getattr */\r
169 0, /* tp_setattr */\r
170 0, /* tp_compare */\r
171 (reprfunc)range_repr, /* tp_repr */\r
172 0, /* tp_as_number */\r
173 &range_as_sequence, /* tp_as_sequence */\r
174 0, /* tp_as_mapping */\r
175 0, /* tp_hash */\r
176 0, /* tp_call */\r
177 0, /* tp_str */\r
178 PyObject_GenericGetAttr, /* tp_getattro */\r
179 0, /* tp_setattro */\r
180 0, /* tp_as_buffer */\r
181 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
182 range_doc, /* tp_doc */\r
183 0, /* tp_traverse */\r
184 0, /* tp_clear */\r
185 0, /* tp_richcompare */\r
186 0, /* tp_weaklistoffset */\r
187 range_iter, /* tp_iter */\r
188 0, /* tp_iternext */\r
189 range_methods, /* tp_methods */\r
190 0, /* tp_members */\r
191 0, /* tp_getset */\r
192 0, /* tp_base */\r
193 0, /* tp_dict */\r
194 0, /* tp_descr_get */\r
195 0, /* tp_descr_set */\r
196 0, /* tp_dictoffset */\r
197 0, /* tp_init */\r
198 0, /* tp_alloc */\r
199 range_new, /* tp_new */\r
200};\r
201\r
202/*********************** Xrange Iterator **************************/\r
203\r
204typedef struct {\r
205 PyObject_HEAD\r
206 long index;\r
207 long start;\r
208 long step;\r
209 long len;\r
210} rangeiterobject;\r
211\r
212static PyObject *\r
213rangeiter_next(rangeiterobject *r)\r
214{\r
215 if (r->index < r->len)\r
216 return PyInt_FromLong(r->start + (r->index++) * r->step);\r
217 return NULL;\r
218}\r
219\r
220static PyObject *\r
221rangeiter_len(rangeiterobject *r)\r
222{\r
223 return PyInt_FromLong(r->len - r->index);\r
224}\r
225\r
226PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
227\r
228static PyMethodDef rangeiter_methods[] = {\r
229 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc},\r
230 {NULL, NULL} /* sentinel */\r
231};\r
232\r
233static PyTypeObject Pyrangeiter_Type = {\r
234 PyObject_HEAD_INIT(&PyType_Type)\r
235 0, /* ob_size */\r
236 "rangeiterator", /* tp_name */\r
237 sizeof(rangeiterobject), /* tp_basicsize */\r
238 0, /* tp_itemsize */\r
239 /* methods */\r
240 (destructor)PyObject_Del, /* tp_dealloc */\r
241 0, /* tp_print */\r
242 0, /* tp_getattr */\r
243 0, /* tp_setattr */\r
244 0, /* tp_compare */\r
245 0, /* tp_repr */\r
246 0, /* tp_as_number */\r
247 0, /* tp_as_sequence */\r
248 0, /* tp_as_mapping */\r
249 0, /* tp_hash */\r
250 0, /* tp_call */\r
251 0, /* tp_str */\r
252 PyObject_GenericGetAttr, /* tp_getattro */\r
253 0, /* tp_setattro */\r
254 0, /* tp_as_buffer */\r
255 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
256 0, /* tp_doc */\r
257 0, /* tp_traverse */\r
258 0, /* tp_clear */\r
259 0, /* tp_richcompare */\r
260 0, /* tp_weaklistoffset */\r
261 PyObject_SelfIter, /* tp_iter */\r
262 (iternextfunc)rangeiter_next, /* tp_iternext */\r
263 rangeiter_methods, /* tp_methods */\r
264 0,\r
265};\r
266\r
267static PyObject *\r
268range_iter(PyObject *seq)\r
269{\r
270 rangeiterobject *it;\r
271\r
272 if (!PyRange_Check(seq)) {\r
273 PyErr_BadInternalCall();\r
274 return NULL;\r
275 }\r
276 it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);\r
277 if (it == NULL)\r
278 return NULL;\r
279 it->index = 0;\r
280 it->start = ((rangeobject *)seq)->start;\r
281 it->step = ((rangeobject *)seq)->step;\r
282 it->len = ((rangeobject *)seq)->len;\r
283 return (PyObject *)it;\r
284}\r
285\r
286static PyObject *\r
287range_reverse(PyObject *seq)\r
288{\r
289 rangeiterobject *it;\r
290 long start, step, len;\r
291\r
292 if (!PyRange_Check(seq)) {\r
293 PyErr_BadInternalCall();\r
294 return NULL;\r
295 }\r
296 it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);\r
297 if (it == NULL)\r
298 return NULL;\r
299\r
300 start = ((rangeobject *)seq)->start;\r
301 step = ((rangeobject *)seq)->step;\r
302 len = ((rangeobject *)seq)->len;\r
303\r
304 it->index = 0;\r
305 it->len = len;\r
306 /* the casts below guard against signed overflow by turning it\r
307 into unsigned overflow instead. The correctness of this\r
308 code still depends on conversion from unsigned long to long\r
309 wrapping modulo ULONG_MAX+1, which isn't guaranteed (see\r
310 C99 6.3.1.3p3) but seems to hold in practice for all\r
311 platforms we're likely to meet.\r
312\r
313 If step == LONG_MIN then we still end up with LONG_MIN\r
314 after negation; but this works out, since we've still got\r
315 the correct value modulo ULONG_MAX+1, and the range_item\r
316 calculation is also done modulo ULONG_MAX+1.\r
317 */\r
318 it->start = (long)(start + (unsigned long)(len-1) * step);\r
319 it->step = (long)(0UL-step);\r
320\r
321 return (PyObject *)it;\r
322}\r