-
-
Notifications
You must be signed in to change notification settings - Fork 31k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-28754: AC on bisect. #177
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,39 @@ Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru). | |
#define PY_SSIZE_T_CLEAN | ||
#include "Python.h" | ||
|
||
static int | ||
ssize_t_converter(PyObject *obj, void *ptr) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ssize_t_converter is not used for parsing arguments. It is used only in optional_ssize_t_converter. Wouldn't be better to inline it? |
||
{ | ||
Py_ssize_t val; | ||
|
||
val = PyLong_AsSsize_t(obj); | ||
if (val == -1 && PyErr_Occurred()) { | ||
return 0; | ||
} | ||
*(Py_ssize_t *)ptr = val; | ||
return 1; | ||
} | ||
|
||
static int | ||
optional_ssize_t_converter(PyObject *obj, void *ptr) | ||
{ | ||
if (obj != Py_None) { | ||
return ssize_t_converter(obj, ptr); | ||
} | ||
else { | ||
*(Py_ssize_t *)ptr = -1; | ||
return 1; | ||
} | ||
} | ||
|
||
|
||
#include "clinic/_bisectmodule.c.h" | ||
|
||
/*[clinic input] | ||
module bisect | ||
[clinic start generated code]*/ | ||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d0e256c42a9e4c13]*/ | ||
|
||
_Py_IDENTIFIER(insert); | ||
|
||
static Py_ssize_t | ||
|
@@ -44,56 +77,79 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t | |
return lo; | ||
} | ||
|
||
/*[python input] | ||
class hi_parameter_converter(CConverter): | ||
type = 'Py_ssize_t' | ||
converter = 'optional_ssize_t_converter' | ||
|
||
[python start generated code]*/ | ||
/*[python end generated code: output=da39a3ee5e6b4b0d input=53c711121eb30d3f]*/ | ||
|
||
|
||
/*[clinic input] | ||
bisect.bisect_right | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use the return converter for simplifying the code.
The body of
|
||
|
||
a: object | ||
x: object | ||
lo: Py_ssize_t(c_default='0') = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
hi: hi_parameter(c_default='-1') = None | ||
|
||
Return the index where to insert item x in list a, assuming a is sorted. | ||
|
||
The return value i is such that all e in a[:i] have e <= x, and all e in | ||
a[i:] have e > x. So if x already appears in the list, i points just | ||
beyond the rightmost x already there. | ||
|
||
Optional args lo (default 0) and hi (default len(a)) bound the | ||
slice of a to be searched. | ||
[clinic start generated code]*/ | ||
|
||
static PyObject * | ||
bisect_right(PyObject *self, PyObject *args, PyObject *kw) | ||
bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, | ||
Py_ssize_t lo, Py_ssize_t hi) | ||
/*[clinic end generated code: output=a2fb3e3261e46954 input=94e1e505e7f1ced8]*/ | ||
{ | ||
PyObject *list, *item; | ||
Py_ssize_t lo = 0; | ||
Py_ssize_t hi = -1; | ||
Py_ssize_t index; | ||
static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | ||
|
||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_right", | ||
keywords, &list, &item, &lo, &hi)) | ||
return NULL; | ||
index = internal_bisect_right(list, item, lo, hi); | ||
index = internal_bisect_right(a, x, lo, hi); | ||
if (index < 0) | ||
return NULL; | ||
return PyLong_FromSsize_t(index); | ||
} | ||
|
||
PyDoc_STRVAR(bisect_right_doc, | ||
"bisect_right(a, x[, lo[, hi]]) -> index\n\ | ||
\n\ | ||
Return the index where to insert item x in list a, assuming a is sorted.\n\ | ||
\n\ | ||
The return value i is such that all e in a[:i] have e <= x, and all e in\n\ | ||
a[i:] have e > x. So if x already appears in the list, i points just\n\ | ||
beyond the rightmost x already there\n\ | ||
\n\ | ||
Optional args lo (default 0) and hi (default len(a)) bound the\n\ | ||
slice of a to be searched.\n"); | ||
/*[clinic input] | ||
bisect.insort_right | ||
|
||
a: object | ||
x: object | ||
lo: Py_ssize_t(c_default='0') = 0 | ||
hi: hi_parameter(c_default='-1') = None | ||
|
||
Insert item x in list a, and keep it sorted assuming a is sorted. | ||
|
||
If x is already in a, insert it to the right of the rightmost x. | ||
|
||
Optional args lo (default 0) and hi (default len(a)) bound the | ||
slice of a to be searched. | ||
|
||
[clinic start generated code]*/ | ||
|
||
static PyObject * | ||
insort_right(PyObject *self, PyObject *args, PyObject *kw) | ||
bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, | ||
Py_ssize_t lo, Py_ssize_t hi) | ||
/*[clinic end generated code: output=6e0b99c731a11c1a input=6790b22da4643197]*/ | ||
{ | ||
PyObject *list, *item, *result; | ||
Py_ssize_t lo = 0; | ||
Py_ssize_t hi = -1; | ||
PyObject *result; | ||
Py_ssize_t index; | ||
static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | ||
|
||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_right", | ||
keywords, &list, &item, &lo, &hi)) | ||
return NULL; | ||
index = internal_bisect_right(list, item, lo, hi); | ||
index = internal_bisect_right(a, x, lo, hi); | ||
if (index < 0) | ||
return NULL; | ||
if (PyList_CheckExact(list)) { | ||
if (PyList_Insert(list, index, item) < 0) | ||
if (PyList_CheckExact(a)) { | ||
if (PyList_Insert(a, index, x) < 0) | ||
return NULL; | ||
} else { | ||
result = _PyObject_CallMethodId(list, &PyId_insert, "nO", index, item); | ||
result = _PyObject_CallMethodId(a, &PyId_insert, "nO", index, x); | ||
if (result == NULL) | ||
return NULL; | ||
Py_DECREF(result); | ||
|
@@ -102,16 +158,6 @@ insort_right(PyObject *self, PyObject *args, PyObject *kw) | |
Py_RETURN_NONE; | ||
} | ||
|
||
PyDoc_STRVAR(insort_right_doc, | ||
"insort_right(a, x[, lo[, hi]])\n\ | ||
\n\ | ||
Insert item x in list a, and keep it sorted assuming a is sorted.\n\ | ||
\n\ | ||
If x is already in a, insert it to the right of the rightmost x.\n\ | ||
\n\ | ||
Optional args lo (default 0) and hi (default len(a)) bound the\n\ | ||
slice of a to be searched.\n"); | ||
|
||
static Py_ssize_t | ||
internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi) | ||
{ | ||
|
@@ -148,56 +194,71 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h | |
return lo; | ||
} | ||
|
||
/*[clinic input] | ||
bisect.bisect_left | ||
|
||
a: object | ||
x: object | ||
lo: Py_ssize_t(c_default='0') = 0 | ||
hi: hi_parameter(c_default='-1') = None | ||
|
||
Return the index where to insert item x in list a, assuming a is sorted. | ||
|
||
The return value i is such that all e in a[:i] have e < x, and all e in | ||
a[i:] have e >= x. So if x already appears in the list, i points just | ||
before the leftmost x already there. | ||
|
||
Optional args lo (default 0) and hi (default len(a)) bound the | ||
slice of a to be searched. | ||
|
||
[clinic start generated code]*/ | ||
|
||
static PyObject * | ||
bisect_left(PyObject *self, PyObject *args, PyObject *kw) | ||
bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, | ||
Py_ssize_t lo, Py_ssize_t hi) | ||
/*[clinic end generated code: output=27a0228c4a0a5fa2 input=fc1e8f6081ccfd7c]*/ | ||
{ | ||
PyObject *list, *item; | ||
Py_ssize_t lo = 0; | ||
Py_ssize_t hi = -1; | ||
Py_ssize_t index; | ||
static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | ||
|
||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_left", | ||
keywords, &list, &item, &lo, &hi)) | ||
return NULL; | ||
index = internal_bisect_left(list, item, lo, hi); | ||
index = internal_bisect_left(a, x, lo, hi); | ||
if (index < 0) | ||
return NULL; | ||
return PyLong_FromSsize_t(index); | ||
} | ||
|
||
PyDoc_STRVAR(bisect_left_doc, | ||
"bisect_left(a, x[, lo[, hi]]) -> index\n\ | ||
\n\ | ||
Return the index where to insert item x in list a, assuming a is sorted.\n\ | ||
\n\ | ||
The return value i is such that all e in a[:i] have e < x, and all e in\n\ | ||
a[i:] have e >= x. So if x already appears in the list, i points just\n\ | ||
before the leftmost x already there.\n\ | ||
\n\ | ||
Optional args lo (default 0) and hi (default len(a)) bound the\n\ | ||
slice of a to be searched.\n"); | ||
/*[clinic input] | ||
bisect.insort_left | ||
|
||
a: object | ||
x: object | ||
lo: Py_ssize_t(c_default='0') = 0 | ||
hi: hi_parameter(c_default='-1') = None | ||
|
||
Insert item x in list a, and keep it sorted assuming a is sorted. | ||
|
||
If x is already in a, insert it to the left of the leftmost x. | ||
|
||
Optional args lo (default 0) and hi (default len(a)) bound the | ||
slice of a to be searched. | ||
|
||
[clinic start generated code]*/ | ||
|
||
static PyObject * | ||
insort_left(PyObject *self, PyObject *args, PyObject *kw) | ||
bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, | ||
Py_ssize_t lo, Py_ssize_t hi) | ||
/*[clinic end generated code: output=aa0228af6970ec52 input=582456c4727c5716]*/ | ||
{ | ||
PyObject *list, *item, *result; | ||
Py_ssize_t lo = 0; | ||
Py_ssize_t hi = -1; | ||
PyObject *result; | ||
Py_ssize_t index; | ||
static char *keywords[] = {"a", "x", "lo", "hi", NULL}; | ||
|
||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_left", | ||
keywords, &list, &item, &lo, &hi)) | ||
return NULL; | ||
index = internal_bisect_left(list, item, lo, hi); | ||
index = internal_bisect_left(a, x, lo, hi); | ||
if (index < 0) | ||
return NULL; | ||
if (PyList_CheckExact(list)) { | ||
if (PyList_Insert(list, index, item) < 0) | ||
if (PyList_CheckExact(a)) { | ||
if (PyList_Insert(a, index, x) < 0) | ||
return NULL; | ||
} else { | ||
result = _PyObject_CallMethodId(list, &PyId_insert, "nO", index, item); | ||
result = _PyObject_CallMethodId(a, &PyId_insert, "nO", index, x); | ||
if (result == NULL) | ||
return NULL; | ||
Py_DECREF(result); | ||
|
@@ -206,25 +267,11 @@ insort_left(PyObject *self, PyObject *args, PyObject *kw) | |
Py_RETURN_NONE; | ||
} | ||
|
||
PyDoc_STRVAR(insort_left_doc, | ||
"insort_left(a, x[, lo[, hi]])\n\ | ||
\n\ | ||
Insert item x in list a, and keep it sorted assuming a is sorted.\n\ | ||
\n\ | ||
If x is already in a, insert it to the left of the leftmost x.\n\ | ||
\n\ | ||
Optional args lo (default 0) and hi (default len(a)) bound the\n\ | ||
slice of a to be searched.\n"); | ||
|
||
static PyMethodDef bisect_methods[] = { | ||
{"bisect_right", (PyCFunction)bisect_right, | ||
METH_VARARGS|METH_KEYWORDS, bisect_right_doc}, | ||
{"insort_right", (PyCFunction)insort_right, | ||
METH_VARARGS|METH_KEYWORDS, insort_right_doc}, | ||
{"bisect_left", (PyCFunction)bisect_left, | ||
METH_VARARGS|METH_KEYWORDS, bisect_left_doc}, | ||
{"insort_left", (PyCFunction)insort_left, | ||
METH_VARARGS|METH_KEYWORDS, insort_left_doc}, | ||
BISECT_BISECT_RIGHT_METHODDEF | ||
BISECT_INSORT_RIGHT_METHODDEF | ||
BISECT_BISECT_LEFT_METHODDEF | ||
BISECT_INSORT_LEFT_METHODDEF | ||
{NULL, NULL} /* sentinel */ | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't check that passing
-1
andNone
is the same as not specifying the hi argument. Compare results withfunc(data, elem)
.