Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/nodes/list.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * list.c
4
 *    implementation for PostgreSQL generic list package
5
 *
6
 * See comments in pg_list.h.
7
 *
8
 *
9
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
10
 * Portions Copyright (c) 1994, Regents of the University of California
11
 *
12
 *
13
 * IDENTIFICATION
14
 *    src/backend/nodes/list.c
15
 *
16
 *-------------------------------------------------------------------------
17
 */
18
#include "postgres.h"
19
20
#include "common/int.h"
21
#include "nodes/pg_list.h"
22
#include "port/pg_bitutils.h"
23
#include "utils/memdebug.h"
24
#include "utils/memutils.h"
25
26
27
/*
28
 * The previous List implementation, since it used a separate palloc chunk
29
 * for each cons cell, had the property that adding or deleting list cells
30
 * did not move the storage of other existing cells in the list.  Quite a
31
 * bit of existing code depended on that, by retaining ListCell pointers
32
 * across such operations on a list.  There is no such guarantee in this
33
 * implementation, so instead we have debugging support that is meant to
34
 * help flush out now-broken assumptions.  Defining DEBUG_LIST_MEMORY_USAGE
35
 * while building this file causes the List operations to forcibly move
36
 * all cells in a list whenever a cell is added or deleted.  In combination
37
 * with MEMORY_CONTEXT_CHECKING and/or Valgrind, this can usually expose
38
 * broken code.  It's a bit expensive though, as there's many more palloc
39
 * cycles and a lot more data-copying than in a default build.
40
 *
41
 * By default, we enable this when building for Valgrind.
42
 */
43
#ifdef USE_VALGRIND
44
#define DEBUG_LIST_MEMORY_USAGE
45
#endif
46
47
/* Overhead for the fixed part of a List header, measured in ListCells */
48
#define LIST_HEADER_OVERHEAD  \
49
0
  ((int) ((offsetof(List, initial_elements) - 1) / sizeof(ListCell) + 1))
50
51
/*
52
 * Macros to simplify writing assertions about the type of a list; a
53
 * NIL list is considered to be an empty list of any type.
54
 */
55
#define IsPointerList(l)    ((l) == NIL || IsA((l), List))
56
#define IsIntegerList(l)    ((l) == NIL || IsA((l), IntList))
57
#define IsOidList(l)      ((l) == NIL || IsA((l), OidList))
58
#define IsXidList(l)      ((l) == NIL || IsA((l), XidList))
59
60
#ifdef USE_ASSERT_CHECKING
61
/*
62
 * Check that the specified List is valid (so far as we can tell).
63
 */
64
static void
65
check_list_invariants(const List *list)
66
{
67
  if (list == NIL)
68
    return;
69
70
  Assert(list->length > 0);
71
  Assert(list->length <= list->max_length);
72
  Assert(list->elements != NULL);
73
74
  Assert(list->type == T_List ||
75
       list->type == T_IntList ||
76
       list->type == T_OidList ||
77
       list->type == T_XidList);
78
}
79
#else
80
0
#define check_list_invariants(l)  ((void) 0)
81
#endif              /* USE_ASSERT_CHECKING */
82
83
/*
84
 * Return a freshly allocated List with room for at least min_size cells.
85
 *
86
 * Since empty non-NIL lists are invalid, new_list() sets the initial length
87
 * to min_size, effectively marking that number of cells as valid; the caller
88
 * is responsible for filling in their data.
89
 */
90
static List *
91
new_list(NodeTag type, int min_size)
92
0
{
93
0
  List     *newlist;
94
0
  int     max_size;
95
96
0
  Assert(min_size > 0);
97
98
  /*
99
   * We allocate all the requested cells, and possibly some more, as part of
100
   * the same palloc request as the List header.  This is a big win for the
101
   * typical case of short fixed-length lists.  It can lose if we allocate a
102
   * moderately long list and then it gets extended; we'll be wasting more
103
   * initial_elements[] space than if we'd made the header small.  However,
104
   * rounding up the request as we do in the normal code path provides some
105
   * defense against small extensions.
106
   */
107
108
0
#ifndef DEBUG_LIST_MEMORY_USAGE
109
110
  /*
111
   * Normally, we set up a list with some extra cells, to allow it to grow
112
   * without a repalloc.  Prefer cell counts chosen to make the total
113
   * allocation a power-of-2, since palloc would round it up to that anyway.
114
   * (That stops being true for very large allocations, but very long lists
115
   * are infrequent, so it doesn't seem worth special logic for such cases.)
116
   *
117
   * The minimum allocation is 8 ListCell units, providing either 4 or 5
118
   * available ListCells depending on the machine's word width.  Counting
119
   * palloc's overhead, this uses the same amount of space as a one-cell
120
   * list did in the old implementation, and less space for any longer list.
121
   *
122
   * We needn't worry about integer overflow; no caller passes min_size
123
   * that's more than twice the size of an existing list, so the size limits
124
   * within palloc will ensure that we don't overflow here.
125
   */
126
0
  max_size = pg_nextpower2_32(Max(8, min_size + LIST_HEADER_OVERHEAD));
127
0
  max_size -= LIST_HEADER_OVERHEAD;
128
#else
129
130
  /*
131
   * For debugging, don't allow any extra space.  This forces any cell
132
   * addition to go through enlarge_list() and thus move the existing data.
133
   */
134
  max_size = min_size;
135
#endif
136
137
0
  newlist = (List *) palloc(offsetof(List, initial_elements) +
138
0
                max_size * sizeof(ListCell));
139
0
  newlist->type = type;
140
0
  newlist->length = min_size;
141
0
  newlist->max_length = max_size;
142
0
  newlist->elements = newlist->initial_elements;
143
144
0
  return newlist;
145
0
}
146
147
/*
148
 * Enlarge an existing non-NIL List to have room for at least min_size cells.
149
 *
150
 * This does *not* update list->length, as some callers would find that
151
 * inconvenient.  (list->length had better be the correct number of existing
152
 * valid cells, though.)
153
 */
154
static void
155
enlarge_list(List *list, int min_size)
156
0
{
157
0
  int     new_max_len;
158
159
0
  Assert(min_size > list->max_length);  /* else we shouldn't be here */
160
161
0
#ifndef DEBUG_LIST_MEMORY_USAGE
162
163
  /*
164
   * As above, we prefer power-of-two total allocations; but here we need
165
   * not account for list header overhead.
166
   */
167
168
  /* clamp the minimum value to 16, a semi-arbitrary small power of 2 */
169
0
  new_max_len = pg_nextpower2_32(Max(16, min_size));
170
171
#else
172
  /* As above, don't allocate anything extra */
173
  new_max_len = min_size;
174
#endif
175
176
0
  if (list->elements == list->initial_elements)
177
0
  {
178
    /*
179
     * Replace original in-line allocation with a separate palloc block.
180
     * Ensure it is in the same memory context as the List header.  (The
181
     * previous List implementation did not offer any guarantees about
182
     * keeping all list cells in the same context, but it seems reasonable
183
     * to create such a guarantee now.)
184
     */
185
0
    list->elements = (ListCell *)
186
0
      MemoryContextAlloc(GetMemoryChunkContext(list),
187
0
                 new_max_len * sizeof(ListCell));
188
0
    memcpy(list->elements, list->initial_elements,
189
0
         list->length * sizeof(ListCell));
190
191
    /*
192
     * We must not move the list header, so it's unsafe to try to reclaim
193
     * the initial_elements[] space via repalloc.  In debugging builds,
194
     * however, we can clear that space and/or mark it inaccessible.
195
     * (wipe_mem includes VALGRIND_MAKE_MEM_NOACCESS.)
196
     */
197
#ifdef CLOBBER_FREED_MEMORY
198
    wipe_mem(list->initial_elements,
199
         list->max_length * sizeof(ListCell));
200
#else
201
0
    VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
202
0
                   list->max_length * sizeof(ListCell));
203
0
#endif
204
0
  }
