1 /* 2 Written by Jim Hugunin and Chris Chase. 3 4 This includes both the singular ellipsis object and slice objects. 5 6 Guido, feel free to do whatever you want in the way of copyrights 7 for this file. 8 */ 9 10 /* 11 Py_Ellipsis encodes the '...' rubber index token. It is similar to 12 the Py_NoneStruct in that there is no way to create other objects of 13 this type and there is exactly one in existence. 14 */ 15 16 #include "Python.h" 17 #include "structmember.h" 18 19 static PyObject * 20 ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 21 { 22 if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { 23 PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments"); 24 return NULL; 25 } 26 Py_INCREF(Py_Ellipsis); 27 return Py_Ellipsis; 28 } 29 30 static PyObject * 31 ellipsis_repr(PyObject *op) 32 { 33 return PyUnicode_FromString("Ellipsis"); 34 } 35 36 static PyObject * 37 ellipsis_reduce(PyObject *op) 38 { 39 return PyUnicode_FromString("Ellipsis"); 40 } 41 42 static PyMethodDef ellipsis_methods[] = { 43 {"__reduce__", (PyCFunction)ellipsis_reduce, METH_NOARGS, NULL}, 44 {NULL, NULL} 45 }; 46 47 PyTypeObject PyEllipsis_Type = { 48 PyVarObject_HEAD_INIT(&PyType_Type, 0) 49 "ellipsis", /* tp_name */ 50 0, /* tp_basicsize */ 51 0, /* tp_itemsize */ 52 0, /*never called*/ /* tp_dealloc */ 53 0, /* tp_print */ 54 0, /* tp_getattr */ 55 0, /* tp_setattr */ 56 0, /* tp_reserved */ 57 ellipsis_repr, /* tp_repr */ 58 0, /* tp_as_number */ 59 0, /* tp_as_sequence */ 60 0, /* tp_as_mapping */ 61 0, /* tp_hash */ 62 0, /* tp_call */ 63 0, /* tp_str */ 64 PyObject_GenericGetAttr, /* tp_getattro */ 65 0, /* tp_setattro */ 66 0, /* tp_as_buffer */ 67 Py_TPFLAGS_DEFAULT, /* tp_flags */ 68 0, /* tp_doc */ 69 0, /* tp_traverse */ 70 0, /* tp_clear */ 71 0, /* tp_richcompare */ 72 0, /* tp_weaklistoffset */ 73 0, /* tp_iter */ 74 0, /* tp_iternext */ 75 ellipsis_methods, /* tp_methods */ 76 0, /* tp_members */ 77 0, /* tp_getset */ 78 0, /* tp_base */ 79 0, /* tp_dict */ 80 0, /* tp_descr_get */ 81 0, /* tp_descr_set */ 82 0, /* tp_dictoffset */ 83 0, /* tp_init */ 84 0, /* tp_alloc */ 85 ellipsis_new, /* tp_new */ 86 }; 87 88 PyObject _Py_EllipsisObject = { 89 _PyObject_EXTRA_INIT 90 1, &PyEllipsis_Type 91 }; 92 93 94 /* Slice object implementation */ 95 96 /* Using a cache is very effective since typically only a single slice is 97 * created and then deleted again 98 */ 99 static PySliceObject *slice_cache = NULL; 100 void PySlice_Fini(void) 101 { 102 PySliceObject *obj = slice_cache; 103 if (obj != NULL) { 104 slice_cache = NULL; 105 PyObject_GC_Del(obj); 106 } 107 } 108 109 /* start, stop, and step are python objects with None indicating no 110 index is present. 111 */ 112 113 PyObject * 114 PySlice_New(PyObject *start, PyObject *stop, PyObject *step) 115 { 116 PySliceObject *obj; 117 if (slice_cache != NULL) { 118 obj = slice_cache; 119 slice_cache = NULL; 120 _Py_NewReference((PyObject *)obj); 121 } else { 122 obj = PyObject_GC_New(PySliceObject, &PySlice_Type); 123 if (obj == NULL) 124 return NULL; 125 } 126 127 if (step == NULL) step = Py_None; 128 Py_INCREF(step); 129 if (start == NULL) start = Py_None; 130 Py_INCREF(start); 131 if (stop == NULL) stop = Py_None; 132 Py_INCREF(stop); 133 134 obj->step = step; 135 obj->start = start; 136 obj->stop = stop; 137 138 _PyObject_GC_TRACK(obj); 139 return (PyObject *) obj; 140 } 141 142 PyObject * 143 _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) 144 { 145 PyObject *start, *end, *slice; 146 start = PyLong_FromSsize_t(istart); 147 if (!start) 148 return NULL; 149 end = PyLong_FromSsize_t(istop); 150 if (!end) { 151 Py_DECREF(start); 152 return NULL; 153 } 154 155 slice = PySlice_New(start, end, NULL); 156 Py_DECREF(start); 157 Py_DECREF(end); 158 return slice; 159 } 160 161 int 162 PySlice_GetIndices(PyObject *_r, Py_ssize_t length, 163 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) 164 { 165 PySliceObject *r = (PySliceObject*)_r; 166 /* XXX support long ints */ 167 if (r->step == Py_None) { 168 *step = 1; 169 } else { 170 if (!PyLong_Check(r->step)) return -1; 171 *step = PyLong_AsSsize_t(r->step); 172 } 173 if (r->start == Py_None) { 174 *start = *step < 0 ? length-1 : 0; 175 } else { 176 if (!PyLong_Check(r->start)) return -1; 177 *start = PyLong_AsSsize_t(r->start); 178 if (*start < 0) *start += length; 179 } 180 if (r->stop == Py_None) { 181 *stop = *step < 0 ? -1 : length; 182 } else { 183 if (!PyLong_Check(r->stop)) return -1; 184 *stop = PyLong_AsSsize_t(r->stop); 185 if (*stop < 0) *stop += length; 186 } 187 if (*stop > length) return -1; 188 if (*start >= length) return -1; 189 if (*step == 0) return -1; 190 return 0; 191 } 192 193 int 194 PySlice_Unpack(PyObject *_r, 195 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) 196 { 197 PySliceObject *r = (PySliceObject*)_r; 198 /* this is harder to get right than you might think */ 199 200 if (r->step == Py_None) { 201 *step = 1; 202 } 203 else { 204 if (!_PyEval_SliceIndex(r->step, step)) return -1; 205 if (*step == 0) { 206 PyErr_SetString(PyExc_ValueError, 207 "slice step cannot be zero"); 208 return -1; 209 } 210 /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it 211 * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it 212 * guards against later undefined behaviour resulting from code that 213 * does "step = -step" as part of a slice reversal. 214 */ 215 if (*step < -PY_SSIZE_T_MAX) 216 *step = -PY_SSIZE_T_MAX; 217 } 218 219 if (r->start == Py_None) { 220 *start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;; 221 } 222 else { 223 if (!_PyEval_SliceIndex(r->start, start)) return -1; 224 } 225 226 if (r->stop == Py_None) { 227 *stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX; 228 } 229 else { 230 if (!_PyEval_SliceIndex(r->stop, stop)) return -1; 231 } 232 233 return 0; 234 } 235 236 Py_ssize_t 237 PySlice_AdjustIndices(Py_ssize_t length, 238 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step) 239 { 240 /* this is harder to get right than you might think */ 241 242 assert(step != 0); 243 assert(step >= -PY_SSIZE_T_MAX); 244 245 if (*start < 0) { 246 *start += length; 247 if (*start < 0) { 248 *start = (step < 0) ? -1 : 0; 249 } 250 } 251 else if (*start >= length) { 252 *start = (step < 0) ? length - 1 : length; 253 } 254 255 if (*stop < 0) { 256 *stop += length; 257 if (*stop < 0) { 258 *stop = (step < 0) ? -1 : 0; 259 } 260 } 261 else if (*stop >= length) { 262 *stop = (step < 0) ? length - 1 : length; 263 } 264 265 if (step < 0) { 266 if (*stop < *start) { 267 return (*start - *stop - 1) / (-step) + 1; 268 } 269 } 270 else { 271 if (*start < *stop) { 272 return (*stop - *start - 1) / step + 1; 273 } 274 } 275 return 0; 276 } 277 278 #undef PySlice_GetIndicesEx 279 280 int 281 PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length, 282 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, 283 Py_ssize_t *slicelength) 284 { 285 if (PySlice_Unpack(_r, start, stop, step) < 0) 286 return -1; 287 *slicelength = PySlice_AdjustIndices(length, start, stop, *step); 288 return 0; 289 } 290 291 static PyObject * 292 slice_new(PyTypeObject *type, PyObject *args, PyObject *kw) 293 { 294 PyObject *start, *stop, *step; 295 296 start = stop = step = NULL; 297 298 if (!_PyArg_NoKeywords("slice()", kw)) 299 return NULL; 300 301 if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step)) 302 return NULL; 303 304 /* This swapping of stop and start is to maintain similarity with 305 range(). */ 306 if (stop == NULL) { 307 stop = start; 308 start = NULL; 309 } 310 return PySlice_New(start, stop, step); 311 } 312 313 PyDoc_STRVAR(slice_doc, 314 "slice(stop)\n\ 315 slice(start, stop[, step])\n\ 316 \n\ 317 Create a slice object. This is used for extended slicing (e.g. a[0:10:2])."); 318 319 static void 320 slice_dealloc(PySliceObject *r) 321 { 322 _PyObject_GC_UNTRACK(r); 323 Py_DECREF(r->step); 324 Py_DECREF(r->start); 325 Py_DECREF(r->stop); 326 if (slice_cache == NULL) 327 slice_cache = r; 328 else 329 PyObject_GC_Del(r); 330 } 331 332 static PyObject * 333 slice_repr(PySliceObject *r) 334 { 335 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step); 336 } 337 338 static PyMemberDef slice_members[] = { 339 {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY}, 340 {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY}, 341 {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY}, 342 {0} 343 }; 344 345 /* Helper function to convert a slice argument to a PyLong, and raise TypeError 346 with a suitable message on failure. */ 347 348 static PyObject* 349 evaluate_slice_index(PyObject *v) 350 { 351 if (PyIndex_Check(v)) { 352 return PyNumber_Index(v); 353 } 354 else { 355 PyErr_SetString(PyExc_TypeError, 356 "slice indices must be integers or " 357 "None or have an __index__ method"); 358 return NULL; 359 } 360 } 361 362 /* Compute slice indices given a slice and length. Return -1 on failure. Used 363 by slice.indices and rangeobject slicing. Assumes that `len` is a 364 nonnegative instance of PyLong. */ 365 366 int 367 _PySlice_GetLongIndices(PySliceObject *self, PyObject *length, 368 PyObject **start_ptr, PyObject **stop_ptr, 369 PyObject **step_ptr) 370 { 371 PyObject *start=NULL, *stop=NULL, *step=NULL; 372 PyObject *upper=NULL, *lower=NULL; 373 int step_is_negative, cmp_result; 374 375 /* Convert step to an integer; raise for zero step. */ 376 if (self->step == Py_None) { 377 step = PyLong_FromLong(1L); 378 if (step == NULL) 379 goto error; 380 step_is_negative = 0; 381 } 382 else { 383 int step_sign; 384 step = evaluate_slice_index(self->step); 385 if (step == NULL) 386 goto error; 387 step_sign = _PyLong_Sign(step); 388 if (step_sign == 0) { 389 PyErr_SetString(PyExc_ValueError, 390 "slice step cannot be zero"); 391 goto error; 392 } 393 step_is_negative = step_sign < 0; 394 } 395 396 /* Find lower and upper bounds for start and stop. */ 397 if (step_is_negative) { 398 lower = PyLong_FromLong(-1L); 399 if (lower == NULL) 400 goto error; 401 402 upper = PyNumber_Add(length, lower); 403 if (upper == NULL) 404 goto error; 405 } 406 else { 407 lower = PyLong_FromLong(0L); 408 if (lower == NULL) 409 goto error; 410 411 upper = length; 412 Py_INCREF(upper); 413 } 414 415 /* Compute start. */ 416 if (self->start == Py_None) { 417 start = step_is_negative ? upper : lower; 418 Py_INCREF(start); 419 } 420 else { 421 start = evaluate_slice_index(self->start); 422 if (start == NULL) 423 goto error; 424 425 if (_PyLong_Sign(start) < 0) { 426 /* start += length */ 427 PyObject *tmp = PyNumber_Add(start, length); 428 Py_DECREF(start); 429 start = tmp; 430 if (start == NULL) 431 goto error; 432 433 cmp_result = PyObject_RichCompareBool(start, lower, Py_LT); 434 if (cmp_result < 0) 435 goto error; 436 if (cmp_result) { 437 Py_INCREF(lower); 438 Py_DECREF(start); 439 start = lower; 440 } 441 } 442 else { 443 cmp_result = PyObject_RichCompareBool(start, upper, Py_GT); 444 if (cmp_result < 0) 445 goto error; 446 if (cmp_result) { 447 Py_INCREF(upper); 448 Py_DECREF(start); 449 start = upper; 450 } 451 } 452 } 453 454 /* Compute stop. */ 455 if (self->stop == Py_None) { 456 stop = step_is_negative ? lower : upper; 457 Py_INCREF(stop); 458 } 459 else { 460 stop = evaluate_slice_index(self->stop); 461 if (stop == NULL) 462 goto error; 463 464 if (_PyLong_Sign(stop) < 0) { 465 /* stop += length */ 466 PyObject *tmp = PyNumber_Add(stop, length); 467 Py_DECREF(stop); 468 stop = tmp; 469 if (stop == NULL) 470 goto error; 471 472 cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT); 473 if (cmp_result < 0) 474 goto error; 475 if (cmp_result) { 476 Py_INCREF(lower); 477 Py_DECREF(stop); 478 stop = lower; 479 } 480 } 481 else { 482 cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT); 483 if (cmp_result < 0) 484 goto error; 485 if (cmp_result) { 486 Py_INCREF(upper); 487 Py_DECREF(stop); 488 stop = upper; 489 } 490 } 491 } 492 493 *start_ptr = start; 494 *stop_ptr = stop; 495 *step_ptr = step; 496 Py_DECREF(upper); 497 Py_DECREF(lower); 498 return 0; 499 500 error: 501 *start_ptr = *stop_ptr = *step_ptr = NULL; 502 Py_XDECREF(start); 503 Py_XDECREF(stop); 504 Py_XDECREF(step); 505 Py_XDECREF(upper); 506 Py_XDECREF(lower); 507 return -1; 508 } 509 510 /* Implementation of slice.indices. */ 511 512 static PyObject* 513 slice_indices(PySliceObject* self, PyObject* len) 514 { 515 PyObject *start, *stop, *step; 516 PyObject *length; 517 int error; 518 519 /* Convert length to an integer if necessary; raise for negative length. */ 520 length = PyNumber_Index(len); 521 if (length == NULL) 522 return NULL; 523 524 if (_PyLong_Sign(length) < 0) { 525 PyErr_SetString(PyExc_ValueError, 526 "length should not be negative"); 527 Py_DECREF(length); 528 return NULL; 529 } 530 531 error = _PySlice_GetLongIndices(self, length, &start, &stop, &step); 532 Py_DECREF(length); 533 if (error == -1) 534 return NULL; 535 else 536 return Py_BuildValue("(NNN)", start, stop, step); 537 } 538 539 PyDoc_STRVAR(slice_indices_doc, 540 "S.indices(len) -> (start, stop, stride)\n\ 541 \n\ 542 Assuming a sequence of length len, calculate the start and stop\n\ 543 indices, and the stride length of the extended slice described by\n\ 544 S. Out of bounds indices are clipped in a manner consistent with the\n\ 545 handling of normal slices."); 546 547 static PyObject * 548 slice_reduce(PySliceObject* self) 549 { 550 return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step); 551 } 552 553 PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); 554 555 static PyMethodDef slice_methods[] = { 556 {"indices", (PyCFunction)slice_indices, 557 METH_O, slice_indices_doc}, 558 {"__reduce__", (PyCFunction)slice_reduce, 559 METH_NOARGS, reduce_doc}, 560 {NULL, NULL} 561 }; 562 563 static PyObject * 564 slice_richcompare(PyObject *v, PyObject *w, int op) 565 { 566 PyObject *t1; 567 PyObject *t2; 568 PyObject *res; 569 570 if (!PySlice_Check(v) || !PySlice_Check(w)) 571 Py_RETURN_NOTIMPLEMENTED; 572 573 if (v == w) { 574 /* XXX Do we really need this shortcut? 575 There's a unit test for it, but is that fair? */ 576 switch (op) { 577 case Py_EQ: 578 case Py_LE: 579 case Py_GE: 580 res = Py_True; 581 break; 582 default: 583 res = Py_False; 584 break; 585 } 586 Py_INCREF(res); 587 return res; 588 } 589 590 t1 = PyTuple_New(3); 591 if (t1 == NULL) 592 return NULL; 593 t2 = PyTuple_New(3); 594 if (t2 == NULL) { 595 Py_DECREF(t1); 596 return NULL; 597 } 598 599 PyTuple_SET_ITEM(t1, 0, ((PySliceObject *)v)->start); 600 PyTuple_SET_ITEM(t1, 1, ((PySliceObject *)v)->stop); 601 PyTuple_SET_ITEM(t1, 2, ((PySliceObject *)v)->step); 602 PyTuple_SET_ITEM(t2, 0, ((PySliceObject *)w)->start); 603 PyTuple_SET_ITEM(t2, 1, ((PySliceObject *)w)->stop); 604 PyTuple_SET_ITEM(t2, 2, ((PySliceObject *)w)->step); 605 606 res = PyObject_RichCompare(t1, t2, op); 607 608 PyTuple_SET_ITEM(t1, 0, NULL); 609 PyTuple_SET_ITEM(t1, 1, NULL); 610 PyTuple_SET_ITEM(t1, 2, NULL); 611 PyTuple_SET_ITEM(t2, 0, NULL); 612 PyTuple_SET_ITEM(t2, 1, NULL); 613 PyTuple_SET_ITEM(t2, 2, NULL); 614 615 Py_DECREF(t1); 616 Py_DECREF(t2); 617 618 return res; 619 } 620 621 static int 622 slice_traverse(PySliceObject *v, visitproc visit, void *arg) 623 { 624 Py_VISIT(v->start); 625 Py_VISIT(v->stop); 626 Py_VISIT(v->step); 627 return 0; 628 } 629 630 PyTypeObject PySlice_Type = { 631 PyVarObject_HEAD_INIT(&PyType_Type, 0) 632 "slice", /* Name of this type */ 633 sizeof(PySliceObject), /* Basic object size */ 634 0, /* Item size for varobject */ 635 (destructor)slice_dealloc, /* tp_dealloc */ 636 0, /* tp_print */ 637 0, /* tp_getattr */ 638 0, /* tp_setattr */ 639 0, /* tp_reserved */ 640 (reprfunc)slice_repr, /* tp_repr */ 641 0, /* tp_as_number */ 642 0, /* tp_as_sequence */ 643 0, /* tp_as_mapping */ 644 PyObject_HashNotImplemented, /* tp_hash */ 645 0, /* tp_call */ 646 0, /* tp_str */ 647 PyObject_GenericGetAttr, /* tp_getattro */ 648 0, /* tp_setattro */ 649 0, /* tp_as_buffer */ 650 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 651 slice_doc, /* tp_doc */ 652 (traverseproc)slice_traverse, /* tp_traverse */ 653 0, /* tp_clear */ 654 slice_richcompare, /* tp_richcompare */ 655 0, /* tp_weaklistoffset */ 656 0, /* tp_iter */ 657 0, /* tp_iternext */ 658 slice_methods, /* tp_methods */ 659 slice_members, /* tp_members */ 660 0, /* tp_getset */ 661 0, /* tp_base */ 662 0, /* tp_dict */ 663 0, /* tp_descr_get */ 664 0, /* tp_descr_set */ 665 0, /* tp_dictoffset */ 666 0, /* tp_init */ 667 0, /* tp_alloc */ 668 slice_new, /* tp_new */ 669 }; 670