Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Objects/setobject.c
Line
Count
Source (jump to first uncovered line)
1
2
/* set object implementation
3
4
   Written and maintained by Raymond D. Hettinger <python@rcn.com>
5
   Derived from Lib/sets.py and Objects/dictobject.c.
6
7
   The basic lookup function used by all operations.
8
   This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
9
10
   The initial probe index is computed as hash mod the table size.
11
   Subsequent probe indices are computed as explained in Objects/dictobject.c.
12
13
   To improve cache locality, each probe inspects a series of consecutive
14
   nearby entries before moving on to probes elsewhere in memory.  This leaves
15
   us with a hybrid of linear probing and randomized probing.  The linear probing
16
   reduces the cost of hash collisions because consecutive memory accesses
17
   tend to be much cheaper than scattered probes.  After LINEAR_PROBES steps,
18
   we then use more of the upper bits from the hash value and apply a simple
19
   linear congruential random number genearator.  This helps break-up long
20
   chains of collisions.
21
22
   All arithmetic on hash should ignore overflow.
23
24
   Unlike the dictionary implementation, the lookkey function can return
25
   NULL if the rich comparison returns an error.
26
27
   Use cases for sets differ considerably from dictionaries where looked-up
28
   keys are more likely to be present.  In contrast, sets are primarily
29
   about membership testing where the presence of an element is not known in
30
   advance.  Accordingly, the set implementation needs to optimize for both
31
   the found and not-found case.
32
*/
33
34
#include "Python.h"
35
#include "pycore_object.h"
36
#include "pycore_pystate.h"
37
#include "structmember.h"
38
39
/* Object used as dummy key to fill deleted entries */
40
static PyObject _dummy_struct;
41
42
15.0k
#define dummy (&_dummy_struct)
43
44
45
/* ======================================================================== */
46
/* ======= Begin logic for probing the hash table ========================= */
47
48
/* Set this to zero to turn-off linear probing */
49
#ifndef LINEAR_PROBES
50
7.11k
#define LINEAR_PROBES 9
51
#endif
52
53
/* This must be >= 1 */
54
724
#define PERTURB_SHIFT 5
55
56
static setentry *
57
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
58
2.60k
{
59
2.60k
    setentry *table;
60
2.60k
    setentry *entry;
61
2.60k
    size_t perturb;
62
2.60k
    size_t mask = so->mask;
63
2.60k
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
64
2.60k
    size_t j;
65
2.60k
    int cmp;
66
67
2.60k
    entry = &so->table[i];
68
2.60k
    if (entry->key == NULL)
69
1.44k
        return entry;
70
71
1.15k
    perturb = hash;
72
73
1.21k
    while (1) {
74
1.21k
        if (entry->hash == hash) {
75
543
            PyObject *startkey = entry->key;
76
            /* startkey cannot be a dummy because the dummy hash field is -1 */
77
543
            assert(startkey != dummy);
78
543
            if (startkey == key)
79
322
                return entry;
80
221
            if (PyUnicode_CheckExact(startkey)
81
221
                && PyUnicode_CheckExact(key)
82
221
                && _PyUnicode_EQ(startkey, key))
83
208
                return entry;
84
13
            table = so->table;
85
13
            Py_INCREF(startkey);
86
13
            cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
87
13
            Py_DECREF(startkey);
88
13
            if (cmp < 0)                                          /* unlikely */
89
0
                return NULL;
90
13
            if (table != so->table || entry->key != startkey)     /* unlikely */
91
0
                return set_lookkey(so, key, hash);
92
13
            if (cmp > 0)                                          /* likely */
93
13
                return entry;
94
0
            mask = so->mask;                 /* help avoid a register spill */
95
0
        }
96
97
672
        if (i + LINEAR_PROBES <= mask) {
98
989
            for (j = 0 ; j < LINEAR_PROBES ; j++) {
99
987
                entry++;
100
987
                if (entry->hash == 0 && entry->key == NULL)
101
447
                    return entry;
102
540
                if (entry->hash == hash) {
103
41
                    PyObject *startkey = entry->key;
104
41
                    assert(startkey != dummy);
105
41
                    if (startkey == key)
106
0
                        return entry;
107
41
                    if (PyUnicode_CheckExact(startkey)
108
41
                        && PyUnicode_CheckExact(key)
109
41
                        && _PyUnicode_EQ(startkey, key))
110
41
                        return entry;
111
0
                    table = so->table;
112
0
                    Py_INCREF(startkey);
113
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
114
0
                    Py_DECREF(startkey);
115
0
                    if (cmp < 0)
116
0
                        return NULL;
117
0
                    if (table != so->table || entry->key != startkey)
118
0
                        return set_lookkey(so, key, hash);
119
0
                    if (cmp > 0)
120
0
                        return entry;
121
0
                    mask = so->mask;
122
0
                }
123
540
            }
124
490
        }
125
126
184
        perturb >>= PERTURB_SHIFT;
127
184
        i = (i * 5 + 1 + perturb) & mask;
128
129
184
        entry = &so->table[i];
130
184
        if (entry->key == NULL)
131
127
            return entry;
132
184
    }
133
1.15k
}
134
135
static int set_table_resize(PySetObject *, Py_ssize_t);
136
137
static int
138
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
139
7.46k
{
140
7.46k
    setentry *table;
141
7.46k
    setentry *freeslot;
142
7.46k
    setentry *entry;
143
7.46k
    size_t perturb;
144
7.46k
    size_t mask;
145
7.46k
    size_t i;                       /* Unsigned for defined overflow behavior */
146
7.46k
    size_t j;
147
7.46k
    int cmp;
148
149
    /* Pre-increment is necessary to prevent arbitrary code in the rich
150
       comparison from deallocating the key just before the insertion. */
151
7.46k
    Py_INCREF(key);
152
153
7.46k
  restart:
154
155
7.46k
    mask = so->mask;
156
7.46k
    i = (size_t)hash & mask;
157
158
7.46k
    entry = &so->table[i];
159
7.46k
    if (entry->key == NULL)
160
5.60k
        goto found_unused;
161
162
1.86k
    freeslot = NULL;
163
1.86k
    perturb = hash;
164
165
2.06k
    while (1) {
166
2.06k
        if (entry->hash == hash) {
167
98
            PyObject *startkey = entry->key;
168
            /* startkey cannot be a dummy because the dummy hash field is -1 */
169
98
            assert(startkey != dummy);
170
98
            if (startkey == key)
171
98
                goto found_active;
172
0
            if (PyUnicode_CheckExact(startkey)
173
0
                && PyUnicode_CheckExact(key)
174
0
                && _PyUnicode_EQ(startkey, key))
175
0
                goto found_active;
176
0
            table = so->table;
177
0
            Py_INCREF(startkey);
178
0
            cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
179
0
            Py_DECREF(startkey);
180
0
            if (cmp > 0)                                          /* likely */
181
0
                goto found_active;
182
0
            if (cmp < 0)
183
0
                goto comparison_error;
184
            /* Continuing the search from the current entry only makes
185
               sense if the table and entry are unchanged; otherwise,
186
               we have to restart from the beginning */
187
0
            if (table != so->table || entry->key != startkey)
188
0
                goto restart;
189
0
            mask = so->mask;                 /* help avoid a register spill */
190
0
        }
191
1.97k
        else if (entry->hash == -1)
192
0
            freeslot = entry;
193
194
1.97k
        if (i + LINEAR_PROBES <= mask) {
195
2.94k
            for (j = 0 ; j < LINEAR_PROBES ; j++) {
196
2.92k
                entry++;
197
2.92k
                if (entry->hash == 0 && entry->key == NULL)
198
1.44k
                    goto found_unused_or_dummy;
199
1.48k
                if (entry->hash == hash) {
200
0
                    PyObject *startkey = entry->key;
201
0
                    assert(startkey != dummy);
202
0
                    if (startkey == key)
203
0
                        goto found_active;
204
0
                    if (PyUnicode_CheckExact(startkey)
205
0
                        && PyUnicode_CheckExact(key)
206
0
                        && _PyUnicode_EQ(startkey, key))
207
0
                        goto found_active;
208
0
                    table = so->table;
209
0
                    Py_INCREF(startkey);
210
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
211
0
                    Py_DECREF(startkey);
212
0
                    if (cmp > 0)
213
0
                        goto found_active;
214
0
                    if (cmp < 0)
215
0
                        goto comparison_error;
216
0
                    if (table != so->table || entry->key != startkey)
217
0
                        goto restart;
218
0
                    mask = so->mask;
219
0
                }
220
1.48k
                else if (entry->hash == -1)
221
0
                    freeslot = entry;
222
1.48k
            }
223
1.45k
        }
224
225
526
        perturb >>= PERTURB_SHIFT;
226
526
        i = (i * 5 + 1 + perturb) & mask;
227
228
526
        entry = &so->table[i];
229
526
        if (entry->key == NULL)
230
320
            goto found_unused_or_dummy;
231
526
    }
232
233
1.76k
  found_unused_or_dummy:
234
1.76k
    if (freeslot == NULL)
235
1.76k
        goto found_unused;
236
0
    so->used++;
237
0
    freeslot->key = key;
238
0
    freeslot->hash = hash;
239
0
    return 0;
240
241
7.36k
  found_unused:
242
7.36k
    so->fill++;
243
7.36k
    so->used++;
244
7.36k
    entry->key = key;
245
7.36k
    entry->hash = hash;
246
7.36k
    if ((size_t)so->fill*5 < mask*3)
247
7.13k
        return 0;
248
226
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
249
250
98
  found_active:
251
98
    Py_DECREF(key);
252
98
    return 0;
253
254
0
  comparison_error:
255
0
    Py_DECREF(key);
256
0
    return -1;
257
7.36k
}
258
259
/*
260
Internal routine used by set_table_resize() to insert an item which is
261
known to be absent from the set.  This routine also assumes that
262
the set contains no deleted entries.  Besides the performance benefit,
263
there is also safety benefit since using set_add_entry() risks making
264
a callback in the middle of a set_table_resize(), see issue 1456209.
265
The caller is responsible for updating the key's reference count and
266
the setobject's fill and used fields.
267
*/
268
static void
269
set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
270
3.66k
{
271
3.66k
    setentry *entry;
272
3.66k
    size_t perturb = hash;
273
3.66k
    size_t i = (size_t)hash & mask;
274
3.66k
    size_t j;
275
276
3.68k
    while (1) {
277
3.68k
        entry = &table[i];
278
3.68k
        if (entry->key == NULL)
279
3.42k
            goto found_null;
280
254
        if (i + LINEAR_PROBES <= mask) {
281
291
            for (j = 0; j < LINEAR_PROBES; j++) {
282
291
                entry++;
283
291
                if (entry->key == NULL)
284
240
                    goto found_null;
285
291
            }
286
240
        }
287
14
        perturb >>= PERTURB_SHIFT;
288
14
        i = (i * 5 + 1 + perturb) & mask;
289
14
    }
290
3.66k
  found_null:
291
3.66k
    entry->key = key;
292
3.66k
    entry->hash = hash;
293
3.66k
}
294
295
/* ======== End logic for probing the hash table ========================== */
296
/* ======================================================================== */
297
298
/*
299
Restructure the table by allocating a new table and reinserting all
300
keys again.  When entries have been deleted, the new table may
301
actually be smaller than the old one.
302
*/
303
static int
304
set_table_resize(PySetObject *so, Py_ssize_t minused)
305
230
{
306
230
    setentry *oldtable, *newtable, *entry;
307
230
    Py_ssize_t oldmask = so->mask;
308
230
    size_t newmask;
309
230
    int is_oldtable_malloced;
310
230
    setentry small_copy[PySet_MINSIZE];
311
312
230
    assert(minused >= 0);
313
314
    /* Find the smallest table size > minused. */
315
    /* XXX speed-up with intrinsics */
316
230
    size_t newsize = PySet_MINSIZE;
317
872
    while (newsize <= (size_t)minused) {
318
642
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
319
642
    }
320
321
    /* Get space for a new table. */
322
230
    oldtable = so->table;
323
230
    assert(oldtable != NULL);
324
230
    is_oldtable_malloced = oldtable != so->smalltable;
325
326
230
    if (newsize == PySet_MINSIZE) {
327
        /* A large table is shrinking, or we can't get any smaller. */
328
0
        newtable = so->smalltable;
329
0
        if (newtable == oldtable) {
330
0
            if (so->fill == so->used) {
331
                /* No dummies, so no point doing anything. */
332
0
                return 0;
333
0
            }
334
            /* We're not going to resize it, but rebuild the
335
               table anyway to purge old dummy entries.
336
               Subtle:  This is *necessary* if fill==size,
337
               as set_lookkey needs at least one virgin slot to
338
               terminate failing searches.  If fill < size, it's
339
               merely desirable, as dummies slow searches. */
340
0
            assert(so->fill > so->used);
341
0
            memcpy(small_copy, oldtable, sizeof(small_copy));
342
0
            oldtable = small_copy;
343
0
        }
344
0
    }
345
230
    else {
346
230
        newtable = PyMem_NEW(setentry, newsize);
347
230
        if (newtable == NULL) {
348
0
            PyErr_NoMemory();
349
0
            return -1;
350
0
        }
351
230
    }
352
353
    /* Make the set empty, using the new table. */
354
230
    assert(newtable != oldtable);
355
230
    memset(newtable, 0, sizeof(setentry) * newsize);
356
230
    so->mask = newsize - 1;
357
230
    so->table = newtable;
358
359
    /* Copy the data over; this is refcount-neutral for active entries;
360
       dummy entries aren't copied over, of course */
361
230
    newmask = (size_t)so->mask;
362
230
    if (so->fill == so->used) {
363
6.29k
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
364
6.06k
            if (entry->key != NULL) {
365
3.65k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
366
3.65k
            }
367
6.06k
        }
368
230
    } else {
369
0
        so->fill = so->used;
370
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
371
0
            if (entry->key != NULL && entry->key != dummy) {
372
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
373
0
            }
374
0
        }