205
0
  else
206
0
  {
207
0
#ifndef DEBUG_LIST_MEMORY_USAGE
208
    /* Normally, let repalloc deal with enlargement */
209
0
    list->elements = (ListCell *) repalloc(list->elements,
210
0
                         new_max_len * sizeof(ListCell));
211
#else
212
    /*
213
     * repalloc() might enlarge the space in-place, which we don't want
214
     * for debugging purposes, so forcibly move the data somewhere else.
215
     */
216
    ListCell   *newelements;
217
218
    newelements = (ListCell *)
219
      MemoryContextAlloc(GetMemoryChunkContext(list),
220
                 new_max_len * sizeof(ListCell));
221
    memcpy(newelements, list->elements,
222
         list->length * sizeof(ListCell));
223
    pfree(list->elements);
224
    list->elements = newelements;
225
#endif
226
0
  }
227
228
0
  list->max_length = new_max_len;
229
0
}
230
231
/*
232
 * Convenience functions to construct short Lists from given values.
233
 * (These are normally invoked via the list_makeN macros.)
234
 */
235
List *
236
list_make1_impl(NodeTag t, ListCell datum1)
237
0
{
238
0
  List     *list = new_list(t, 1);
239
240
0
  list->elements[0] = datum1;
241
0
  check_list_invariants(list);
242
0
  return list;
243
0
}
244
245
List *
246
list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2)
247
0
{
248
0
  List     *list = new_list(t, 2);
249
250
0
  list->elements[0] = datum1;
251
0
  list->elements[1] = datum2;
252
0
  check_list_invariants(list);
253
0
  return list;
254
0
}
255
256
List *
257
list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2,
258
        ListCell datum3)
259
0
{
260
0
  List     *list = new_list(t, 3);
261
262
0
  list->elements[0] = datum1;
263
0
  list->elements[1] = datum2;
264
0
  list->elements[2] = datum3;
265
0
  check_list_invariants(list);
266
0
  return list;
267
0
}
268
269
List *
270
list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2,
271
        ListCell datum3, ListCell datum4)
272
0
{
273
0
  List     *list = new_list(t, 4);
274
275
0
  list->elements[0] = datum1;
276
0
  list->elements[1] = datum2;
277
0
  list->elements[2] = datum3;
278
0
  list->elements[3] = datum4;
279
0
  check_list_invariants(list);
280
0
  return list;
281
0
}
282
283
List *
284
list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2,
285
        ListCell datum3, ListCell datum4, ListCell datum5)
286
0
{
287
0
  List     *list = new_list(t, 5);
288
289
0
  list->elements[0] = datum1;
290
0
  list->elements[1] = datum2;
291
0
  list->elements[2] = datum3;
292
0
  list->elements[3] = datum4;
293
0
  list->elements[4] = datum5;
294
0
  check_list_invariants(list);
295
0
  return list;
296
0
}
297
298
/*
299
 * Make room for a new head cell in the given (non-NIL) list.
300
 *
301
 * The data in the new head cell is undefined; the caller should be
302
 * sure to fill it in
303
 */
304
static void
305
new_head_cell(List *list)
306
0
{
307
  /* Enlarge array if necessary */
308
0
  if (list->length >= list->max_length)
309
0
    enlarge_list(list, list->length + 1);
310
  /* Now shove the existing data over */
311
0
  memmove(&list->elements[1], &list->elements[0],
312
0
      list->length * sizeof(ListCell));
313
0
  list->length++;
314
0
}
315
316
/*
317
 * Make room for a new tail cell in the given (non-NIL) list.
318
 *
319
 * The data in the new tail cell is undefined; the caller should be
320
 * sure to fill it in
321
 */
322
static void
323
new_tail_cell(List *list)
324
0
{
325
  /* Enlarge array if necessary */
326
0
  if (list->length >= list->max_length)
327
0
    enlarge_list(list, list->length + 1);
328
0
  list->length++;
329
0
}
330
331
/*
332
 * Append a pointer to the list. A pointer to the modified list is
333
 * returned. Note that this function may or may not destructively
334
 * modify the list; callers should always use this function's return
335
 * value, rather than continuing to use the pointer passed as the
336
 * first argument.
337
 */
338
List *
339
lappend(List *list, void *datum)
340
0
{
341
0
  Assert(IsPointerList(list));
342
343
0
  if (list == NIL)
344
0
    list = new_list(T_List, 1);
345
0
  else
346
0
    new_tail_cell(list);
347
348
0
  llast(list) = datum;
349
0
  check_list_invariants(list);
350
0
  return list;
351
0
}
352
353
/*
354
 * Append an integer to the specified list. See lappend()
355
 */
356
List *
357
lappend_int(List *list, int datum)
358
0
{
359
0
  Assert(IsIntegerList(list));
360
361
0
  if (list == NIL)
362
0
    list = new_list(T_IntList, 1);
363
0
  else
364
0
    new_tail_cell(list);
365
366
0
  llast_int(list) = datum;
367
0
  check_list_invariants(list);
368
0
  return list;
369
0
}
370
371
/*
372
 * Append an OID to the specified list. See lappend()
373
 */
374
List *
375
lappend_oid(List *list, Oid datum)
376
0
{
377
0
  Assert(IsOidList(list));
378
379
0
  if (list == NIL)
380
0
    list = new_list(T_OidList, 1);
381
0
  else
382
0
    new_tail_cell(list);
383
384
0
  llast_oid(list) = datum;
385
0
  check_list_invariants(list);
386
0
  return list;
387
0
}
388
389
/*
390
 * Append a TransactionId to the specified list. See lappend()
391
 */
392
List *
393
lappend_xid(List *list, TransactionId datum)
394
0
{
395
0
  Assert(IsXidList(list));
396
397
0
  if (list == NIL)
398
0
    list = new_list(T_XidList, 1);
399
0
  else
400
0
    new_tail_cell(list);
401
402
0
  llast_xid(list) = datum;
403
0
  check_list_invariants(list);
404
0
  return list;
405
0
}
406
407
/*
408
 * Make room for a new cell at position 'pos' (measured from 0).
409
 * The data in the cell is left undefined, and must be filled in by the
410
 * caller. 'list' is assumed to be non-NIL, and 'pos' must be a valid
411
 * list position, ie, 0 <= pos <= list's length.
412
 * Returns address of the new cell.
413
 */
