}
/*
- * Sort a list using qsort. A sorted list is built but the cells of the
- * original list are re-used. The comparator function receives arguments of
- * type ListCell **
+ * Sort a list as though by qsort.
+ *
+ * A new list is built and returned. Like list_copy, this doesn't make
+ * fresh copies of any pointed-to data.
+ *
+ * The comparator function receives arguments of type ListCell **.
*/
List *
list_qsort(const List *list, list_qsort_comparator cmp)
{
- ListCell *cell;
- int i;
int len = list_length(list);
ListCell **list_arr;
- List *new_list;
+ List *newlist;
+ ListCell *newlist_prev;
+ ListCell *cell;
+ int i;
+ /* Empty list is easy */
if (len == 0)
return NIL;
+ /* Flatten list cells into an array, so we can use qsort */
+ list_arr = (ListCell **) palloc(sizeof(ListCell *) * len);
i = 0;
- list_arr = palloc(sizeof(ListCell *) * len);
foreach(cell, list)
list_arr[i++] = cell;
qsort(list_arr, len, sizeof(ListCell *), cmp);
- new_list = (List *) palloc(sizeof(List));
- new_list->type = list->type;
- new_list->length = len;
- new_list->head = list_arr[0];
- new_list->tail = list_arr[len - 1];
+ /* Construct new list (this code is much like list_copy) */
+ newlist = new_list(list->type);
+ newlist->length = len;
+
+ /*
+ * Copy over the data in the first cell; new_list() has already allocated
+ * the head cell itself
+ */
+ newlist->head->data = list_arr[0]->data;
+
+ newlist_prev = newlist->head;
+ for (i = 1; i < len; i++)
+ {
+ ListCell *newlist_cur;
+
+ newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
+ newlist_cur->data = list_arr[i]->data;
+ newlist_prev->next = newlist_cur;
- for (i = 0; i < len - 1; i++)
- list_arr[i]->next = list_arr[i + 1];
+ newlist_prev = newlist_cur;
+ }
- list_arr[len - 1]->next = NULL;
+ newlist_prev->next = NULL;
+ newlist->tail = newlist_prev;
+
+ /* Might as well free the workspace array */
pfree(list_arr);
- return new_list;
+
+ check_list_invariants(newlist);
+ return newlist;
}
/*