375
0
    }
376
377
230
    if (is_oldtable_malloced)
378
64
        PyMem_DEL(oldtable);
379
230
    return 0;
380
230
}
381
382
static int
383
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
384
2.53k
{
385
2.53k
    setentry *entry;
386
387
2.53k
    entry = set_lookkey(so, key, hash);
388
2.53k
    if (entry != NULL)
389
2.53k
        return entry->key != NULL;
390
0
    return -1;
391
2.53k
}
392
393
73
#define DISCARD_NOTFOUND 0
394
0
#define DISCARD_FOUND 1
395
396
static int
397
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
398
73
{
399
73
    setentry *entry;
400
73
    PyObject *old_key;
401
402
73
    entry = set_lookkey(so, key, hash);
403
73
    if (entry == NULL)
404
0
        return -1;
405
73
    if (entry->key == NULL)
406
73
        return DISCARD_NOTFOUND;
407
0
    old_key = entry->key;
408
0
    entry->key = dummy;
409
0
    entry->hash = -1;
410
0
    so->used--;
411
0
    Py_DECREF(old_key);
412
0
    return DISCARD_FOUND;
413
73
}
414
415
static int
416
set_add_key(PySetObject *so, PyObject *key)
417
7.44k
{
418
7.44k
    Py_hash_t hash;
419
420
7.44k
    if (!PyUnicode_CheckExact(key) ||
421
7.44k
        (hash = ((PyASCIIObject *) key)->hash) == -1) {
422
6.40k
        hash = PyObject_Hash(key);
423
6.40k
        if (hash == -1)
424
0
            return -1;
425
6.40k
    }
426
7.44k
    return set_add_entry(so, key, hash);
427
7.44k
}
428
429
static int
430
set_contains_key(PySetObject *so, PyObject *key)
431
2.47k
{
432
2.47k
    Py_hash_t hash;
433
434
2.47k
    if (!PyUnicode_CheckExact(key) ||
435
2.47k
        (hash = ((PyASCIIObject *) key)->hash) == -1) {
436
1.96k
        hash = PyObject_Hash(key);
437
1.96k
        if (hash == -1)
438
0
            return -1;
439
1.96k
    }
440
2.47k
    return set_contains_entry(so, key, hash);
441
2.47k
}
442
443
static int
444
set_discard_key(PySetObject *so, PyObject *key)
445
73
{
446
73
    Py_hash_t hash;
447
448
73
    if (!PyUnicode_CheckExact(key) ||
449
73
        (hash = ((PyASCIIObject *) key)->hash) == -1) {
450
0
        hash = PyObject_Hash(key);
451
0
        if (hash == -1)
452
0
            return -1;
453
0
    }
454
73
    return set_discard_entry(so, key, hash);
455
73
}
456
457
static void
458
set_empty_to_minsize(PySetObject *so)
459
143
{
460
143
    memset(so->smalltable, 0, sizeof(so->smalltable));
461
143
    so->fill = 0;
462
143
    so->used = 0;
463
143
    so->mask = PySet_MINSIZE - 1;
464
143
    so->table = so->smalltable;
465
143
    so->hash = -1;
466
143
}
467
468
static int
469
set_clear_internal(PySetObject *so)
470
143
{
471
143
    setentry *entry;
472
143
    setentry *table = so->table;
473
143
    Py_ssize_t fill = so->fill;
474
143
    Py_ssize_t used = so->used;
475
143
    int table_is_malloced = table != so->smalltable;
476
143
    setentry small_copy[PySet_MINSIZE];
477
478
143
    assert (PyAnySet_Check(so));
479
143
    assert(table != NULL);
480
481
    /* This is delicate.  During the process of clearing the set,
482
     * decrefs can cause the set to mutate.  To avoid fatal confusion
483
     * (voice of experience), we have to make the set empty before
484
     * clearing the slots, and never refer to anything via so->ref while
485
     * clearing.
486
     */
487
143
    if (table_is_malloced)
488
0
        set_empty_to_minsize(so);
489
490
143
    else if (fill > 0) {
491
        /* It's a small table with something that needs to be cleared.
492
         * Afraid the only safe way is to copy the set entries into
493
         * another small table first.
494
         */
495
143
        memcpy(small_copy, table, sizeof(small_copy));
496
143
        table = small_copy;
497
143
        set_empty_to_minsize(so);
498
143
    }
499
    /* else it's a small table that's already empty */
500
501
    /* Now we can finally clear things.  If C had refcounts, we could
502
     * assert that the refcount on table is 1 now, i.e. that this function
503
     * has unique access to it, so decref side-effects can't alter it.
504
     */
505
637
    for (entry = table; used > 0; entry++) {
506
494
        if (entry->key && entry->key != dummy) {
507
143
            used--;
508
143
            Py_DECREF(entry->key);
509
143
        }
510
494
    }
511
512
143
    if (table_is_malloced)
513
0
        PyMem_DEL(table);
514
143
    return 0;
515
143
}
516
517
/*
518
 * Iterate over a set table.  Use like so:
519
 *
520
 *     Py_ssize_t pos;
521
 *     setentry *entry;
522
 *     pos = 0;   # important!  pos should not otherwise be changed by you
523
 *     while (set_next(yourset, &pos, &entry)) {
524
 *              Refer to borrowed reference in entry->key.
525
 *     }
526
 *
527
 * CAUTION:  In general, it isn't safe to use set_next in a loop that
528
 * mutates the table.
529
 */
530
static int
531
set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
532
15.8k
{
533
15.8k
    Py_ssize_t i;
534
15.8k
    Py_ssize_t mask;
535
15.8k
    setentry *entry;
536
537
15.8k
    assert (PyAnySet_Check(so));
538
15.8k
    i = *pos_ptr;
539
15.8k
    assert(i >= 0);
540
15.8k
    mask = so->mask;
541
15.8k
    entry = &so->table[i];
542
54.3k
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
543
38.5k
        i++;
544
38.5k
        entry++;
545
38.5k
    }
546
15.8k
    *pos_ptr = i+1;
547
15.8k
    if (i > mask)
548
2.13k
        return 0;
549
13.6k
    assert(entry != NULL);
550
13.6k
    *entry_ptr = entry;
551
13.6k
    return 1;
552
15.8k
}
553
554
static void
555
set_dealloc(PySetObject *so)
556
330
{
557
330
    setentry *entry;
558
330
    Py_ssize_t used = so->used;
559
560
    /* bpo-31095: UnTrack is needed before calling any callbacks */
561
330
    PyObject_GC_UnTrack(so);
562
330
    Py_TRASHCAN_BEGIN(so, set_dealloc)
563
330
    if (so->weakreflist != NULL)
564
0
        PyObject_ClearWeakRefs((PyObject *) so);
565
566
1.72k
    for (entry = so->table; used > 0; entry++) {
567
1.39k
        if (entry->key && entry->key != dummy) {
568
427
                used--;
569
427
                Py_DECREF(entry->key);
570
427
        }
571
1.39k
    }
572
330
    if (so->table != so->smalltable)
573
14
        PyMem_DEL(so->table);
574
330
    Py_TYPE(so)->tp_free(so);
575
330
    Py_TRASHCAN_END
576
330
}
577
578
static PyObject *
579
set_repr(PySetObject *so)
580
0
{
581
0
    PyObject *result=NULL, *keys, *listrepr, *tmp;
582
0
    int status = Py_ReprEnter((PyObject*)so);
583
584
0
    if (status != 0) {
585
0
        if (status < 0)
586
0
            return NULL;
587
0
        return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name);
588
0
    }
589
590
    /* shortcut for the empty set */
591
0
    if (!so->used) {
592
0
        Py_ReprLeave((PyObject*)so);
593
0
        return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
594
0
    }
595
596
0
    keys = PySequence_List((PyObject *)so);
597
0
    if (keys == NULL)
598
0
        goto done;
599
600
    /* repr(keys)[1:-1] */
601
0
    listrepr = PyObject_Repr(keys);
602
0
    Py_DECREF(keys);
603
0
    if (listrepr == NULL)
604
0
        goto done;
605
0
    tmp = PyUnicode_Substring(listrepr, 1, PyUnicode_GET_LENGTH(listrepr)-1);
606
0
    Py_DECREF(listrepr);
607
0
    if (tmp == NULL)
608
0
        goto done;
609
0
    listrepr = tmp;
610
611
0
    if (Py_TYPE(so) != &PySet_Type)
612
0
        result = PyUnicode_FromFormat("%s({%U})",
613
0
                                      Py_TYPE(so)->tp_name,
614
0
                                      listrepr);
615
0
    else
616
0
        result = PyUnicode_FromFormat("{%U}", listrepr);
617
0
    Py_DECREF(listrepr);
618
0
done:
619
0
    Py_ReprLeave((PyObject*)so);
620
0
    return result;
621
0
}
622
623
static Py_ssize_t
624
set_len(PyObject *so)
625
484
{
626
484
    return ((PySetObject *)so)->used;
627
484
}
628
629
static int
630
set_merge(PySetObject *so, PyObject *otherset)
631
106
{
632
106
    PySetObject *other;
633
106
    PyObject *key;
634
106
    Py_ssize_t i;
635
106
    setentry *so_entry;
636
106
    setentry *other_entry;
637
638
106
    assert (PyAnySet_Check(so));
639
106
    assert (PyAnySet_Check(otherset));
640
641
106
    other = (PySetObject*)otherset;
642
106
    if (other == so || other->used == 0)
643
        /* a.update(a) or a.update(set()); nothing to do */
644
96
        return 0;
645
    /* Do one big resize at the start, rather than
646
     * incrementally resizing as we insert new keys.  Expect
647
     * that there will be no (or few) overlapping keys.
648
     */
649
10
    if ((so->fill + other->used)*5 >= so->mask*3) {
650
3
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
651
0
            return -1;
652
3
    }
653
10
    so_entry = so->table;
654
10
    other_entry = other->table;
655
656
    /* If our table is empty, and both tables have the same size, and
657
       there are no dummies to eliminate, then just copy the pointers. */
658
10
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
659
54
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
660
48
            key = other_entry->key;
661
48
            if (key != NULL) {
662
10
                assert(so_entry->key == NULL);
663
10
                Py_INCREF(key);
664
10
                so_entry->key = key;
665
10
                so_entry->hash = other_entry->hash;
666
10
            }
667
48
        }