414
static ListCell *
415
insert_new_cell(List *list, int pos)
416
0
{
417
0
  Assert(pos >= 0 && pos <= list->length);
418
419
  /* Enlarge array if necessary */
420
0
  if (list->length >= list->max_length)
421
0
    enlarge_list(list, list->length + 1);
422
  /* Now shove the existing data over */
423
0
  if (pos < list->length)
424
0
    memmove(&list->elements[pos + 1], &list->elements[pos],
425
0
        (list->length - pos) * sizeof(ListCell));
426
0
  list->length++;
427
428
0
  return &list->elements[pos];
429
0
}
430
431
/*
432
 * Insert the given datum at position 'pos' (measured from 0) in the list.
433
 * 'pos' must be valid, ie, 0 <= pos <= list's length.
434
 *
435
 * Note that this takes time proportional to the distance to the end of the
436
 * list, since the following entries must be moved.
437
 */
438
List *
439
list_insert_nth(List *list, int pos, void *datum)
440
0
{
441
0
  if (list == NIL)
442
0
  {
443
0
    Assert(pos == 0);
444
0
    return list_make1(datum);
445
0
  }
446
0
  Assert(IsPointerList(list));
447
0
  lfirst(insert_new_cell(list, pos)) = datum;
448
0
  check_list_invariants(list);
449
0
  return list;
450
0
}
451
452
List *
453
list_insert_nth_int(List *list, int pos, int datum)
454
0
{
455
0
  if (list == NIL)
456
0
  {
457
0
    Assert(pos == 0);
458
0
    return list_make1_int(datum);
459
0
  }
460
0
  Assert(IsIntegerList(list));
461
0
  lfirst_int(insert_new_cell(list, pos)) = datum;
462
0
  check_list_invariants(list);
463
0
  return list;
464
0
}
465
466
List *
467
list_insert_nth_oid(List *list, int pos, Oid datum)
468
0
{
469
0
  if (list == NIL)
470
0
  {
471
0
    Assert(pos == 0);
472
0
    return list_make1_oid(datum);
473
0
  }
474
0
  Assert(IsOidList(list));
475
0
  lfirst_oid(insert_new_cell(list, pos)) = datum;
476
0
  check_list_invariants(list);
477
0
  return list;
478
0
}
479
480
/*
481
 * Prepend a new element to the list. A pointer to the modified list
482
 * is returned. Note that this function may or may not destructively
483
 * modify the list; callers should always use this function's return
484
 * value, rather than continuing to use the pointer passed as the
485
 * second argument.
486
 *
487
 * Note that this takes time proportional to the length of the list,
488
 * since the existing entries must be moved.
489
 *
490
 * Caution: before Postgres 8.0, the original List was unmodified and
491
 * could be considered to retain its separate identity.  This is no longer
492
 * the case.
493
 */
494
List *
495
lcons(void *datum, List *list)
496
0
{
497
0
  Assert(IsPointerList(list));
498
499
0
  if (list == NIL)
500
0
    list = new_list(T_List, 1);
501
0
  else
502
0
    new_head_cell(list);
503
504
0
  linitial(list) = datum;
505
0
  check_list_invariants(list);
506
0
  return list;
507
0
}
508
509
/*
510
 * Prepend an integer to the list. See lcons()
511
 */
512
List *
513
lcons_int(int datum, List *list)
514
0
{
515
0
  Assert(IsIntegerList(list));
516
517
0
  if (list == NIL)
518
0
    list = new_list(T_IntList, 1);
519
0
  else
520
0
    new_head_cell(list);
521
522
0
  linitial_int(list) = datum;
523
0
  check_list_invariants(list);
524
0
  return list;
525
0
}
526
527
/*
528
 * Prepend an OID to the list. See lcons()
529
 */
530
List *
531
lcons_oid(Oid datum, List *list)
532
0
{
533
0
  Assert(IsOidList(list));
534
535
0
  if (list == NIL)
536
0
    list = new_list(T_OidList, 1);
537
0
  else
538
0
    new_head_cell(list);
539
540
0
  linitial_oid(list) = datum;
541
0
  check_list_invariants(list);
542
0
  return list;
543
0
}
544
545
/*
546
 * Concatenate list2 to the end of list1, and return list1.
547
 *
548
 * This is equivalent to lappend'ing each element of list2, in order, to list1.
549
 * list1 is destructively changed, list2 is not.  (However, in the case of
550
 * pointer lists, list1 and list2 will point to the same structures.)
551
 *
552
 * Callers should be sure to use the return value as the new pointer to the
553
 * concatenated list: the 'list1' input pointer may or may not be the same
554
 * as the returned pointer.
555
 *
556
 * Note that this takes at least time proportional to the length of list2.
557
 * It'd typically be the case that we have to enlarge list1's storage,
558
 * probably adding time proportional to the length of list1.
559
 */
560
List *
561
list_concat(List *list1, const List *list2)
562
0
{
563
0
  int     new_len;
564
565
0
  if (list1 == NIL)
566
0
    return list_copy(list2);
567
0
  if (list2 == NIL)
568
0
    return list1;
569
570
0
  Assert(list1->type == list2->type);
571
572
0
  new_len = list1->length + list2->length;
573
  /* Enlarge array if necessary */
574
0
  if (new_len > list1->max_length)
575
0
    enlarge_list(list1, new_len);
576
577
  /* Even if list1 == list2, using memcpy should be safe here */
578
0
  memcpy(&list1->elements[list1->length], &list2->elements[0],
579
0
       list2->length * sizeof(ListCell));
580
0
  list1->length = new_len;
581
582
0
  check_list_invariants(list1);
583
0
  return list1;
584
0
}
585
586
/*
587
 * Form a new list by concatenating the elements of list1 and list2.
588
 *
589
 * Neither input list is modified.  (However, if they are pointer lists,
590
 * the output list will point to the same structures.)
591
 *
592
 * This is equivalent to, but more efficient than,
593
 * list_concat(list_copy(list1), list2).
594
 * Note that some pre-v13 code might list_copy list2 as well, but that's
595
 * pointless now.
596
 */
597
List *
598
list_concat_copy(const List *list1, const List *list2)
599
0
{
600
0
  List     *result;
601
0
  int     new_len;
602
603
0
  if (list1 == NIL)
604
0
    return list_copy(list2);
605
0
  if (list2 == NIL)
606
0
    return list_copy(list1);
607
608
0
  Assert(list1->type == list2->type);
609
610
0
  new_len = list1->length + list2->length;
611
0
  result = new_list(list1->type, new_len);
612
0
  memcpy(result->elements, list1->elements,
613
0
       list1->length * sizeof(ListCell));
614
0
  memcpy(result->elements + list1->length, list2->elements,
615
0
       list2->length * sizeof(ListCell));
616
617
0
  check_list_invariants(result);
618
0
  return result;
619
0
}
620
621
/*
622
 * Truncate 'list' to contain no more than 'new_size' elements. This
623
 * modifies the list in-place! Despite this, callers should use the
624
 * pointer returned by this function to refer to the newly truncated
625
 * list -- it may or may not be the same as the pointer that was
626
 * passed.
627
 *
628
 * Note that any cells removed by list_truncate() are NOT pfree'd.
629
 */
