Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pg_list.h636 linesDownload Raw Back to nodes
1/*-------------------------------------------------------------------------2 *3 * pg_list.h4 *	  interface for PostgreSQL generic list package5 *6 * Once upon a time, parts of Postgres were written in Lisp and used real7 * cons-cell lists for major data structures.  When that code was rewritten8 * in C, we initially had a faithful emulation of cons-cell lists, which9 * unsurprisingly was a performance bottleneck.  A couple of major rewrites10 * later, these data structures are actually simple expansible arrays;11 * but the "List" name and a lot of the notation survives.12 *13 * One important concession to the original implementation is that an empty14 * list is always represented by a null pointer (preferentially written NIL).15 * Non-empty lists have a header, which will not be relocated as long as the16 * list remains non-empty, and an expansible data array.17 *18 * We support four types of lists:19 *20 *	T_List: lists of pointers21 *		(in practice usually pointers to Nodes, but not always;22 *		declared as "void *" to minimize casting annoyances)23 *	T_IntList: lists of integers24 *	T_OidList: lists of Oids25 *	T_XidList: lists of TransactionIds26 *		(the XidList infrastructure is less complete than the other cases)27 *28 * (At the moment, ints, Oids, and XIDs are the same size, but they may not29 * always be so; be careful to use the appropriate list type for your data.)30 *31 *32 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group33 * Portions Copyright (c) 1994, Regents of the University of California34 *35 * src/include/nodes/pg_list.h36 *37 *-------------------------------------------------------------------------38 */39#ifndef PG_LIST_H40#define PG_LIST_H41 42#include "nodes/nodes.h"43 44 45typedef union ListCell46{47	void	   *ptr_value;48	int			int_value;49	Oid			oid_value;50	TransactionId xid_value;51} ListCell;52 53typedef struct List54{55	NodeTag		type;			/* T_List, T_IntList, T_OidList, or T_XidList */56	int			length;			/* number of elements currently present */57	int			max_length;		/* allocated length of elements[] */58	ListCell   *elements;		/* re-allocatable array of cells */59	/* We may allocate some cells along with the List header: */60	ListCell	initial_elements[FLEXIBLE_ARRAY_MEMBER];61	/* If elements == initial_elements, it's not a separate allocation */62} List;63 64/*65 * The *only* valid representation of an empty list is NIL; in other66 * words, a non-NIL list is guaranteed to have length >= 1.67 */68#define NIL						((List *) NULL)69 70/*71 * State structs for various looping macros below.72 */73typedef struct ForEachState74{75	const List *l;				/* list we're looping through */76	int			i;				/* current element index */77} ForEachState;78 79typedef struct ForBothState80{81	const List *l1;				/* lists we're looping through */82	const List *l2;83	int			i;				/* common element index */84} ForBothState;85 86typedef struct ForBothCellState87{88	const List *l1;				/* lists we're looping through */89	const List *l2;90	int			i1;				/* current element indexes */91	int			i2;92} ForBothCellState;93 94typedef struct ForThreeState95{96	const List *l1;				/* lists we're looping through */97	const List *l2;98	const List *l3;99	int			i;				/* common element index */100} ForThreeState;101 102typedef struct ForFourState103{104	const List *l1;				/* lists we're looping through */105	const List *l2;106	const List *l3;107	const List *l4;108	int			i;				/* common element index */109} ForFourState;110 111typedef struct ForFiveState112{113	const List *l1;				/* lists we're looping through */114	const List *l2;115	const List *l3;116	const List *l4;117	const List *l5;118	int			i;				/* common element index */119} ForFiveState;120 121/*122 * These routines are small enough, and used often enough, to justify being123 * inline.124 */125 126/* Fetch address of list's first cell; NULL if empty list */127static inline ListCell *128list_head(const List *l)129{130	return l ? &l->elements[0] : NULL;131}132 133/* Fetch address of list's last cell; NULL if empty list */134static inline ListCell *135list_tail(const List *l)136{137	return l ? &l->elements[l->length - 1] : NULL;138}139 140/* Fetch address of list's second cell, if it has one, else NULL */141static inline ListCell *142list_second_cell(const List *l)143{144	if (l && l->length >= 2)145		return &l->elements[1];146	else147		return NULL;148}149 150/* Fetch list's length */151static inline int152list_length(const List *l)153{154	return l ? l->length : 0;155}156 157/*158 * Macros to access the data values within List cells.159 *160 * Note that with the exception of the "xxx_node" macros, these are161 * lvalues and can be assigned to.162 *163 * NB: There is an unfortunate legacy from a previous incarnation of164 * the List API: the macro lfirst() was used to mean "the data in this165 * cons cell". To avoid changing every usage of lfirst(), that meaning166 * has been kept. As a result, lfirst() takes a ListCell and returns167 * the data it contains; to get the data in the first cell of a168 * List, use linitial(). Worse, lsecond() is more closely related to169 * linitial() than lfirst(): given a List, lsecond() returns the data170 * in the second list cell.171 */172#define lfirst(lc)				((lc)->ptr_value)173#define lfirst_int(lc)			((lc)->int_value)174#define lfirst_oid(lc)			((lc)->oid_value)175#define lfirst_xid(lc)			((lc)->xid_value)176#define lfirst_node(type,lc)	castNode(type, lfirst(lc))177 178#define linitial(l)				lfirst(list_nth_cell(l, 0))179#define linitial_int(l)			lfirst_int(list_nth_cell(l, 0))180#define linitial_oid(l)			lfirst_oid(list_nth_cell(l, 0))181#define linitial_node(type,l)	castNode(type, linitial(l))182 183#define lsecond(l)				lfirst(list_nth_cell(l, 1))184#define lsecond_int(l)			lfirst_int(list_nth_cell(l, 1))185#define lsecond_oid(l)			lfirst_oid(list_nth_cell(l, 1))186#define lsecond_node(type,l)	castNode(type, lsecond(l))187 188#define lthird(l)				lfirst(list_nth_cell(l, 2))189#define lthird_int(l)			lfirst_int(list_nth_cell(l, 2))190#define lthird_oid(l)			lfirst_oid(list_nth_cell(l, 2))191#define lthird_node(type,l)		castNode(type, lthird(l))192 193#define lfourth(l)				lfirst(list_nth_cell(l, 3))194#define lfourth_int(l)			lfirst_int(list_nth_cell(l, 3))195#define lfourth_oid(l)			lfirst_oid(list_nth_cell(l, 3))196#define lfourth_node(type,l)	castNode(type, lfourth(l))197 198#define llast(l)				lfirst(list_last_cell(l))199#define llast_int(l)			lfirst_int(list_last_cell(l))200#define llast_oid(l)			lfirst_oid(list_last_cell(l))201#define llast_xid(l)			lfirst_xid(list_last_cell(l))202#define llast_node(type,l)		castNode(type, llast(l))203 204/*205 * Convenience macros for building fixed-length lists206 */207#define list_make_ptr_cell(v)	((ListCell) {.ptr_value = (v)})208#define list_make_int_cell(v)	((ListCell) {.int_value = (v)})209#define list_make_oid_cell(v)	((ListCell) {.oid_value = (v)})210#define list_make_xid_cell(v)	((ListCell) {.xid_value = (v)})211 212#define list_make1(x1) \213	list_make1_impl(T_List, list_make_ptr_cell(x1))214#define list_make2(x1,x2) \215	list_make2_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2))216#define list_make3(x1,x2,x3) \217	list_make3_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \218					list_make_ptr_cell(x3))219#define list_make4(x1,x2,x3,x4) \220	list_make4_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \221					list_make_ptr_cell(x3), list_make_ptr_cell(x4))222#define list_make5(x1,x2,x3,x4,x5) \223	list_make5_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \224					list_make_ptr_cell(x3), list_make_ptr_cell(x4), \225					list_make_ptr_cell(x5))226 227#define list_make1_int(x1) \228	list_make1_impl(T_IntList, list_make_int_cell(x1))229#define list_make2_int(x1,x2) \230	list_make2_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2))231#define list_make3_int(x1,x2,x3) \232	list_make3_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \233					list_make_int_cell(x3))234#define list_make4_int(x1,x2,x3,x4) \235	list_make4_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \236					list_make_int_cell(x3), list_make_int_cell(x4))237#define list_make5_int(x1,x2,x3,x4,x5) \238	list_make5_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \239					list_make_int_cell(x3), list_make_int_cell(x4), \240					list_make_int_cell(x5))241 242#define list_make1_oid(x1) \243	list_make1_impl(T_OidList, list_make_oid_cell(x1))244#define list_make2_oid(x1,x2) \245	list_make2_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2))246#define list_make3_oid(x1,x2,x3) \247	list_make3_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \248					list_make_oid_cell(x3))249#define list_make4_oid(x1,x2,x3,x4) \250	list_make4_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \251					list_make_oid_cell(x3), list_make_oid_cell(x4))252#define list_make5_oid(x1,x2,x3,x4,x5) \253	list_make5_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \254					list_make_oid_cell(x3), list_make_oid_cell(x4), \255					list_make_oid_cell(x5))256 257#define list_make1_xid(x1) \258	list_make1_impl(T_XidList, list_make_xid_cell(x1))259#define list_make2_xid(x1,x2) \260	list_make2_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2))261#define list_make3_xid(x1,x2,x3) \262	list_make3_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \263					list_make_xid_cell(x3))264#define list_make4_xid(x1,x2,x3,x4) \265	list_make4_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \266					list_make_xid_cell(x3), list_make_xid_cell(x4))267#define list_make5_xid(x1,x2,x3,x4,x5) \268	list_make5_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \269					list_make_xid_cell(x3), list_make_xid_cell(x4), \270					list_make_xid_cell(x5))271 272/*273 * Locate the n'th cell (counting from 0) of the list.274 * It is an assertion failure if there is no such cell.275 */276static inline ListCell *277list_nth_cell(const List *list, int n)278{279	Assert(list != NIL);280	Assert(n >= 0 && n < list->length);281	return &list->elements[n];282}283 284/*285 * Return the last cell in a non-NIL List.286 */287static inline ListCell *288list_last_cell(const List *list)289{290	Assert(list != NIL);291	return &list->elements[list->length - 1];292}293 294/*295 * Return the pointer value contained in the n'th element of the296 * specified list. (List elements begin at 0.)297 */298static inline void *299list_nth(const List *list, int n)300{301	Assert(IsA(list, List));302	return lfirst(list_nth_cell(list, n));303}304 305/*306 * Return the integer value contained in the n'th element of the307 * specified list.308 */309static inline int310list_nth_int(const List *list, int n)311{312	Assert(IsA(list, IntList));313	return lfirst_int(list_nth_cell(list, n));314}315 316/*317 * Return the OID value contained in the n'th element of the specified318 * list.319 */320static inline Oid321list_nth_oid(const List *list, int n)322{323	Assert(IsA(list, OidList));324	return lfirst_oid(list_nth_cell(list, n));325}326 327#define list_nth_node(type,list,n)	castNode(type, list_nth(list, n))328 329/*330 * Get the given ListCell's index (from 0) in the given List.331 */332static inline int333list_cell_number(const List *l, const ListCell *c)334{335	Assert(c >= &l->elements[0] && c < &l->elements[l->length]);336	return c - l->elements;337}338 339/*340 * Get the address of the next cell after "c" within list "l", or NULL if none.341 */342static inline ListCell *343lnext(const List *l, const ListCell *c)344{345	Assert(c >= &l->elements[0] && c < &l->elements[l->length]);346	c++;347	if (c < &l->elements[l->length])348		return (ListCell *) c;349	else350		return NULL;351}352 353/*354 * foreach -355 *	  a convenience macro for looping through a list356 *357 * "cell" must be the name of a "ListCell *" variable; it's made to point358 * to each List element in turn.  "cell" will be NULL after normal exit from359 * the loop, but an early "break" will leave it pointing at the current360 * List element.361 *362 * Beware of changing the List object while the loop is iterating.363 * The current semantics are that we examine successive list indices in364 * each iteration, so that insertion or deletion of list elements could365 * cause elements to be re-visited or skipped unexpectedly.  Previous366 * implementations of foreach() behaved differently.  However, it's safe367 * to append elements to the List (or in general, insert them after the368 * current element); such new elements are guaranteed to be visited.369 * Also, the current element of the List can be deleted, if you use370 * foreach_delete_current() to do so.  BUT: either of these actions will371 * invalidate the "cell" pointer for the remainder of the current iteration.372 */373#define foreach(cell, lst)	\374	for (ForEachState cell##__state = {(lst), 0}; \375		 (cell##__state.l != NIL && \376		  cell##__state.i < cell##__state.l->length) ? \377		 (cell = &cell##__state.l->elements[cell##__state.i], true) : \378		 (cell = NULL, false); \379		 cell##__state.i++)380 381/*382 * foreach_delete_current -383 *	  delete the current list element from the List associated with a384 *	  surrounding foreach() loop, returning the new List pointer.385 *386 * This is equivalent to list_delete_cell(), but it also adjusts the foreach387 * loop's state so that no list elements will be missed.  Do not delete388 * elements from an active foreach loop's list in any other way!389 */390#define foreach_delete_current(lst, cell)	\391	(cell##__state.i--, \392	 (List *) (cell##__state.l = list_delete_cell(lst, cell)))393 394/*395 * foreach_current_index -396 *	  get the zero-based list index of a surrounding foreach() loop's397 *	  current element; pass the name of the "ListCell *" iterator variable.398 *399 * Beware of using this after foreach_delete_current(); the value will be400 * out of sync for the rest of the current loop iteration.  Anyway, since401 * you just deleted the current element, the value is pretty meaningless.402 */403#define foreach_current_index(cell)  (cell##__state.i)404 405/*406 * for_each_from -407 *	  Like foreach(), but start from the N'th (zero-based) list element,408 *	  not necessarily the first one.409 *410 * It's okay for N to exceed the list length, but not for it to be negative.411 *412 * The caveats for foreach() apply equally here.413 */414#define for_each_from(cell, lst, N)	\415	for (ForEachState cell##__state = for_each_from_setup(lst, N); \416		 (cell##__state.l != NIL && \417		  cell##__state.i < cell##__state.l->length) ? \418		 (cell = &cell##__state.l->elements[cell##__state.i], true) : \419		 (cell = NULL, false); \420		 cell##__state.i++)421 422static inline ForEachState423for_each_from_setup(const List *lst, int N)424{425	ForEachState r = {lst, N};426 427	Assert(N >= 0);428	return r;429}430 431/*432 * for_each_cell -433 *	  a convenience macro which loops through a list starting from a434 *	  specified cell435 *436 * The caveats for foreach() apply equally here.437 */438#define for_each_cell(cell, lst, initcell)	\439	for (ForEachState cell##__state = for_each_cell_setup(lst, initcell); \440		 (cell##__state.l != NIL && \441		  cell##__state.i < cell##__state.l->length) ? \442		 (cell = &cell##__state.l->elements[cell##__state.i], true) : \443		 (cell = NULL, false); \444		 cell##__state.i++)445 446static inline ForEachState447for_each_cell_setup(const List *lst, const ListCell *initcell)448{449	ForEachState r = {lst,450	initcell ? list_cell_number(lst, initcell) : list_length(lst)};451 452	return r;453}454 455/*456 * forboth -457 *	  a convenience macro for advancing through two linked lists458 *	  simultaneously. This macro loops through both lists at the same459 *	  time, stopping when either list runs out of elements. Depending460 *	  on the requirements of the call site, it may also be wise to461 *	  assert that the lengths of the two lists are equal. (But, if they462 *	  are not, some callers rely on the ending cell values being separately463 *	  NULL or non-NULL as defined here; don't try to optimize that.)464 *465 * The caveats for foreach() apply equally here.466 */467#define forboth(cell1, list1, cell2, list2)							\468	for (ForBothState cell1##__state = {(list1), (list2), 0}; \469		 multi_for_advance_cell(cell1, cell1##__state, l1, i), \470		 multi_for_advance_cell(cell2, cell1##__state, l2, i), \471		 (cell1 != NULL && cell2 != NULL); \472		 cell1##__state.i++)473 474#define multi_for_advance_cell(cell, state, l, i) \475	(cell = (state.l != NIL && state.i < state.l->length) ? \476	 &state.l->elements[state.i] : NULL)477 478/*479 * for_both_cell -480 *	  a convenience macro which loops through two lists starting from the481 *	  specified cells of each. This macro loops through both lists at the same482 *	  time, stopping when either list runs out of elements.  Depending on the483 *	  requirements of the call site, it may also be wise to assert that the484 *	  lengths of the two lists are equal, and initcell1 and initcell2 are at485 *	  the same position in the respective lists.486 *487 * The caveats for foreach() apply equally here.488 */489#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2)	\490	for (ForBothCellState cell1##__state = \491			 for_both_cell_setup(list1, initcell1, list2, initcell2); \492		 multi_for_advance_cell(cell1, cell1##__state, l1, i1), \493		 multi_for_advance_cell(cell2, cell1##__state, l2, i2), \494		 (cell1 != NULL && cell2 != NULL); \495		 cell1##__state.i1++, cell1##__state.i2++)496 497static inline ForBothCellState498for_both_cell_setup(const List *list1, const ListCell *initcell1,499					const List *list2, const ListCell *initcell2)500{501	ForBothCellState r = {list1, list2,502		initcell1 ? list_cell_number(list1, initcell1) : list_length(list1),503	initcell2 ? list_cell_number(list2, initcell2) : list_length(list2)};504 505	return r;506}507 508/*509 * forthree -510 *	  the same for three lists511 */512#define forthree(cell1, list1, cell2, list2, cell3, list3) \513	for (ForThreeState cell1##__state = {(list1), (list2), (list3), 0}; \514		 multi_for_advance_cell(cell1, cell1##__state, l1, i), \515		 multi_for_advance_cell(cell2, cell1##__state, l2, i), \516		 multi_for_advance_cell(cell3, cell1##__state, l3, i), \517		 (cell1 != NULL && cell2 != NULL && cell3 != NULL); \518		 cell1##__state.i++)519 520/*521 * forfour -522 *	  the same for four lists523 */524#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \525	for (ForFourState cell1##__state = {(list1), (list2), (list3), (list4), 0}; \526		 multi_for_advance_cell(cell1, cell1##__state, l1, i), \527		 multi_for_advance_cell(cell2, cell1##__state, l2, i), \528		 multi_for_advance_cell(cell3, cell1##__state, l3, i), \529		 multi_for_advance_cell(cell4, cell1##__state, l4, i), \530		 (cell1 != NULL && cell2 != NULL && cell3 != NULL && cell4 != NULL); \531		 cell1##__state.i++)532 533/*534 * forfive -535 *	  the same for five lists536 */537#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \538	for (ForFiveState cell1##__state = {(list1), (list2), (list3), (list4), (list5), 0}; \539		 multi_for_advance_cell(cell1, cell1##__state, l1, i), \540		 multi_for_advance_cell(cell2, cell1##__state, l2, i), \541		 multi_for_advance_cell(cell3, cell1##__state, l3, i), \542		 multi_for_advance_cell(cell4, cell1##__state, l4, i), \543		 multi_for_advance_cell(cell5, cell1##__state, l5, i), \544		 (cell1 != NULL && cell2 != NULL && cell3 != NULL && \545		  cell4 != NULL && cell5 != NULL); \546		 cell1##__state.i++)547 548/* Functions in src/backend/nodes/list.c */549 550extern List *list_make1_impl(NodeTag t, ListCell datum1);551extern List *list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2);552extern List *list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2,553							 ListCell datum3);554extern List *list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2,555							 ListCell datum3, ListCell datum4);556extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2,557							 ListCell datum3, ListCell datum4,558							 ListCell datum5);559 560extern pg_nodiscard List *lappend(List *list, void *datum);561extern pg_nodiscard List *lappend_int(List *list, int datum);562extern pg_nodiscard List *lappend_oid(List *list, Oid datum);563extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum);564 565extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum);566extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum);567extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum);568 569extern pg_nodiscard List *lcons(void *datum, List *list);570extern pg_nodiscard List *lcons_int(int datum, List *list);571extern pg_nodiscard List *lcons_oid(Oid datum, List *list);572 573extern pg_nodiscard List *list_concat(List *list1, const List *list2);574extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2);575 576extern pg_nodiscard List *list_truncate(List *list, int new_size);577 578extern bool list_member(const List *list, const void *datum);579extern bool list_member_ptr(const List *list, const void *datum);580extern bool list_member_int(const List *list, int datum);581extern bool list_member_oid(const List *list, Oid datum);582extern bool list_member_xid(const List *list, TransactionId datum);583 584extern pg_nodiscard List *list_delete(List *list, void *datum);585extern pg_nodiscard List *list_delete_ptr(List *list, void *datum);586extern pg_nodiscard List *list_delete_int(List *list, int datum);587extern pg_nodiscard List *list_delete_oid(List *list, Oid datum);588extern pg_nodiscard List *list_delete_first(List *list);589extern pg_nodiscard List *list_delete_last(List *list);590extern pg_nodiscard List *list_delete_first_n(List *list, int n);591extern pg_nodiscard List *list_delete_nth_cell(List *list, int n);592extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell);593 594extern List *list_union(const List *list1, const List *list2);595extern List *list_union_ptr(const List *list1, const List *list2);596extern List *list_union_int(const List *list1, const List *list2);597extern List *list_union_oid(const List *list1, const List *list2);598 599extern List *list_intersection(const List *list1, const List *list2);600extern List *list_intersection_int(const List *list1, const List *list2);601 602/* currently, there's no need for list_intersection_ptr etc */603 604extern List *list_difference(const List *list1, const List *list2);605extern List *list_difference_ptr(const List *list1, const List *list2);606extern List *list_difference_int(const List *list1, const List *list2);607extern List *list_difference_oid(const List *list1, const List *list2);608 609extern pg_nodiscard List *list_append_unique(List *list, void *datum);610extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum);611extern pg_nodiscard List *list_append_unique_int(List *list, int datum);612extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum);613 614extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2);615extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2);616extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2);617extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2);618 619extern void list_deduplicate_oid(List *list);620 621extern void list_free(List *list);622extern void list_free_deep(List *list);623 624extern pg_nodiscard List *list_copy(const List *oldlist);625extern pg_nodiscard List *list_copy_head(const List *oldlist, int len);626extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip);627extern pg_nodiscard List *list_copy_deep(const List *oldlist);628 629typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b);630extern void list_sort(List *list, list_sort_comparator cmp);631 632extern int	list_int_cmp(const ListCell *p1, const ListCell *p2);633extern int	list_oid_cmp(const ListCell *p1, const ListCell *p2);634 635#endif							/* PG_LIST_H */636 
codekingpro/portable-devtools · Team Ai