668
6
        so->fill = other->fill;
669
6
        so->used = other->used;
670
6
        return 0;
671
6
    }
672
673
    /* If our table is empty, we can use set_insert_clean() */
674
4
    if (so->fill == 0) {
675
3
        setentry *newtable = so->table;
676
3
        size_t newmask = (size_t)so->mask;
677
3
        so->fill = other->used;
678
3
        so->used = other->used;
679
99
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
680
96
            key = other_entry->key;
681
96
            if (key != NULL && key != dummy) {
682
17
                Py_INCREF(key);
683
17
                set_insert_clean(newtable, newmask, key, other_entry->hash);
684
17
            }
685
96
        }
686
3
        return 0;
687
3
    }
688
689
    /* We can't assure there are no duplicates, so do normal insertions */
690
9
    for (i = 0; i <= other->mask; i++) {
691
8
        other_entry = &other->table[i];
692
8
        key = other_entry->key;
693
8
        if (key != NULL && key != dummy) {
694
2
            if (set_add_entry(so, key, other_entry->hash))
695
0
                return -1;
696
2
        }
697
8
    }
698
1
    return 0;
699
1
}
700
701
static PyObject *
702
set_pop(PySetObject *so, PyObject *Py_UNUSED(ignored))
703
0
{
704
    /* Make sure the search finger is in bounds */
705
0
    setentry *entry = so->table + (so->finger & so->mask);
706
0
    setentry *limit = so->table + so->mask;
707
0
    PyObject *key;
708
709
0
    if (so->used == 0) {
710
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
711
0
        return NULL;
712
0
    }
713
0
    while (entry->key == NULL || entry->key==dummy) {
714
0
        entry++;
715
0
        if (entry > limit)
716
0
            entry = so->table;
717
0
    }
718
0
    key = entry->key;
719
0
    entry->key = dummy;
720
0
    entry->hash = -1;
721
0
    so->used--;
722
0
    so->finger = entry - so->table + 1;   /* next place to start */
723
0
    return key;
724
0
}
725
726
PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element.\n\
727
Raises KeyError if the set is empty.");
728
729
static int
730
set_traverse(PySetObject *so, visitproc visit, void *arg)
731
1.96k
{
732
1.96k
    Py_ssize_t pos = 0;
733
1.96k
    setentry *entry;
734
735
15.3k
    while (set_next(so, &pos, &entry))
736
13.3k
        Py_VISIT(entry->key);
737
1.96k
    return 0;
738
1.96k
}
739
740
/* Work to increase the bit dispersion for closely spaced hash values.
741
   This is important because some use cases have many combinations of a
742
   small number of elements with nearby hashes so that many distinct
743
   combinations collapse to only a handful of distinct hash values. */
744
745
static Py_uhash_t
746
_shuffle_bits(Py_uhash_t h)
747
0
{
748
0
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
749
0
}
750
751
/* Most of the constants in this hash algorithm are randomly chosen
752
   large primes with "interesting bit patterns" and that passed tests
753
   for good collision statistics on a variety of problematic datasets
754
   including powersets and graph structures (such as David Eppstein's
755
   graph recipes in Lib/test/test_set.py) */
756
757
static Py_hash_t
758
frozenset_hash(PyObject *self)
759
0
{
760
0
    PySetObject *so = (PySetObject *)self;
761
0
    Py_uhash_t hash = 0;
762
0
    setentry *entry;
763
764
0
    if (so->hash != -1)
765
0
        return so->hash;
766
767
    /* Xor-in shuffled bits from every entry's hash field because xor is
768
       commutative and a frozenset hash should be independent of order.
769
770
       For speed, include null entries and dummy entries and then
771
       subtract out their effect afterwards so that the final hash
772
       depends only on active entries.  This allows the code to be
773
       vectorized by the compiler and it saves the unpredictable
774
       branches that would arise when trying to exclude null and dummy
775
       entries on every iteration. */
776
777
0
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
778
0
        hash ^= _shuffle_bits(entry->hash);
779
780
    /* Remove the effect of an odd number of NULL entries */
781
0
    if ((so->mask + 1 - so->fill) & 1)
782
0
        hash ^= _shuffle_bits(0);
783
784
    /* Remove the effect of an odd number of dummy entries */
785
0
    if ((so->fill - so->used) & 1)
786
0
        hash ^= _shuffle_bits(-1);
787
788
    /* Factor in the number of active entries */
789
0
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
790
791
    /* Disperse patterns arising in nested frozensets */
792
0
    hash ^= (hash >> 11) ^ (hash >> 25);
793
0
    hash = hash * 69069U + 907133923UL;
794
795
    /* -1 is reserved as an error code */
796
0
    if (hash == (Py_uhash_t)-1)
797
0
        hash = 590923713UL;
798
799
0
    so->hash = hash;
800
0
    return hash;
801
0
}
802
803
/***** Set iterator type ***********************************************/
804
805
typedef struct {
806
    PyObject_HEAD
807
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
808
    Py_ssize_t si_used;
809
    Py_ssize_t si_pos;
810
    Py_ssize_t len;
811
} setiterobject;
812
813
static void
814
setiter_dealloc(setiterobject *si)
815
489
{
816
    /* bpo-31095: UnTrack is needed before calling any callbacks */
817
489
    _PyObject_GC_UNTRACK(si);
818
489
    Py_XDECREF(si->si_set);
819
489
    PyObject_GC_Del(si);
820
489
}
821
822
static int
823
setiter_traverse(setiterobject *si, visitproc visit, void *arg)
824
0
{
825
0
    Py_VISIT(si->si_set);
826
0
    return 0;
827
0
}
828
829
static PyObject *
830
setiter_len(setiterobject *si, PyObject *Py_UNUSED(ignored))
831
0
{
832
0
    Py_ssize_t len = 0;
833
0
    if (si->si_set != NULL && si->si_used == si->si_set->used)
834
0
        len = si->len;
835
0
    return PyLong_FromSsize_t(len);
836
0
}
837
838
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
839
840
static PyObject *setiter_iternext(setiterobject *si);
841
842
static PyObject *
843
setiter_reduce(setiterobject *si, PyObject *Py_UNUSED(ignored))
844
0
{
845
0
    _Py_IDENTIFIER(iter);
846
    /* copy the iterator state */
847
0
    setiterobject tmp = *si;
848
0
    Py_XINCREF(tmp.si_set);
849
850
    /* iterate the temporary into a list */
851
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
852
0
    Py_XDECREF(tmp.si_set);
853
0
    if (list == NULL) {
854
0
        return NULL;
855
0
    }
856
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
857
0
}
858
859
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
860
861
static PyMethodDef setiter_methods[] = {
862
    {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc},
863
    {"__reduce__", (PyCFunction)setiter_reduce, METH_NOARGS, reduce_doc},
864
    {NULL,              NULL}           /* sentinel */
865
};
866
867
static PyObject *setiter_iternext(setiterobject *si)
868
1.26k
{
869
1.26k
    PyObject *key;
870
1.26k
    Py_ssize_t i, mask;
871
1.26k
    setentry *entry;
872
1.26k
    PySetObject *so = si->si_set;
873
874
1.26k
    if (so == NULL)
875
0
        return NULL;
876
1.26k
    assert (PyAnySet_Check(so));
877
878
1.26k
    if (si->si_used != so->used) {
879
0
        PyErr_SetString(PyExc_RuntimeError,
880
0
                        "Set changed size during iteration");
881
0
        si->si_used = -1; /* Make this state sticky */
882
0
        return NULL;
883
0
    }
884
885
1.26k
    i = si->si_pos;
886
1.26k
    assert(i>=0);
887
1.26k
    entry = so->table;
888
1.26k
    mask = so->mask;
889
5.09k
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
890
3.82k
        i++;
891
1.26k
    si->si_pos = i+1;
892
1.26k
    if (i > mask)
893
475
        goto fail;
894
794
    si->len--;
895
794
    key = entry[i].key;
896
794
    Py_INCREF(key);
897
794
    return key;
898
899
475
fail:
900
475
    si->si_set = NULL;
901
475
    Py_DECREF(so);
902
475
    return NULL;
903
1.26k
}
904
905
PyTypeObject PySetIter_Type = {
906
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
907
    "set_iterator",                             /* tp_name */
908
    sizeof(setiterobject),                      /* tp_basicsize */
909
    0,                                          /* tp_itemsize */
910
    /* methods */
911
    (destructor)setiter_dealloc,                /* tp_dealloc */
912
    0,                                          /* tp_vectorcall_offset */
913
    0,                                          /* tp_getattr */
914
    0,                                          /* tp_setattr */
915
    0,                                          /* tp_as_async */
916
    0,                                          /* tp_repr */
917
    0,                                          /* tp_as_number */
918
    0,                                          /* tp_as_sequence */
919
    0,                                          /* tp_as_mapping */
920
    0,                                          /* tp_hash */
921
    0,                                          /* tp_call */
922
    0,                                          /* tp_str */
923
    PyObject_GenericGetAttr,                    /* tp_getattro */
924
    0,                                          /* tp_setattro */
925
    0,                                          /* tp_as_buffer */
926
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
927
    0,                                          /* tp_doc */
928
    (traverseproc)setiter_traverse,             /* tp_traverse */
929
    0,                                          /* tp_clear */
930
    0,                                          /* tp_richcompare */
931
    0,                                          /* tp_weaklistoffset */
932
    PyObject_SelfIter,                          /* tp_iter */
933
    (iternextfunc)setiter_iternext,             /* tp_iternext */
934
    setiter_methods,                            /* tp_methods */
935
    0,
936
};
937
938
static PyObject *
939
set_iter(PySetObject *so)
940
489
{
941
489
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
942
489
    if (si == NULL)
943
0
        return NULL;
944
489
    Py_INCREF(so);
945
489
    si->si_set = so;
946
489
    si->si_used = so->used;
947
489
    si->si_pos = 0;
948
489
    si->len = so->used;
949
489
    _PyObject_GC_TRACK(si);
950
489
    return (PyObject *)si;
951
489
}
952
953
static int
954
set_update_internal(PySetObject *so, PyObject *other)
955
148
{
956
148
    PyObject *key, *it;
957
958
148
    if (PyAnySet_Check(other))
959
106
        return set_merge(so, other);
960
961
42
    if (PyDict_CheckExact(other)) {
962
5
        PyObject *value;
963
5
        Py_ssize_t pos = 0;
964
5
        Py_hash_t hash;
965
5
        Py_ssize_t dictsize = PyDict_GET_SIZE(other);
966
967
        /* Do one big resize at the start, rather than
968
        * incrementally resizing as we insert new keys.  Expect
969
        * that there will be no (or few) overlapping keys.
970
        */
971
5
        if (dictsize < 0)
972
0
            return -1;
973
5
        if ((so->fill + dictsize)*5 >= so->mask*3) {
974
1
            if (set_table_resize(so, (so->used + dictsize)*2) != 0)
975
0
                return -1;
976
1
        }
977
22
        while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
978
17
            if (set_add_entry(so, key, hash))
979
0
                return -1;
980
17
        }
981
5
        return 0;
982
5
    }
983
984
37
    it = PyObject_GetIter(other);
985
37
    if (it == NULL)
986
0
        return -1;