630
List *
631
list_truncate(List *list, int new_size)
632
0
{
633
0
  if (new_size <= 0)
634
0
    return NIL;       /* truncate to zero length */
635
636
  /* If asked to effectively extend the list, do nothing */
637
0
  if (new_size < list_length(list))
638
0
    list->length = new_size;
639
640
  /*
641
   * Note: unlike the individual-list-cell deletion functions, we don't move
642
   * the list cells to new storage, even in DEBUG_LIST_MEMORY_USAGE mode.
643
   * This is because none of them can move in this operation, so just like
644
   * in the old cons-cell-based implementation, this function doesn't
645
   * invalidate any pointers to cells of the list.  This is also the reason
646
   * for not wiping the memory of the deleted cells: the old code didn't
647
   * free them either.  Perhaps later we'll tighten this up.
648
   */
649
650
0
  return list;
651
0
}
652
653
/*
654
 * Return true iff 'datum' is a member of the list. Equality is
655
 * determined via equal(), so callers should ensure that they pass a
656
 * Node as 'datum'.
657
 *
658
 * This does a simple linear search --- avoid using it on long lists.
659
 */
660
bool
661
list_member(const List *list, const void *datum)
662
0
{
663
0
  const ListCell *cell;
664
665
0
  Assert(IsPointerList(list));
666
0
  check_list_invariants(list);
667
668
0
  foreach(cell, list)
669
0
  {
670
0
    if (equal(lfirst(cell), datum))
671
0
      return true;
672
0
  }
673
674
0
  return false;
675
0
}
676
677
/*
678
 * Return true iff 'datum' is a member of the list. Equality is
679
 * determined by using simple pointer comparison.
680
 */
681
bool
682
list_member_ptr(const List *list, const void *datum)
683
0
{
684
0
  const ListCell *cell;
685
686
0
  Assert(IsPointerList(list));
687
0
  check_list_invariants(list);
688
689
0
  foreach(cell, list)
690
0
  {
691
0
    if (lfirst(cell) == datum)
692
0
      return true;
693
0
  }
694
695
0
  return false;
696
0
}
697
698
/*
699
 * Return true iff the integer 'datum' is a member of the list.
700
 */
701
bool
702
list_member_int(const List *list, int datum)
703
0
{
704
0
  const ListCell *cell;
705
706
0
  Assert(IsIntegerList(list));
707
0
  check_list_invariants(list);
708
709
0
  foreach(cell, list)
710
0
  {
711
0
    if (lfirst_int(cell) == datum)
712
0
      return true;
713
0
  }
714
715
0
  return false;
716
0
}
717
718
/*
719
 * Return true iff the OID 'datum' is a member of the list.
720
 */
721
bool
722
list_member_oid(const List *list, Oid datum)
723
0
{
724
0
  const ListCell *cell;
725
726
0
  Assert(IsOidList(list));
727
0
  check_list_invariants(list);
728
729
0
  foreach(cell, list)
730
0
  {
731
0
    if (lfirst_oid(cell) == datum)
732
0
      return true;
733
0
  }
734
735
0
  return false;
736
0
}
737
738
/*
739
 * Return true iff the TransactionId 'datum' is a member of the list.
740
 */
741
bool
742
list_member_xid(const List *list, TransactionId datum)
743
0
{
744
0
  const ListCell *cell;
745
746
0
  Assert(IsXidList(list));
747
0
  check_list_invariants(list);
748
749
0
  foreach(cell, list)
750
0
  {
751
0
    if (lfirst_xid(cell) == datum)
752
0
      return true;
753
0
  }
754
755
0
  return false;
756
0
}
757
758
/*
759
 * Delete the n'th cell (counting from 0) in list.
760
 *
761
 * The List is pfree'd if this was the last member.
762
 *
763
 * Note that this takes time proportional to the distance to the end of the
764
 * list, since the following entries must be moved.
765
 */
766
List *
767
list_delete_nth_cell(List *list, int n)
768
0
{
769
0
  check_list_invariants(list);
770
771
0
  Assert(n >= 0 && n < list->length);
772
773
  /*
774
   * If we're about to delete the last node from the list, free the whole
775
   * list instead and return NIL, which is the only valid representation of
776
   * a zero-length list.
777
   */
778
0
  if (list->length == 1)
779
0
  {
780
0
    list_free(list);
781
0
    return NIL;
782
0
  }
783
784
  /*
785
   * Otherwise, we normally just collapse out the removed element.  But for
786
   * debugging purposes, move the whole list contents someplace else.
787
   *
788
   * (Note that we *must* keep the contents in the same memory context.)
789
   */
790
0
#ifndef DEBUG_LIST_MEMORY_USAGE
791
0
  memmove(&list->elements[n], &list->elements[n + 1],
792
0
      (list->length - 1 - n) * sizeof(ListCell));
793
0
  list->length--;
794
#else
795
  {
796
    ListCell   *newelems;
797
    int     newmaxlen = list->length - 1;
798
799
    newelems = (ListCell *)
800
      MemoryContextAlloc(GetMemoryChunkContext(list),
801
                 newmaxlen * sizeof(ListCell));
802
    memcpy(newelems, list->elements, n * sizeof(ListCell));
803
    memcpy(&newelems[n], &list->elements[n + 1],
804
         (list->length - 1 - n) * sizeof(ListCell));
805
    if (list->elements != list->initial_elements)
806
      pfree(list->elements);
807
    else
808
    {
809
      /*
810
       * As in enlarge_list(), clear the initial_elements[] space and/or
811
       * mark it inaccessible.
812
       */
813
#ifdef CLOBBER_FREED_MEMORY
814
      wipe_mem(list->initial_elements,
815
           list->max_length * sizeof(ListCell));
816
#else
817
      VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
818
                     list->max_length * sizeof(ListCell));
819
#endif
820
    }
821
    list->elements = newelems;
822
    list->max_length = newmaxlen;
823
    list->length--;
824
    check_list_invariants(list);
825
  }
826
#endif
827
828
0
  return list;
829
0
}
830
831
/*
832
 * Delete 'cell' from 'list'.
833
 *
834
 * The List is pfree'd if this was the last member.  However, we do not
835
 * touch any data the cell might've been pointing to.
836
 *
837
 * Note that this takes time proportional to the distance to the end of the
838
 * list, since the following entries must be moved.
839
 */
840
List *
841
list_delete_cell(List *list, ListCell *cell)
842
0
{
843
0
  return list_delete_nth_cell(list, cell - list->elements);
844
0
}
845
846
/*
847
 * Delete the first cell in list that matches datum, if any.
848
 * Equality is determined via equal().
849
 *
850
 * This does a simple linear search --- avoid using it on long lists.
851
 */
