Header And Logo

PostgreSQL
| The world's most advanced open source database.

list.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * list.c
00004  *    implementation for PostgreSQL generic linked list package
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  *
00011  * IDENTIFICATION
00012  *    src/backend/nodes/list.c
00013  *
00014  *-------------------------------------------------------------------------
00015  */
00016 #include "postgres.h"
00017 
00018 /* see pg_list.h */
00019 #define PG_LIST_INCLUDE_DEFINITIONS
00020 
00021 #include "nodes/pg_list.h"
00022 
00023 
00024 /*
00025  * Routines to simplify writing assertions about the type of a list; a
00026  * NIL list is considered to be an empty list of any type.
00027  */
00028 #define IsPointerList(l)        ((l) == NIL || IsA((l), List))
00029 #define IsIntegerList(l)        ((l) == NIL || IsA((l), IntList))
00030 #define IsOidList(l)            ((l) == NIL || IsA((l), OidList))
00031 
00032 #ifdef USE_ASSERT_CHECKING
00033 /*
00034  * Check that the specified List is valid (so far as we can tell).
00035  */
00036 static void
00037 check_list_invariants(const List *list)
00038 {
00039     if (list == NIL)
00040         return;
00041 
00042     Assert(list->length > 0);
00043     Assert(list->head != NULL);
00044     Assert(list->tail != NULL);
00045 
00046     Assert(list->type == T_List ||
00047            list->type == T_IntList ||
00048            list->type == T_OidList);
00049 
00050     if (list->length == 1)
00051         Assert(list->head == list->tail);
00052     if (list->length == 2)
00053         Assert(list->head->next == list->tail);
00054     Assert(list->tail->next == NULL);
00055 }
00056 #else
00057 #define check_list_invariants(l)
00058 #endif   /* USE_ASSERT_CHECKING */
00059 
00060 /*
00061  * Return a freshly allocated List. Since empty non-NIL lists are
00062  * invalid, new_list() also allocates the head cell of the new list:
00063  * the caller should be sure to fill in that cell's data.
00064  */
00065 static List *
00066 new_list(NodeTag type)
00067 {
00068     List       *new_list;
00069     ListCell   *new_head;
00070 
00071     new_head = (ListCell *) palloc(sizeof(*new_head));
00072     new_head->next = NULL;
00073     /* new_head->data is left undefined! */
00074 
00075     new_list = (List *) palloc(sizeof(*new_list));
00076     new_list->type = type;
00077     new_list->length = 1;
00078     new_list->head = new_head;
00079     new_list->tail = new_head;
00080 
00081     return new_list;
00082 }
00083 
00084 /*
00085  * Allocate a new cell and make it the head of the specified
00086  * list. Assumes the list it is passed is non-NIL.
00087  *
00088  * The data in the new head cell is undefined; the caller should be
00089  * sure to fill it in
00090  */
00091 static void
00092 new_head_cell(List *list)
00093 {
00094     ListCell   *new_head;
00095 
00096     new_head = (ListCell *) palloc(sizeof(*new_head));
00097     new_head->next = list->head;
00098 
00099     list->head = new_head;
00100     list->length++;
00101 }
00102 
00103 /*
00104  * Allocate a new cell and make it the tail of the specified
00105  * list. Assumes the list it is passed is non-NIL.
00106  *
00107  * The data in the new tail cell is undefined; the caller should be
00108  * sure to fill it in
00109  */
00110 static void
00111 new_tail_cell(List *list)
00112 {
00113     ListCell   *new_tail;
00114 
00115     new_tail = (ListCell *) palloc(sizeof(*new_tail));
00116     new_tail->next = NULL;
00117 
00118     list->tail->next = new_tail;
00119     list->tail = new_tail;
00120     list->length++;
00121 }
00122 
00123 /*
00124  * Append a pointer to the list. A pointer to the modified list is
00125  * returned. Note that this function may or may not destructively
00126  * modify the list; callers should always use this function's return
00127  * value, rather than continuing to use the pointer passed as the
00128  * first argument.
00129  */
00130 List *
00131 lappend(List *list, void *datum)
00132 {
00133     Assert(IsPointerList(list));
00134 
00135     if (list == NIL)
00136         list = new_list(T_List);
00137     else
00138         new_tail_cell(list);
00139 
00140     lfirst(list->tail) = datum;
00141     check_list_invariants(list);
00142     return list;
00143 }
00144 
00145 /*
00146  * Append an integer to the specified list. See lappend()
00147  */
00148 List *
00149 lappend_int(List *list, int datum)
00150 {
00151     Assert(IsIntegerList(list));
00152 
00153     if (list == NIL)
00154         list = new_list(T_IntList);
00155     else
00156         new_tail_cell(list);
00157 
00158     lfirst_int(list->tail) = datum;
00159     check_list_invariants(list);
00160     return list;
00161 }
00162 
00163 /*
00164  * Append an OID to the specified list. See lappend()
00165  */
00166 List *
00167 lappend_oid(List *list, Oid datum)
00168 {
00169     Assert(IsOidList(list));
00170 
00171     if (list == NIL)
00172         list = new_list(T_OidList);
00173     else
00174         new_tail_cell(list);
00175 
00176     lfirst_oid(list->tail) = datum;
00177     check_list_invariants(list);
00178     return list;
00179 }
00180 
00181 /*
00182  * Add a new cell to the list, in the position after 'prev_cell'. The
00183  * data in the cell is left undefined, and must be filled in by the
00184  * caller. 'list' is assumed to be non-NIL, and 'prev_cell' is assumed
00185  * to be non-NULL and a member of 'list'.
00186  */
00187 static ListCell *
00188 add_new_cell(List *list, ListCell *prev_cell)
00189 {
00190     ListCell   *new_cell;
00191 
00192     new_cell = (ListCell *) palloc(sizeof(*new_cell));
00193     /* new_cell->data is left undefined! */
00194     new_cell->next = prev_cell->next;
00195     prev_cell->next = new_cell;
00196 
00197     if (list->tail == prev_cell)
00198         list->tail = new_cell;
00199 
00200     list->length++;
00201 
00202     return new_cell;
00203 }
00204 
00205 /*
00206  * Add a new cell to the specified list (which must be non-NIL);
00207  * it will be placed after the list cell 'prev' (which must be
00208  * non-NULL and a member of 'list'). The data placed in the new cell
00209  * is 'datum'. The newly-constructed cell is returned.
00210  */
00211 ListCell *
00212 lappend_cell(List *list, ListCell *prev, void *datum)
00213 {
00214     ListCell   *new_cell;
00215 
00216     Assert(IsPointerList(list));
00217 
00218     new_cell = add_new_cell(list, prev);
00219     lfirst(new_cell) = datum;
00220     check_list_invariants(list);
00221     return new_cell;
00222 }
00223 
00224 ListCell *
00225 lappend_cell_int(List *list, ListCell *prev, int datum)
00226 {
00227     ListCell   *new_cell;
00228 
00229     Assert(IsIntegerList(list));
00230 
00231     new_cell = add_new_cell(list, prev);
00232     lfirst_int(new_cell) = datum;
00233     check_list_invariants(list);
00234     return new_cell;
00235 }
00236 
00237 ListCell *
00238 lappend_cell_oid(List *list, ListCell *prev, Oid datum)
00239 {
00240     ListCell   *new_cell;
00241 
00242     Assert(IsOidList(list));
00243 
00244     new_cell = add_new_cell(list, prev);
00245     lfirst_oid(new_cell) = datum;
00246     check_list_invariants(list);
00247     return new_cell;
00248 }
00249 
00250 /*
00251  * Prepend a new element to the list. A pointer to the modified list
00252  * is returned. Note that this function may or may not destructively
00253  * modify the list; callers should always use this function's return
00254  * value, rather than continuing to use the pointer passed as the
00255  * second argument.
00256  *
00257  * Caution: before Postgres 8.0, the original List was unmodified and
00258  * could be considered to retain its separate identity.  This is no longer
00259  * the case.
00260  */
00261 List *
00262 lcons(void *datum, List *list)
00263 {
00264     Assert(IsPointerList(list));
00265 
00266     if (list == NIL)
00267         list = new_list(T_List);
00268     else
00269         new_head_cell(list);
00270 
00271     lfirst(list->head) = datum;
00272     check_list_invariants(list);
00273     return list;
00274 }
00275 
00276 /*
00277  * Prepend an integer to the list. See lcons()
00278  */
00279 List *
00280 lcons_int(int datum, List *list)
00281 {
00282     Assert(IsIntegerList(list));
00283 
00284     if (list == NIL)
00285         list = new_list(T_IntList);
00286     else
00287         new_head_cell(list);
00288 
00289     lfirst_int(list->head) = datum;
00290     check_list_invariants(list);
00291     return list;
00292 }
00293 
00294 /*
00295  * Prepend an OID to the list. See lcons()
00296  */
00297 List *
00298 lcons_oid(Oid datum, List *list)
00299 {
00300     Assert(IsOidList(list));
00301 
00302     if (list == NIL)
00303         list = new_list(T_OidList);
00304     else
00305         new_head_cell(list);
00306 
00307     lfirst_oid(list->head) = datum;
00308     check_list_invariants(list);
00309     return list;
00310 }
00311 
00312 /*
00313  * Concatenate list2 to the end of list1, and return list1. list1 is
00314  * destructively changed. Callers should be sure to use the return
00315  * value as the new pointer to the concatenated list: the 'list1'
00316  * input pointer may or may not be the same as the returned pointer.
00317  *
00318  * The nodes in list2 are merely appended to the end of list1 in-place
00319  * (i.e. they aren't copied; the two lists will share some of the same
00320  * storage). Therefore, invoking list_free() on list2 will also
00321  * invalidate a portion of list1.
00322  */
00323 List *
00324 list_concat(List *list1, List *list2)
00325 {
00326     if (list1 == NIL)
00327         return list2;
00328     if (list2 == NIL)
00329         return list1;
00330     if (list1 == list2)
00331         elog(ERROR, "cannot list_concat() a list to itself");
00332 
00333     Assert(list1->type == list2->type);
00334 
00335     list1->length += list2->length;
00336     list1->tail->next = list2->head;
00337     list1->tail = list2->tail;
00338 
00339     check_list_invariants(list1);
00340     return list1;
00341 }
00342 
00343 /*
00344  * Truncate 'list' to contain no more than 'new_size' elements. This
00345  * modifies the list in-place! Despite this, callers should use the
00346  * pointer returned by this function to refer to the newly truncated
00347  * list -- it may or may not be the same as the pointer that was
00348  * passed.
00349  *
00350  * Note that any cells removed by list_truncate() are NOT pfree'd.
00351  */
00352 List *
00353 list_truncate(List *list, int new_size)
00354 {
00355     ListCell   *cell;
00356     int         n;
00357 
00358     if (new_size <= 0)
00359         return NIL;             /* truncate to zero length */
00360 
00361     /* If asked to effectively extend the list, do nothing */
00362     if (new_size >= list_length(list))
00363         return list;
00364 
00365     n = 1;
00366     foreach(cell, list)
00367     {
00368         if (n == new_size)
00369         {
00370             cell->next = NULL;
00371             list->tail = cell;
00372             list->length = new_size;
00373             check_list_invariants(list);
00374             return list;
00375         }
00376         n++;
00377     }
00378 
00379     /* keep the compiler quiet; never reached */
00380     Assert(false);
00381     return list;
00382 }
00383 
00384 /*
00385  * Locate the n'th cell (counting from 0) of the list.  It is an assertion
00386  * failure if there is no such cell.
00387  */
00388 static ListCell *
00389 list_nth_cell(const List *list, int n)
00390 {
00391     ListCell   *match;
00392 
00393     Assert(list != NIL);
00394     Assert(n >= 0);
00395     Assert(n < list->length);
00396     check_list_invariants(list);
00397 
00398     /* Does the caller actually mean to fetch the tail? */
00399     if (n == list->length - 1)
00400         return list->tail;
00401 
00402     for (match = list->head; n-- > 0; match = match->next)
00403         ;
00404 
00405     return match;
00406 }
00407 
00408 /*
00409  * Return the data value contained in the n'th element of the
00410  * specified list. (List elements begin at 0.)
00411  */
00412 void *
00413 list_nth(const List *list, int n)
00414 {
00415     Assert(IsPointerList(list));
00416     return lfirst(list_nth_cell(list, n));
00417 }
00418 
00419 /*
00420  * Return the integer value contained in the n'th element of the
00421  * specified list.
00422  */
00423 int
00424 list_nth_int(const List *list, int n)
00425 {
00426     Assert(IsIntegerList(list));
00427     return lfirst_int(list_nth_cell(list, n));
00428 }
00429 
00430 /*
00431  * Return the OID value contained in the n'th element of the specified
00432  * list.
00433  */
00434 Oid
00435 list_nth_oid(const List *list, int n)
00436 {
00437     Assert(IsOidList(list));
00438     return lfirst_oid(list_nth_cell(list, n));
00439 }
00440 
00441 /*
00442  * Return true iff 'datum' is a member of the list. Equality is
00443  * determined via equal(), so callers should ensure that they pass a
00444  * Node as 'datum'.
00445  */
00446 bool
00447 list_member(const List *list, const void *datum)
00448 {
00449     const ListCell *cell;
00450 
00451     Assert(IsPointerList(list));
00452     check_list_invariants(list);
00453 
00454     foreach(cell, list)
00455     {
00456         if (equal(lfirst(cell), datum))
00457             return true;
00458     }
00459 
00460     return false;
00461 }
00462 
00463 /*
00464  * Return true iff 'datum' is a member of the list. Equality is
00465  * determined by using simple pointer comparison.
00466  */
00467 bool
00468 list_member_ptr(const List *list, const void *datum)
00469 {
00470     const ListCell *cell;
00471 
00472     Assert(IsPointerList(list));
00473     check_list_invariants(list);
00474 
00475     foreach(cell, list)
00476     {
00477         if (lfirst(cell) == datum)
00478             return true;
00479     }
00480 
00481     return false;
00482 }
00483 
00484 /*
00485  * Return true iff the integer 'datum' is a member of the list.
00486  */
00487 bool
00488 list_member_int(const List *list, int datum)
00489 {
00490     const ListCell *cell;
00491 
00492     Assert(IsIntegerList(list));
00493     check_list_invariants(list);
00494 
00495     foreach(cell, list)
00496     {
00497         if (lfirst_int(cell) == datum)
00498             return true;
00499     }
00500 
00501     return false;
00502 }
00503 
00504 /*
00505  * Return true iff the OID 'datum' is a member of the list.
00506  */
00507 bool
00508 list_member_oid(const List *list, Oid datum)
00509 {
00510     const ListCell *cell;
00511 
00512     Assert(IsOidList(list));
00513     check_list_invariants(list);
00514 
00515     foreach(cell, list)
00516     {
00517         if (lfirst_oid(cell) == datum)
00518             return true;
00519     }
00520 
00521     return false;
00522 }
00523 
00524 /*
00525  * Delete 'cell' from 'list'; 'prev' is the previous element to 'cell'
00526  * in 'list', if any (i.e. prev == NULL iff list->head == cell)
00527  *
00528  * The cell is pfree'd, as is the List header if this was the last member.
00529  */
00530 List *
00531 list_delete_cell(List *list, ListCell *cell, ListCell *prev)
00532 {
00533     check_list_invariants(list);
00534     Assert(prev != NULL ? lnext(prev) == cell : list_head(list) == cell);
00535 
00536     /*
00537      * If we're about to delete the last node from the list, free the whole
00538      * list instead and return NIL, which is the only valid representation of
00539      * a zero-length list.
00540      */
00541     if (list->length == 1)
00542     {
00543         list_free(list);
00544         return NIL;
00545     }
00546 
00547     /*
00548      * Otherwise, adjust the necessary list links, deallocate the particular
00549      * node we have just removed, and return the list we were given.
00550      */
00551     list->length--;
00552 
00553     if (prev)
00554         prev->next = cell->next;
00555     else
00556         list->head = cell->next;
00557 
00558     if (list->tail == cell)
00559         list->tail = prev;
00560 
00561     pfree(cell);
00562     return list;
00563 }
00564 
00565 /*
00566  * Delete the first cell in list that matches datum, if any.
00567  * Equality is determined via equal().
00568  */
00569 List *
00570 list_delete(List *list, void *datum)
00571 {
00572     ListCell   *cell;
00573     ListCell   *prev;
00574 
00575     Assert(IsPointerList(list));
00576     check_list_invariants(list);
00577 
00578     prev = NULL;
00579     foreach(cell, list)
00580     {
00581         if (equal(lfirst(cell), datum))
00582             return list_delete_cell(list, cell, prev);
00583 
00584         prev = cell;
00585     }
00586 
00587     /* Didn't find a match: return the list unmodified */
00588     return list;
00589 }
00590 
00591 /* As above, but use simple pointer equality */
00592 List *
00593 list_delete_ptr(List *list, void *datum)
00594 {
00595     ListCell   *cell;
00596     ListCell   *prev;
00597 
00598     Assert(IsPointerList(list));
00599     check_list_invariants(list);
00600 
00601     prev = NULL;
00602     foreach(cell, list)
00603     {
00604         if (lfirst(cell) == datum)
00605             return list_delete_cell(list, cell, prev);
00606 
00607         prev = cell;
00608     }
00609 
00610     /* Didn't find a match: return the list unmodified */
00611     return list;
00612 }
00613 
00614 /* As above, but for integers */
00615 List *
00616 list_delete_int(List *list, int datum)
00617 {
00618     ListCell   *cell;
00619     ListCell   *prev;
00620 
00621     Assert(IsIntegerList(list));
00622     check_list_invariants(list);
00623 
00624     prev = NULL;
00625     foreach(cell, list)
00626     {
00627         if (lfirst_int(cell) == datum)
00628             return list_delete_cell(list, cell, prev);
00629 
00630         prev = cell;
00631     }
00632 
00633     /* Didn't find a match: return the list unmodified */
00634     return list;
00635 }
00636 
00637 /* As above, but for OIDs */
00638 List *
00639 list_delete_oid(List *list, Oid datum)
00640 {
00641     ListCell   *cell;
00642     ListCell   *prev;
00643 
00644     Assert(IsOidList(list));
00645     check_list_invariants(list);
00646 
00647     prev = NULL;
00648     foreach(cell, list)
00649     {
00650         if (lfirst_oid(cell) == datum)
00651             return list_delete_cell(list, cell, prev);
00652 
00653         prev = cell;
00654     }
00655 
00656     /* Didn't find a match: return the list unmodified */
00657     return list;
00658 }
00659 
00660 /*
00661  * Delete the first element of the list.
00662  *
00663  * This is useful to replace the Lisp-y code "list = lnext(list);" in cases
00664  * where the intent is to alter the list rather than just traverse it.
00665  * Beware that the removed cell is freed, whereas the lnext() coding leaves
00666  * the original list head intact if there's another pointer to it.
00667  */
00668 List *
00669 list_delete_first(List *list)
00670 {
00671     check_list_invariants(list);
00672 
00673     if (list == NIL)
00674         return NIL;             /* would an error be better? */
00675 
00676     return list_delete_cell(list, list_head(list), NULL);
00677 }
00678 
00679 /*
00680  * Generate the union of two lists. This is calculated by copying
00681  * list1 via list_copy(), then adding to it all the members of list2
00682  * that aren't already in list1.
00683  *
00684  * Whether an element is already a member of the list is determined
00685  * via equal().
00686  *
00687  * The returned list is newly-allocated, although the content of the
00688  * cells is the same (i.e. any pointed-to objects are not copied).
00689  *
00690  * NB: this function will NOT remove any duplicates that are present
00691  * in list1 (so it only performs a "union" if list1 is known unique to
00692  * start with).  Also, if you are about to write "x = list_union(x, y)"
00693  * you probably want to use list_concat_unique() instead to avoid wasting
00694  * the list cells of the old x list.
00695  *
00696  * This function could probably be implemented a lot faster if it is a
00697  * performance bottleneck.
00698  */
00699 List *
00700 list_union(const List *list1, const List *list2)
00701 {
00702     List       *result;
00703     const ListCell *cell;
00704 
00705     Assert(IsPointerList(list1));
00706     Assert(IsPointerList(list2));
00707 
00708     result = list_copy(list1);
00709     foreach(cell, list2)
00710     {
00711         if (!list_member(result, lfirst(cell)))
00712             result = lappend(result, lfirst(cell));
00713     }
00714 
00715     check_list_invariants(result);
00716     return result;
00717 }
00718 
00719 /*
00720  * This variant of list_union() determines duplicates via simple
00721  * pointer comparison.
00722  */
00723 List *
00724 list_union_ptr(const List *list1, const List *list2)
00725 {
00726     List       *result;
00727     const ListCell *cell;
00728 
00729     Assert(IsPointerList(list1));
00730     Assert(IsPointerList(list2));
00731 
00732     result = list_copy(list1);
00733     foreach(cell, list2)
00734     {
00735         if (!list_member_ptr(result, lfirst(cell)))
00736             result = lappend(result, lfirst(cell));
00737     }
00738 
00739     check_list_invariants(result);
00740     return result;
00741 }
00742 
00743 /*
00744  * This variant of list_union() operates upon lists of integers.
00745  */
00746 List *
00747 list_union_int(const List *list1, const List *list2)
00748 {
00749     List       *result;
00750     const ListCell *cell;
00751 
00752     Assert(IsIntegerList(list1));
00753     Assert(IsIntegerList(list2));
00754 
00755     result = list_copy(list1);
00756     foreach(cell, list2)
00757     {
00758         if (!list_member_int(result, lfirst_int(cell)))
00759             result = lappend_int(result, lfirst_int(cell));
00760     }
00761 
00762     check_list_invariants(result);
00763     return result;
00764 }
00765 
00766 /*
00767  * This variant of list_union() operates upon lists of OIDs.
00768  */
00769 List *
00770 list_union_oid(const List *list1, const List *list2)
00771 {
00772     List       *result;
00773     const ListCell *cell;
00774 
00775     Assert(IsOidList(list1));
00776     Assert(IsOidList(list2));
00777 
00778     result = list_copy(list1);
00779     foreach(cell, list2)
00780     {
00781         if (!list_member_oid(result, lfirst_oid(cell)))
00782             result = lappend_oid(result, lfirst_oid(cell));
00783     }
00784 
00785     check_list_invariants(result);
00786     return result;
00787 }
00788 
00789 /*
00790  * Return a list that contains all the cells that are in both list1 and
00791  * list2.  The returned list is freshly allocated via palloc(), but the
00792  * cells themselves point to the same objects as the cells of the
00793  * input lists.
00794  *
00795  * Duplicate entries in list1 will not be suppressed, so it's only a true
00796  * "intersection" if list1 is known unique beforehand.
00797  *
00798  * This variant works on lists of pointers, and determines list
00799  * membership via equal().  Note that the list1 member will be pointed
00800  * to in the result.
00801  */
00802 List *
00803 list_intersection(const List *list1, const List *list2)
00804 {
00805     List       *result;
00806     const ListCell *cell;
00807 
00808     if (list1 == NIL || list2 == NIL)
00809         return NIL;
00810 
00811     Assert(IsPointerList(list1));
00812     Assert(IsPointerList(list2));
00813 
00814     result = NIL;
00815     foreach(cell, list1)
00816     {
00817         if (list_member(list2, lfirst(cell)))
00818             result = lappend(result, lfirst(cell));
00819     }
00820 
00821     check_list_invariants(result);
00822     return result;
00823 }
00824 
00825 /*
00826  * Return a list that contains all the cells in list1 that are not in
00827  * list2. The returned list is freshly allocated via palloc(), but the
00828  * cells themselves point to the same objects as the cells of the
00829  * input lists.
00830  *
00831  * This variant works on lists of pointers, and determines list
00832  * membership via equal()
00833  */
00834 List *
00835 list_difference(const List *list1, const List *list2)
00836 {
00837     const ListCell *cell;
00838     List       *result = NIL;
00839 
00840     Assert(IsPointerList(list1));
00841     Assert(IsPointerList(list2));
00842 
00843     if (list2 == NIL)
00844         return list_copy(list1);
00845 
00846     foreach(cell, list1)
00847     {
00848         if (!list_member(list2, lfirst(cell)))
00849             result = lappend(result, lfirst(cell));
00850     }
00851 
00852     check_list_invariants(result);
00853     return result;
00854 }
00855 
00856 /*
00857  * This variant of list_difference() determines list membership via
00858  * simple pointer equality.
00859  */
00860 List *
00861 list_difference_ptr(const List *list1, const List *list2)
00862 {
00863     const ListCell *cell;
00864     List       *result = NIL;
00865 
00866     Assert(IsPointerList(list1));
00867     Assert(IsPointerList(list2));
00868 
00869     if (list2 == NIL)
00870         return list_copy(list1);
00871 
00872     foreach(cell, list1)
00873     {
00874         if (!list_member_ptr(list2, lfirst(cell)))
00875             result = lappend(result, lfirst(cell));
00876     }
00877 
00878     check_list_invariants(result);
00879     return result;
00880 }
00881 
00882 /*
00883  * This variant of list_difference() operates upon lists of integers.
00884  */
00885 List *
00886 list_difference_int(const List *list1, const List *list2)
00887 {
00888     const ListCell *cell;
00889     List       *result = NIL;
00890 
00891     Assert(IsIntegerList(list1));
00892     Assert(IsIntegerList(list2));
00893 
00894     if (list2 == NIL)
00895         return list_copy(list1);
00896 
00897     foreach(cell, list1)
00898     {
00899         if (!list_member_int(list2, lfirst_int(cell)))
00900             result = lappend_int(result, lfirst_int(cell));
00901     }
00902 
00903     check_list_invariants(result);
00904     return result;
00905 }
00906 
00907 /*
00908  * This variant of list_difference() operates upon lists of OIDs.
00909  */
00910 List *
00911 list_difference_oid(const List *list1, const List *list2)
00912 {
00913     const ListCell *cell;
00914     List       *result = NIL;
00915 
00916     Assert(IsOidList(list1));
00917     Assert(IsOidList(list2));
00918 
00919     if (list2 == NIL)
00920         return list_copy(list1);
00921 
00922     foreach(cell, list1)
00923     {
00924         if (!list_member_oid(list2, lfirst_oid(cell)))
00925             result = lappend_oid(result, lfirst_oid(cell));
00926     }
00927 
00928     check_list_invariants(result);
00929     return result;
00930 }
00931 
00932 /*
00933  * Append datum to list, but only if it isn't already in the list.
00934  *
00935  * Whether an element is already a member of the list is determined
00936  * via equal().
00937  */
00938 List *
00939 list_append_unique(List *list, void *datum)
00940 {
00941     if (list_member(list, datum))
00942         return list;
00943     else
00944         return lappend(list, datum);
00945 }
00946 
00947 /*
00948  * This variant of list_append_unique() determines list membership via
00949  * simple pointer equality.
00950  */
00951 List *
00952 list_append_unique_ptr(List *list, void *datum)
00953 {
00954     if (list_member_ptr(list, datum))
00955         return list;
00956     else
00957         return lappend(list, datum);
00958 }
00959 
00960 /*
00961  * This variant of list_append_unique() operates upon lists of integers.
00962  */
00963 List *
00964 list_append_unique_int(List *list, int datum)
00965 {
00966     if (list_member_int(list, datum))
00967         return list;
00968     else
00969         return lappend_int(list, datum);
00970 }
00971 
00972 /*
00973  * This variant of list_append_unique() operates upon lists of OIDs.
00974  */
00975 List *
00976 list_append_unique_oid(List *list, Oid datum)
00977 {
00978     if (list_member_oid(list, datum))
00979         return list;
00980     else
00981         return lappend_oid(list, datum);
00982 }
00983 
00984 /*
00985  * Append to list1 each member of list2 that isn't already in list1.
00986  *
00987  * Whether an element is already a member of the list is determined
00988  * via equal().
00989  *
00990  * This is almost the same functionality as list_union(), but list1 is
00991  * modified in-place rather than being copied.  Note also that list2's cells
00992  * are not inserted in list1, so the analogy to list_concat() isn't perfect.
00993  */
00994 List *
00995 list_concat_unique(List *list1, List *list2)
00996 {
00997     ListCell   *cell;
00998 
00999     Assert(IsPointerList(list1));
01000     Assert(IsPointerList(list2));
01001 
01002     foreach(cell, list2)
01003     {
01004         if (!list_member(list1, lfirst(cell)))
01005             list1 = lappend(list1, lfirst(cell));
01006     }
01007 
01008     check_list_invariants(list1);
01009     return list1;
01010 }
01011 
01012 /*
01013  * This variant of list_concat_unique() determines list membership via
01014  * simple pointer equality.
01015  */
01016 List *
01017 list_concat_unique_ptr(List *list1, List *list2)
01018 {
01019     ListCell   *cell;
01020 
01021     Assert(IsPointerList(list1));
01022     Assert(IsPointerList(list2));
01023 
01024     foreach(cell, list2)
01025     {
01026         if (!list_member_ptr(list1, lfirst(cell)))
01027             list1 = lappend(list1, lfirst(cell));
01028     }
01029 
01030     check_list_invariants(list1);
01031     return list1;
01032 }
01033 
01034 /*
01035  * This variant of list_concat_unique() operates upon lists of integers.
01036  */
01037 List *
01038 list_concat_unique_int(List *list1, List *list2)
01039 {
01040     ListCell   *cell;
01041 
01042     Assert(IsIntegerList(list1));
01043     Assert(IsIntegerList(list2));
01044 
01045     foreach(cell, list2)
01046     {
01047         if (!list_member_int(list1, lfirst_int(cell)))
01048             list1 = lappend_int(list1, lfirst_int(cell));
01049     }
01050 
01051     check_list_invariants(list1);
01052     return list1;
01053 }
01054 
01055 /*
01056  * This variant of list_concat_unique() operates upon lists of OIDs.
01057  */
01058 List *
01059 list_concat_unique_oid(List *list1, List *list2)
01060 {
01061     ListCell   *cell;
01062 
01063     Assert(IsOidList(list1));
01064     Assert(IsOidList(list2));
01065 
01066     foreach(cell, list2)
01067     {
01068         if (!list_member_oid(list1, lfirst_oid(cell)))
01069             list1 = lappend_oid(list1, lfirst_oid(cell));
01070     }
01071 
01072     check_list_invariants(list1);
01073     return list1;
01074 }
01075 
01076 /*
01077  * Free all storage in a list, and optionally the pointed-to elements
01078  */
01079 static void
01080 list_free_private(List *list, bool deep)
01081 {
01082     ListCell   *cell;
01083 
01084     check_list_invariants(list);
01085 
01086     cell = list_head(list);
01087     while (cell != NULL)
01088     {
01089         ListCell   *tmp = cell;
01090 
01091         cell = lnext(cell);
01092         if (deep)
01093             pfree(lfirst(tmp));
01094         pfree(tmp);
01095     }
01096 
01097     if (list)
01098         pfree(list);
01099 }
01100 
01101 /*
01102  * Free all the cells of the list, as well as the list itself. Any
01103  * objects that are pointed-to by the cells of the list are NOT
01104  * free'd.
01105  *
01106  * On return, the argument to this function has been freed, so the
01107  * caller would be wise to set it to NIL for safety's sake.
01108  */
01109 void
01110 list_free(List *list)
01111 {
01112     list_free_private(list, false);
01113 }
01114 
01115 /*
01116  * Free all the cells of the list, the list itself, and all the
01117  * objects pointed-to by the cells of the list (each element in the
01118  * list must contain a pointer to a palloc()'d region of memory!)
01119  *
01120  * On return, the argument to this function has been freed, so the
01121  * caller would be wise to set it to NIL for safety's sake.
01122  */
01123 void
01124 list_free_deep(List *list)
01125 {
01126     /*
01127      * A "deep" free operation only makes sense on a list of pointers.
01128      */
01129     Assert(IsPointerList(list));
01130     list_free_private(list, true);
01131 }
01132 
01133 /*
01134  * Return a shallow copy of the specified list.
01135  */
01136 List *
01137 list_copy(const List *oldlist)
01138 {
01139     List       *newlist;
01140     ListCell   *newlist_prev;
01141     ListCell   *oldlist_cur;
01142 
01143     if (oldlist == NIL)
01144         return NIL;
01145 
01146     newlist = new_list(oldlist->type);
01147     newlist->length = oldlist->length;
01148 
01149     /*
01150      * Copy over the data in the first cell; new_list() has already allocated
01151      * the head cell itself
01152      */
01153     newlist->head->data = oldlist->head->data;
01154 
01155     newlist_prev = newlist->head;
01156     oldlist_cur = oldlist->head->next;
01157     while (oldlist_cur)
01158     {
01159         ListCell   *newlist_cur;
01160 
01161         newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
01162         newlist_cur->data = oldlist_cur->data;
01163         newlist_prev->next = newlist_cur;
01164 
01165         newlist_prev = newlist_cur;
01166         oldlist_cur = oldlist_cur->next;
01167     }
01168 
01169     newlist_prev->next = NULL;
01170     newlist->tail = newlist_prev;
01171 
01172     check_list_invariants(newlist);
01173     return newlist;
01174 }
01175 
01176 /*
01177  * Return a shallow copy of the specified list, without the first N elements.
01178  */
01179 List *
01180 list_copy_tail(const List *oldlist, int nskip)
01181 {
01182     List       *newlist;
01183     ListCell   *newlist_prev;
01184     ListCell   *oldlist_cur;
01185 
01186     if (nskip < 0)
01187         nskip = 0;              /* would it be better to elog? */
01188 
01189     if (oldlist == NIL || nskip >= oldlist->length)
01190         return NIL;
01191 
01192     newlist = new_list(oldlist->type);
01193     newlist->length = oldlist->length - nskip;
01194 
01195     /*
01196      * Skip over the unwanted elements.
01197      */
01198     oldlist_cur = oldlist->head;
01199     while (nskip-- > 0)
01200         oldlist_cur = oldlist_cur->next;
01201 
01202     /*
01203      * Copy over the data in the first remaining cell; new_list() has already
01204      * allocated the head cell itself
01205      */
01206     newlist->head->data = oldlist_cur->data;
01207 
01208     newlist_prev = newlist->head;
01209     oldlist_cur = oldlist_cur->next;
01210     while (oldlist_cur)
01211     {
01212         ListCell   *newlist_cur;
01213 
01214         newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
01215         newlist_cur->data = oldlist_cur->data;
01216         newlist_prev->next = newlist_cur;
01217 
01218         newlist_prev = newlist_cur;
01219         oldlist_cur = oldlist_cur->next;
01220     }
01221 
01222     newlist_prev->next = NULL;
01223     newlist->tail = newlist_prev;
01224 
01225     check_list_invariants(newlist);
01226     return newlist;
01227 }
01228 
01229 /*
01230  * Temporary compatibility functions
01231  *
01232  * In order to avoid warnings for these function definitions, we need
01233  * to include a prototype here as well as in pg_list.h. That's because
01234  * we don't enable list API compatibility in list.c, so we
01235  * don't see the prototypes for these functions.
01236  */
01237 
01238 /*
01239  * Given a list, return its length. This is merely defined for the
01240  * sake of backward compatibility: we can't afford to define a macro
01241  * called "length", so it must be a function. New code should use the
01242  * list_length() macro in order to avoid the overhead of a function
01243  * call.
01244  */
01245 int         length(const List *list);
01246 
01247 int
01248 length(const List *list)
01249 {
01250     return list_length(list);
01251 }