static PyObject* Row_repr(PyObject* o) { Row* self = (Row*)o; if (self->cValues == 0) return PyString_FromString("()"); Object pieces(PyTuple_New(self->cValues)); if (!pieces) return 0; Py_ssize_t length = 2 + (2 * (self->cValues-1)); // parens + ', ' separators for (Py_ssize_t i = 0; i < self->cValues; i++) { PyObject* piece = PyObject_Repr(self->apValues[i]); if (!piece) return 0; length += Text_Size(piece); PyTuple_SET_ITEM(pieces.Get(), i, piece); } if (self->cValues == 1) { // Need a trailing comma: (value,) length += 2; } PyObject* result = Text_New(length); if (!result) return 0; TEXT_T* buffer = Text_Buffer(result); Py_ssize_t offset = 0; buffer[offset++] = '('; for (Py_ssize_t i = 0; i < self->cValues; i++) { PyObject* item = PyTuple_GET_ITEM(pieces.Get(), i); memcpy(&buffer[offset], Text_Buffer(item), Text_Size(item) * sizeof(TEXT_T)); offset += Text_Size(item); if (i != self->cValues-1 || self->cValues == 1) { buffer[offset++] = ','; buffer[offset++] = ' '; } } buffer[offset++] = ')'; I(offset == length); return result; }
static PyObject *py_sorted_tree_items(PyObject *self, PyObject *args) { struct tree_item *qsort_entries = NULL; int name_order, num_entries, n = 0, i; PyObject *entries, *py_name_order, *ret, *key, *value, *py_mode, *py_sha; Py_ssize_t pos = 0; int (*cmp)(const void *, const void *); if (!PyArg_ParseTuple(args, "OO", &entries, &py_name_order)) goto error; if (!PyDict_Check(entries)) { PyErr_SetString(PyExc_TypeError, "Argument not a dictionary"); goto error; } name_order = PyObject_IsTrue(py_name_order); if (name_order == -1) goto error; cmp = name_order ? cmp_tree_item_name_order : cmp_tree_item; num_entries = PyDict_Size(entries); if (PyErr_Occurred()) goto error; qsort_entries = PyMem_New(struct tree_item, num_entries); if (!qsort_entries) { PyErr_NoMemory(); goto error; } while (PyDict_Next(entries, &pos, &key, &value)) { if (!Text_Check(key)) { PyErr_SetString(PyExc_TypeError, "Name is not a string"); goto error; } if (PyTuple_Size(value) != 2) { PyErr_SetString(PyExc_ValueError, "Tuple has invalid size"); goto error; } py_mode = PyTuple_GET_ITEM(value, 0); if (!PyInt_Check(py_mode)) { PyErr_SetString(PyExc_TypeError, "Mode is not an integral type"); goto error; } py_sha = PyTuple_GET_ITEM(value, 1); if (!Text_Check(py_sha)) { PyErr_SetString(PyExc_TypeError, "SHA is not a string"); goto error; } qsort_entries[n].name = Text_Buffer(key); qsort_entries[n].mode = PyInt_AS_LONG(py_mode); qsort_entries[n].tuple = PyObject_CallFunctionObjArgs( tree_entry_cls, key, py_mode, py_sha, NULL); if (qsort_entries[n].tuple == NULL) goto error; n++; } qsort(qsort_entries, num_entries, sizeof(struct tree_item), cmp); ret = PyList_New(num_entries); if (ret == NULL) { PyErr_NoMemory(); goto error; } for (i = 0; i < num_entries; i++) { PyList_SET_ITEM(ret, i, qsort_entries[i].tuple); } PyMem_Free(qsort_entries); return ret; error: for (i = 0; i < n; i++) { Py_XDECREF(qsort_entries[i].tuple); } PyMem_Free(qsort_entries); return NULL; }