987
988
4.82k
    while ((key = PyIter_Next(it)) != NULL) {
989
4.78k
        if (set_add_key(so, key)) {
990
0
            Py_DECREF(it);
991
0
            Py_DECREF(key);
992
0
            return -1;
993
0
        }
994
4.78k
        Py_DECREF(key);
995
4.78k
    }
996
37
    Py_DECREF(it);
997
37
    if (PyErr_Occurred())
998
0
        return -1;
999
37
    return 0;
1000
37
}
1001
1002
static PyObject *
1003
set_update(PySetObject *so, PyObject *args)
1004
0
{
1005
0
    Py_ssize_t i;
1006
1007
0
    for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
1008
0
        PyObject *other = PyTuple_GET_ITEM(args, i);
1009
0
        if (set_update_internal(so, other))
1010
0
            return NULL;
1011
0
    }
1012
0
    Py_RETURN_NONE;
1013
0
}
1014
1015
PyDoc_STRVAR(update_doc,
1016
"Update a set with the union of itself and others.");
1017
1018
/* XXX Todo:
1019
   If aligned memory allocations become available, make the
1020
   set object 64 byte aligned so that most of the fields
1021
   can be retrieved or updated in a single cache line.
1022
*/
1023
1024
static PyObject *
1025
make_new_set(PyTypeObject *type, PyObject *iterable)
1026
1.38k
{
1027
1.38k
    PySetObject *so;
1028
1029
1.38k
    so = (PySetObject *)type->tp_alloc(type, 0);
1030
1.38k
    if (so == NULL)
1031
0
        return NULL;
1032
1033
1.38k
    so->fill = 0;
1034
1.38k
    so->used = 0;
1035
1.38k
    so->mask = PySet_MINSIZE - 1;
1036
1.38k
    so->table = so->smalltable;
1037
1.38k
    so->hash = -1;
1038
1.38k
    so->finger = 0;
1039
1.38k
    so->weakreflist = NULL;
1040
1041
1.38k
    if (iterable != NULL) {
1042
27
        if (set_update_internal(so, iterable)) {
1043
0
            Py_DECREF(so);
1044
0
            return NULL;
1045
0
        }
1046
27
    }
1047
1048
1.38k
    return (PyObject *)so;
1049
1.38k
}
1050
1051
static PyObject *
1052
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1053
6
{
1054
6
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1055
0
        if (PyType_IsSubtype(type, &PySet_Type))
1056
0
            type = &PySet_Type;
1057
0
        else
1058
0
            type = &PyFrozenSet_Type;
1059
0
    }
1060
6
    return make_new_set(type, iterable);
1061
6
}
1062
1063
/* The empty frozenset is a singleton */
1064
static PyObject *emptyfrozenset = NULL;
1065
1066
static PyObject *
1067
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1068
8
{
1069
8
    PyObject *iterable = NULL, *result;
1070
1071
8
    if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset", kwds))
1072
0
        return NULL;
1073
1074
8
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
1075
0
        return NULL;
1076
1077
8
    if (type != &PyFrozenSet_Type)
1078
0
        return make_new_set(type, iterable);
1079
1080
8
    if (iterable != NULL) {
1081
        /* frozenset(f) is idempotent */
1082
8
        if (PyFrozenSet_CheckExact(iterable)) {
1083
0
            Py_INCREF(iterable);
1084
0
            return iterable;
1085
0
        }
1086
8
        result = make_new_set(type, iterable);
1087
8
        if (result == NULL || PySet_GET_SIZE(result))
1088
8
            return result;
1089
0
        Py_DECREF(result);
1090
0
    }
1091
    /* The empty frozenset is a singleton */
1092
0
    if (emptyfrozenset == NULL)
1093
0
        emptyfrozenset = make_new_set(type, NULL);
1094
0
    Py_XINCREF(emptyfrozenset);
1095
0
    return emptyfrozenset;
1096
8
}
1097
1098
static PyObject *
1099
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1100
233
{
1101
233
    return make_new_set(type, NULL);
1102
233
}
1103
1104
/* set_swap_bodies() switches the contents of any two sets by moving their
1105
   internal data pointers and, if needed, copying the internal smalltables.
1106
   Semantically equivalent to:
1107
1108
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1109
1110
   The function always succeeds and it leaves both objects in a stable state.
1111
   Useful for operations that update in-place (by allowing an intermediate
1112
   result to be swapped into one of the original inputs).
1113
*/
1114
1115
static void
1116
set_swap_bodies(PySetObject *a, PySetObject *b)
1117
0
{
1118
0
    Py_ssize_t t;
1119
0
    setentry *u;
1120
0
    setentry tab[PySet_MINSIZE];
1121
0
    Py_hash_t h;
1122
1123
0
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1124
0
    t = a->used;     a->used   = b->used;        b->used  = t;
1125
0
    t = a->mask;     a->mask   = b->mask;        b->mask  = t;
1126
1127
0
    u = a->table;
1128
0
    if (a->table == a->smalltable)
1129
0
        u = b->smalltable;
1130
0
    a->table  = b->table;
1131
0
    if (b->table == b->smalltable)
1132
0
        a->table = a->smalltable;
1133
0
    b->table = u;
1134
1135
0
    if (a->table == a->smalltable || b->table == b->smalltable) {
1136
0
        memcpy(tab, a->smalltable, sizeof(tab));
1137
0
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1138
0
        memcpy(b->smalltable, tab, sizeof(tab));
1139
0
    }
1140
1141
0
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1142
0
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1143
0
        h = a->hash;     a->hash = b->hash;  b->hash = h;
1144
0
    } else {
1145
0
        a->hash = -1;
1146
0
        b->hash = -1;
1147
0
    }
1148
0
}
1149
1150
static PyObject *
1151
set_copy(PySetObject *so, PyObject *Py_UNUSED(ignored))
1152
1
{
1153
1
    return make_new_set_basetype(Py_TYPE(so), (PyObject *)so);
1154
1
}
1155
1156
static PyObject *
1157
frozenset_copy(PySetObject *so, PyObject *Py_UNUSED(ignored))
1158
0
{
1159
0
    if (PyFrozenSet_CheckExact(so)) {
1160
0
        Py_INCREF(so);
1161
0
        return (PyObject *)so;
1162
0
    }
1163
0
    return set_copy(so, NULL);
1164
0
}
1165
1166
PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set.");
1167
1168
static PyObject *
1169
set_clear(PySetObject *so, PyObject *Py_UNUSED(ignored))
1170
0
{
1171
0
    set_clear_internal(so);
1172
0
    Py_RETURN_NONE;
1173
0
}
1174
1175
PyDoc_STRVAR(clear_doc, "Remove all elements from this set.");
1176
1177
static PyObject *
1178
set_union(PySetObject *so, PyObject *args)
1179
0
{
1180
0
    PySetObject *result;
1181
0
    PyObject *other;
1182
0
    Py_ssize_t i;
1183
1184
0
    result = (PySetObject *)set_copy(so, NULL);
1185
0
    if (result == NULL)
1186
0
        return NULL;
1187
1188
0
    for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
1189
0
        other = PyTuple_GET_ITEM(args, i);
1190
0
        if ((PyObject *)so == other)
1191
0
            continue;
1192
0
        if (set_update_internal(result, other)) {
1193
0
            Py_DECREF(result);
1194
0
            return NULL;
1195
0
        }
1196
0
    }
1197
0
    return (PyObject *)result;
1198
0
}
1199
1200
PyDoc_STRVAR(union_doc,
1201
 "Return the union of sets as a new set.\n\
1202
\n\
1203
(i.e. all elements that are in either set.)");
1204
1205
static PyObject *
1206
set_or(PySetObject *so, PyObject *other)
1207
1
{
1208
1
    PySetObject *result;
1209
1210
1
    if (!PyAnySet_Check(so) || !PyAnySet_Check(other))
1211
0
        Py_RETURN_NOTIMPLEMENTED;
1212
1213
1
    result = (PySetObject *)set_copy(so, NULL);
1214
1
    if (result == NULL)
1215
0
        return NULL;
1216
1
    if ((PyObject *)so == other)
1217
0
        return (PyObject *)result;
1218
1
    if (set_update_internal(result, other)) {
1219
0
        Py_DECREF(result);
1220
0
        return NULL;
1221
0
    }
1222
1
    return (PyObject *)result;
1223
1
}
1224
1225
static PyObject *
1226
set_ior(PySetObject *so, PyObject *other)
1227
84
{
1228
84
    if (!PyAnySet_Check(other))
1229
0
        Py_RETURN_NOTIMPLEMENTED;
1230
1231
84
    if (set_update_internal(so, other))
1232
0
        return NULL;
1233
84
    Py_INCREF(so);
1234
84
    return (PyObject *)so;
1235
84
}
1236
1237
static PyObject *
1238
set_intersection(PySetObject *so, PyObject *other)
1239
5
{
1240
5
    PySetObject *result;
1241
5
    PyObject *key, *it, *tmp;
1242
5
    Py_hash_t hash;
1243
5
    int rv;
1244
1245
5
    if ((PyObject *)so == other)
1246
0
        return set_copy(so, NULL);
1247
1248
5
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1249
5
    if (result == NULL)
1250
0
        return NULL;
1251
1252
5
    if (PyAnySet_Check(other)) {
1253
5
        Py_ssize_t pos = 0;
1254
5
        setentry *entry;
1255
1256
5
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1257
4
            tmp = (PyObject *)so;
1258
4
            so = (PySetObject *)other;
1259
4
            other = tmp;
1260
4
        }
1261
1262
7
        while (set_next((PySetObject *)other, &pos, &entry)) {
1263
2
            key = entry->key;
1264
2
            hash = entry->hash;
1265
2
            rv = set_contains_entry(so, key, hash);
1266
2
            if (rv < 0) {
1267
0
                Py_DECREF(result);
1268
0
                return NULL;
1269
0
            }
1270
2
            if (rv) {
1271
0
                if (set_add_entry(result, key, hash)) {
1272
0
                    Py_DECREF(result);
1273
0
                    return NULL;
1274
0
                }
1275
0
            }
1276
2
        }
1277
5
        return (PyObject *)result;
1278
5
    }
1279
1280
0
    it = PyObject_GetIter(other);
1281
0
    if (it == NULL) {
1282
0
        Py_DECREF(result);
1283
0
        return NULL;
1284
0
    }
1285
1286
0
    while ((key = PyIter_Next(it)) != NULL) {
1287
0
        hash = PyObject_Hash(key);
1288
0
        if (hash == -1)
1289
0
            goto error;
1290
0
        rv = set_contains_entry(so, key, hash);
1291
0
        if (rv < 0)
1292
0
            goto error;
1293
0
        if (rv) {
1294
0
            if (set_add_entry(result, key, hash))
1295
0
                goto error;
1296
0
        }
1297
0
        Py_DECREF(key);
1298
0
    }
1299
0
    Py_DECREF(it);
1300
0
    if (PyErr_Occurred()) {
1301
0
        Py_DECREF(result);
1302
0
        return NULL;
1303
0
    }
1304
0
    return (PyObject *)result;
1305
0
  error:
1306
0
    Py_DECREF(it);
1307
0
    Py_DECREF(result);
1308
0
    Py_DECREF(key);
1309
0
    return NULL;
1310
0
}
1311
1312
static PyObject *
1313
set_intersection_multi(PySetObject *so, PyObject *args)
1314
0
{
1315
0
    Py_ssize_t i;
1316
0
    PyObject *result = (PyObject *)so;
1317
1318
0
    if (PyTuple_GET_SIZE(args) == 0)
1319
0
        return set_copy(so, NULL);
1320
1321
0
    Py_INCREF(so);
1322
0
    for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
1323
0
        PyObject *other = PyTuple_GET_ITEM(args, i);
1324
0
        PyObject *newresult = set_intersection((PySetObject *)result, other);
1325
0
        if (newresult == NULL) {
1326
0
            Py_DECREF(result);
1327
0
            return NULL;
1328
0
        }
1329
0
        Py_DECREF(result);
1330
0
        result = newresult;
1331
0
    }
