1
/*-------------------------------------------------------------------------
4
* implementation for PostgreSQL generic linked list package
7
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
12
* $PostgreSQL: pgsql/src/backend/nodes/list.c,v 1.63 2004-12-31 21:59:55 pgsql Exp $
14
*-------------------------------------------------------------------------
18
#include "nodes/pg_list.h"
22
* Routines to simplify writing assertions about the type of a list; a
23
* NIL list is considered to be an empty list of any type.
25
#define IsPointerList(l) ((l) == NIL || IsA((l), List))
26
#define IsIntegerList(l) ((l) == NIL || IsA((l), IntList))
27
#define IsOidList(l) ((l) == NIL || IsA((l), OidList))
29
#ifdef USE_ASSERT_CHECKING
31
* Check that the specified List is valid (so far as we can tell).
34
check_list_invariants(List *list)
39
Assert(list->length > 0);
40
Assert(list->head != NULL);
41
Assert(list->tail != NULL);
43
Assert(list->type == T_List ||
44
list->type == T_IntList ||
45
list->type == T_OidList);
47
if (list->length == 1)
48
Assert(list->head == list->tail);
49
if (list->length == 2)
50
Assert(list->head->next == list->tail);
51
Assert(list->tail->next == NULL);
55
#define check_list_invariants(l)
56
#endif /* USE_ASSERT_CHECKING */
59
* Return a freshly allocated List. Since empty non-NIL lists are
60
* invalid, new_list() also allocates the head cell of the new list:
61
* the caller should be sure to fill in that cell's data.
64
new_list(NodeTag type)
69
new_head = (ListCell *) palloc(sizeof(*new_head));
70
new_head->next = NULL;
71
/* new_head->data is left undefined! */
73
new_list = (List *) palloc(sizeof(*new_list));
74
new_list->type = type;
76
new_list->head = new_head;
77
new_list->tail = new_head;
83
* Allocate a new cell and make it the head of the specified
84
* list. Assumes the list it is passed is non-NIL.
86
* The data in the new head cell is undefined; the caller should be
90
new_head_cell(List *list)
94
new_head = (ListCell *) palloc(sizeof(*new_head));
95
new_head->next = list->head;
97
list->head = new_head;
102
* Allocate a new cell and make it the tail of the specified
103
* list. Assumes the list it is passed is non-NIL.
105
* The data in the new tail cell is undefined; the caller should be
109
new_tail_cell(List *list)
113
new_tail = (ListCell *) palloc(sizeof(*new_tail));
114
new_tail->next = NULL;
116
list->tail->next = new_tail;
117
list->tail = new_tail;
122
* Append a pointer to the list. A pointer to the modified list is
123
* returned. Note that this function may or may not destructively
124
* modify the list; callers should always use this function's return
125
* value, rather than continuing to use the pointer passed as the
129
lappend(List *list, void *datum)
131
Assert(IsPointerList(list));
134
list = new_list(T_List);
138
lfirst(list->tail) = datum;
139
check_list_invariants(list);
144
* Append an integer to the specified list. See lappend()
147
lappend_int(List *list, int datum)
149
Assert(IsIntegerList(list));
152
list = new_list(T_IntList);
156
lfirst_int(list->tail) = datum;
157
check_list_invariants(list);
162
* Append an OID to the specified list. See lappend()
165
lappend_oid(List *list, Oid datum)
167
Assert(IsOidList(list));
170
list = new_list(T_OidList);
174
lfirst_oid(list->tail) = datum;
175
check_list_invariants(list);
180
* Add a new cell to the list, in the position after 'prev_cell'. The
181
* data in the cell is left undefined, and must be filled in by the
182
* caller. 'list' is assumed to be non-NIL, and 'prev_cell' is assumed
183
* to be non-NULL and a member of 'list'.
186
add_new_cell(List *list, ListCell *prev_cell)
190
new_cell = (ListCell *) palloc(sizeof(*new_cell));
191
/* new_cell->data is left undefined! */
192
new_cell->next = prev_cell->next;
193
prev_cell->next = new_cell;
195
if (list->tail == prev_cell)
196
list->tail = new_cell;
204
* Add a new cell to the specified list (which must be non-NIL);
205
* it will be placed after the list cell 'prev' (which must be
206
* non-NULL and a member of 'list'). The data placed in the new cell
207
* is 'datum'. The newly-constructed cell is returned.
210
lappend_cell(List *list, ListCell *prev, void *datum)
214
Assert(IsPointerList(list));
216
new_cell = add_new_cell(list, prev);
217
lfirst(new_cell) = datum;
218
check_list_invariants(list);
223
lappend_cell_int(List *list, ListCell *prev, int datum)
227
Assert(IsIntegerList(list));
229
new_cell = add_new_cell(list, prev);
230
lfirst_int(new_cell) = datum;
231
check_list_invariants(list);
236
lappend_cell_oid(List *list, ListCell *prev, Oid datum)
240
Assert(IsOidList(list));
242
new_cell = add_new_cell(list, prev);
243
lfirst_oid(new_cell) = datum;
244
check_list_invariants(list);
249
* Prepend a new element to the list. A pointer to the modified list
250
* is returned. Note that this function may or may not destructively
251
* modify the list; callers should always use this function's return
252
* value, rather than continuing to use the pointer passed as the
255
* Caution: before Postgres 8.0, the original List was unmodified and
256
* could be considered to retain its separate identity. This is no longer
260
lcons(void *datum, List *list)
262
Assert(IsPointerList(list));
265
list = new_list(T_List);
269
lfirst(list->head) = datum;
270
check_list_invariants(list);
275
* Prepend an integer to the list. See lcons()
278
lcons_int(int datum, List *list)
280
Assert(IsIntegerList(list));
283
list = new_list(T_IntList);
287
lfirst_int(list->head) = datum;
288
check_list_invariants(list);
293
* Prepend an OID to the list. See lcons()
296
lcons_oid(Oid datum, List *list)
298
Assert(IsOidList(list));
301
list = new_list(T_OidList);
305
lfirst_oid(list->head) = datum;
306
check_list_invariants(list);
311
* Concatenate list2 to the end of list1, and return list1. list1 is
312
* destructively changed. Callers should be sure to use the return
313
* value as the new pointer to the concatenated list: the 'list1'
314
* input pointer may or may not be the same as the returned pointer.
316
* The nodes in list2 are merely appended to the end of list1 in-place
317
* (i.e. they aren't copied; the two lists will share some of the same
318
* storage). Therefore, invoking list_free() on list2 will also
319
* invalidate a portion of list1.
322
list_concat(List *list1, List *list2)
329
elog(ERROR, "cannot list_concat() a list to itself");
331
Assert(list1->type == list2->type);
333
list1->length += list2->length;
334
list1->tail->next = list2->head;
335
list1->tail = list2->tail;
337
check_list_invariants(list1);
342
* Truncate 'list' to contain no more than 'new_size' elements. This
343
* modifies the list in-place! Despite this, callers should use the
344
* pointer returned by this function to refer to the newly truncated
345
* list -- it may or may not be the same as the pointer that was
348
* Note that any cells removed by list_truncate() are NOT pfree'd.
351
list_truncate(List *list, int new_size)
357
return NIL; /* truncate to zero length */
359
/* If asked to effectively extend the list, do nothing */
360
if (new_size >= list_length(list))
370
list->length = new_size;
371
check_list_invariants(list);
377
/* keep the compiler quiet; never reached */
383
* Locate the n'th cell (counting from 0) of the list. It is an assertion
384
* error if there isn't one.
387
list_nth_cell(List *list, int n)
393
Assert(n < list->length);
394
check_list_invariants(list);
396
/* Does the caller actually mean to fetch the tail? */
397
if (n == list->length - 1)
400
for (match = list->head; n-- > 0; match = match->next)
407
* Return the data value contained in the n'th element of the
408
* specified list. (List elements begin at 0.)
411
list_nth(List *list, int n)
413
Assert(IsPointerList(list));
414
return lfirst(list_nth_cell(list, n));
418
* Return the integer value contained in the n'th element of the
422
list_nth_int(List *list, int n)
424
Assert(IsIntegerList(list));
425
return lfirst_int(list_nth_cell(list, n));
429
* Return the OID value contained in the n'th element of the specified
433
list_nth_oid(List *list, int n)
435
Assert(IsOidList(list));
436
return lfirst_oid(list_nth_cell(list, n));
440
* Return true iff 'datum' is a member of the list. Equality is
441
* determined via equal(), so callers should ensure that they pass a
445
list_member(List *list, void *datum)
449
Assert(IsPointerList(list));
450
check_list_invariants(list);
454
if (equal(lfirst(cell), datum))
462
* Return true iff 'datum' is a member of the list. Equality is
463
* determined by using simple pointer comparison.
466
list_member_ptr(List *list, void *datum)
470
Assert(IsPointerList(list));
471
check_list_invariants(list);
475
if (lfirst(cell) == datum)
483
* Return true iff the integer 'datum' is a member of the list.
486
list_member_int(List *list, int datum)
490
Assert(IsIntegerList(list));
491
check_list_invariants(list);
495
if (lfirst_int(cell) == datum)
503
* Return true iff the OID 'datum' is a member of the list.
506
list_member_oid(List *list, Oid datum)
510
Assert(IsOidList(list));
511
check_list_invariants(list);
515
if (lfirst_oid(cell) == datum)
523
* Delete 'cell' from 'list'; 'prev' is the previous element to 'cell'
524
* in 'list', if any (i.e. prev == NULL iff list->head == cell)
526
* The cell is pfree'd, as is the List header if this was the last member.
529
list_delete_cell(List *list, ListCell *cell, ListCell *prev)
531
check_list_invariants(list);
532
Assert(prev != NULL ? lnext(prev) == cell : list_head(list) == cell);
535
* If we're about to delete the last node from the list, free the
536
* whole list instead and return NIL, which is the only valid
537
* representation of a zero-length list.
539
if (list->length == 1)
546
* Otherwise, adjust the necessary list links, deallocate the
547
* particular node we have just removed, and return the list we were
553
prev->next = cell->next;
555
list->head = cell->next;
557
if (list->tail == cell)
565
* Delete the first cell in list that matches datum, if any.
566
* Equality is determined via equal().
569
list_delete(List *list, void *datum)
574
Assert(IsPointerList(list));
575
check_list_invariants(list);
580
if (equal(lfirst(cell), datum))
581
return list_delete_cell(list, cell, prev);
586
/* Didn't find a match: return the list unmodified */
590
/* As above, but use simple pointer equality */
592
list_delete_ptr(List *list, void *datum)
597
Assert(IsPointerList(list));
598
check_list_invariants(list);
603
if (lfirst(cell) == datum)
604
return list_delete_cell(list, cell, prev);
609
/* Didn't find a match: return the list unmodified */
613
/* As above, but for integers */
615
list_delete_int(List *list, int datum)
620
Assert(IsIntegerList(list));
621
check_list_invariants(list);
626
if (lfirst_int(cell) == datum)
627
return list_delete_cell(list, cell, prev);
632
/* Didn't find a match: return the list unmodified */
636
/* As above, but for OIDs */
638
list_delete_oid(List *list, Oid datum)
643
Assert(IsOidList(list));
644
check_list_invariants(list);
649
if (lfirst_oid(cell) == datum)
650
return list_delete_cell(list, cell, prev);
655
/* Didn't find a match: return the list unmodified */
660
* Delete the first element of the list.
662
* This is useful to replace the Lisp-y code "list = lnext(list);" in cases
663
* where the intent is to alter the list rather than just traverse it.
664
* Beware that the removed cell is freed, whereas the lnext() coding leaves
665
* the original list head intact if there's another pointer to it.
668
list_delete_first(List *list)
670
check_list_invariants(list);
673
return NIL; /* would an error be better? */
675
return list_delete_cell(list, list_head(list), NULL);
679
* Generate the union of two lists. This is calculated by copying
680
* list1 via list_copy(), then adding to it all the members of list2
681
* that aren't already in list1.
683
* Whether an element is already a member of the list is determined
686
* The returned list is newly-allocated, although the content of the
687
* cells is the same (i.e. any pointed-to objects are not copied).
689
* NB: Bizarrely, this function will NOT remove any duplicates that
690
* are present in list1 (so it is not really a union at all!). Also,
691
* this function could probably be implemented a lot faster if it is a
692
* performance bottleneck.
695
list_union(List *list1, List *list2)
700
Assert(IsPointerList(list1));
701
Assert(IsPointerList(list2));
703
result = list_copy(list1);
706
if (!list_member(result, lfirst(cell)))
707
result = lappend(result, lfirst(cell));
710
check_list_invariants(result);
715
* This variant of list_union() determines duplicates via simple
716
* pointer comparison.
719
list_union_ptr(List *list1, List *list2)
724
Assert(IsPointerList(list1));
725
Assert(IsPointerList(list2));
727
result = list_copy(list1);
730
if (!list_member_ptr(result, lfirst(cell)))
731
result = lappend(result, lfirst(cell));
734
check_list_invariants(result);
739
* This variant of list_union() operates upon lists of integers.
742
list_union_int(List *list1, List *list2)
747
Assert(IsIntegerList(list1));
748
Assert(IsIntegerList(list2));
750
result = list_copy(list1);
753
if (!list_member_int(result, lfirst_int(cell)))
754
result = lappend_int(result, lfirst_int(cell));
757
check_list_invariants(result);
762
* This variant of list_union() operates upon lists of OIDs.
765
list_union_oid(List *list1, List *list2)
770
Assert(IsOidList(list1));
771
Assert(IsOidList(list2));
773
result = list_copy(list1);
776
if (!list_member_oid(result, lfirst_oid(cell)))
777
result = lappend_oid(result, lfirst_oid(cell));
780
check_list_invariants(result);
785
* Return a list that contains all the cells in list1 that are not in
786
* list2. The returned list is freshly allocated via palloc(), but the
787
* cells themselves point to the same objects as the cells of the
790
* This variant works on lists of pointers, and determines list
791
* membership via equal()
794
list_difference(List *list1, List *list2)
799
Assert(IsPointerList(list1));
800
Assert(IsPointerList(list2));
803
return list_copy(list1);
807
if (!list_member(list2, lfirst(cell)))
808
result = lappend(result, lfirst(cell));
811
check_list_invariants(result);
816
* This variant of list_difference() determines list membership via
817
* simple pointer equality.
820
list_difference_ptr(List *list1, List *list2)
825
Assert(IsPointerList(list1));
826
Assert(IsPointerList(list2));
829
return list_copy(list1);
833
if (!list_member_ptr(list2, lfirst(cell)))
834
result = lappend(result, lfirst(cell));
837
check_list_invariants(result);
842
* This variant of list_difference() operates upon lists of integers.
845
list_difference_int(List *list1, List *list2)
850
Assert(IsIntegerList(list1));
851
Assert(IsIntegerList(list2));
854
return list_copy(list1);
858
if (!list_member_int(list2, lfirst_int(cell)))
859
result = lappend_int(result, lfirst_int(cell));
862
check_list_invariants(result);
867
* This variant of list_difference() operates upon lists of OIDs.
870
list_difference_oid(List *list1, List *list2)
875
Assert(IsOidList(list1));
876
Assert(IsOidList(list2));
879
return list_copy(list1);
883
if (!list_member_oid(list2, lfirst_oid(cell)))
884
result = lappend_oid(result, lfirst_oid(cell));
887
check_list_invariants(result);
891
/* Free all storage in a list, and optionally the pointed-to elements */
893
list_free_private(List *list, bool deep)
897
check_list_invariants(list);
899
cell = list_head(list);
902
ListCell *tmp = cell;
915
* Free all the cells of the list, as well as the list itself. Any
916
* objects that are pointed-to by the cells of the list are NOT
919
* On return, the argument to this function has been freed, so the
920
* caller would be wise to set it to NIL for safety's sake.
923
list_free(List *list)
925
list_free_private(list, false);
929
* Free all the cells of the list, the list itself, and all the
930
* objects pointed-to by the cells of the list (each element in the
931
* list must contain a pointer to a palloc()'d region of memory!)
933
* On return, the argument to this function has been freed, so the
934
* caller would be wise to set it to NIL for safety's sake.
937
list_free_deep(List *list)
940
* A "deep" free operation only makes sense on a list of pointers.
942
Assert(IsPointerList(list));
943
list_free_private(list, true);
947
* Return a shallow copy of the specified list.
950
list_copy(List *oldlist)
953
ListCell *newlist_prev;
954
ListCell *oldlist_cur;
959
newlist = new_list(oldlist->type);
960
newlist->length = oldlist->length;
963
* Copy over the data in the first cell; new_list() has already
964
* allocated the head cell itself
966
newlist->head->data = oldlist->head->data;
968
newlist_prev = newlist->head;
969
oldlist_cur = oldlist->head->next;
972
ListCell *newlist_cur;
974
newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
975
newlist_cur->data = oldlist_cur->data;
976
newlist_prev->next = newlist_cur;
978
newlist_prev = newlist_cur;
979
oldlist_cur = oldlist_cur->next;
982
newlist_prev->next = NULL;
983
newlist->tail = newlist_prev;
985
check_list_invariants(newlist);
990
* Return a shallow copy of the specified list, without the first N elements.
993
list_copy_tail(List *oldlist, int nskip)
996
ListCell *newlist_prev;
997
ListCell *oldlist_cur;
1000
nskip = 0; /* would it be better to elog? */
1002
if (oldlist == NIL || nskip >= oldlist->length)
1005
newlist = new_list(oldlist->type);
1006
newlist->length = oldlist->length - nskip;
1009
* Skip over the unwanted elements.
1011
oldlist_cur = oldlist->head;
1013
oldlist_cur = oldlist_cur->next;
1016
* Copy over the data in the first remaining cell; new_list() has
1017
* already allocated the head cell itself
1019
newlist->head->data = oldlist_cur->data;
1021
newlist_prev = newlist->head;
1022
oldlist_cur = oldlist_cur->next;
1025
ListCell *newlist_cur;
1027
newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
1028
newlist_cur->data = oldlist_cur->data;
1029
newlist_prev->next = newlist_cur;
1031
newlist_prev = newlist_cur;
1032
oldlist_cur = oldlist_cur->next;
1035
newlist_prev->next = NULL;
1036
newlist->tail = newlist_prev;
1038
check_list_invariants(newlist);
1043
* When using non-GCC compilers, we can't define these as inline
1044
* functions in pg_list.h, so they are defined here.
1046
* TODO: investigate supporting inlining for some non-GCC compilers.
1053
return l ? l->head : NULL;
1059
return l ? l->tail : NULL;
1063
list_length(List *l)
1065
return l ? l->length : 0;
1067
#endif /* ! __GNUC__ */
1070
* Temporary compatibility functions
1072
* In order to avoid warnings for these function definitions, we need
1073
* to include a prototype here as well as in pg_list.h. That's because
1074
* we don't enable list API compatibility in list.c, so we
1075
* don't see the prototypes for these functions.
1079
* Given a list, return its length. This is merely defined for the
1080
* sake of backward compatibility: we can't afford to define a macro
1081
* called "length", so it must be a function. New code should use the
1082
* list_length() macro in order to avoid the overhead of a function
1085
int length(List *list);
1090
return list_length(list);