852
List *
853
list_delete(List *list, void *datum)
854
0
{
855
0
  ListCell   *cell;
856
857
0
  Assert(IsPointerList(list));
858
0
  check_list_invariants(list);
859
860
0
  foreach(cell, list)
861
0
  {
862
0
    if (equal(lfirst(cell), datum))
863
0
      return list_delete_cell(list, cell);
864
0
  }
865
866
  /* Didn't find a match: return the list unmodified */
867
0
  return list;
868
0
}
869
870
/* As above, but use simple pointer equality */
871
List *
872
list_delete_ptr(List *list, void *datum)
873
0
{
874
0
  ListCell   *cell;
875
876
0
  Assert(IsPointerList(list));
877
0
  check_list_invariants(list);
878
879
0
  foreach(cell, list)
880
0
  {
881
0
    if (lfirst(cell) == datum)
882
0
      return list_delete_cell(list, cell);
883
0
  }
884
885
  /* Didn't find a match: return the list unmodified */
886
0
  return list;
887
0
}
888
889
/* As above, but for integers */
890
List *
891
list_delete_int(List *list, int datum)
892
0
{
893
0
  ListCell   *cell;
894
895
0
  Assert(IsIntegerList(list));
896
0
  check_list_invariants(list);
897
898
0
  foreach(cell, list)
899
0
  {
900
0
    if (lfirst_int(cell) == datum)
901
0
      return list_delete_cell(list, cell);
902
0
  }
903
904
  /* Didn't find a match: return the list unmodified */
905
0
  return list;
906
0
}
907
908
/* As above, but for OIDs */
909
List *
910
list_delete_oid(List *list, Oid datum)
911
0
{
912
0
  ListCell   *cell;
913
914
0
  Assert(IsOidList(list));
915
0
  check_list_invariants(list);
916
917
0
  foreach(cell, list)
918
0
  {
919
0
    if (lfirst_oid(cell) == datum)
920
0
      return list_delete_cell(list, cell);
921
0
  }
922
923
  /* Didn't find a match: return the list unmodified */
924
0
  return list;
925
0
}
926
927
/*
928
 * Delete the first element of the list.
929
 *
930
 * This is useful to replace the Lisp-y code "list = lnext(list);" in cases
931
 * where the intent is to alter the list rather than just traverse it.
932
 * Beware that the list is modified, whereas the Lisp-y coding leaves
933
 * the original list head intact in case there's another pointer to it.
934
 *
935
 * Note that this takes time proportional to the length of the list,
936
 * since the remaining entries must be moved.  Consider reversing the
937
 * list order so that you can use list_delete_last() instead.  However,
938
 * if that causes you to replace lappend() with lcons(), you haven't
939
 * improved matters.  (In short, you can make an efficient stack from
940
 * a List, but not an efficient FIFO queue.)
941
 */
942
List *
943
list_delete_first(List *list)
944
0
{
945
0
  check_list_invariants(list);
946
947
0
  if (list == NIL)
948
0
    return NIL;       /* would an error be better? */
949
950
0
  return list_delete_nth_cell(list, 0);
951
0
}
952
953
/*
954
 * Delete the last element of the list.
955
 */
956
List *
957
list_delete_last(List *list)
958
0
{
959
0
  check_list_invariants(list);
960
961
0
  if (list == NIL)
962
0
    return NIL;       /* would an error be better? */
963
964
  /* list_truncate won't free list if it goes to empty, but this should */
965
0
  if (list_length(list) <= 1)
966
0
  {
967
0
    list_free(list);
968
0
    return NIL;
969
0
  }
970
971
0
  return list_truncate(list, list_length(list) - 1);
972
0
}
973
974
/*
975
 * Delete the first N cells of the list.
976
 *
977
 * The List is pfree'd if the request causes all cells to be deleted.
978
 *
979
 * Note that this takes time proportional to the distance to the end of the
980
 * list, since the following entries must be moved.
981
 */
982
List *
983
list_delete_first_n(List *list, int n)
984
0
{
985
0
  check_list_invariants(list);
986
987
  /* No-op request? */
988
0
  if (n <= 0)
989
0
    return list;
990
991
  /* Delete whole list? */
992
0
  if (n >= list_length(list))
993
0
  {
994
0
    list_free(list);
995
0
    return NIL;
996
0
  }
997
998
  /*
999
   * Otherwise, we normally just collapse out the removed elements.  But for
1000
   * debugging purposes, move the whole list contents someplace else.
1001
   *
1002
   * (Note that we *must* keep the contents in the same memory context.)
1003
   */
1004
0
#ifndef DEBUG_LIST_MEMORY_USAGE
1005
0
  memmove(&list->elements[0], &list->elements[n],
1006
0
      (list->length - n) * sizeof(ListCell));
1007
0
  list->length -= n;
1008
#else
1009
  {
1010
    ListCell   *newelems;
1011
    int     newmaxlen = list->length - n;
1012
1013
    newelems = (ListCell *)
1014
      MemoryContextAlloc(GetMemoryChunkContext(list),
1015
                 newmaxlen * sizeof(ListCell));
1016
    memcpy(newelems, &list->elements[n], newmaxlen * sizeof(ListCell));
1017
    if (list->elements != list->initial_elements)
1018
      pfree(list->elements);
1019
    else
1020
    {
1021
      /*
1022
       * As in enlarge_list(), clear the initial_elements[] space and/or
1023
       * mark it inaccessible.
1024
       */
1025
#ifdef CLOBBER_FREED_MEMORY
1026
      wipe_mem(list->initial_elements,
1027
           list->max_length * sizeof(ListCell));
1028
#else
1029
      VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
1030
                     list->max_length * sizeof(ListCell));
1031
#endif
1032
    }
1033
    list->elements = newelems;
1034
    list->max_length = newmaxlen;
1035
    list->length = newmaxlen;
1036
    check_list_invariants(list);
1037
  }
1038
#endif
1039
1040
0
  return list;
1041
0
}
1042
1043
/*
1044
 * Generate the union of two lists. This is calculated by copying
1045
 * list1 via list_copy(), then adding to it all the members of list2
1046
 * that aren't already in list1.
1047
 *
1048
 * Whether an element is already a member of the list is determined
1049
 * via equal().
1050
 *
1051
 * The returned list is newly-allocated, although the content of the
1052
 * cells is the same (i.e. any pointed-to objects are not copied).
1053
 *
1054
 * NB: this function will NOT remove any duplicates that are present
1055
 * in list1 (so it only performs a "union" if list1 is known unique to
1056
 * start with).  Also, if you are about to write "x = list_union(x, y)"
1057
 * you probably want to use list_concat_unique() instead to avoid wasting
1058
 * the storage of the old x list.
1059
 *
1060
 * Note that this takes time proportional to the product of the list
1061
 * lengths, so beware of using it on long lists.  (We could probably
1062
 * improve that, but really you should be using some other data structure
1063
 * if this'd be a performance bottleneck.)
1064
 */