1332
0
    return result;
1333
0
}
1334
1335
PyDoc_STRVAR(intersection_doc,
1336
"Return the intersection of two sets as a new set.\n\
1337
\n\
1338
(i.e. all elements that are in both sets.)");
1339
1340
static PyObject *
1341
set_intersection_update(PySetObject *so, PyObject *other)
1342
0
{
1343
0
    PyObject *tmp;
1344
1345
0
    tmp = set_intersection(so, other);
1346
0
    if (tmp == NULL)
1347
0
        return NULL;
1348
0
    set_swap_bodies(so, (PySetObject *)tmp);
1349
0
    Py_DECREF(tmp);
1350
0
    Py_RETURN_NONE;
1351
0
}
1352
1353
static PyObject *
1354
set_intersection_update_multi(PySetObject *so, PyObject *args)
1355
0
{
1356
0
    PyObject *tmp;
1357
1358
0
    tmp = set_intersection_multi(so, args);
1359
0
    if (tmp == NULL)
1360
0
        return NULL;
1361
0
    set_swap_bodies(so, (PySetObject *)tmp);
1362
0
    Py_DECREF(tmp);
1363
0
    Py_RETURN_NONE;
1364
0
}
1365
1366
PyDoc_STRVAR(intersection_update_doc,
1367
"Update a set with the intersection of itself and another.");
1368
1369
static PyObject *
1370
set_and(PySetObject *so, PyObject *other)
1371
5
{
1372
5
    if (!PyAnySet_Check(so) || !PyAnySet_Check(other))
1373
0
        Py_RETURN_NOTIMPLEMENTED;
1374
5
    return set_intersection(so, other);
1375
5
}
1376
1377
static PyObject *
1378
set_iand(PySetObject *so, PyObject *other)
1379
0
{
1380
0
    PyObject *result;
1381
1382
0
    if (!PyAnySet_Check(other))
1383
0
        Py_RETURN_NOTIMPLEMENTED;
1384
0
    result = set_intersection_update(so, other);
1385
0
    if (result == NULL)
1386
0
        return NULL;
1387
0
    Py_DECREF(result);
1388
0
    Py_INCREF(so);
1389
0
    return (PyObject *)so;
1390
0
}
1391
1392
static PyObject *
1393
set_isdisjoint(PySetObject *so, PyObject *other)
1394
0
{
1395
0
    PyObject *key, *it, *tmp;
1396
0
    int rv;
1397
1398
0
    if ((PyObject *)so == other) {
1399
0
        if (PySet_GET_SIZE(so) == 0)
1400
0
            Py_RETURN_TRUE;
1401
0
        else
1402
0
            Py_RETURN_FALSE;
1403
0
    }
1404
1405
0
    if (PyAnySet_CheckExact(other)) {
1406
0
        Py_ssize_t pos = 0;
1407
0
        setentry *entry;
1408
1409
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1410
0
            tmp = (PyObject *)so;
1411
0
            so = (PySetObject *)other;
1412
0
            other = tmp;
1413
0
        }
1414
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1415
0
            rv = set_contains_entry(so, entry->key, entry->hash);
1416
0
            if (rv < 0)
1417
0
                return NULL;
1418
0
            if (rv)
1419
0
                Py_RETURN_FALSE;
1420
0
        }
1421
0
        Py_RETURN_TRUE;
1422
0
    }
1423
1424
0
    it = PyObject_GetIter(other);
1425
0
    if (it == NULL)
1426
0
        return NULL;
1427
1428
0
    while ((key = PyIter_Next(it)) != NULL) {
1429
0
        Py_hash_t hash = PyObject_Hash(key);
1430
1431
0
        if (hash == -1) {
1432
0
            Py_DECREF(key);
1433
0
            Py_DECREF(it);
1434
0
            return NULL;
1435
0
        }
1436
0
        rv = set_contains_entry(so, key, hash);
1437
0
        Py_DECREF(key);
1438
0
        if (rv < 0) {
1439
0
            Py_DECREF(it);
1440
0
            return NULL;
1441
0
        }
1442
0
        if (rv) {
1443
0
            Py_DECREF(it);
1444
0
            Py_RETURN_FALSE;
1445
0
        }
1446
0
    }
1447
0
    Py_DECREF(it);
1448
0
    if (PyErr_Occurred())
1449
0
        return NULL;
1450
0
    Py_RETURN_TRUE;
1451
0
}
1452
1453
PyDoc_STRVAR(isdisjoint_doc,
1454
"Return True if two sets have a null intersection.");
1455
1456
static int
1457
set_difference_update_internal(PySetObject *so, PyObject *other)
1458
0
{
1459
0
    if ((PyObject *)so == other)
1460
0
        return set_clear_internal(so);
1461
1462
0
    if (PyAnySet_Check(other)) {
1463
0
        setentry *entry;
1464
0
        Py_ssize_t pos = 0;
1465
1466
0
        while (set_next((PySetObject *)other, &pos, &entry))
1467
0
            if (set_discard_entry(so, entry->key, entry->hash) < 0)
1468
0
                return -1;
1469
0
    } else {
1470
0
        PyObject *key, *it;
1471
0
        it = PyObject_GetIter(other);
1472
0
        if (it == NULL)
1473
0
            return -1;
1474
1475
0
        while ((key = PyIter_Next(it)) != NULL) {
1476
0
            if (set_discard_key(so, key) < 0) {
1477
0
                Py_DECREF(it);
1478
0
                Py_DECREF(key);
1479
0
                return -1;
1480
0
            }
1481
0
            Py_DECREF(key);
1482
0
        }
1483
0
        Py_DECREF(it);
1484
0
        if (PyErr_Occurred())
1485
0
            return -1;
1486
0
    }
1487
    /* If more than 1/4th are dummies, then resize them away. */
1488
0
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1489
0
        return 0;
1490
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1491
0
}
1492
1493
static PyObject *
1494
set_difference_update(PySetObject *so, PyObject *args)
1495
0
{
1496
0
    Py_ssize_t i;
1497
1498
0
    for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
1499
0
        PyObject *other = PyTuple_GET_ITEM(args, i);
1500
0
        if (set_difference_update_internal(so, other))
1501
0
            return NULL;
1502
0
    }
1503
0
    Py_RETURN_NONE;
1504
0
}
1505
1506
PyDoc_STRVAR(difference_update_doc,
1507
"Remove all elements of another set from this set.");
1508
1509
static PyObject *
1510
set_copy_and_difference(PySetObject *so, PyObject *other)
1511
0
{
1512
0
    PyObject *result;
1513
1514
0
    result = set_copy(so, NULL);
1515
0
    if (result == NULL)
1516
0
        return NULL;
1517
0
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1518
0
        return result;
1519
0
    Py_DECREF(result);
1520
0
    return NULL;
1521
0
}
1522
1523
static PyObject *
1524
set_difference(PySetObject *so, PyObject *other)
1525
0
{
1526
0
    PyObject *result;
1527
0
    PyObject *key;
1528
0
    Py_hash_t hash;
1529
0
    setentry *entry;
1530
0
    Py_ssize_t pos = 0, other_size;
1531
0
    int rv;
1532
1533
0
    if (PyAnySet_Check(other)) {
1534
0
        other_size = PySet_GET_SIZE(other);
1535
0
    }
1536
0
    else if (PyDict_CheckExact(other)) {
1537
0
        other_size = PyDict_GET_SIZE(other);
1538
0
    }
1539
0
    else {
1540
0
        return set_copy_and_difference(so, other);
1541
0
    }
1542
1543
    /* If len(so) much more than len(other), it's more efficient to simply copy
1544
     * so and then iterate other looking for common elements. */
1545
0
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1546
0
        return set_copy_and_difference(so, other);
1547
0
    }
1548
1549
0
    result = make_new_set_basetype(Py_TYPE(so), NULL);
1550
0
    if (result == NULL)
1551
0
        return NULL;
1552
1553
0
    if (PyDict_CheckExact(other)) {
1554
0
        while (set_next(so, &pos, &entry)) {
1555
0
            key = entry->key;
1556
0
            hash = entry->hash;
1557
0
            rv = _PyDict_Contains(other, key, hash);
1558
0
            if (rv < 0) {
1559
0
                Py_DECREF(result);
1560
0
                return NULL;
1561
0
            }
1562
0
            if (!rv) {
1563
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
1564
0
                    Py_DECREF(result);
1565
0
                    return NULL;
1566
0
                }
1567
0
            }
1568
0
        }
1569
0
        return result;
1570
0
    }
1571
1572
    /* Iterate over so, checking for common elements in other. */
1573
0
    while (set_next(so, &pos, &entry)) {
1574
0
        key = entry->key;
1575
0
        hash = entry->hash;
1576
0
        rv = set_contains_entry((PySetObject *)other, key, hash);
1577
0
        if (rv < 0) {
1578
0
            Py_DECREF(result);
1579
0
            return NULL;
1580
0
        }
1581
0
        if (!rv) {
1582
0
            if (set_add_entry((PySetObject *)result, key, hash)) {
1583
0
                Py_DECREF(result);
1584
0
                return NULL;
1585
0
            }
1586
0
        }
1587
0
    }
1588
0
    return result;
1589
0
}
1590
1591
static PyObject *
1592
set_difference_multi(PySetObject *so, PyObject *args)
1593
0
{
1594
0
    Py_ssize_t i;
1595
0
    PyObject *result, *other;
1596
1597
0
    if (PyTuple_GET_SIZE(args) == 0)
1598
0
        return set_copy(so, NULL);
1599
1600
0
    other = PyTuple_GET_ITEM(args, 0);
1601
0
    result = set_difference(so, other);
1602
0
    if (result == NULL)
1603
0
        return NULL;
1604
1605
0
    for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) {
1606
0
        other = PyTuple_GET_ITEM(args, i);
1607
0
        if (set_difference_update_internal((PySetObject *)result, other)) {
1608
0
            Py_DECREF(result);
1609
0
            return NULL;
1610
0
        }
1611
0
    }
1612
0
    return result;
