/* Set new unique item at `i` index in LDAPValueList to `newitem`. Case-insensitive, the `newitem` is also appended to the added list, or remove from the deleted list. Same goes for the replaced item. */ int LDAPValueList_SetItem(LDAPValueList *self, Py_ssize_t i, PyObject *newitem) { int rc = -1; PyObject *olditem; if (UniqueList_SetItem((UniqueList *)self, i, newitem) != 0) return -1; olditem = PyList_GetItem((PyObject *)self, i); if (olditem == NULL) return -1; rc = UniqueList_Remove_wFlg(self->added, olditem); if (rc == -1) return -1; if (rc == 0) { if (UniqueList_Append(self->deleted, olditem) == -1) { PyErr_BadInternalCall(); return -1; } } rc = UniqueList_Remove_wFlg(self->deleted, newitem); if (rc == -1) return -1; if (rc == 0) { if (UniqueList_Append(self->added, newitem) == -1) { PyErr_BadInternalCall(); return -1; } } return 0; }
static int UL_ass_item(UniqueList *self, Py_ssize_t i, PyObject *v) { if (i < 0 || i >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); return -1; } if (v == NULL) return UniqueList_SetSlice(self, i, i+1, v); return UniqueList_SetItem(self, i, v); }
/* This function is based on list_ass_subscript from Python source listobject.c. But it uses UniqueList's setslice and setitem functions instead of memory opertation. It is probably a much more slower, but cleaner (easier) solution. */ static int UL_ass_subscript(UniqueList *self, PyObject *item, PyObject *value) { size_t cur; Py_ssize_t i; Py_ssize_t start, stop, step, slicelength; PyObject *seq; PyObject **seqitems; if (PyIndex_Check(item)) { i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return -1; if (i < 0) i += PyList_GET_SIZE(self); return UL_ass_item(self, i, value); } else if (PySlice_Check(item)) { if (PySlice_GetIndicesEx(item, Py_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return -1; } if (step == 1) return UniqueList_SetSlice(self, start, stop, value); /* Make sure s[5:2] = [..] inserts at the right place: before 5, not before 2. */ if ((step < 0 && start < stop) || (step > 0 && start > stop)) { stop = start; } if (value == NULL) { /* delete slice */ if (slicelength <= 0) return 0; if (step < 0) { stop = start + 1; start = stop + step*(slicelength - 1) - 1; step = -step; } for (cur = start, i = 0; cur < (size_t)stop; cur += step, i++) { if (UniqueList_SetSlice(self, cur-i, cur+1-i, (PyObject *)NULL) != 0) { return -1; } } return 0; } else { /* assign slice */ /* protect against a[::-1] = a */ if (self == (UniqueList *)value) { seq = PyList_GetSlice(value, 0, PyList_GET_SIZE(value)); } else { seq = PySequence_Fast(value, "must assign iterable to extended slice"); } if (!seq) return -1; if (PySequence_Fast_GET_SIZE(seq) != slicelength) { PyErr_Format(PyExc_ValueError, "attempt to assign sequence of size %zd to extended slice of " "size %zd", PySequence_Fast_GET_SIZE(seq), slicelength); Py_DECREF(seq); return -1; } if (!slicelength) { Py_DECREF(seq); return 0; } seqitems = PySequence_Fast_ITEMS(seq); for (cur = start, i = 0; i < slicelength; cur += (size_t)step, i++) { if (UniqueList_SetItem(self, cur, seqitems[i]) != 0) { return -1; } } Py_DECREF(seq); return 0; } } else { PyErr_Format(PyExc_TypeError, "list indices must be integers, not %.200s", item->ob_type->tp_name); return -1; } }