1065
List *
1066
list_union(const List *list1, const List *list2)
1067
0
{
1068
0
  List     *result;
1069
0
  const ListCell *cell;
1070
1071
0
  Assert(IsPointerList(list1));
1072
0
  Assert(IsPointerList(list2));
1073
1074
0
  result = list_copy(list1);
1075
0
  foreach(cell, list2)
1076
0
  {
1077
0
    if (!list_member(result, lfirst(cell)))
1078
0
      result = lappend(result, lfirst(cell));
1079
0
  }
1080
1081
0
  check_list_invariants(result);
1082
0
  return result;
1083
0
}
1084
1085
/*
1086
 * This variant of list_union() determines duplicates via simple
1087
 * pointer comparison.
1088
 */
1089
List *
1090
list_union_ptr(const List *list1, const List *list2)
1091
0
{
1092
0
  List     *result;
1093
0
  const ListCell *cell;
1094
1095
0
  Assert(IsPointerList(list1));
1096
0
  Assert(IsPointerList(list2));
1097
1098
0
  result = list_copy(list1);
1099
0
  foreach(cell, list2)
1100
0
  {
1101
0
    if (!list_member_ptr(result, lfirst(cell)))
1102
0
      result = lappend(result, lfirst(cell));
1103
0
  }
1104
1105
0
  check_list_invariants(result);
1106
0
  return result;
1107
0
}
1108
1109
/*
1110
 * This variant of list_union() operates upon lists of integers.
1111
 */
1112
List *
1113
list_union_int(const List *list1, const List *list2)
1114
0
{
1115
0
  List     *result;
1116
0
  const ListCell *cell;
1117
1118
0
  Assert(IsIntegerList(list1));
1119
0
  Assert(IsIntegerList(list2));
1120
1121
0
  result = list_copy(list1);
1122
0
  foreach(cell, list2)
1123
0
  {
1124
0
    if (!list_member_int(result, lfirst_int(cell)))
1125
0
      result = lappend_int(result, lfirst_int(cell));
1126
0
  }
1127
1128
0
  check_list_invariants(result);
1129
0
  return result;
1130
0
}
1131
1132
/*
1133
 * This variant of list_union() operates upon lists of OIDs.
1134
 */
1135
List *
1136
list_union_oid(const List *list1, const List *list2)
1137
0
{
1138
0
  List     *result;
1139
0
  const ListCell *cell;
1140
1141
0
  Assert(IsOidList(list1));
1142
0
  Assert(IsOidList(list2));
1143
1144
0
  result = list_copy(list1);
1145
0
  foreach(cell, list2)
1146
0
  {
1147
0
    if (!list_member_oid(result, lfirst_oid(cell)))
1148
0
      result = lappend_oid(result, lfirst_oid(cell));
1149
0
  }
1150
1151
0
  check_list_invariants(result);
1152
0
  return result;
1153
0
}
1154
1155
/*
1156
 * Return a list that contains all the cells that are in both list1 and
1157
 * list2.  The returned list is freshly allocated via palloc(), but the
1158
 * cells themselves point to the same objects as the cells of the
1159
 * input lists.
1160
 *
1161
 * Duplicate entries in list1 will not be suppressed, so it's only a true
1162
 * "intersection" if list1 is known unique beforehand.
1163
 *
1164
 * This variant works on lists of pointers, and determines list
1165
 * membership via equal().  Note that the list1 member will be pointed
1166
 * to in the result.
1167
 *
1168
 * Note that this takes time proportional to the product of the list
1169
 * lengths, so beware of using it on long lists.  (We could probably
1170
 * improve that, but really you should be using some other data structure
1171
 * if this'd be a performance bottleneck.)
1172
 */
1173
List *
1174
list_intersection(const List *list1, const List *list2)
1175
0
{
1176
0
  List     *result;
1177
0
  const ListCell *cell;
1178
1179
0
  if (list1 == NIL || list2 == NIL)
1180
0
    return NIL;
1181
1182
0
  Assert(IsPointerList(list1));
1183
0
  Assert(IsPointerList(list2));
1184
1185
0
  result = NIL;
1186
0
  foreach(cell, list1)
1187
0
  {
1188
0
    if (list_member(list2, lfirst(cell)))
1189
0
      result = lappend(result, lfirst(cell));
1190
0
  }
1191
1192
0
  check_list_invariants(result);
1193
0
  return result;
1194
0
}
1195
1196
/*
1197
 * As list_intersection but operates on lists of integers.
1198
 */
1199
List *
1200
list_intersection_int(const List *list1, const List *list2)
1201
0
{
1202
0
  List     *result;
1203
0
  const ListCell *cell;
1204
1205
0
  if (list1 == NIL || list2 == NIL)
1206
0
    return NIL;
1207
1208
0
  Assert(IsIntegerList(list1));
1209
0
  Assert(IsIntegerList(list2));
1210
1211
0
  result = NIL;
1212
0
  foreach(cell, list1)
1213
0
  {
1214
0
    if (list_member_int(list2, lfirst_int(cell)))
1215
0
      result = lappend_int(result, lfirst_int(cell));
1216
0
  }
1217
1218
0
  check_list_invariants(result);
1219
0
  return result;
1220
0
}
1221
1222
/*
1223
 * Return a list that contains all the cells in list1 that are not in
1224
 * list2. The returned list is freshly allocated via palloc(), but the
1225
 * cells themselves point to the same objects as the cells of the
1226
 * input lists.
1227
 *
1228
 * This variant works on lists of pointers, and determines list
1229
 * membership via equal()
1230
 *
1231
 * Note that this takes time proportional to the product of the list
1232
 * lengths, so beware of using it on long lists.  (We could probably
1233
 * improve that, but really you should be using some other data structure
1234
 * if this'd be a performance bottleneck.)
1235
 */
1236
List *
1237
list_difference(const List *list1, const List *list2)
1238
0
{
1239
0
  const ListCell *cell;
1240
0
  List     *result = NIL;
1241
1242
0
  Assert(IsPointerList(list1));
1243
0
  Assert(IsPointerList(list2));
1244
1245
0
  if (list2 == NIL)
1246
0
    return list_copy(list1);
1247
1248
0
  foreach(cell, list1)
1249
0
  {
1250
0
    if (!list_member(list2, lfirst(cell)))
1251
0
      result = lappend(result, lfirst(cell));
1252
0
  }
1253
1254
0
  check_list_invariants(result);
1255
0
  return result;
1256
0
}
1257
1258
/*
1259
 * This variant of list_difference() determines list membership via
1260
 * simple pointer equality.
1261
 */
1262
List *
1263
list_difference_ptr(const List *list1, const List *list2)
1264
0
{
1265
0
  const ListCell *cell;
1266
0
  List     *result = NIL;
1267
1268
0
  Assert(IsPointerList(list1));
1269
0
  Assert(IsPointerList(list2));
1270
1271
0
  if (list2 == NIL)
1272
0
    return list_copy(list1);
1273
1274
0
  foreach(cell, list1)
1275
0
  {
1276
0
    if (!list_member_ptr(list2, lfirst(cell)))
1277
0
      result = lappend(result, lfirst(cell));
1278
0
  }
1279
1280
0
  check_list_invariants(result);
1281
0
  return result;
1282
0
}
1283
1284
/*
1285
 * This variant of list_difference() operates upon lists of integers.
1286
 */