1613
0
}
1614
1615
PyDoc_STRVAR(difference_doc,
1616
"Return the difference of two or more sets as a new set.\n\
1617
\n\
1618
(i.e. all elements that are in this set but not the others.)");
1619
static PyObject *
1620
set_sub(PySetObject *so, PyObject *other)
1621
0
{
1622
0
    if (!PyAnySet_Check(so) || !PyAnySet_Check(other))
1623
0
        Py_RETURN_NOTIMPLEMENTED;
1624
0
    return set_difference(so, other);
1625
0
}
1626
1627
static PyObject *
1628
set_isub(PySetObject *so, PyObject *other)
1629
0
{
1630
0
    if (!PyAnySet_Check(other))
1631
0
        Py_RETURN_NOTIMPLEMENTED;
1632
0
    if (set_difference_update_internal(so, other))
1633
0
        return NULL;
1634
0
    Py_INCREF(so);
1635
0
    return (PyObject *)so;
1636
0
}
1637
1638
static PyObject *
1639
set_symmetric_difference_update(PySetObject *so, PyObject *other)
1640
0
{
1641
0
    PySetObject *otherset;
1642
0
    PyObject *key;
1643
0
    Py_ssize_t pos = 0;
1644
0
    Py_hash_t hash;
1645
0
    setentry *entry;
1646
0
    int rv;
1647
1648
0
    if ((PyObject *)so == other)
1649
0
        return set_clear(so, NULL);
1650
1651
0
    if (PyDict_CheckExact(other)) {
1652
0
        PyObject *value;
1653
0
        while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1654
0
            Py_INCREF(key);
1655
0
            rv = set_discard_entry(so, key, hash);
1656
0
            if (rv < 0) {
1657
0
                Py_DECREF(key);
1658
0
                return NULL;
1659
0
            }
1660
0
            if (rv == DISCARD_NOTFOUND) {
1661
0
                if (set_add_entry(so, key, hash)) {
1662
0
                    Py_DECREF(key);
1663
0
                    return NULL;
1664
0
                }
1665
0
            }
1666
0
            Py_DECREF(key);
1667
0
        }
1668
0
        Py_RETURN_NONE;
1669
0
    }
1670
1671
0
    if (PyAnySet_Check(other)) {
1672
0
        Py_INCREF(other);
1673
0
        otherset = (PySetObject *)other;
1674
0
    } else {
1675
0
        otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
1676
0
        if (otherset == NULL)
1677
0
            return NULL;
1678
0
    }
1679
1680
0
    while (set_next(otherset, &pos, &entry)) {
1681
0
        key = entry->key;
1682
0
        hash = entry->hash;
1683
0
        rv = set_discard_entry(so, key, hash);
1684
0
        if (rv < 0) {
1685
0
            Py_DECREF(otherset);
1686
0
            return NULL;
1687
0
        }
1688
0
        if (rv == DISCARD_NOTFOUND) {
1689
0
            if (set_add_entry(so, key, hash)) {
1690
0
                Py_DECREF(otherset);
1691
0
                return NULL;
1692
0
            }
1693
0
        }
1694
0
    }
1695
0
    Py_DECREF(otherset);
1696
0
    Py_RETURN_NONE;
1697
0
}
1698
1699
PyDoc_STRVAR(symmetric_difference_update_doc,
1700
"Update a set with the symmetric difference of itself and another.");
1701
1702
static PyObject *
1703
set_symmetric_difference(PySetObject *so, PyObject *other)
1704
0
{
1705
0
    PyObject *rv;
1706
0
    PySetObject *otherset;
1707
1708
0
    otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
1709
0
    if (otherset == NULL)
1710
0
        return NULL;
1711
0
    rv = set_symmetric_difference_update(otherset, (PyObject *)so);
1712
0
    if (rv == NULL) {
1713
0
        Py_DECREF(otherset);
1714
0
        return NULL;
1715
0
    }
1716
0
    Py_DECREF(rv);
1717
0
    return (PyObject *)otherset;
1718
0
}
1719
1720
PyDoc_STRVAR(symmetric_difference_doc,
1721
"Return the symmetric difference of two sets as a new set.\n\
1722
\n\
1723
(i.e. all elements that are in exactly one of the sets.)");
1724
1725
static PyObject *
1726
set_xor(PySetObject *so, PyObject *other)
1727
0
{
1728
0
    if (!PyAnySet_Check(so) || !PyAnySet_Check(other))
1729
0
        Py_RETURN_NOTIMPLEMENTED;
1730
0
    return set_symmetric_difference(so, other);
1731
0
}
1732
1733
static PyObject *
1734
set_ixor(PySetObject *so, PyObject *other)
1735
0
{
1736
0
    PyObject *result;
1737
1738
0
    if (!PyAnySet_Check(other))
1739
0
        Py_RETURN_NOTIMPLEMENTED;
1740
0
    result = set_symmetric_difference_update(so, other);
1741
0
    if (result == NULL)
1742
0
        return NULL;
1743
0
    Py_DECREF(result);
1744
0
    Py_INCREF(so);
1745
0
    return (PyObject *)so;
1746
0
}
1747
1748
static PyObject *
1749
set_issubset(PySetObject *so, PyObject *other)
1750
28
{
1751
28
    setentry *entry;
1752
28
    Py_ssize_t pos = 0;
1753
28
    int rv;
1754
1755
28
    if (!PyAnySet_Check(other)) {
1756
0
        PyObject *tmp, *result;
1757
0
        tmp = make_new_set(&PySet_Type, other);
1758
0
        if (tmp == NULL)
1759
0
            return NULL;
1760
0
        result = set_issubset(so, tmp);
1761
0
        Py_DECREF(tmp);
1762
0
        return result;
1763
0
    }
1764
28
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
1765
0
        Py_RETURN_FALSE;
1766
1767
84
    while (set_next(so, &pos, &entry)) {
1768
56
        rv = set_contains_entry((PySetObject *)other, entry->key, entry->hash);
1769
56
        if (rv < 0)
1770
0
            return NULL;
1771
56
        if (!rv)
1772
0
            Py_RETURN_FALSE;
1773
56
    }
1774
28
    Py_RETURN_TRUE;
1775
28
}
1776
1777
PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set.");
1778
1779
static PyObject *
1780
set_issuperset(PySetObject *so, PyObject *other)
1781
0
{
1782
0
    PyObject *tmp, *result;
1783
1784
0
    if (!PyAnySet_Check(other)) {
1785
0
        tmp = make_new_set(&PySet_Type, other);
1786
0
        if (tmp == NULL)
1787
0
            return NULL;
1788
0
        result = set_issuperset(so, tmp);
1789
0
        Py_DECREF(tmp);
1790
0
        return result;
1791
0
    }
1792
0
    return set_issubset((PySetObject *)other, (PyObject *)so);
1793
0
}
1794
1795
PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");
1796
1797
static PyObject *
1798
set_richcompare(PySetObject *v, PyObject *w, int op)
1799
28
{
1800
28
    PyObject *r1;
1801
28
    int r2;
1802
1803
28
    if(!PyAnySet_Check(w))
1804
0
        Py_RETURN_NOTIMPLEMENTED;
1805
1806
28
    switch (op) {
1807
0
    case Py_EQ:
1808
0
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
1809
0
            Py_RETURN_FALSE;
1810
0
        if (v->hash != -1  &&
1811
0
            ((PySetObject *)w)->hash != -1 &&
1812
0
            v->hash != ((PySetObject *)w)->hash)
1813
0
            Py_RETURN_FALSE;
1814
0
        return set_issubset(v, w);
1815
0
    case Py_NE:
1816
0
        r1 = set_richcompare(v, w, Py_EQ);
1817
0
        if (r1 == NULL)
1818
0
            return NULL;
1819
0
        r2 = PyObject_IsTrue(r1);
1820
0
        Py_DECREF(r1);
1821
0
        if (r2 < 0)
1822
0
            return NULL;
1823
0
        return PyBool_FromLong(!r2);
1824
28
    case Py_LE:
1825
28
        return set_issubset(v, w);
1826
0
    case Py_GE:
1827
0
        return set_issuperset(v, w);
1828
0
    case Py_LT:
1829
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
1830
0
            Py_RETURN_FALSE;
1831
0
        return set_issubset(v, w);
1832
0
    case Py_GT:
1833
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
1834
0
            Py_RETURN_FALSE;
1835
0
        return set_issuperset(v, w);
1836
28
    }
1837
28
    Py_RETURN_NOTIMPLEMENTED;
1838
28
}
1839
1840
static PyObject *
1841
set_add(PySetObject *so, PyObject *key)
1842
829
{
1843
829
    if (set_add_key(so, key))
1844
0
        return NULL;
1845
829
    Py_RETURN_NONE;
1846
829
}
1847
1848
PyDoc_STRVAR(add_doc,
1849
"Add an element to a set.\n\
1850
\n\
1851
This has no effect if the element is already present.");
1852
1853
static int
1854
set_contains(PySetObject *so, PyObject *key)
1855
2.06k
{
1856
2.06k
    PyObject *tmpkey;
1857
2.06k
    int rv;
1858
1859
2.06k
    rv = set_contains_key(so, key);
1860
2.06k
    if (rv < 0) {
1861
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
1862
0
            return -1;
1863
0
        PyErr_Clear();
1864
0
        tmpkey = make_new_set(&PyFrozenSet_Type, key);
1865
0
        if (tmpkey == NULL)
1866
0
            return -1;
1867
0
        rv = set_contains_key(so, tmpkey);
1868
0
        Py_DECREF(tmpkey);
1869
0
    }
1870
2.06k
    return rv;
1871
2.06k
}
1872
1873
static PyObject *
1874
set_direct_contains(PySetObject *so, PyObject *key)
1875
11
{
1876
11
    long result;
1877
1878
11
    result = set_contains(so, key);
1879
11
    if (result < 0)
1880
0
        return NULL;
1881
11
    return PyBool_FromLong(result);
1882
11
}
1883
1884
PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x.");
1885
1886
static PyObject *
1887
set_remove(PySetObject *so, PyObject *key)
1888
0
{
1889
0
    PyObject *tmpkey;
1890
0
    int rv;
1891
1892
0
    rv = set_discard_key(so, key);
1893
0
    if (rv < 0) {
1894
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
1895
0
            return NULL;
1896
0
        PyErr_Clear();
1897
0
        tmpkey = make_new_set(&PyFrozenSet_Type, key);
1898
0
        if (tmpkey == NULL)
1899
0
            return NULL;
1900
0
        rv = set_discard_key(so, tmpkey);
1901
0
        Py_DECREF(tmpkey);
1902
0
        if (rv < 0)
1903
0
            return NULL;
1904
0
    }
1905
1906
0
    if (rv == DISCARD_NOTFOUND) {
1907
0
        _PyErr_SetKeyError(key);
1908
0
        return NULL;
1909
0
    }
1910
0
    Py_RETURN_NONE;
1911
0
}
1912
1913
PyDoc_STRVAR(remove_doc,
1914
"Remove an element from a set; it must be a member.\n\
1915
\n\
1916
If the element is not a member, raise a KeyError.");
1917
1918
static PyObject *
1919
set_discard(PySetObject *so, PyObject *key)
1920
0
{
1921
0
    PyObject *tmpkey;
1922
0
    int rv;
1923
1924
0
    rv = set_discard_key(so, key);
1925
0
    if (rv < 0) {
1926
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
1927
0
            return NULL;
1928
0
        PyErr_Clear();
1929
0
        tmpkey = make_new_set(&PyFrozenSet_Type, key);
1930
0
        if (tmpkey == NULL)
1931
0
            return NULL;
1932
0
        rv = set_discard_key(so, tmpkey);
1933
0
        Py_DECREF(tmpkey);
1934
0
        if (rv < 0)
1935
0
            return NULL;
1936
0
    }
1937
0
    Py_RETURN_NONE;
1938
0
}
1939
1940
PyDoc_STRVAR(discard_doc,
1941
"Remove an element from a set if it is a member.\n\
1942
\n\
1943
If the element is not a member, do nothing.");
1944
1945
static PyObject *
1946
set_reduce(PySetObject *so, PyObject *Py_UNUSED(ignored))
1947
0
{
1948
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL;
1949
0
    _Py_IDENTIFIER(__dict__);
1950
1951
0
    keys = PySequence_List((PyObject *)so);
1952
0
    if (keys == NULL)
1953
0
        goto done;
1954
0
    args = PyTuple_Pack(1, keys);
1955
0
    if (args == NULL)
1956
0
        goto done;
1957
0
    if (_PyObject_LookupAttrId((PyObject *)so, &PyId___dict__, &dict) < 0) {
1958
0
        goto done;
1959
0
    }
1960
0
    if (dict == NULL) {
1961
0
        dict = Py_None;
1962
0
        Py_INCREF(dict);
1963
0
    }
1964
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, dict);
1965
0
done:
1966
0
    Py_XDECREF(args);
1967
0
    Py_XDECREF(keys);
1968
0
    Py_XDECREF(dict);
1969
0
    return result;
1970
0
}
1971
1972
static PyObject *
1973
set_sizeof(PySetObject *so, PyObject *Py_UNUSED(ignored))
1974
0
{
1975
0
    Py_ssize_t res;
1976
1977
0
    res = _PyObject_SIZE(Py_TYPE(so));
1978
0
    if (so->table != so->smalltable)
1979
0
        res = res + (so->mask + 1) * sizeof(setentry);
1980
0
    return PyLong_FromSsize_t(res);
1981
0
}
1982
1983
PyDoc_STRVAR(sizeof_doc, "S.__sizeof__() -> size of S in memory, in bytes");
1984
static int
1985
set_init(PySetObject *self, PyObject *args, PyObject *kwds)
1986
233
{
1987
233
    PyObject *iterable = NULL;
1988
1989
233
    if (!_PyArg_NoKeywords("set", kwds))
1990
0
        return -1;
1991
233
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
1992
0
        return -1;
1993
233
    if (self->fill)
1994
0
        set_clear_internal(self);
1995
233
    self->hash = -1;
1996
233
    if (iterable == NULL)
1997
197
        return 0;
1998
36
    return set_update_internal(self, iterable);
1999
233
}
2000
2001
static PySequenceMethods set_as_sequence = {
2002
    set_len,                            /* sq_length */
2003
    0,                                  /* sq_concat */
2004
    0,                                  /* sq_repeat */
2005
    0,                                  /* sq_item */
2006
    0,                                  /* sq_slice */
2007
    0,                                  /* sq_ass_item */
2008
    0,                                  /* sq_ass_slice */
2009
    (objobjproc)set_contains,           /* sq_contains */
2010
};
2011
2012
/* set object ********************************************************/
2013
2014
#ifdef Py_DEBUG
2015
static PyObject *test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored));
2016
2017
PyDoc_STRVAR(test_c_api_doc, "Exercises C API.  Returns True.\n\
2018
All is well if assertions don't fail.");
2019
#endif
2020
2021
static PyMethodDef set_methods[] = {
2022
    {"add",             (PyCFunction)set_add,           METH_O,
2023
     add_doc},
2024
    {"clear",           (PyCFunction)set_clear,         METH_NOARGS,
2025
     clear_doc},
2026
    {"__contains__",(PyCFunction)set_direct_contains,           METH_O | METH_COEXIST,
2027
     contains_doc},
2028
    {"copy",            (PyCFunction)set_copy,          METH_NOARGS,
2029
     copy_doc},
2030
    {"discard",         (PyCFunction)set_discard,       METH_O,
2031
     discard_doc},
2032
    {"difference",      (PyCFunction)set_difference_multi,      METH_VARARGS,
2033
     difference_doc},
2034
    {"difference_update",       (PyCFunction)set_difference_update,     METH_VARARGS,
2035
     difference_update_doc},
2036
    {"intersection",(PyCFunction)set_intersection_multi,        METH_VARARGS,
2037
     intersection_doc},
2038
    {"intersection_update",(PyCFunction)set_intersection_update_multi,          METH_VARARGS,
2039
     intersection_update_doc},
2040
    {"isdisjoint",      (PyCFunction)set_isdisjoint,    METH_O,
2041
     isdisjoint_doc},
2042
    {"issubset",        (PyCFunction)set_issubset,      METH_O,
2043
     issubset_doc},
2044
    {"issuperset",      (PyCFunction)set_issuperset,    METH_O,
2045
     issuperset_doc},
2046
    {"pop",             (PyCFunction)set_pop,           METH_NOARGS,
2047
     pop_doc},
2048
    {"__reduce__",      (PyCFunction)set_reduce,        METH_NOARGS,
2049
     reduce_doc},
2050
    {"remove",          (PyCFunction)set_remove,        METH_O,
2051
     remove_doc},
2052
    {"__sizeof__",      (PyCFunction)set_sizeof,        METH_NOARGS,
2053
     sizeof_doc},
2054
    {"symmetric_difference",(PyCFunction)set_symmetric_difference,      METH_O,
2055
     symmetric_difference_doc},
2056
    {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update,        METH_O,
2057
     symmetric_difference_update_doc},
2058
#ifdef Py_DEBUG
2059
    {"test_c_api",      (PyCFunction)test_c_api,        METH_NOARGS,
2060
     test_c_api_doc},
2061
#endif
2062
    {"union",           (PyCFunction)set_union,         METH_VARARGS,
2063
     union_doc},
2064
    {"update",          (PyCFunction)set_update,        METH_VARARGS,
2065
     update_doc},
2066
    {NULL,              NULL}   /* sentinel */
2067
};
2068
2069
static PyNumberMethods set_as_number = {
2070
    0,                                  /*nb_add*/
2071
    (binaryfunc)set_sub,                /*nb_subtract*/
2072
    0,                                  /*nb_multiply*/
2073
    0,                                  /*nb_remainder*/
2074
    0,                                  /*nb_divmod*/
2075
    0,                                  /*nb_power*/
2076
    0,                                  /*nb_negative*/
2077
    0,                                  /*nb_positive*/
2078
    0,                                  /*nb_absolute*/
2079
    0,                                  /*nb_bool*/
2080
    0,                                  /*nb_invert*/
2081
    0,                                  /*nb_lshift*/
2082
    0,                                  /*nb_rshift*/
2083
    (binaryfunc)set_and,                /*nb_and*/
2084
    (binaryfunc)set_xor,                /*nb_xor*/
2085
    (binaryfunc)set_or,                 /*nb_or*/
2086
    0,                                  /*nb_int*/
2087
    0,                                  /*nb_reserved*/
2088
    0,                                  /*nb_float*/
2089
    0,                                  /*nb_inplace_add*/
2090
    (binaryfunc)set_isub,               /*nb_inplace_subtract*/
2091
    0,                                  /*nb_inplace_multiply*/
2092
    0,                                  /*nb_inplace_remainder*/
2093
    0,                                  /*nb_inplace_power*/
2094
    0,                                  /*nb_inplace_lshift*/
2095
    0,                                  /*nb_inplace_rshift*/
2096
    (binaryfunc)set_iand,               /*nb_inplace_and*/
2097
    (binaryfunc)set_ixor,               /*nb_inplace_xor*/
2098
    (binaryfunc)set_ior,                /*nb_inplace_or*/
2099
};
2100
2101
PyDoc_STRVAR(set_doc,
2102
"set() -> new empty set object\n\
2103
set(iterable) -> new set object\n\
2104
\n\
2105
Build an unordered collection of unique elements.");
2106
2107
PyTypeObject PySet_Type = {
2108
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2109
    "set",                              /* tp_name */
2110
    sizeof(PySetObject),                /* tp_basicsize */
2111
    0,                                  /* tp_itemsize */
2112
    /* methods */
2113
    (destructor)set_dealloc,            /* tp_dealloc */
2114
    0,                                  /* tp_vectorcall_offset */
2115
    0,                                  /* tp_getattr */
2116
    0,                                  /* tp_setattr */
2117
    0,                                  /* tp_as_async */
2118
    (reprfunc)set_repr,                 /* tp_repr */
2119
    &set_as_number,                     /* tp_as_number */
2120
    &set_as_sequence,                   /* tp_as_sequence */
2121
    0,                                  /* tp_as_mapping */
2122
    PyObject_HashNotImplemented,        /* tp_hash */
2123
    0,                                  /* tp_call */
2124
    0,                                  /* tp_str */
2125
    PyObject_GenericGetAttr,            /* tp_getattro */
2126
    0,                                  /* tp_setattro */
2127
    0,                                  /* tp_as_buffer */
2128
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2129
        Py_TPFLAGS_BASETYPE,            /* tp_flags */
2130
    set_doc,                            /* tp_doc */
2131
    (traverseproc)set_traverse,         /* tp_traverse */
2132
    (inquiry)set_clear_internal,        /* tp_clear */
2133
    (richcmpfunc)set_richcompare,       /* tp_richcompare */
2134
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2135
    (getiterfunc)set_iter,              /* tp_iter */
2136
    0,                                  /* tp_iternext */
2137
    set_methods,                        /* tp_methods */
2138
    0,                                  /* tp_members */
2139
    0,                                  /* tp_getset */
2140
    0,                                  /* tp_base */
2141
    0,                                  /* tp_dict */
2142
    0,                                  /* tp_descr_get */
2143
    0,                                  /* tp_descr_set */
2144
    0,                                  /* tp_dictoffset */
2145
    (initproc)set_init,                 /* tp_init */
2146
    PyType_GenericAlloc,                /* tp_alloc */
2147
    set_new,                            /* tp_new */
2148
    PyObject_GC_Del,                    /* tp_free */
2149
};
2150
2151
/* frozenset object ********************************************************/
2152
2153
2154
static PyMethodDef frozenset_methods[] = {
2155
    {"__contains__",(PyCFunction)set_direct_contains,           METH_O | METH_COEXIST,
2156
     contains_doc},
2157
    {"copy",            (PyCFunction)frozenset_copy,    METH_NOARGS,
2158
     copy_doc},
2159
    {"difference",      (PyCFunction)set_difference_multi,      METH_VARARGS,
2160
     difference_doc},
2161
    {"intersection",    (PyCFunction)set_intersection_multi,    METH_VARARGS,
2162
     intersection_doc},
2163
    {"isdisjoint",      (PyCFunction)set_isdisjoint,    METH_O,
2164
     isdisjoint_doc},
2165
    {"issubset",        (PyCFunction)set_issubset,      METH_O,
2166
     issubset_doc},
2167
    {"issuperset",      (PyCFunction)set_issuperset,    METH_O,
2168
     issuperset_doc},
2169
    {"__reduce__",      (PyCFunction)set_reduce,        METH_NOARGS,
2170
     reduce_doc},
2171
    {"__sizeof__",      (PyCFunction)set_sizeof,        METH_NOARGS,
2172
     sizeof_doc},
2173
    {"symmetric_difference",(PyCFunction)set_symmetric_difference,      METH_O,
2174
     symmetric_difference_doc},
2175
    {"union",           (PyCFunction)set_union,         METH_VARARGS,
2176
     union_doc},
2177
    {NULL,              NULL}   /* sentinel */
2178
};
2179
2180
static PyNumberMethods frozenset_as_number = {
2181
    0,                                  /*nb_add*/
2182
    (binaryfunc)set_sub,                /*nb_subtract*/
2183
    0,                                  /*nb_multiply*/
2184
    0,                                  /*nb_remainder*/
2185
    0,                                  /*nb_divmod*/
2186
    0,                                  /*nb_power*/
2187
    0,                                  /*nb_negative*/
2188
    0,                                  /*nb_positive*/
2189
    0,                                  /*nb_absolute*/
2190
    0,                                  /*nb_bool*/
2191
    0,                                  /*nb_invert*/
2192
    0,                                  /*nb_lshift*/
2193
    0,                                  /*nb_rshift*/
2194
    (binaryfunc)set_and,                /*nb_and*/
2195
    (binaryfunc)set_xor,                /*nb_xor*/
2196
    (binaryfunc)set_or,                 /*nb_or*/
2197
};
2198
2199
PyDoc_STRVAR(frozenset_doc,
2200
"frozenset() -> empty frozenset object\n\
2201
frozenset(iterable) -> frozenset object\n\
2202
\n\
2203
Build an immutable unordered collection of unique elements.");
2204
2205
PyTypeObject PyFrozenSet_Type = {
2206
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2207
    "frozenset",                        /* tp_name */
2208
    sizeof(PySetObject),                /* tp_basicsize */
2209
    0,                                  /* tp_itemsize */
2210
    /* methods */
2211
    (destructor)set_dealloc,            /* tp_dealloc */
2212
    0,                                  /* tp_vectorcall_offset */
2213
    0,                                  /* tp_getattr */
2214
    0,                                  /* tp_setattr */
2215
    0,                                  /* tp_as_async */
2216
    (reprfunc)set_repr,                 /* tp_repr */
2217
    &frozenset_as_number,               /* tp_as_number */
2218
    &set_as_sequence,                   /* tp_as_sequence */
2219
    0,                                  /* tp_as_mapping */
2220
    frozenset_hash,                     /* tp_hash */
2221
    0,                                  /* tp_call */
2222
    0,                                  /* tp_str */
2223
    PyObject_GenericGetAttr,            /* tp_getattro */
2224
    0,                                  /* tp_setattro */
2225
    0,                                  /* tp_as_buffer */
2226
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2227
        Py_TPFLAGS_BASETYPE,            /* tp_flags */
2228
    frozenset_doc,                      /* tp_doc */
2229
    (traverseproc)set_traverse,         /* tp_traverse */
2230
    (inquiry)set_clear_internal,        /* tp_clear */
2231
    (richcmpfunc)set_richcompare,       /* tp_richcompare */
2232
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2233
    (getiterfunc)set_iter,              /* tp_iter */
2234
    0,                                  /* tp_iternext */
2235
    frozenset_methods,                  /* tp_methods */
2236
    0,                                  /* tp_members */
2237
    0,                                  /* tp_getset */
2238
    0,                                  /* tp_base */
2239
    0,                                  /* tp_dict */
2240
    0,                                  /* tp_descr_get */
2241
    0,                                  /* tp_descr_set */
2242
    0,                                  /* tp_dictoffset */
2243
    0,                                  /* tp_init */
2244
    PyType_GenericAlloc,                /* tp_alloc */
2245
    frozenset_new,                      /* tp_new */
2246
    PyObject_GC_Del,                    /* tp_free */
2247
};
2248
2249
2250
/***** C API functions *************************************************/
2251
2252
PyObject *
2253
PySet_New(PyObject *iterable)
2254
662
{
2255
662
    return make_new_set(&PySet_Type, iterable);
2256
662
}
2257
2258
PyObject *
2259
PyFrozenSet_New(PyObject *iterable)
2260
478
{
2261
478
    return make_new_set(&PyFrozenSet_Type, iterable);
2262
478
}
2263
2264
Py_ssize_t
2265
PySet_Size(PyObject *anyset)
2266
143
{
2267
143
    if (!PyAnySet_Check(anyset)) {
2268
0
        PyErr_BadInternalCall();
2269
0
        return -1;
2270
0
    }
2271
143
    return PySet_GET_SIZE(anyset);
2272
143
}
2273
2274
int
2275
PySet_Clear(PyObject *set)
2276
143
{
2277
143
    if (!PySet_Check(set)) {
2278
0
        PyErr_BadInternalCall();
2279
0
        return -1;
2280
0
    }
2281
143
    return set_clear_internal((PySetObject *)set);
2282
143
}
2283
2284
int
2285
PySet_Contains(PyObject *anyset, PyObject *key)
2286
413
{
2287
413
    if (!PyAnySet_Check(anyset)) {
2288
0
        PyErr_BadInternalCall();
2289
0
        return -1;
2290
0
    }
2291
413
    return set_contains_key((PySetObject *)anyset, key);
2292
413
}
2293
2294
int
2295
PySet_Discard(PyObject *set, PyObject *key)
2296
73
{
2297
73
    if (!PySet_Check(set)) {
2298
0
        PyErr_BadInternalCall();
2299
0
        return -1;
2300
0
    }
2301
73
    return set_discard_key((PySetObject *)set, key);
2302
73
}
2303
2304
int
2305
PySet_Add(PyObject *anyset, PyObject *key)
2306
1.83k
{
2307
1.83k
    if (!PySet_Check(anyset) &&
2308
1.83k
        (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {
2309
0
        PyErr_BadInternalCall();
2310
0
        return -1;
2311
0
    }
2312
1.83k
    return set_add_key((PySetObject *)anyset, key);
2313
1.83k
}
2314
2315
int
2316
PySet_ClearFreeList(void)
2317
0
{
2318
0
    return 0;
2319
0
}
2320
2321
void
2322
PySet_Fini(void)
2323
0
{
2324
0
    Py_CLEAR(emptyfrozenset);
2325
0
}
2326
2327
int
2328
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2329
413
{
2330
413
    setentry *entry;
2331
2332
413
    if (!PyAnySet_Check(set)) {
2333
0
        PyErr_BadInternalCall();
2334
0
        return -1;
2335
0
    }
2336
413
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2337
143
        return 0;
2338
270
    *key = entry->key;
2339
270
    *hash = entry->hash;
2340
270
    return 1;
2341
413
}
2342
2343
PyObject *
2344
PySet_Pop(PyObject *set)
2345
0
{
2346
0
    if (!PySet_Check(set)) {
2347
0
        PyErr_BadInternalCall();
2348
0
        return NULL;
2349
0
    }
2350
0
    return set_pop((PySetObject *)set, NULL);
2351
0
}
2352
2353
int
2354
_PySet_Update(PyObject *set, PyObject *iterable)
2355
0
{
2356
0
    if (!PySet_Check(set)) {
2357
0
        PyErr_BadInternalCall();
2358
0
        return -1;
2359
0
    }
2360
0
    return set_update_internal((PySetObject *)set, iterable);
2361
0
}
2362
2363
/* Exported for the gdb plugin's benefit. */
2364
PyObject *_PySet_Dummy = dummy;
2365
2366
#ifdef Py_DEBUG
2367
2368
/* Test code to be called with any three element set.
2369
   Returns True and original set is restored. */
2370
2371
#define assertRaises(call_return_value, exception)              \
2372
    do {                                                        \
2373
        assert(call_return_value);                              \
2374
        assert(PyErr_ExceptionMatches(exception));              \
2375
        PyErr_Clear();                                          \
2376
    } while(0)
2377
2378
static PyObject *
2379
test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored))
2380
{
2381
    Py_ssize_t count;
2382
    const char *s;
2383
    Py_ssize_t i;
2384
    PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x=NULL;
2385
    PyObject *ob = (PyObject *)so;
2386
    Py_hash_t hash;
2387
    PyObject *str;
2388
2389
    /* Verify preconditions */
2390
    assert(PyAnySet_Check(ob));
2391
    assert(PyAnySet_CheckExact(ob));
2392
    assert(!PyFrozenSet_CheckExact(ob));
2393
2394
    /* so.clear(); so |= set("abc"); */
2395
    str = PyUnicode_FromString("abc");
2396
    if (str == NULL)
2397
        return NULL;
2398
    set_clear_internal(so);
2399
    if (set_update_internal(so, str)) {
2400
        Py_DECREF(str);
2401
        return NULL;
2402
    }
2403
    Py_DECREF(str);
2404
2405
    /* Exercise type/size checks */
2406
    assert(PySet_Size(ob) == 3);
2407
    assert(PySet_GET_SIZE(ob) == 3);
2408
2409
    /* Raise TypeError for non-iterable constructor arguments */
2410
    assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError);
2411
    assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError);
2412
2413
    /* Raise TypeError for unhashable key */
2414
    dup = PySet_New(ob);
2415
    assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError);
2416
    assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError);
2417
    assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError);
