1472 static PyObject *
1473 BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
1474 {
when considering range: -128 <= value <= 1
taking False path
1475 PyObject *min = Py_None;
1476 PyObject *max = Py_None;
1477 int excludemin = 0;
1478 int excludemax = 0;
1479 int rc;
1480 Bucket *lowbucket = NULL;
1481 Bucket *highbucket = NULL;
1482 int lowoffset;
1483 int highoffset;
1484 PyObject *result;
1485
1486 if (args) {
taking True path
1487 if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
when PyArg_ParseTupleAndKeywords() succeeds
taking False path
1488 &min,
1489 &max,
1490 &excludemin,
1491 &excludemax))
1492 return NULL;
1493 }
1494
1495 UNLESS (PER_USE(self)) return NULL;
when considering range: -128 <= value <= -2
taking True path
when considering range: -128 <= value <= -1
taking False path
taking False path
1496
1497 UNLESS (self->data && self->len) goto empty;
when treating unknown struct BTreeItem * from src/BTrees/BTreeTemplate.c:1497 as non-NULL
taking False path
when considering range: -0x80000000 <= value <= -1
taking False path
1498
1499 /* Find the low range */
1500 if (min != Py_None) {
taking True path
1501 if ((rc = BTree_findRangeEnd(self, min, 1, excludemin,
when considering range: 1 <= value <= 0x7fffffff
taking False path
1502 &lowbucket, &lowoffset)) <= 0) {
1503 if (rc < 0) goto err;
1504 goto empty;
1505 }
1506 }
1507 else {
1508 lowbucket = self->firstbucket;
1509 lowoffset = 0;
1510 if (excludemin) {
1511 int bucketlen;
1512 UNLESS (PER_USE(lowbucket)) goto err;
1513 bucketlen = lowbucket->len;
1514 PER_UNUSE(lowbucket);
1515 if (bucketlen > 1)
1516 lowoffset = 1;
1517 else if (self->len < 2)
1518 goto empty;
1519 else { /* move to first item in next bucket */
1520 Bucket *next;
1521 UNLESS (PER_USE(lowbucket)) goto err;
1522 next = lowbucket->next;
1523 PER_UNUSE(lowbucket);
1524 assert(next != NULL);
1525 lowbucket = next;
1526 /* and lowoffset is still 0 */
1527 assert(lowoffset == 0);
1528 }
1529 }
1530 Py_INCREF(lowbucket);
1531 }
1532
1533 /* Find the high range */
1534 if (max != Py_None) {
taking True path
1535 if ((rc = BTree_findRangeEnd(self, max, 0, excludemax,
when considering range: -0x80000000 <= value <= 0
taking True path
1536 &highbucket, &highoffset)) <= 0) {
1537 Py_DECREF(lowbucket);
when treating unknown struct Bucket * * from src/BTrees/BTreeTemplate.c:1501 as non-NULL
when considering value == (Py_ssize_t)0 from src/BTrees/BTreeTemplate.c:1537
taking False path
when treating unknown struct _typeobject * from src/BTrees/BTreeTemplate.c:1537 as non-NULL
calling unknown void (*destructor) (struct PyObject *) from src/BTrees/BTreeTemplate.c:1537
1538 if (rc < 0) goto err;
when considering range: -0x80000000 <= value <= -1
taking True path
1539 goto empty;
1540 }
1541 }
1542 else {
1543 int bucketlen;
1544 highbucket = BTree_lastBucket(self);
1545 assert(highbucket != NULL); /* we know self isn't empty */
1546 UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
1547 bucketlen = highbucket->len;
1548 PER_UNUSE(highbucket);
1549 highoffset = bucketlen - 1;
1550 if (excludemax) {
1551 if (highoffset > 0)
1552 --highoffset;
1553 else if (self->len < 2)
1554 goto empty_and_decref_buckets;
1555 else { /* move to last item of preceding bucket */
1556 int status;
1557 assert(highbucket != self->firstbucket);
1558 Py_DECREF(highbucket);
1559 status = PreviousBucket(&highbucket, self->firstbucket);
1560 if (status < 0) {
1561 Py_DECREF(lowbucket);
1562 goto err;
1563 }
1564 assert(status > 0);
1565 Py_INCREF(highbucket);
1566 UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
1567 highoffset = highbucket->len - 1;
1568 PER_UNUSE(highbucket);
1569 }
1570 }
1571 assert(highoffset >= 0);
1572 }
1573
1574 /* It's still possible that the range is empty, even if min < max. For
1575 * example, if min=3 and max=4, and 3 and 4 aren't in the BTree, but 2 and
1576 * 5 are, then the low position points to the 5 now and the high position
1577 * points to the 2 now. They're not necessarily even in the same bucket,
1578 * so there's no trick we can play with pointer compares to get out
1579 * cheap in general.
1580 */
1581 if (lowbucket == highbucket && lowoffset > highoffset)
1582 goto empty_and_decref_buckets; /* definitely empty */
1583
1584 /* The buckets differ, or they're the same and the offsets show a non-
1585 * empty range.
1586 */
1587 if (min != Py_None && max != Py_None && /* both args user-supplied */
1588 lowbucket != highbucket) /* and different buckets */ {
1589 KEY_TYPE first;
1590 KEY_TYPE last;
1591 int cmp;
1592
1593 /* Have to check the hard way: see how the endpoints compare. */
1594 UNLESS (PER_USE(lowbucket)) goto err_and_decref_buckets;
1595 COPY_KEY(first, lowbucket->keys[lowoffset]);
1596 PER_UNUSE(lowbucket);
1597
1598 UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
1599 COPY_KEY(last, highbucket->keys[highoffset]);
1600 PER_UNUSE(highbucket);
1601
1602 TEST_KEY_SET_OR(cmp, first, last) goto err_and_decref_buckets;
1603 if (cmp > 0) goto empty_and_decref_buckets;
1604 }
1605
1606 PER_UNUSE(self);
1607
1608 result = newBTreeItems(type, lowbucket, lowoffset, highbucket, highoffset);
1609 Py_DECREF(lowbucket);
1610 Py_DECREF(highbucket);
1611 return result;
1612
1613 err_and_decref_buckets:
1614 Py_DECREF(lowbucket);
1615 Py_DECREF(highbucket);
1616
1617 err:
1618 PER_UNUSE(self);
when treating unknown struct cPersistenceCAPIstruct * from src/persistent/cPersistence.h:112 as non-NULL
calling unknown void (*) (struct cPersistentObject *) from src/BTrees/BTreeTemplate.c:1618
1619 return NULL;
1620
1621 empty_and_decref_buckets:
1622 Py_DECREF(lowbucket);
1623 Py_DECREF(highbucket);
1624
1625 empty:
1626 PER_UNUSE(self);
1627 return newBTreeItems(type, 0, 0, 0, 0);
1628 }
returning (PyObject*)NULL without setting an exception
found 7 similar trace(s) to this