1287
List *
1288
list_difference_int(const List *list1, const List *list2)
1289
0
{
1290
0
  const ListCell *cell;
1291
0
  List     *result = NIL;
1292
1293
0
  Assert(IsIntegerList(list1));
1294
0
  Assert(IsIntegerList(list2));
1295
1296
0
  if (list2 == NIL)
1297
0
    return list_copy(list1);
1298
1299
0
  foreach(cell, list1)
1300
0
  {
1301
0
    if (!list_member_int(list2, lfirst_int(cell)))
1302
0
      result = lappend_int(result, lfirst_int(cell));
1303
0
  }
1304
1305
0
  check_list_invariants(result);
1306
0
  return result;
1307
0
}
1308
1309
/*
1310
 * This variant of list_difference() operates upon lists of OIDs.
1311
 */
1312
List *
1313
list_difference_oid(const List *list1, const List *list2)
1314
0
{
1315
0
  const ListCell *cell;
1316
0
  List     *result = NIL;
1317
1318
0
  Assert(IsOidList(list1));
1319
0
  Assert(IsOidList(list2));
1320
1321
0
  if (list2 == NIL)
1322
0
    return list_copy(list1);
1323
1324
0
  foreach(cell, list1)
1325
0
  {
1326
0
    if (!list_member_oid(list2, lfirst_oid(cell)))
1327
0
      result = lappend_oid(result, lfirst_oid(cell));
1328
0
  }
1329
1330
0
  check_list_invariants(result);
1331
0
  return result;
1332
0
}
1333
1334
/*
1335
 * Append datum to list, but only if it isn't already in the list.
1336
 *
1337
 * Whether an element is already a member of the list is determined
1338
 * via equal().
1339
 *
1340
 * This does a simple linear search --- avoid using it on long lists.
1341
 */
1342
List *
1343
list_append_unique(List *list, void *datum)
1344
0
{
1345
0
  if (list_member(list, datum))
1346
0
    return list;
1347
0
  else
1348
0
    return lappend(list, datum);
1349
0
}
1350
1351
/*
1352
 * This variant of list_append_unique() determines list membership via
1353
 * simple pointer equality.
1354
 */
1355
List *
1356
list_append_unique_ptr(List *list, void *datum)
1357
0
{
1358
0
  if (list_member_ptr(list, datum))
1359
0
    return list;
1360
0
  else
1361
0
    return lappend(list, datum);
1362
0
}
1363
1364
/*
1365
 * This variant of list_append_unique() operates upon lists of integers.
1366
 */
1367
List *
1368
list_append_unique_int(List *list, int datum)
1369
0
{
1370
0
  if (list_member_int(list, datum))
1371
0
    return list;
1372
0
  else
1373
0
    return lappend_int(list, datum);
1374
0
}
1375
1376
/*
1377
 * This variant of list_append_unique() operates upon lists of OIDs.
1378
 */
1379
List *
1380
list_append_unique_oid(List *list, Oid datum)
1381
0
{
1382
0
  if (list_member_oid(list, datum))
1383
0
    return list;
1384
0
  else
1385
0
    return lappend_oid(list, datum);
1386
0
}
1387
1388
/*
1389
 * Append to list1 each member of list2 that isn't already in list1.
1390
 *
1391
 * Whether an element is already a member of the list is determined
1392
 * via equal().
1393
 *
1394
 * This is almost the same functionality as list_union(), but list1 is
1395
 * modified in-place rather than being copied. However, callers of this
1396
 * function may have strict ordering expectations -- i.e. that the relative
1397
 * order of those list2 elements that are not duplicates is preserved.
1398
 *
1399
 * Note that this takes time proportional to the product of the list
1400
 * lengths, so beware of using it on long lists.  (We could probably
1401
 * improve that, but really you should be using some other data structure
1402
 * if this'd be a performance bottleneck.)
1403
 */
1404
List *
1405
list_concat_unique(List *list1, const List *list2)
1406
0
{
1407
0
  ListCell   *cell;
1408
1409
0
  Assert(IsPointerList(list1));
1410
0
  Assert(IsPointerList(list2));
1411
1412
0
  foreach(cell, list2)
1413
0
  {
1414
0
    if (!list_member(list1, lfirst(cell)))
1415
0
      list1 = lappend(list1, lfirst(cell));
1416
0
  }
1417
1418
0
  check_list_invariants(list1);
1419
0
  return list1;
1420
0
}
1421
1422
/*
1423
 * This variant of list_concat_unique() determines list membership via
1424
 * simple pointer equality.
1425
 */
1426
List *
1427
list_concat_unique_ptr(List *list1, const List *list2)
1428
0
{
1429
0
  ListCell   *cell;
1430
1431
0
  Assert(IsPointerList(list1));
1432
0
  Assert(IsPointerList(list2));
1433
1434
0
  foreach(cell, list2)
1435
0
  {
1436
0
    if (!list_member_ptr(list1, lfirst(cell)))
1437
0
      list1 = lappend(list1, lfirst(cell));
1438
0
  }
1439
1440
0
  check_list_invariants(list1);
1441
0
  return list1;
1442
0
}
1443
1444
/*
1445
 * This variant of list_concat_unique() operates upon lists of integers.
1446
 */
1447
List *
1448
list_concat_unique_int(List *list1, const List *list2)
1449
0
{
1450
0
  ListCell   *cell;
1451
1452
0
  Assert(IsIntegerList(list1));
1453
0
  Assert(IsIntegerList(list2));
1454
1455
0
  foreach(cell, list2)
1456
0
  {
1457
0
    if (!list_member_int(list1, lfirst_int(cell)))
1458
0
      list1 = lappend_int(list1, lfirst_int(cell));
1459
0
  }
1460
1461
0
  check_list_invariants(list1);
1462
0
  return list1;
1463
0
}
1464
1465
/*
1466
 * This variant of list_concat_unique() operates upon lists of OIDs.
1467
 */
1468
List *
1469
list_concat_unique_oid(List *list1, const List *list2)
1470
0
{
1471
0
  ListCell   *cell;
1472
1473
0
  Assert(IsOidList(list1));
1474
0
  Assert(IsOidList(list2));
1475
1476
0
  foreach(cell, list2)
1477
0
  {
1478
0
    if (!list_member_oid(list1, lfirst_oid(cell)))
1479
0
      list1 = lappend_oid(list1, lfirst_oid(cell));
1480
0
  }
1481
1482
0
  check_list_invariants(list1);
1483
0
  return list1;
1484
0
}
1485
1486
/*
1487
 * Remove adjacent duplicates in a list of OIDs.
1488
 *
1489
 * It is caller's responsibility to have sorted the list to bring duplicates
1490
 * together, perhaps via list_sort(list, list_oid_cmp).
1491
 *
1492
 * Note that this takes time proportional to the length of the list.
1493
 */