2418
2419
    /* Exercise successful pop, contains, add, and discard */
2420
    elem = PySet_Pop(ob);
2421
    assert(PySet_Contains(ob, elem) == 0);
2422
    assert(PySet_GET_SIZE(ob) == 2);
2423
    assert(PySet_Add(ob, elem) == 0);
2424
    assert(PySet_Contains(ob, elem) == 1);
2425
    assert(PySet_GET_SIZE(ob) == 3);
2426
    assert(PySet_Discard(ob, elem) == 1);
2427
    assert(PySet_GET_SIZE(ob) == 2);
2428
    assert(PySet_Discard(ob, elem) == 0);
2429
    assert(PySet_GET_SIZE(ob) == 2);
2430
2431
    /* Exercise clear */
2432
    dup2 = PySet_New(dup);
2433
    assert(PySet_Clear(dup2) == 0);
2434
    assert(PySet_Size(dup2) == 0);
2435
    Py_DECREF(dup2);
2436
2437
    /* Raise SystemError on clear or update of frozen set */
2438
    f = PyFrozenSet_New(dup);
2439
    assertRaises(PySet_Clear(f) == -1, PyExc_SystemError);
2440
    assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError);
2441
    assert(PySet_Add(f, elem) == 0);
2442
    Py_INCREF(f);