1494
void
1495
list_deduplicate_oid(List *list)
1496
0
{
1497
0
  int     len;
1498
1499
0
  Assert(IsOidList(list));
1500
0
  len = list_length(list);
1501
0
  if (len > 1)
1502
0
  {
1503
0
    ListCell   *elements = list->elements;
1504
0
    int     i = 0;
1505
1506
0
    for (int j = 1; j < len; j++)
1507
0
    {
1508
0
      if (elements[i].oid_value != elements[j].oid_value)
1509
0
        elements[++i].oid_value = elements[j].oid_value;
1510
0
    }
1511
0
    list->length = i + 1;
1512
0
  }
1513
0
  check_list_invariants(list);
1514
0
}
1515
1516
/*
1517
 * Free all storage in a list, and optionally the pointed-to elements
1518
 */
1519
static void
1520
list_free_private(List *list, bool deep)
1521
0
{
1522
0
  if (list == NIL)
1523
0
    return;         /* nothing to do */
1524
1525
0
  check_list_invariants(list);
1526
1527
0
  if (deep)
1528
0
  {
1529
0
    for (int i = 0; i < list->length; i++)
1530
0
      pfree(lfirst(&list->elements[i]));
1531
0
  }
1532
0
  if (list->elements != list->initial_elements)
1533
0
    pfree(list->elements);
1534
0
  pfree(list);
1535
0
}
1536
1537
/*
1538
 * Free all the cells of the list, as well as the list itself. Any
1539
 * objects that are pointed-to by the cells of the list are NOT
1540
 * free'd.
1541
 *
1542
 * On return, the argument to this function has been freed, so the
1543
 * caller would be wise to set it to NIL for safety's sake.
1544
 */
1545
void
1546
list_free(List *list)
1547
0
{
1548
0
  list_free_private(list, false);
1549
0
}
1550
1551
/*
1552
 * Free all the cells of the list, the list itself, and all the
1553
 * objects pointed-to by the cells of the list (each element in the
1554
 * list must contain a pointer to a palloc()'d region of memory!)
1555
 *
1556
 * On return, the argument to this function has been freed, so the
1557
 * caller would be wise to set it to NIL for safety's sake.
1558
 */
1559
void
1560
list_free_deep(List *list)
1561
0
{
1562
  /*
1563
   * A "deep" free operation only makes sense on a list of pointers.
1564
   */
1565
0
  Assert(IsPointerList(list));
1566
0
  list_free_private(list, true);
1567
0
}
1568
1569
/*
1570
 * Return a shallow copy of the specified list.
1571
 */
1572
List *
1573
list_copy(const List *oldlist)
1574
0
{
1575
0
  List     *newlist;
1576
1577
0
  if (oldlist == NIL)
1578
0
    return NIL;
1579
1580
0
  newlist = new_list(oldlist->type, oldlist->length);
1581
0
  memcpy(newlist->elements, oldlist->elements,
1582
0
       newlist->length * sizeof(ListCell));
1583
1584
0
  check_list_invariants(newlist);
1585
0
  return newlist;
1586
0
}
1587
1588
/*
1589
 * Return a shallow copy of the specified list containing only the first 'len'
1590
 * elements.  If oldlist is shorter than 'len' then we copy the entire list.
1591
 */
1592
List *
1593
list_copy_head(const List *oldlist, int len)
1594
0
{
1595
0
  List     *newlist;
1596
1597
0
  if (oldlist == NIL || len <= 0)
1598
0
    return NIL;
1599
1600
0
  len = Min(oldlist->length, len);
1601
1602
0
  newlist = new_list(oldlist->type, len);
1603
0
  memcpy(newlist->elements, oldlist->elements, len * sizeof(ListCell));
1604
1605
0
  check_list_invariants(newlist);
1606
0
  return newlist;
1607
0
}
1608
1609
/*
1610
 * Return a shallow copy of the specified list, without the first N elements.
1611
 */
1612
List *
1613
list_copy_tail(const List *oldlist, int nskip)
1614
0
{
1615
0
  List     *newlist;
1616
1617
0
  if (nskip < 0)
1618
0
    nskip = 0;       /* would it be better to elog? */
1619
1620
0
  if (oldlist == NIL || nskip >= oldlist->length)
1621
0
    return NIL;
1622
1623
0
  newlist = new_list(oldlist->type, oldlist->length - nskip);
1624
0
  memcpy(newlist->elements, &oldlist->elements[nskip],
1625
0
       newlist->length * sizeof(ListCell));
1626
1627
0
  check_list_invariants(newlist);
1628
0
  return newlist;
1629
0
}
1630
1631
/*
1632
 * Return a deep copy of the specified list.
1633
 *
1634
 * The list elements are copied via copyObject(), so that this function's
1635
 * idea of a "deep" copy is considerably deeper than what list_free_deep()
1636
 * means by the same word.
1637
 */
1638
List *
1639
list_copy_deep(const List *oldlist)
1640
0
{
1641
0
  List     *newlist;
1642
1643
0
  if (oldlist == NIL)
1644
0
    return NIL;
1645
1646
  /* This is only sensible for pointer Lists */
1647
0
  Assert(IsA(oldlist, List));
1648
1649
0
  newlist = new_list(oldlist->type, oldlist->length);
1650
0
  for (int i = 0; i < newlist->length; i++)
1651
0
    lfirst(&newlist->elements[i]) =
1652
0
      copyObjectImpl(lfirst(&oldlist->elements[i]));
1653
1654
0
  check_list_invariants(newlist);
1655
0
  return newlist;
1656
0
}
1657
1658
/*
1659
 * Sort a list according to the specified comparator function.
1660
 *
1661
 * The list is sorted in-place.
1662
 *
1663
 * The comparator function is declared to receive arguments of type
1664
 * const ListCell *; this allows it to use lfirst() and variants
1665
 * without casting its arguments.  Otherwise it behaves the same as
1666
 * the comparator function for standard qsort().
1667
 *
1668
 * Like qsort(), this provides no guarantees about sort stability
1669
 * for equal keys.
1670
 *
1671
 * This is based on qsort(), so it likewise has O(N log N) runtime.
1672
 */
1673
void
1674
list_sort(List *list, list_sort_comparator cmp)
1675
0
{
1676
0
  typedef int (*qsort_comparator) (const void *a, const void *b);
1677
0
  int     len;
1678
1679
0
  check_list_invariants(list);
1680
1681
  /* Nothing to do if there's less than two elements */
1682
0
  len = list_length(list);
1683
0
  if (len > 1)
1684
0
    qsort(list->elements, len, sizeof(ListCell), (qsort_comparator) cmp);
1685
0
}
1686
1687
/*
1688
 * list_sort comparator for sorting a list into ascending int order.
1689
 */
1690
int
1691
list_int_cmp(const ListCell *p1, const ListCell *p2)
1692
0
{
1693
0
  int     v1 = lfirst_int(p1);
1694
0
  int     v2 = lfirst_int(p2);
1695
1696
0
  return pg_cmp_s32(v1, v2);
1697
0
}
1698
1699
/*
1700
 * list_sort comparator for sorting a list into ascending OID order.
1701
 */
1702
int
1703
list_oid_cmp(const ListCell *p1, const ListCell *p2)
1704
0
{
1705
0
  Oid     v1 = lfirst_oid(p1);
1706
0
  Oid     v2 = lfirst_oid(p2);
1707
1708
0
  return pg_cmp_u32(v1, v2);
1709
0
}