2443
    assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError);
2444
    Py_DECREF(f);
2445
    Py_DECREF(f);
2446
2447
    /* Exercise direct iteration */
2448
    i = 0, count = 0;
2449
    while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) {
2450
        s = PyUnicode_AsUTF8(x);
2451
        assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c'));
2452
        count++;
2453
    }
2454
    assert(count == 3);
2455
2456
    /* Exercise updates */
2457
    dup2 = PySet_New(NULL);
2458
    assert(_PySet_Update(dup2, dup) == 0);
2459
    assert(PySet_Size(dup2) == 3);
2460
    assert(_PySet_Update(dup2, dup) == 0);
2461
    assert(PySet_Size(dup2) == 3);
2462
    Py_DECREF(dup2);
2463
2464
    /* Raise SystemError when self argument is not a set or frozenset. */
2465
    t = PyTuple_New(0);
2466
    assertRaises(PySet_Size(t) == -1, PyExc_SystemError);
2467
    assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError);
2468
    Py_DECREF(t);
2469
2470
    /* Raise SystemError when self argument is not a set. */
2471
    f = PyFrozenSet_New(dup);
2472
    assert(PySet_Size(f) == 3);
2473
    assert(PyFrozenSet_CheckExact(f));
2474
    assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError);
2475
    assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError);
2476
    Py_DECREF(f);
2477
2478
    /* Raise KeyError when popping from an empty set */
2479
    assert(PyNumber_InPlaceSubtract(ob, ob) == ob);
2480
    Py_DECREF(ob);
2481
    assert(PySet_GET_SIZE(ob) == 0);
2482
    assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError);
2483
2484
    /* Restore the set from the copy using the PyNumber API */
2485
    assert(PyNumber_InPlaceOr(ob, dup) == ob);
2486
    Py_DECREF(ob);
2487
2488
    /* Verify constructors accept NULL arguments */
2489
    f = PySet_New(NULL);
2490
    assert(f != NULL);
2491
    assert(PySet_GET_SIZE(f) == 0);
2492
    Py_DECREF(f);
2493
    f = PyFrozenSet_New(NULL);
2494
    assert(f != NULL);
2495
    assert(PyFrozenSet_CheckExact(f));
2496
    assert(PySet_GET_SIZE(f) == 0);
2497
    Py_DECREF(f);
2498
2499
    Py_DECREF(elem);
2500
    Py_DECREF(dup);
2501
    Py_RETURN_TRUE;
2502
}
2503
2504
#undef assertRaises
2505
2506
#endif
2507
2508
/***** Dummy Struct  *************************************************/
2509
2510
static PyObject *
2511
dummy_repr(PyObject *op)
2512
0
{
2513
0
    return PyUnicode_FromString("<dummy key>");
2514
0
}
2515
2516
static void
2517
dummy_dealloc(PyObject* ignore)
2518
0
{
2519
0
    Py_FatalError("deallocating <dummy key>");
2520
0
}
2521
2522
static PyTypeObject _PySetDummy_Type = {
2523
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2524
    "<dummy key> type",
2525
    0,
2526
    0,
2527
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
2528
    0,                  /*tp_vectorcall_offset*/
2529
    0,                  /*tp_getattr*/
2530
    0,                  /*tp_setattr*/
2531
    0,                  /*tp_as_async*/
2532
    dummy_repr,         /*tp_repr*/
2533
    0,                  /*tp_as_number*/
2534
    0,                  /*tp_as_sequence*/
2535
    0,                  /*tp_as_mapping*/
2536
    0,                  /*tp_hash */
2537
    0,                  /*tp_call */
2538
    0,                  /*tp_str */
2539
    0,                  /*tp_getattro */
2540
    0,                  /*tp_setattro */
2541
    0,                  /*tp_as_buffer */
2542
    Py_TPFLAGS_DEFAULT, /*tp_flags */
2543
};
2544
2545
static PyObject _dummy_struct = {
2546
  _PyObject_EXTRA_INIT
2547
  2, &_PySetDummy_Type
2548
};
2549