Coverage Report

Created: 2025-10-10 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/setobject.c
Line
Count
Source
1
2
/* set object implementation
3
4
   Written and maintained by Raymond D. Hettinger <python@rcn.com>
5
   Derived from 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 generator.  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_ceval.h"               // _PyEval_GetBuiltin()
36
#include "pycore_critical_section.h"    // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
37
#include "pycore_dict.h"                // _PyDict_Contains_KnownHash()
38
#include "pycore_modsupport.h"          // _PyArg_NoKwnames()
39
#include "pycore_object.h"              // _PyObject_GC_UNTRACK()
40
#include "pycore_pyatomic_ft_wrappers.h"  // FT_ATOMIC_LOAD_SSIZE_RELAXED()
41
#include "pycore_pyerrors.h"            // _PyErr_SetKeyError()
42
#include "pycore_setobject.h"           // _PySet_NextEntry() definition
43
#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
44
45
#include "stringlib/eq.h"               // unicode_eq()
46
#include <stddef.h>                     // offsetof()
47
#include "clinic/setobject.c.h"
48
49
/*[clinic input]
50
class set "PySetObject *" "&PySet_Type"
51
class frozenset "PySetObject *" "&PyFrozenSet_Type"
52
[clinic start generated code]*/
53
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=97ad1d3e9f117079]*/
54
55
/*[python input]
56
class setobject_converter(self_converter):
57
    type = "PySetObject *"
58
[python start generated code]*/
59
/*[python end generated code: output=da39a3ee5e6b4b0d input=33a44506d4d57793]*/
60
61
/* Object used as dummy key to fill deleted entries */
62
static PyObject _dummy_struct;
63
64
6.50M
#define dummy (&_dummy_struct)
65
66
67
/* ======================================================================== */
68
/* ======= Begin logic for probing the hash table ========================= */
69
70
/* Set this to zero to turn-off linear probing */
71
#ifndef LINEAR_PROBES
72
68.9M
#define LINEAR_PROBES 9
73
#endif
74
75
/* This must be >= 1 */
76
10.0M
#define PERTURB_SHIFT 5
77
78
static setentry *
79
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
80
47.3M
{
81
47.3M
    setentry *table;
82
47.3M
    setentry *entry;
83
47.3M
    size_t perturb = hash;
84
47.3M
    size_t mask = so->mask;
85
47.3M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
86
47.3M
    int probes;
87
47.3M
    int cmp;
88
89
47.3M
    int frozenset = PyFrozenSet_CheckExact(so);
90
91
57.3M
    while (1) {
92
57.3M
        entry = &so->table[i];
93
57.3M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
94
69.1M
        do {
95
69.1M
            if (entry->hash == 0 && entry->key == NULL)
96
31.9M
                return entry;
97
37.1M
            if (entry->hash == hash) {
98
15.4M
                PyObject *startkey = entry->key;
99
15.4M
                assert(startkey != dummy);
100
15.4M
                if (startkey == key)
101
15.4M
                    return entry;
102
2.95k
                if (PyUnicode_CheckExact(startkey)
103
2.95k
                    && PyUnicode_CheckExact(key)
104
897
                    && unicode_eq(startkey, key))
105
897
                    return entry;
106
2.05k
                table = so->table;
107
2.05k
                if (frozenset) {
108
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
109
0
                    if (cmp < 0)
110
0
                        return NULL;
111
2.05k
                } else {
112
                    // incref startkey because it can be removed from the set by the compare
113
2.05k
                    Py_INCREF(startkey);
114
2.05k
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
115
2.05k
                    Py_DECREF(startkey);
116
2.05k
                    if (cmp < 0)
117
0
                        return NULL;
118
2.05k
                    if (table != so->table || entry->key != startkey)
119
0
                        return set_lookkey(so, key, hash);
120
2.05k
                }
121
2.05k
                if (cmp > 0)
122
2.05k
                    return entry;
123
0
                mask = so->mask;
124
0
            }
125
21.7M
            entry++;
126
21.7M
        } while (probes--);
127
9.97M
        perturb >>= PERTURB_SHIFT;
128
9.97M
        i = (i * 5 + 1 + perturb) & mask;
129
9.97M
    }
130
47.3M
}
131
132
static int set_table_resize(PySetObject *, Py_ssize_t);
133
134
static int
135
set_add_entry_takeref(PySetObject *so, PyObject *key, Py_hash_t hash)
136
743k
{
137
743k
    setentry *table;
138
743k
    setentry *freeslot;
139
743k
    setentry *entry;
140
743k
    size_t perturb;
141
743k
    size_t mask;
142
743k
    size_t i;                       /* Unsigned for defined overflow behavior */
143
743k
    int probes;
144
743k
    int cmp;
145
146
743k
  restart:
147
148
743k
    mask = so->mask;
149
743k
    i = (size_t)hash & mask;
150
743k
    freeslot = NULL;
151
743k
    perturb = hash;
152
153
778k
    while (1) {
154
778k
        entry = &so->table[i];
155
778k
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
156
867k
        do {
157
867k
            if (entry->hash == 0 && entry->key == NULL)
158
401k
                goto found_unused_or_dummy;
159
466k
            if (entry->hash == hash) {
160
342k
                PyObject *startkey = entry->key;
161
342k
                assert(startkey != dummy);
162
342k
                if (startkey == key)
163
16.5k
                    goto found_active;
164
325k
                if (PyUnicode_CheckExact(startkey)
165
325k
                    && PyUnicode_CheckExact(key)
166
325k
                    && unicode_eq(startkey, key))
167
325k
                    goto found_active;
168
3
                table = so->table;
169
3
                Py_INCREF(startkey);
170
3
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
171
3
                Py_DECREF(startkey);
172
3
                if (cmp > 0)
173
0
                    goto found_active;
174
3
                if (cmp < 0)
175
0
                    goto comparison_error;
176
3
                if (table != so->table || entry->key != startkey)
177
0
                    goto restart;
178
3
                mask = so->mask;
179
3
            }
180
124k
            else if (entry->hash == -1) {
181
0
                assert (entry->key == dummy);
182
0
                freeslot = entry;
183
0
            }
184
124k
            entry++;
185
124k
        } while (probes--);
186
35.4k
        perturb >>= PERTURB_SHIFT;
187
35.4k
        i = (i * 5 + 1 + perturb) & mask;
188
35.4k
    }
189
190
401k
  found_unused_or_dummy:
191
401k
    if (freeslot == NULL)
192
401k
        goto found_unused;
193
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
194
0
    freeslot->key = key;
195
0
    freeslot->hash = hash;
196
0
    return 0;
197
198
401k
  found_unused:
199
401k
    so->fill++;
200
401k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
201
401k
    entry->key = key;
202
401k
    entry->hash = hash;
203
401k
    if ((size_t)so->fill*5 < mask*3)
204
389k
        return 0;
205
11.7k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
206
207
342k
  found_active:
208
342k
    Py_DECREF(key);
209
342k
    return 0;
210
211
0
  comparison_error:
212
0
    Py_DECREF(key);
213
0
    return -1;
214
401k
}
215
216
static int
217
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
218
741k
{
219
741k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
220
221
741k
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
222
741k
}
223
224
static void
225
set_unhashable_type(PyObject *key)
226
0
{
227
0
    PyObject *exc = PyErr_GetRaisedException();
228
0
    assert(exc != NULL);
229
0
    if (!Py_IS_TYPE(exc, (PyTypeObject*)PyExc_TypeError)) {
230
0
        PyErr_SetRaisedException(exc);
231
0
        return;
232
0
    }
233
234
0
    PyErr_Format(PyExc_TypeError,
235
0
                 "cannot use '%T' as a set element (%S)",
236
0
                 key, exc);
237
0
    Py_DECREF(exc);
238
0
}
239
240
int
241
_PySet_AddTakeRef(PySetObject *so, PyObject *key)
242
1.76k
{
243
1.76k
    Py_hash_t hash = _PyObject_HashFast(key);
244
1.76k
    if (hash == -1) {
245
0
        set_unhashable_type(key);
246
0
        Py_DECREF(key);
247
0
        return -1;
248
0
    }
249
    // We don't pre-increment here, the caller holds a strong
250
    // reference to the object which we are stealing.
251
1.76k
    return set_add_entry_takeref(so, key, hash);
252
1.76k
}
253
254
/*
255
Internal routine used by set_table_resize() to insert an item which is
256
known to be absent from the set.  Besides the performance benefit,
257
there is also safety benefit since using set_add_entry() risks making
258
a callback in the middle of a set_table_resize(), see issue 1456209.
259
The caller is responsible for updating the key's reference count and
260
the setobject's fill and used fields.
261
*/
262
static void
263
set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
264
131k
{
265
131k
    setentry *entry;
266
131k
    size_t perturb = hash;
267
131k
    size_t i = (size_t)hash & mask;
268
131k
    size_t j;
269
270
133k
    while (1) {
271
133k
        entry = &table[i];
272
133k
        if (entry->key == NULL)
273
124k
            goto found_null;
274
8.79k
        if (i + LINEAR_PROBES <= mask) {
275
7.80k
            for (j = 0; j < LINEAR_PROBES; j++) {
276
7.80k
                entry++;
277
7.80k
                if (entry->key == NULL)
278
6.88k
                    goto found_null;
279
7.80k
            }
280
6.88k
        }
281
1.91k
        perturb >>= PERTURB_SHIFT;
282
1.91k
        i = (i * 5 + 1 + perturb) & mask;
283
1.91k
    }
284
131k
  found_null:
285
131k
    entry->key = key;
286
131k
    entry->hash = hash;
287
131k
}
288
289
/* ======== End logic for probing the hash table ========================== */
290
/* ======================================================================== */
291
292
/*
293
Restructure the table by allocating a new table and reinserting all
294
keys again.  When entries have been deleted, the new table may
295
actually be smaller than the old one.
296
*/
297
static int
298
set_table_resize(PySetObject *so, Py_ssize_t minused)
299
17.9k
{
300
17.9k
    setentry *oldtable, *newtable, *entry;
301
17.9k
    Py_ssize_t oldmask = so->mask;
302
17.9k
    size_t newmask;
303
17.9k
    int is_oldtable_malloced;
304
17.9k
    setentry small_copy[PySet_MINSIZE];
305
306
17.9k
    assert(minused >= 0);
307
308
    /* Find the smallest table size > minused. */
309
    /* XXX speed-up with intrinsics */
310
17.9k
    size_t newsize = PySet_MINSIZE;
311
57.1k
    while (newsize <= (size_t)minused) {
312
39.2k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
313
39.2k
    }
314
315
    /* Get space for a new table. */
316
17.9k
    oldtable = so->table;
317
17.9k
    assert(oldtable != NULL);
318
17.9k
    is_oldtable_malloced = oldtable != so->smalltable;
319
320
17.9k
    if (newsize == PySet_MINSIZE) {
321
        /* A large table is shrinking, or we can't get any smaller. */
322
0
        newtable = so->smalltable;
323
0
        if (newtable == oldtable) {
324
0
            if (so->fill == so->used) {
325
                /* No dummies, so no point doing anything. */
326
0
                return 0;
327
0
            }
328
            /* We're not going to resize it, but rebuild the
329
               table anyway to purge old dummy entries.
330
               Subtle:  This is *necessary* if fill==size,
331
               as set_lookkey needs at least one virgin slot to
332
               terminate failing searches.  If fill < size, it's
333
               merely desirable, as dummies slow searches. */
334
0
            assert(so->fill > so->used);
335
0
            memcpy(small_copy, oldtable, sizeof(small_copy));
336
0
            oldtable = small_copy;
337
0
        }
338
0
    }
339
17.9k
    else {
340
17.9k
        newtable = PyMem_NEW(setentry, newsize);
341
17.9k
        if (newtable == NULL) {
342
0
            PyErr_NoMemory();
343
0
            return -1;
344
0
        }
345
17.9k
    }
346
347
    /* Make the set empty, using the new table. */
348
17.9k
    assert(newtable != oldtable);
349
17.9k
    memset(newtable, 0, sizeof(setentry) * newsize);
350
17.9k
    so->mask = newsize - 1;
351
17.9k
    so->table = newtable;
352
353
    /* Copy the data over; this is refcount-neutral for active entries;
354
       dummy entries aren't copied over, of course */
355
17.9k
    newmask = (size_t)so->mask;
356
17.9k
    if (so->fill == so->used) {
357
259k
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
358
241k
            if (entry->key != NULL) {
359
123k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
360
123k
            }
361
241k
        }
362
17.9k
    } else {
363
0
        so->fill = so->used;
364
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
365
0
            if (entry->key != NULL && entry->key != dummy) {
366
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
367
0
            }
368
0
        }
369
0
    }
370
371
17.9k
    if (is_oldtable_malloced)
372
2.97k
        PyMem_Free(oldtable);
373
17.9k
    return 0;
374
17.9k
}
375
376
static int
377
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
378
47.3M
{
379
47.3M
    setentry *entry;
380
381
47.3M
    entry = set_lookkey(so, key, hash);
382
47.3M
    if (entry != NULL)
383
47.3M
        return entry->key != NULL;
384
0
    return -1;
385
47.3M
}
386
387
71.6k
#define DISCARD_NOTFOUND 0
388
1.57k
#define DISCARD_FOUND 1
389
390
static int
391
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
392
73.1k
{
393
73.1k
    setentry *entry;
394
73.1k
    PyObject *old_key;
395
396
73.1k
    entry = set_lookkey(so, key, hash);
397
73.1k
    if (entry == NULL)
398
0
        return -1;
399
73.1k
    if (entry->key == NULL)
400
71.6k
        return DISCARD_NOTFOUND;
401
1.57k
    old_key = entry->key;
402
1.57k
    entry->key = dummy;
403
1.57k
    entry->hash = -1;
404
1.57k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
405
1.57k
    Py_DECREF(old_key);
406
1.57k
    return DISCARD_FOUND;
407
73.1k
}
408
409
static int
410
set_add_key(PySetObject *so, PyObject *key)
411
698k
{
412
698k
    Py_hash_t hash = _PyObject_HashFast(key);
413
698k
    if (hash == -1) {
414
0
        set_unhashable_type(key);
415
0
        return -1;
416
0
    }
417
698k
    return set_add_entry(so, key, hash);
418
698k
}
419
420
static int
421
set_contains_key(PySetObject *so, PyObject *key)
422
47.3M
{
423
47.3M
    Py_hash_t hash = _PyObject_HashFast(key);
424
47.3M
    if (hash == -1) {
425
0
        set_unhashable_type(key);
426
0
        return -1;
427
0
    }
428
47.3M
    return set_contains_entry(so, key, hash);
429
47.3M
}
430
431
static int
432
set_discard_key(PySetObject *so, PyObject *key)
433
73.1k
{
434
73.1k
    Py_hash_t hash = _PyObject_HashFast(key);
435
73.1k
    if (hash == -1) {
436
0
        set_unhashable_type(key);
437
0
        return -1;
438
0
    }
439
73.1k
    return set_discard_entry(so, key, hash);
440
73.1k
}
441
442
static void
443
set_empty_to_minsize(PySetObject *so)
444
188
{
445
188
    memset(so->smalltable, 0, sizeof(so->smalltable));
446
188
    so->fill = 0;
447
188
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
448
188
    so->mask = PySet_MINSIZE - 1;
449
188
    so->table = so->smalltable;
450
188
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
451
188
}
452
453
static int
454
set_clear_internal(PyObject *self)
455
188
{
456
188
    PySetObject *so = _PySet_CAST(self);
457
188
    setentry *entry;
458
188
    setentry *table = so->table;
459
188
    Py_ssize_t fill = so->fill;
460
188
    Py_ssize_t used = so->used;
461
188
    int table_is_malloced = table != so->smalltable;
462
188
    setentry small_copy[PySet_MINSIZE];
463
464
188
    assert (PyAnySet_Check(so));
465
188
    assert(table != NULL);
466
467
    /* This is delicate.  During the process of clearing the set,
468
     * decrefs can cause the set to mutate.  To avoid fatal confusion
469
     * (voice of experience), we have to make the set empty before
470
     * clearing the slots, and never refer to anything via so->ref while
471
     * clearing.
472
     */
473
188
    if (table_is_malloced)
474
0
        set_empty_to_minsize(so);
475
476
188
    else if (fill > 0) {
477
        /* It's a small table with something that needs to be cleared.
478
         * Afraid the only safe way is to copy the set entries into
479
         * another small table first.
480
         */
481
188
        memcpy(small_copy, table, sizeof(small_copy));
482
188
        table = small_copy;
483
188
        set_empty_to_minsize(so);
484
188
    }
485
    /* else it's a small table that's already empty */
486
487
    /* Now we can finally clear things.  If C had refcounts, we could
488
     * assert that the refcount on table is 1 now, i.e. that this function
489
     * has unique access to it, so decref side-effects can't alter it.
490
     */
491
1.06k
    for (entry = table; used > 0; entry++) {
492
880
        if (entry->key && entry->key != dummy) {
493
188
            used--;
494
188
            Py_DECREF(entry->key);
495
188
        }
496
880
    }
497
498
188
    if (table_is_malloced)
499
0
        PyMem_Free(table);
500
188
    return 0;
501
188
}
502
503
/*
504
 * Iterate over a set table.  Use like so:
505
 *
506
 *     Py_ssize_t pos;
507
 *     setentry *entry;
508
 *     pos = 0;   # important!  pos should not otherwise be changed by you
509
 *     while (set_next(yourset, &pos, &entry)) {
510
 *              Refer to borrowed reference in entry->key.
511
 *     }
512
 *
513
 * CAUTION:  In general, it isn't safe to use set_next in a loop that
514
 * mutates the table.
515
 */
516
static int
517
set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
518
6.65M
{
519
6.65M
    Py_ssize_t i;
520
6.65M
    Py_ssize_t mask;
521
6.65M
    setentry *entry;
522
523
6.65M
    assert (PyAnySet_Check(so));
524
6.65M
    i = *pos_ptr;
525
6.65M
    assert(i >= 0);
526
6.65M
    mask = so->mask;
527
6.65M
    entry = &so->table[i];
528
21.6M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
529
15.0M
        i++;
530
15.0M
        entry++;
531
15.0M
    }
532
6.65M
    *pos_ptr = i+1;
533
6.65M
    if (i > mask)
534
832k
        return 0;
535
6.65M
    assert(entry != NULL);
536
5.82M
    *entry_ptr = entry;
537
5.82M
    return 1;
538
6.65M
}
539
540
static void
541
set_dealloc(PyObject *self)
542
673k
{
543
673k
    PySetObject *so = _PySet_CAST(self);
544
673k
    setentry *entry;
545
673k
    Py_ssize_t used = so->used;
546
547
    /* bpo-31095: UnTrack is needed before calling any callbacks */
548
673k
    PyObject_GC_UnTrack(so);
549
673k
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
550
551
2.44M
    for (entry = so->table; used > 0; entry++) {
552
1.76M
        if (entry->key && entry->key != dummy) {
553
462k
                used--;
554
462k
                Py_DECREF(entry->key);
555
462k
        }
556
1.76M
    }
557
673k
    if (so->table != so->smalltable)
558
14.4k
        PyMem_Free(so->table);
559
673k
    Py_TYPE(so)->tp_free(so);
560
673k
}
561
562
static PyObject *
563
set_repr_lock_held(PySetObject *so)
564
0
{
565
0
    PyObject *result=NULL, *keys, *listrepr, *tmp;
566
0
    int status = Py_ReprEnter((PyObject*)so);
567
568
0
    if (status != 0) {
569
0
        if (status < 0)
570
0
            return NULL;
571
0
        return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name);
572
0
    }
573
574
    /* shortcut for the empty set */
575
0
    if (!so->used) {
576
0
        Py_ReprLeave((PyObject*)so);
577
0
        return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
578
0
    }
579
580
    // gh-129967: avoid PySequence_List because it might re-lock the object
581
    // lock or the GIL and allow something to clear the set from underneath us.
582
0
    keys = PyList_New(so->used);
583
0
    if (keys == NULL) {
584
0
        goto done;
585
0
    }
586
587
0
    Py_ssize_t pos = 0, idx = 0;
588
0
    setentry *entry;
589
0
    while (set_next(so, &pos, &entry)) {
590
0
        PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key));
591
0
    }
592
593
    /* repr(keys)[1:-1] */
594
0
    listrepr = PyObject_Repr(keys);
595
0
    Py_DECREF(keys);
596
0
    if (listrepr == NULL)
597
0
        goto done;
598
0
    tmp = PyUnicode_Substring(listrepr, 1, PyUnicode_GET_LENGTH(listrepr)-1);
599
0
    Py_DECREF(listrepr);
600
0
    if (tmp == NULL)
601
0
        goto done;
602
0
    listrepr = tmp;
603
604
0
    if (!PySet_CheckExact(so))
605
0
        result = PyUnicode_FromFormat("%s({%U})",
606
0
                                      Py_TYPE(so)->tp_name,
607
0
                                      listrepr);
608
0
    else
609
0
        result = PyUnicode_FromFormat("{%U}", listrepr);
610
0
    Py_DECREF(listrepr);
611
0
done:
612
0
    Py_ReprLeave((PyObject*)so);
613
0
    return result;
614
0
}
615
616
static PyObject *
617
set_repr(PyObject *self)
618
0
{
619
0
    PySetObject *so = _PySet_CAST(self);
620
0
    PyObject *result;
621
0
    Py_BEGIN_CRITICAL_SECTION(so);
622
0
    result = set_repr_lock_held(so);
623
0
    Py_END_CRITICAL_SECTION();
624
0
    return result;
625
0
}
626
627
static Py_ssize_t
628
set_len(PyObject *self)
629
271k
{
630
271k
    PySetObject *so = _PySet_CAST(self);
631
271k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
632
271k
}
633
634
static int
635
set_merge_lock_held(PySetObject *so, PyObject *otherset)
636
106k
{
637
106k
    PySetObject *other;
638
106k
    PyObject *key;
639
106k
    Py_ssize_t i;
640
106k
    setentry *so_entry;
641
106k
    setentry *other_entry;
642
643
106k
    assert (PyAnySet_Check(so));
644
106k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
645
106k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
646
647
106k
    other = _PySet_CAST(otherset);
648
106k
    if (other == so || other->used == 0)
649
        /* a.update(a) or a.update(set()); nothing to do */
650
62.9k
        return 0;
651
    /* Do one big resize at the start, rather than
652
     * incrementally resizing as we insert new keys.  Expect
653
     * that there will be no (or few) overlapping keys.
654
     */
655
43.8k
    if ((so->fill + other->used)*5 >= so->mask*3) {
656
6.19k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
657
0
            return -1;
658
6.19k
    }
659
43.8k
    so_entry = so->table;
660
43.8k
    other_entry = other->table;
661
662
    /* If our table is empty, and both tables have the same size, and
663
       there are no dummies to eliminate, then just copy the pointers. */
664
43.8k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
665
323k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
666
293k
            key = other_entry->key;
667
293k
            if (key != NULL) {
668
74.4k
                assert(so_entry->key == NULL);
669
74.4k
                so_entry->key = Py_NewRef(key);
670
74.4k
                so_entry->hash = other_entry->hash;
671
74.4k
            }
672
293k
        }
673
29.7k
        so->fill = other->fill;
674
29.7k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
675
29.7k
        return 0;
676
29.7k
    }
677
678
    /* If our table is empty, we can use set_insert_clean() */
679
14.1k
    if (so->fill == 0) {
680
1.01k
        setentry *newtable = so->table;
681
1.01k
        size_t newmask = (size_t)so->mask;
682
1.01k
        so->fill = other->used;
683
1.01k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
684
41.8k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
685
40.8k
            key = other_entry->key;
686
40.8k
            if (key != NULL && key != dummy) {
687
8.31k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
688
8.31k
                                 other_entry->hash);
689
8.31k
            }
690
40.8k
        }
691
1.01k
        return 0;
692
1.01k
    }
693
694
    /* We can't assure there are no duplicates, so do normal insertions */
695
158k
    for (i = 0; i <= other->mask; i++) {
696
144k
        other_entry = &other->table[i];
697
144k
        key = other_entry->key;
698
144k
        if (key != NULL && key != dummy) {
699
42.5k
            if (set_add_entry(so, key, other_entry->hash))
700
0
                return -1;
701
42.5k
        }
702
144k
    }
703
13.1k
    return 0;
704
13.1k
}
705
706
/*[clinic input]
707
@critical_section
708
set.pop
709
    so: setobject
710
711
Remove and return an arbitrary set element.
712
713
Raises KeyError if the set is empty.
714
[clinic start generated code]*/
715
716
static PyObject *
717
set_pop_impl(PySetObject *so)
718
/*[clinic end generated code: output=4d65180f1271871b input=9296c84921125060]*/
719
141
{
720
    /* Make sure the search finger is in bounds */
721
141
    setentry *entry = so->table + (so->finger & so->mask);
722
141
    setentry *limit = so->table + so->mask;
723
141
    PyObject *key;
724
725
141
    if (so->used == 0) {
726
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
727
0
        return NULL;
728
0
    }
729
448
    while (entry->key == NULL || entry->key==dummy) {
730
307
        entry++;
731
307
        if (entry > limit)
732
0
            entry = so->table;
733
307
    }
734
141
    key = entry->key;
735
141
    entry->key = dummy;
736
141
    entry->hash = -1;
737
141
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
738
141
    so->finger = entry - so->table + 1;   /* next place to start */
739
141
    return key;
740
141
}
741
742
static int
743
set_traverse(PyObject *self, visitproc visit, void *arg)
744
811k
{
745
811k
    PySetObject *so = _PySet_CAST(self);
746
811k
    Py_ssize_t pos = 0;
747
811k
    setentry *entry;
748
749
6.52M
    while (set_next(so, &pos, &entry))
750
5.71M
        Py_VISIT(entry->key);
751
811k
    return 0;
752
811k
}
753
754
/* Work to increase the bit dispersion for closely spaced hash values.
755
   This is important because some use cases have many combinations of a
756
   small number of elements with nearby hashes so that many distinct
757
   combinations collapse to only a handful of distinct hash values. */
758
759
static Py_uhash_t
760
_shuffle_bits(Py_uhash_t h)
761
3.85k
{
762
3.85k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
763
3.85k
}
764
765
/* Most of the constants in this hash algorithm are randomly chosen
766
   large primes with "interesting bit patterns" and that passed tests
767
   for good collision statistics on a variety of problematic datasets
768
   including powersets and graph structures (such as David Eppstein's
769
   graph recipes in Lib/test/test_set.py).
770
771
   This hash algorithm can be used on either a frozenset or a set.
772
   When it is used on a set, it computes the hash value of the equivalent
773
   frozenset without creating a new frozenset object. */
774
775
static Py_hash_t
776
frozenset_hash_impl(PyObject *self)
777
165
{
778
165
    PySetObject *so = _PySet_CAST(self);
779
165
    Py_uhash_t hash = 0;
780
165
    setentry *entry;
781
782
    /* Xor-in shuffled bits from every entry's hash field because xor is
783
       commutative and a frozenset hash should be independent of order.
784
785
       For speed, include null entries and dummy entries and then
786
       subtract out their effect afterwards so that the final hash
787
       depends only on active entries.  This allows the code to be
788
       vectorized by the compiler and it saves the unpredictable
789
       branches that would arise when trying to exclude null and dummy
790
       entries on every iteration. */
791
792
3.93k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
793
3.76k
        hash ^= _shuffle_bits(entry->hash);
794
795
    /* Remove the effect of an odd number of NULL entries */
796
165
    if ((so->mask + 1 - so->fill) & 1)
797
87
        hash ^= _shuffle_bits(0);
798
799
    /* Remove the effect of an odd number of dummy entries */
800
165
    if ((so->fill - so->used) & 1)
801
0
        hash ^= _shuffle_bits(-1);
802
803
    /* Factor in the number of active entries */
804
165
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
805
806
    /* Disperse patterns arising in nested frozensets */
807
165
    hash ^= (hash >> 11) ^ (hash >> 25);
808
165
    hash = hash * 69069U + 907133923UL;
809
810
    /* -1 is reserved as an error code */
811
165
    if (hash == (Py_uhash_t)-1)
812
0
        hash = 590923713UL;
813
814
165
    return (Py_hash_t)hash;
815
165
}
816
817
static Py_hash_t
818
frozenset_hash(PyObject *self)
819
275
{
820
275
    PySetObject *so = _PySet_CAST(self);
821
275
    Py_uhash_t hash;
822
823
275
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
824
110
        return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
825
110
    }
826
827
165
    hash = frozenset_hash_impl(self);
828
165
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
829
165
    return hash;
830
275
}
831
832
/***** Set iterator type ***********************************************/
833
834
typedef struct {
835
    PyObject_HEAD
836
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
837
    Py_ssize_t si_used;
838
    Py_ssize_t si_pos;
839
    Py_ssize_t len;
840
} setiterobject;
841
842
static void
843
setiter_dealloc(PyObject *self)
844
266k
{
845
266k
    setiterobject *si = (setiterobject*)self;
846
    /* bpo-31095: UnTrack is needed before calling any callbacks */
847
266k
    _PyObject_GC_UNTRACK(si);
848
266k
    Py_XDECREF(si->si_set);
849
266k
    PyObject_GC_Del(si);
850
266k
}
851
852
static int
853
setiter_traverse(PyObject *self, visitproc visit, void *arg)
854
0
{
855
0
    setiterobject *si = (setiterobject*)self;
856
0
    Py_VISIT(si->si_set);
857
0
    return 0;
858
0
}
859
860
static PyObject *
861
setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
862
10
{
863
10
    setiterobject *si = (setiterobject*)op;
864
10
    Py_ssize_t len = 0;
865
10
    if (si->si_set != NULL && si->si_used == si->si_set->used)
866
10
        len = si->len;
867
10
    return PyLong_FromSsize_t(len);
868
10
}
869
870
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
871
872
static PyObject *
873
setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
874
0
{
875
0
    setiterobject *si = (setiterobject*)op;
876
877
    /* copy the iterator state */
878
0
    setiterobject tmp = *si;
879
0
    Py_XINCREF(tmp.si_set);
880
881
    /* iterate the temporary into a list */
882
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
883
0
    Py_XDECREF(tmp.si_set);
884
0
    if (list == NULL) {
885
0
        return NULL;
886
0
    }
887
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
888
0
}
889
890
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
891
892
static PyMethodDef setiter_methods[] = {
893
    {"__length_hint__", setiter_len, METH_NOARGS, length_hint_doc},
894
    {"__reduce__", setiter_reduce, METH_NOARGS, reduce_doc},
895
    {NULL,              NULL}           /* sentinel */
896
};
897
898
static PyObject *setiter_iternext(PyObject *self)
899
428k
{
900
428k
    setiterobject *si = (setiterobject*)self;
901
428k
    PyObject *key = NULL;
902
428k
    Py_ssize_t i, mask;
903
428k
    setentry *entry;
904
428k
    PySetObject *so = si->si_set;
905
906
428k
    if (so == NULL)
907
0
        return NULL;
908
428k
    assert (PyAnySet_Check(so));
909
910
428k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
911
428k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
912
428k
    if (si_used != so_used) {
913
0
        PyErr_SetString(PyExc_RuntimeError,
914
0
                        "Set changed size during iteration");
915
0
        si->si_used = -1; /* Make this state sticky */
916
0
        return NULL;
917
0
    }
918
919
428k
    Py_BEGIN_CRITICAL_SECTION(so);
920
428k
    i = si->si_pos;
921
428k
    assert(i>=0);
922
428k
    entry = so->table;
923
428k
    mask = so->mask;
924
2.54M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
925
2.11M
        i++;
926
2.11M
    }
927
428k
    if (i <= mask) {
928
161k
        key = Py_NewRef(entry[i].key);
929
161k
    }
930
428k
    Py_END_CRITICAL_SECTION();
931
428k
    si->si_pos = i+1;
932
428k
    if (key == NULL) {
933
266k
        si->si_set = NULL;
934
266k
        Py_DECREF(so);
935
266k
        return NULL;
936
266k
    }
937
161k
    si->len--;
938
161k
    return key;
939
428k
}
940
941
PyTypeObject PySetIter_Type = {
942
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
943
    "set_iterator",                             /* tp_name */
944
    sizeof(setiterobject),                      /* tp_basicsize */
945
    0,                                          /* tp_itemsize */
946
    /* methods */
947
    setiter_dealloc,                            /* tp_dealloc */
948
    0,                                          /* tp_vectorcall_offset */
949
    0,                                          /* tp_getattr */
950
    0,                                          /* tp_setattr */
951
    0,                                          /* tp_as_async */
952
    0,                                          /* tp_repr */
953
    0,                                          /* tp_as_number */
954
    0,                                          /* tp_as_sequence */
955
    0,                                          /* tp_as_mapping */
956
    0,                                          /* tp_hash */
957
    0,                                          /* tp_call */
958
    0,                                          /* tp_str */
959
    PyObject_GenericGetAttr,                    /* tp_getattro */
960
    0,                                          /* tp_setattro */
961
    0,                                          /* tp_as_buffer */
962
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
963
    0,                                          /* tp_doc */
964
    setiter_traverse,                           /* tp_traverse */
965
    0,                                          /* tp_clear */
966
    0,                                          /* tp_richcompare */
967
    0,                                          /* tp_weaklistoffset */
968
    PyObject_SelfIter,                          /* tp_iter */
969
    setiter_iternext,                           /* tp_iternext */
970
    setiter_methods,                            /* tp_methods */
971
    0,
972
};
973
974
static PyObject *
975
set_iter(PyObject *so)
976
266k
{
977
266k
    Py_ssize_t size = set_len(so);
978
266k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
979
266k
    if (si == NULL)
980
0
        return NULL;
981
266k
    si->si_set = (PySetObject*)Py_NewRef(so);
982
266k
    si->si_used = size;
983
266k
    si->si_pos = 0;
984
266k
    si->len = size;
985
266k
    _PyObject_GC_TRACK(si);
986
266k
    return (PyObject *)si;
987
266k
}
988
989
static int
990
set_update_dict_lock_held(PySetObject *so, PyObject *other)
991
94
{
992
94
    assert(PyDict_CheckExact(other));
993
994
94
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
995
94
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
996
997
    /* Do one big resize at the start, rather than
998
    * incrementally resizing as we insert new keys.  Expect
999
    * that there will be no (or few) overlapping keys.
1000
    */
1001
94
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1002
94
    if ((so->fill + dictsize)*5 >= so->mask*3) {
1003
4
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
1004
0
            return -1;
1005
0
        }
1006
4
    }
1007
1008
94
    Py_ssize_t pos = 0;
1009
94
    PyObject *key;
1010
94
    PyObject *value;
1011
94
    Py_hash_t hash;
1012
206
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1013
112
        if (set_add_entry(so, key, hash)) {
1014
0
            return -1;
1015
0
        }
1016
112
    }
1017
94
    return 0;
1018
94
}
1019
1020
static int
1021
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1022
16.8k
{
1023
16.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1024
1025
16.8k
    PyObject *it = PyObject_GetIter(other);
1026
16.8k
    if (it == NULL) {
1027
0
        return -1;
1028
0
    }
1029
1030
16.8k
    PyObject *key;
1031
74.2k
    while ((key = PyIter_Next(it)) != NULL) {
1032
57.3k
        if (set_add_key(so, key)) {
1033
0
            Py_DECREF(it);
1034
0
            Py_DECREF(key);
1035
0
            return -1;
1036
0
        }
1037
57.3k
        Py_DECREF(key);
1038
57.3k
    }
1039
16.8k
    Py_DECREF(it);
1040
16.8k
    if (PyErr_Occurred())
1041
0
        return -1;
1042
16.8k
    return 0;
1043
16.8k
}
1044
1045
static int
1046
set_update_lock_held(PySetObject *so, PyObject *other)
1047
0
{
1048
0
    if (PyAnySet_Check(other)) {
1049
0
        return set_merge_lock_held(so, other);
1050
0
    }
1051
0
    else if (PyDict_CheckExact(other)) {
1052
0
        return set_update_dict_lock_held(so, other);
1053
0
    }
1054
0
    return set_update_iterable_lock_held(so, other);
1055
0
}
1056
1057
// set_update for a `so` that is only visible to the current thread
1058
static int
1059
set_update_local(PySetObject *so, PyObject *other)
1060
65.0k
{
1061
65.0k
    assert(Py_REFCNT(so) == 1);
1062
65.0k
    if (PyAnySet_Check(other)) {
1063
48.0k
        int rv;
1064
48.0k
        Py_BEGIN_CRITICAL_SECTION(other);
1065
48.0k
        rv = set_merge_lock_held(so, other);
1066
48.0k
        Py_END_CRITICAL_SECTION();
1067
48.0k
        return rv;
1068
48.0k
    }
1069
16.9k
    else if (PyDict_CheckExact(other)) {
1070
94
        int rv;
1071
94
        Py_BEGIN_CRITICAL_SECTION(other);
1072
94
        rv = set_update_dict_lock_held(so, other);
1073
94
        Py_END_CRITICAL_SECTION();
1074
94
        return rv;
1075
94
    }
1076
16.8k
    return set_update_iterable_lock_held(so, other);
1077
65.0k
}
1078
1079
static int
1080
set_update_internal(PySetObject *so, PyObject *other)
1081
58.7k
{
1082
58.7k
    if (PyAnySet_Check(other)) {
1083
58.7k
        if (Py_Is((PyObject *)so, other)) {
1084
0
            return 0;
1085
0
        }
1086
58.7k
        int rv;
1087
58.7k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1088
58.7k
        rv = set_merge_lock_held(so, other);
1089
58.7k
        Py_END_CRITICAL_SECTION2();
1090
58.7k
        return rv;
1091
58.7k
    }
1092
0
    else if (PyDict_CheckExact(other)) {
1093
0
        int rv;
1094
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1095
0
        rv = set_update_dict_lock_held(so, other);
1096
0
        Py_END_CRITICAL_SECTION2();
1097
0
        return rv;
1098
0
    }
1099
0
    else {
1100
0
        int rv;
1101
0
        Py_BEGIN_CRITICAL_SECTION(so);
1102
0
        rv = set_update_iterable_lock_held(so, other);
1103
0
        Py_END_CRITICAL_SECTION();
1104
0
        return rv;
1105
0
    }
1106
58.7k
}
1107
1108
/*[clinic input]
1109
set.update
1110
    so: setobject
1111
    *others: array
1112
1113
Update the set, adding elements from all others.
1114
[clinic start generated code]*/
1115
1116
static PyObject *
1117
set_update_impl(PySetObject *so, PyObject * const *others,
1118
                Py_ssize_t others_length)
1119
/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
1120
0
{
1121
0
    Py_ssize_t i;
1122
1123
0
    for (i = 0; i < others_length; i++) {
1124
0
        PyObject *other = others[i];
1125
0
        if (set_update_internal(so, other))
1126
0
            return NULL;
1127
0
    }
1128
0
    Py_RETURN_NONE;
1129
0
}
1130
1131
/* XXX Todo:
1132
   If aligned memory allocations become available, make the
1133
   set object 64 byte aligned so that most of the fields
1134
   can be retrieved or updated in a single cache line.
1135
*/
1136
1137
static PyObject *
1138
make_new_set(PyTypeObject *type, PyObject *iterable)
1139
675k
{
1140
675k
    assert(PyType_Check(type));
1141
675k
    PySetObject *so;
1142
1143
675k
    so = (PySetObject *)type->tp_alloc(type, 0);
1144
675k
    if (so == NULL)
1145
0
        return NULL;
1146
1147
675k
    so->fill = 0;
1148
675k
    so->used = 0;
1149
675k
    so->mask = PySet_MINSIZE - 1;
1150
675k
    so->table = so->smalltable;
1151
675k
    so->hash = -1;
1152
675k
    so->finger = 0;
1153
675k
    so->weakreflist = NULL;
1154
1155
675k
    if (iterable != NULL) {
1156
65.0k
        if (set_update_local(so, iterable)) {
1157
0
            Py_DECREF(so);
1158
0
            return NULL;
1159
0
        }
1160
65.0k
    }
1161
1162
675k
    return (PyObject *)so;
1163
675k
}
1164
1165
static PyObject *
1166
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1167
130
{
1168
130
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1169
0
        if (PyType_IsSubtype(type, &PySet_Type))
1170
0
            type = &PySet_Type;
1171
0
        else
1172
0
            type = &PyFrozenSet_Type;
1173
0
    }
1174
130
    return make_new_set(type, iterable);
1175
130
}
1176
1177
static PyObject *
1178
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1179
155
{
1180
155
    if (type != &PyFrozenSet_Type) {
1181
0
        return make_new_set(type, iterable);
1182
0
    }
1183
1184
155
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1185
        /* frozenset(f) is idempotent */
1186
0
        return Py_NewRef(iterable);
1187
0
    }
1188
155
    return make_new_set(type, iterable);
1189
155
}
1190
1191
static PyObject *
1192
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1193
0
{
1194
0
    PyObject *iterable = NULL;
1195
1196
0
    if ((type == &PyFrozenSet_Type ||
1197
0
         type->tp_init == PyFrozenSet_Type.tp_init) &&
1198
0
        !_PyArg_NoKeywords("frozenset", kwds)) {
1199
0
        return NULL;
1200
0
    }
1201
1202
0
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1203
0
        return NULL;
1204
0
    }
1205
1206
0
    return make_new_frozenset(type, iterable);
1207
0
}
1208
1209
static PyObject *
1210
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1211
                     size_t nargsf, PyObject *kwnames)
1212
155
{
1213
155
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1214
0
        return NULL;
1215
0
    }
1216
1217
155
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1218
155
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1219
0
        return NULL;
1220
0
    }
1221
1222
155
    PyObject *iterable = (nargs ? args[0] : NULL);
1223
155
    return make_new_frozenset(_PyType_CAST(type), iterable);
1224
155
}
1225
1226
static PyObject *
1227
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1228
0
{
1229
0
    return make_new_set(type, NULL);
1230
0
}
1231
1232
/* set_swap_bodies() switches the contents of any two sets by moving their
1233
   internal data pointers and, if needed, copying the internal smalltables.
1234
   Semantically equivalent to:
1235
1236
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1237
1238
   The function always succeeds and it leaves both objects in a stable state.
1239
   Useful for operations that update in-place (by allowing an intermediate
1240
   result to be swapped into one of the original inputs).
1241
*/
1242
1243
static void
1244
set_swap_bodies(PySetObject *a, PySetObject *b)
1245
0
{
1246
0
    Py_ssize_t t;
1247
0
    setentry *u;
1248
0
    setentry tab[PySet_MINSIZE];
1249
0
    Py_hash_t h;
1250
1251
0
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1252
0
    t = a->used;
1253
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1254
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
1255
0
    t = a->mask;     a->mask   = b->mask;        b->mask  = t;
1256
1257
0
    u = a->table;
1258
0
    if (a->table == a->smalltable)
1259
0
        u = b->smalltable;
1260
0
    a->table  = b->table;
1261
0
    if (b->table == b->smalltable)
1262
0
        a->table = a->smalltable;
1263
0
    b->table = u;
1264
1265
0
    if (a->table == a->smalltable || b->table == b->smalltable) {
1266
0
        memcpy(tab, a->smalltable, sizeof(tab));
1267
0
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1268
0
        memcpy(b->smalltable, tab, sizeof(tab));
1269
0
    }
1270
1271
0
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1272
0
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1273
0
        h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
1274
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
1275
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
1276
0
    } else {
1277
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
1278
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
1279
0
    }
1280
0
}
1281
1282
/*[clinic input]
1283
@critical_section
1284
set.copy
1285
    so: setobject
1286
1287
Return a shallow copy of a set.
1288
[clinic start generated code]*/
1289
1290
static PyObject *
1291
set_copy_impl(PySetObject *so)
1292
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1293
34
{
1294
34
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1295
34
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1296
34
    if (copy == NULL) {
1297
0
        return NULL;
1298
0
    }
1299
34
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1300
0
        Py_DECREF(copy);
1301
0
        return NULL;
1302
0
    }
1303
34
    return copy;
1304
34
}
1305
1306
/*[clinic input]
1307
@critical_section
1308
frozenset.copy
1309
    so: setobject
1310
1311
Return a shallow copy of a set.
1312
[clinic start generated code]*/
1313
1314
static PyObject *
1315
frozenset_copy_impl(PySetObject *so)
1316
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1317
0
{
1318
0
    if (PyFrozenSet_CheckExact(so)) {
1319
0
        return Py_NewRef(so);
1320
0
    }
1321
0
    return set_copy_impl(so);
1322
0
}
1323
1324
/*[clinic input]
1325
@critical_section
1326
set.clear
1327
    so: setobject
1328
1329
Remove all elements from this set.
1330
[clinic start generated code]*/
1331
1332
static PyObject *
1333
set_clear_impl(PySetObject *so)
1334
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1335
188
{
1336
188
    set_clear_internal((PyObject*)so);
1337
188
    Py_RETURN_NONE;
1338
188
}
1339
1340
/*[clinic input]
1341
set.union
1342
    so: setobject
1343
    *others: array
1344
1345
Return a new set with elements from the set and all others.
1346
[clinic start generated code]*/
1347
1348
static PyObject *
1349
set_union_impl(PySetObject *so, PyObject * const *others,
1350
               Py_ssize_t others_length)
1351
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1352
2
{
1353
2
    PySetObject *result;
1354
2
    PyObject *other;
1355
2
    Py_ssize_t i;
1356
1357
2
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1358
2
    if (result == NULL)
1359
0
        return NULL;
1360
1361
4
    for (i = 0; i < others_length; i++) {
1362
2
        other = others[i];
1363
2
        if ((PyObject *)so == other)
1364
0
            continue;
1365
2
        if (set_update_local(result, other)) {
1366
0
            Py_DECREF(result);
1367
0
            return NULL;
1368
0
        }
1369
2
    }
1370
2
    return (PyObject *)result;
1371
2
}
1372
1373
static PyObject *
1374
set_or(PyObject *self, PyObject *other)
1375
26
{
1376
26
    PySetObject *result;
1377
1378
26
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1379
0
        Py_RETURN_NOTIMPLEMENTED;
1380
1381
26
    result = (PySetObject *)set_copy(self, NULL);
1382
26
    if (result == NULL) {
1383
0
        return NULL;
1384
0
    }
1385
26
    if (Py_Is(self, other)) {
1386
0
        return (PyObject *)result;
1387
0
    }
1388
26
    if (set_update_local(result, other)) {
1389
0
        Py_DECREF(result);
1390
0
        return NULL;
1391
0
    }
1392
26
    return (PyObject *)result;
1393
26
}
1394
1395
static PyObject *
1396
set_ior(PyObject *self, PyObject *other)
1397
58.7k
{
1398
58.7k
    if (!PyAnySet_Check(other))
1399
0
        Py_RETURN_NOTIMPLEMENTED;
1400
58.7k
    PySetObject *so = _PySet_CAST(self);
1401
1402
58.7k
    if (set_update_internal(so, other)) {
1403
0
        return NULL;
1404
0
    }
1405
58.7k
    return Py_NewRef(so);
1406
58.7k
}
1407
1408
static PyObject *
1409
set_intersection(PySetObject *so, PyObject *other)
1410
94
{
1411
94
    PySetObject *result;
1412
94
    PyObject *key, *it, *tmp;
1413
94
    Py_hash_t hash;
1414
94
    int rv;
1415
1416
94
    if ((PyObject *)so == other)
1417
0
        return set_copy_impl(so);
1418
1419
94
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1420
94
    if (result == NULL)
1421
0
        return NULL;
1422
1423
94
    if (PyAnySet_Check(other)) {
1424
94
        Py_ssize_t pos = 0;
1425
94
        setentry *entry;
1426
1427
94
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1428
72
            tmp = (PyObject *)so;
1429
72
            so = (PySetObject *)other;
1430
72
            other = tmp;
1431
72
        }
1432
1433
138
        while (set_next((PySetObject *)other, &pos, &entry)) {
1434
44
            key = entry->key;
1435
44
            hash = entry->hash;
1436
44
            Py_INCREF(key);
1437
44
            rv = set_contains_entry(so, key, hash);
1438
44
            if (rv < 0) {
1439
0
                Py_DECREF(result);
1440
0
                Py_DECREF(key);
1441
0
                return NULL;
1442
0
            }
1443
44
            if (rv) {
1444
0
                if (set_add_entry(result, key, hash)) {
1445
0
                    Py_DECREF(result);
1446
0
                    Py_DECREF(key);
1447
0
                    return NULL;
1448
0
                }
1449
0
            }
1450
44
            Py_DECREF(key);
1451
44
        }
1452
94
        return (PyObject *)result;
1453
94
    }
1454
1455
0
    it = PyObject_GetIter(other);
1456
0
    if (it == NULL) {
1457
0
        Py_DECREF(result);
1458
0
        return NULL;
1459
0
    }
1460
1461
0
    while ((key = PyIter_Next(it)) != NULL) {
1462
0
        hash = PyObject_Hash(key);
1463
0
        if (hash == -1)
1464
0
            goto error;
1465
0
        rv = set_contains_entry(so, key, hash);
1466
0
        if (rv < 0)
1467
0
            goto error;
1468
0
        if (rv) {
1469
0
            if (set_add_entry(result, key, hash))
1470
0
                goto error;
1471
0
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1472
0
                Py_DECREF(key);
1473
0
                break;
1474
0
            }
1475
0
        }
1476
0
        Py_DECREF(key);
1477
0
    }
1478
0
    Py_DECREF(it);
1479
0
    if (PyErr_Occurred()) {
1480
0
        Py_DECREF(result);
1481
0
        return NULL;
1482
0
    }
1483
0
    return (PyObject *)result;
1484
0
  error:
1485
0
    Py_DECREF(it);
1486
0
    Py_DECREF(result);
1487
0
    Py_DECREF(key);
1488
0
    return NULL;
1489
0
}
1490
1491
/*[clinic input]
1492
set.intersection as set_intersection_multi
1493
    so: setobject
1494
    *others: array
1495
1496
Return a new set with elements common to the set and all others.
1497
[clinic start generated code]*/
1498
1499
static PyObject *
1500
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1501
                            Py_ssize_t others_length)
1502
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1503
0
{
1504
0
    Py_ssize_t i;
1505
1506
0
    if (others_length == 0) {
1507
0
        return set_copy((PyObject *)so, NULL);
1508
0
    }
1509
1510
0
    PyObject *result = Py_NewRef(so);
1511
0
    for (i = 0; i < others_length; i++) {
1512
0
        PyObject *other = others[i];
1513
0
        PyObject *newresult;
1514
0
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1515
0
        newresult = set_intersection((PySetObject *)result, other);
1516
0
        Py_END_CRITICAL_SECTION2();
1517
0
        if (newresult == NULL) {
1518
0
            Py_DECREF(result);
1519
0
            return NULL;
1520
0
        }
1521
0
        Py_SETREF(result, newresult);
1522
0
    }
1523
0
    return result;
1524
0
}
1525
1526
static PyObject *
1527
set_intersection_update(PySetObject *so, PyObject *other)
1528
0
{
1529
0
    PyObject *tmp;
1530
1531
0
    tmp = set_intersection(so, other);
1532
0
    if (tmp == NULL)
1533
0
        return NULL;
1534
0
    set_swap_bodies(so, (PySetObject *)tmp);
1535
0
    Py_DECREF(tmp);
1536
0
    Py_RETURN_NONE;
1537
0
}
1538
1539
/*[clinic input]
1540
set.intersection_update as set_intersection_update_multi
1541
    so: setobject
1542
    *others: array
1543
1544
Update the set, keeping only elements found in it and all others.
1545
[clinic start generated code]*/
1546
1547
static PyObject *
1548
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1549
                                   Py_ssize_t others_length)
1550
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1551
0
{
1552
0
    PyObject *tmp;
1553
1554
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1555
0
    if (tmp == NULL)
1556
0
        return NULL;
1557
0
    Py_BEGIN_CRITICAL_SECTION(so);
1558
0
    set_swap_bodies(so, (PySetObject *)tmp);
1559
0
    Py_END_CRITICAL_SECTION();
1560
0
    Py_DECREF(tmp);
1561
0
    Py_RETURN_NONE;
1562
0
}
1563
1564
static PyObject *
1565
set_and(PyObject *self, PyObject *other)
1566
94
{
1567
94
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1568
0
        Py_RETURN_NOTIMPLEMENTED;
1569
94
    PySetObject *so = _PySet_CAST(self);
1570
1571
94
    PyObject *rv;
1572
94
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1573
94
    rv = set_intersection(so, other);
1574
94
    Py_END_CRITICAL_SECTION2();
1575
1576
94
    return rv;
1577
94
}
1578
1579
static PyObject *
1580
set_iand(PyObject *self, PyObject *other)
1581
0
{
1582
0
    PyObject *result;
1583
1584
0
    if (!PyAnySet_Check(other))
1585
0
        Py_RETURN_NOTIMPLEMENTED;
1586
0
    PySetObject *so = _PySet_CAST(self);
1587
1588
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1589
0
    result = set_intersection_update(so, other);
1590
0
    Py_END_CRITICAL_SECTION2();
1591
1592
0
    if (result == NULL)
1593
0
        return NULL;
1594
0
    Py_DECREF(result);
1595
0
    return Py_NewRef(so);
1596
0
}
1597
1598
/*[clinic input]
1599
@critical_section so other
1600
set.isdisjoint
1601
    so: setobject
1602
    other: object
1603
    /
1604
1605
Return True if two sets have a null intersection.
1606
[clinic start generated code]*/
1607
1608
static PyObject *
1609
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1610
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1611
16.3k
{
1612
16.3k
    PyObject *key, *it, *tmp;
1613
16.3k
    int rv;
1614
1615
16.3k
    if ((PyObject *)so == other) {
1616
0
        if (PySet_GET_SIZE(so) == 0)
1617
0
            Py_RETURN_TRUE;
1618
0
        else
1619
0
            Py_RETURN_FALSE;
1620
0
    }
1621
1622
16.3k
    if (PyAnySet_CheckExact(other)) {
1623
0
        Py_ssize_t pos = 0;
1624
0
        setentry *entry;
1625
1626
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1627
0
            tmp = (PyObject *)so;
1628
0
            so = (PySetObject *)other;
1629
0
            other = tmp;
1630
0
        }
1631
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1632
0
            PyObject *key = entry->key;
1633
0
            Py_INCREF(key);
1634
0
            rv = set_contains_entry(so, key, entry->hash);
1635
0
            Py_DECREF(key);
1636
0
            if (rv < 0) {
1637
0
                return NULL;
1638
0
            }
1639
0
            if (rv) {
1640
0
                Py_RETURN_FALSE;
1641
0
            }
1642
0
        }
1643
0
        Py_RETURN_TRUE;
1644
0
    }
1645
1646
16.3k
    it = PyObject_GetIter(other);
1647
16.3k
    if (it == NULL)
1648
0
        return NULL;
1649
1650
22.7k
    while ((key = PyIter_Next(it)) != NULL) {
1651
22.5k
        rv = set_contains_key(so, key);
1652
22.5k
        Py_DECREF(key);
1653
22.5k
        if (rv < 0) {
1654
0
            Py_DECREF(it);
1655
0
            return NULL;
1656
0
        }
1657
22.5k
        if (rv) {
1658
16.2k
            Py_DECREF(it);
1659
16.2k
            Py_RETURN_FALSE;
1660
16.2k
        }
1661
22.5k
    }
1662
173
    Py_DECREF(it);
1663
173
    if (PyErr_Occurred())
1664
0
        return NULL;
1665
173
    Py_RETURN_TRUE;
1666
173
}
1667
1668
static int
1669
set_difference_update_internal(PySetObject *so, PyObject *other)
1670
6
{
1671
6
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1672
6
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1673
1674
6
    if ((PyObject *)so == other)
1675
0
        return set_clear_internal((PyObject*)so);
1676
1677
6
    if (PyAnySet_Check(other)) {
1678
6
        setentry *entry;
1679
6
        Py_ssize_t pos = 0;
1680
1681
        /* Optimization:  When the other set is more than 8 times
1682
           larger than the base set, replace the other set with
1683
           intersection of the two sets.
1684
        */
1685
6
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1686
0
            other = set_intersection(so, other);
1687
0
            if (other == NULL)
1688
0
                return -1;
1689
6
        } else {
1690
6
            Py_INCREF(other);
1691
6
        }
1692
1693
12
        while (set_next((PySetObject *)other, &pos, &entry)) {
1694
6
            PyObject *key = entry->key;
1695
6
            Py_INCREF(key);
1696
6
            if (set_discard_entry(so, key, entry->hash) < 0) {
1697
0
                Py_DECREF(other);
1698
0
                Py_DECREF(key);
1699
0
                return -1;
1700
0
            }
1701
6
            Py_DECREF(key);
1702
6
        }
1703
1704
6
        Py_DECREF(other);
1705
6
    } else {
1706
0
        PyObject *key, *it;
1707
0
        it = PyObject_GetIter(other);
1708
0
        if (it == NULL)
1709
0
            return -1;
1710
1711
0
        while ((key = PyIter_Next(it)) != NULL) {
1712
0
            if (set_discard_key(so, key) < 0) {
1713
0
                Py_DECREF(it);
1714
0
                Py_DECREF(key);
1715
0
                return -1;
1716
0
            }
1717
0
            Py_DECREF(key);
1718
0
        }
1719
0
        Py_DECREF(it);
1720
0
        if (PyErr_Occurred())
1721
0
            return -1;
1722
0
    }
1723
    /* If more than 1/4th are dummies, then resize them away. */
1724
6
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1725
6
        return 0;
1726
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1727
6
}
1728
1729
/*[clinic input]
1730
set.difference_update
1731
    so: setobject
1732
    *others: array
1733
1734
Update the set, removing elements found in others.
1735
[clinic start generated code]*/
1736
1737
static PyObject *
1738
set_difference_update_impl(PySetObject *so, PyObject * const *others,
1739
                           Py_ssize_t others_length)
1740
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
1741
0
{
1742
0
    Py_ssize_t i;
1743
1744
0
    for (i = 0; i < others_length; i++) {
1745
0
        PyObject *other = others[i];
1746
0
        int rv;
1747
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1748
0
        rv = set_difference_update_internal(so, other);
1749
0
        Py_END_CRITICAL_SECTION2();
1750
0
        if (rv) {
1751
0
            return NULL;
1752
0
        }
1753
0
    }
1754
0
    Py_RETURN_NONE;
1755
0
}
1756
1757
static PyObject *
1758
set_copy_and_difference(PySetObject *so, PyObject *other)
1759
6
{
1760
6
    PyObject *result;
1761
1762
6
    result = set_copy_impl(so);
1763
6
    if (result == NULL)
1764
0
        return NULL;
1765
6
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1766
6
        return result;
1767
0
    Py_DECREF(result);
1768
0
    return NULL;
1769
6
}
1770
1771
static PyObject *
1772
set_difference(PySetObject *so, PyObject *other)
1773
8
{
1774
8
    PyObject *result;
1775
8
    PyObject *key;
1776
8
    Py_hash_t hash;
1777
8
    setentry *entry;
1778
8
    Py_ssize_t pos = 0, other_size;
1779
8
    int rv;
1780
1781
8
    if (PyAnySet_Check(other)) {
1782
8
        other_size = PySet_GET_SIZE(other);
1783
8
    }
1784
0
    else if (PyDict_CheckExact(other)) {
1785
0
        other_size = PyDict_GET_SIZE(other);
1786
0
    }
1787
0
    else {
1788
0
        return set_copy_and_difference(so, other);
1789
0
    }
1790
1791
    /* If len(so) much more than len(other), it's more efficient to simply copy
1792
     * so and then iterate other looking for common elements. */
1793
8
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1794
6
        return set_copy_and_difference(so, other);
1795
6
    }
1796
1797
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
1798
2
    if (result == NULL)
1799
0
        return NULL;
1800
1801
2
    if (PyDict_CheckExact(other)) {
1802
0
        while (set_next(so, &pos, &entry)) {
1803
0
            key = entry->key;
1804
0
            hash = entry->hash;
1805
0
            Py_INCREF(key);
1806
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
1807
0
            if (rv < 0) {
1808
0
                Py_DECREF(result);
1809
0
                Py_DECREF(key);
1810
0
                return NULL;
1811
0
            }
1812
0
            if (!rv) {
1813
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
1814
0
                    Py_DECREF(result);
1815
0
                    Py_DECREF(key);
1816
0
                    return NULL;
1817
0
                }
1818
0
            }
1819
0
            Py_DECREF(key);
1820
0
        }
1821
0
        return result;
1822
0
    }
1823
1824
    /* Iterate over so, checking for common elements in other. */
1825
28
    while (set_next(so, &pos, &entry)) {
1826
26
        key = entry->key;
1827
26
        hash = entry->hash;
1828
26
        Py_INCREF(key);
1829
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
1830
26
        if (rv < 0) {
1831
0
            Py_DECREF(result);
1832
0
            Py_DECREF(key);
1833
0
            return NULL;
1834
0
        }
1835
26
        if (!rv) {
1836
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
1837
0
                Py_DECREF(result);
1838
0
                Py_DECREF(key);
1839
0
                return NULL;
1840
0
            }
1841
20
        }
1842
26
        Py_DECREF(key);
1843
26
    }
1844
2
    return result;
1845
2
}
1846
1847
/*[clinic input]
1848
set.difference as set_difference_multi
1849
    so: setobject
1850
    *others: array
1851
1852
Return a new set with elements in the set that are not in the others.
1853
[clinic start generated code]*/
1854
1855
static PyObject *
1856
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
1857
                          Py_ssize_t others_length)
1858
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
1859
0
{
1860
0
    Py_ssize_t i;
1861
0
    PyObject *result, *other;
1862
1863
0
    if (others_length == 0) {
1864
0
        return set_copy((PyObject *)so, NULL);
1865
0
    }
1866
1867
0
    other = others[0];
1868
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1869
0
    result = set_difference(so, other);
1870
0
    Py_END_CRITICAL_SECTION2();
1871
0
    if (result == NULL)
1872
0
        return NULL;
1873
1874
0
    for (i = 1; i < others_length; i++) {
1875
0
        other = others[i];
1876
0
        int rv;
1877
0
        Py_BEGIN_CRITICAL_SECTION(other);
1878
0
        rv = set_difference_update_internal((PySetObject *)result, other);
1879
0
        Py_END_CRITICAL_SECTION();
1880
0
        if (rv) {
1881
0
            Py_DECREF(result);
1882
0
            return NULL;
1883
0
        }
1884
0
    }
1885
0
    return result;
1886
0
}
1887
1888
static PyObject *
1889
set_sub(PyObject *self, PyObject *other)
1890
8
{
1891
8
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1892
0
        Py_RETURN_NOTIMPLEMENTED;
1893
8
    PySetObject *so = _PySet_CAST(self);
1894
1895
8
    PyObject *rv;
1896
8
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1897
8
    rv = set_difference(so, other);
1898
8
    Py_END_CRITICAL_SECTION2();
1899
8
    return rv;
1900
8
}
1901
1902
static PyObject *
1903
set_isub(PyObject *self, PyObject *other)
1904
0
{
1905
0
    if (!PyAnySet_Check(other))
1906
0
        Py_RETURN_NOTIMPLEMENTED;
1907
0
    PySetObject *so = _PySet_CAST(self);
1908
1909
0
    int rv;
1910
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1911
0
    rv = set_difference_update_internal(so, other);
1912
0
    Py_END_CRITICAL_SECTION2();
1913
0
    if (rv < 0) {
1914
0
        return NULL;
1915
0
    }
1916
0
    return Py_NewRef(so);
1917
0
}
1918
1919
static int
1920
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
1921
0
{
1922
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1923
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1924
1925
0
    Py_ssize_t pos = 0;
1926
0
    PyObject *key, *value;
1927
0
    Py_hash_t hash;
1928
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1929
0
        Py_INCREF(key);
1930
0
        int rv = set_discard_entry(so, key, hash);
1931
0
        if (rv < 0) {
1932
0
            Py_DECREF(key);
1933
0
            return -1;
1934
0
        }
1935
0
        if (rv == DISCARD_NOTFOUND) {
1936
0
            if (set_add_entry(so, key, hash)) {
1937
0
                Py_DECREF(key);
1938
0
                return -1;
1939
0
            }
1940
0
        }
1941
0
        Py_DECREF(key);
1942
0
    }
1943
0
    return 0;
1944
0
}
1945
1946
static int
1947
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
1948
0
{
1949
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1950
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1951
1952
0
    Py_ssize_t pos = 0;
1953
0
    setentry *entry;
1954
0
    while (set_next(other, &pos, &entry)) {
1955
0
        PyObject *key = Py_NewRef(entry->key);
1956
0
        Py_hash_t hash = entry->hash;
1957
0
        int rv = set_discard_entry(so, key, hash);
1958
0
        if (rv < 0) {
1959
0
            Py_DECREF(key);
1960
0
            return -1;
1961
0
        }
1962
0
        if (rv == DISCARD_NOTFOUND) {
1963
0
            if (set_add_entry(so, key, hash)) {
1964
0
                Py_DECREF(key);
1965
0
                return -1;
1966
0
            }
1967
0
        }
1968
0
        Py_DECREF(key);
1969
0
    }
1970
0
    return 0;
1971
0
}
1972
1973
/*[clinic input]
1974
@permit_long_summary
1975
set.symmetric_difference_update
1976
    so: setobject
1977
    other: object
1978
    /
1979
1980
Update the set, keeping only elements found in either set, but not in both.
1981
[clinic start generated code]*/
1982
1983
static PyObject *
1984
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
1985
/*[clinic end generated code: output=79f80b4ee5da66c1 input=86a3dddac9bfb15e]*/
1986
0
{
1987
0
    if (Py_Is((PyObject *)so, other)) {
1988
0
        return set_clear((PyObject *)so, NULL);
1989
0
    }
1990
1991
0
    int rv;
1992
0
    if (PyDict_CheckExact(other)) {
1993
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1994
0
        rv = set_symmetric_difference_update_dict(so, other);
1995
0
        Py_END_CRITICAL_SECTION2();
1996
0
    }
1997
0
    else if (PyAnySet_Check(other)) {
1998
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1999
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
2000
0
        Py_END_CRITICAL_SECTION2();
2001
0
    }
2002
0
    else {
2003
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
2004
0
        if (otherset == NULL) {
2005
0
            return NULL;
2006
0
        }
2007
2008
0
        Py_BEGIN_CRITICAL_SECTION(so);
2009
0
        rv = set_symmetric_difference_update_set(so, otherset);
2010
0
        Py_END_CRITICAL_SECTION();
2011
2012
0
        Py_DECREF(otherset);
2013
0
    }
2014
0
    if (rv < 0) {
2015
0
        return NULL;
2016
0
    }
2017
0
    Py_RETURN_NONE;
2018
0
}
2019
2020
/*[clinic input]
2021
@critical_section so other
2022
set.symmetric_difference
2023
    so: setobject
2024
    other: object
2025
    /
2026
2027
Return a new set with elements in either the set or other but not both.
2028
[clinic start generated code]*/
2029
2030
static PyObject *
2031
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2032
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2033
0
{
2034
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2035
0
    if (result == NULL) {
2036
0
        return NULL;
2037
0
    }
2038
0
    if (set_update_lock_held(result, other) < 0) {
2039
0
        Py_DECREF(result);
2040
0
        return NULL;
2041
0
    }
2042
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2043
0
        Py_DECREF(result);
2044
0
        return NULL;
2045
0
    }
2046
0
    return (PyObject *)result;
2047
0
}
2048
2049
static PyObject *
2050
set_xor(PyObject *self, PyObject *other)
2051
0
{
2052
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2053
0
        Py_RETURN_NOTIMPLEMENTED;
2054
0
    PySetObject *so = _PySet_CAST(self);
2055
0
    return set_symmetric_difference((PyObject*)so, other);
2056
0
}
2057
2058
static PyObject *
2059
set_ixor(PyObject *self, PyObject *other)
2060
0
{
2061
0
    PyObject *result;
2062
2063
0
    if (!PyAnySet_Check(other))
2064
0
        Py_RETURN_NOTIMPLEMENTED;
2065
0
    PySetObject *so = _PySet_CAST(self);
2066
2067
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2068
0
    if (result == NULL)
2069
0
        return NULL;
2070
0
    Py_DECREF(result);
2071
0
    return Py_NewRef(so);
2072
0
}
2073
2074
/*[clinic input]
2075
@critical_section so other
2076
set.issubset
2077
    so: setobject
2078
    other: object
2079
    /
2080
2081
Report whether another set contains this set.
2082
[clinic start generated code]*/
2083
2084
static PyObject *
2085
set_issubset_impl(PySetObject *so, PyObject *other)
2086
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2087
74
{
2088
74
    setentry *entry;
2089
74
    Py_ssize_t pos = 0;
2090
74
    int rv;
2091
2092
74
    if (!PyAnySet_Check(other)) {
2093
0
        PyObject *tmp = set_intersection(so, other);
2094
0
        if (tmp == NULL) {
2095
0
            return NULL;
2096
0
        }
2097
0
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2098
0
        Py_DECREF(tmp);
2099
0
        return PyBool_FromLong(result);
2100
0
    }
2101
74
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2102
0
        Py_RETURN_FALSE;
2103
2104
380
    while (set_next(so, &pos, &entry)) {
2105
306
        PyObject *key = entry->key;
2106
306
        Py_INCREF(key);
2107
306
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2108
306
        Py_DECREF(key);
2109
306
        if (rv < 0) {
2110
0
            return NULL;
2111
0
        }
2112
306
        if (!rv) {
2113
0
            Py_RETURN_FALSE;
2114
0
        }
2115
306
    }
2116
74
    Py_RETURN_TRUE;
2117
74
}
2118
2119
/*[clinic input]
2120
@critical_section so other
2121
set.issuperset
2122
    so: setobject
2123
    other: object
2124
    /
2125
2126
Report whether this set contains another set.
2127
[clinic start generated code]*/
2128
2129
static PyObject *
2130
set_issuperset_impl(PySetObject *so, PyObject *other)
2131
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2132
282
{
2133
282
    if (PyAnySet_Check(other)) {
2134
0
        return set_issubset(other, (PyObject *)so);
2135
0
    }
2136
2137
282
    PyObject *key, *it = PyObject_GetIter(other);
2138
282
    if (it == NULL) {
2139
0
        return NULL;
2140
0
    }
2141
1.15k
    while ((key = PyIter_Next(it)) != NULL) {
2142
870
        int rv = set_contains_key(so, key);
2143
870
        Py_DECREF(key);
2144
870
        if (rv < 0) {
2145
0
            Py_DECREF(it);
2146
0
            return NULL;
2147
0
        }
2148
870
        if (!rv) {
2149
0
            Py_DECREF(it);
2150
0
            Py_RETURN_FALSE;
2151
0
        }
2152
870
    }
2153
282
    Py_DECREF(it);
2154
282
    if (PyErr_Occurred()) {
2155
0
        return NULL;
2156
0
    }
2157
282
    Py_RETURN_TRUE;
2158
282
}
2159
2160
static PyObject *
2161
set_richcompare(PyObject *self, PyObject *w, int op)
2162
74
{
2163
74
    PySetObject *v = _PySet_CAST(self);
2164
74
    PyObject *r1;
2165
74
    int r2;
2166
2167
74
    if(!PyAnySet_Check(w))
2168
0
        Py_RETURN_NOTIMPLEMENTED;
2169
2170
74
    switch (op) {
2171
40
    case Py_EQ:
2172
40
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2173
0
            Py_RETURN_FALSE;
2174
40
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2175
40
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2176
40
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2177
0
            Py_RETURN_FALSE;
2178
40
        return set_issubset((PyObject*)v, w);
2179
0
    case Py_NE:
2180
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2181
0
        if (r1 == NULL)
2182
0
            return NULL;
2183
0
        r2 = PyObject_IsTrue(r1);
2184
0
        Py_DECREF(r1);
2185
0
        if (r2 < 0)
2186
0
            return NULL;
2187
0
        return PyBool_FromLong(!r2);
2188
34
    case Py_LE:
2189
34
        return set_issubset((PyObject*)v, w);
2190
0
    case Py_GE:
2191
0
        return set_issuperset((PyObject*)v, w);
2192
0
    case Py_LT:
2193
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2194
0
            Py_RETURN_FALSE;
2195
0
        return set_issubset((PyObject*)v, w);
2196
0
    case Py_GT:
2197
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2198
0
            Py_RETURN_FALSE;
2199
0
        return set_issuperset((PyObject*)v, w);
2200
74
    }
2201
74
    Py_RETURN_NOTIMPLEMENTED;
2202
74
}
2203
2204
/*[clinic input]
2205
@critical_section
2206
set.add
2207
    so: setobject
2208
    object as key: object
2209
    /
2210
2211
Add an element to a set.
2212
2213
This has no effect if the element is already present.
2214
[clinic start generated code]*/
2215
2216
static PyObject *
2217
set_add_impl(PySetObject *so, PyObject *key)
2218
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2219
594k
{
2220
594k
    if (set_add_key(so, key))
2221
0
        return NULL;
2222
594k
    Py_RETURN_NONE;
2223
594k
}
2224
2225
static int
2226
set_contains_lock_held(PySetObject *so, PyObject *key)
2227
47.1M
{
2228
47.1M
    int rv;
2229
2230
47.1M
    rv = set_contains_key(so, key);
2231
47.1M
    if (rv < 0) {
2232
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2233
0
            return -1;
2234
0
        PyErr_Clear();
2235
0
        Py_hash_t hash;
2236
0
        Py_BEGIN_CRITICAL_SECTION(key);
2237
0
        hash = frozenset_hash_impl(key);
2238
0
        Py_END_CRITICAL_SECTION();
2239
0
        rv = set_contains_entry(so, key, hash);
2240
0
    }
2241
47.1M
    return rv;
2242
47.1M
}
2243
2244
int
2245
_PySet_Contains(PySetObject *so, PyObject *key)
2246
28.7M
{
2247
28.7M
    assert(so);
2248
2249
28.7M
    int rv;
2250
28.7M
    if (PyFrozenSet_CheckExact(so)) {
2251
108k
        rv = set_contains_lock_held(so, key);
2252
28.6M
    } else {
2253
28.6M
        Py_BEGIN_CRITICAL_SECTION(so);
2254
28.6M
        rv = set_contains_lock_held(so, key);
2255
28.6M
        Py_END_CRITICAL_SECTION();
2256
28.6M
    }
2257
28.7M
    return rv;
2258
28.7M
}
2259
2260
static int
2261
set_contains(PyObject *self, PyObject *key)
2262
357
{
2263
357
    PySetObject *so = _PySet_CAST(self);
2264
357
    return _PySet_Contains(so, key);
2265
357
}
2266
2267
/*[clinic input]
2268
@critical_section
2269
@coexist
2270
set.__contains__
2271
    so: setobject
2272
    object as key: object
2273
    /
2274
2275
x.__contains__(y) <==> y in x.
2276
[clinic start generated code]*/
2277
2278
static PyObject *
2279
set___contains___impl(PySetObject *so, PyObject *key)
2280
/*[clinic end generated code: output=b44863d034b3c70e input=4a7d568459617f24]*/
2281
18.4M
{
2282
18.4M
    long result;
2283
2284
18.4M
    result = set_contains_lock_held(so, key);
2285
18.4M
    if (result < 0)
2286
0
        return NULL;
2287
18.4M
    return PyBool_FromLong(result);
2288
18.4M
}
2289
2290
/*[clinic input]
2291
@coexist
2292
frozenset.__contains__
2293
    so: setobject
2294
    object as key: object
2295
    /
2296
2297
x.__contains__(y) <==> y in x.
2298
[clinic start generated code]*/
2299
2300
static PyObject *
2301
frozenset___contains___impl(PySetObject *so, PyObject *key)
2302
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2303
448
{
2304
448
    long result;
2305
2306
448
    result = set_contains_lock_held(so, key);
2307
448
    if (result < 0)
2308
0
        return NULL;
2309
448
    return PyBool_FromLong(result);
2310
448
}
2311
2312
/*[clinic input]
2313
@critical_section
2314
set.remove
2315
    so: setobject
2316
    object as key: object
2317
    /
2318
2319
Remove an element from a set; it must be a member.
2320
2321
If the element is not a member, raise a KeyError.
2322
[clinic start generated code]*/
2323
2324
static PyObject *
2325
set_remove_impl(PySetObject *so, PyObject *key)
2326
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2327
0
{
2328
0
    int rv;
2329
2330
0
    rv = set_discard_key(so, key);
2331
0
    if (rv < 0) {
2332
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2333
0
            return NULL;
2334
0
        PyErr_Clear();
2335
0
        Py_hash_t hash;
2336
0
        Py_BEGIN_CRITICAL_SECTION(key);
2337
0
        hash = frozenset_hash_impl(key);
2338
0
        Py_END_CRITICAL_SECTION();
2339
0
        rv = set_discard_entry(so, key, hash);
2340
0
        if (rv < 0)
2341
0
            return NULL;
2342
0
    }
2343
2344
0
    if (rv == DISCARD_NOTFOUND) {
2345
0
        _PyErr_SetKeyError(key);
2346
0
        return NULL;
2347
0
    }
2348
0
    Py_RETURN_NONE;
2349
0
}
2350
2351
/*[clinic input]
2352
@critical_section
2353
set.discard
2354
    so: setobject
2355
    object as key: object
2356
    /
2357
2358
Remove an element from a set if it is a member.
2359
2360
Unlike set.remove(), the discard() method does not raise
2361
an exception when an element is missing from the set.
2362
[clinic start generated code]*/
2363
2364
static PyObject *
2365
set_discard_impl(PySetObject *so, PyObject *key)
2366
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2367
0
{
2368
0
    int rv;
2369
2370
0
    rv = set_discard_key(so, key);
2371
0
    if (rv < 0) {
2372
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2373
0
            return NULL;
2374
0
        PyErr_Clear();
2375
0
        Py_hash_t hash;
2376
0
        Py_BEGIN_CRITICAL_SECTION(key);
2377
0
        hash = frozenset_hash_impl(key);
2378
0
        Py_END_CRITICAL_SECTION();
2379
0
        rv = set_discard_entry(so, key, hash);
2380
0
        if (rv < 0)
2381
0
            return NULL;
2382
0
    }
2383
0
    Py_RETURN_NONE;
2384
0
}
2385
2386
/*[clinic input]
2387
@critical_section
2388
set.__reduce__
2389
    so: setobject
2390
2391
Return state information for pickling.
2392
[clinic start generated code]*/
2393
2394
static PyObject *
2395
set___reduce___impl(PySetObject *so)
2396
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2397
0
{
2398
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2399
2400
0
    keys = PySequence_List((PyObject *)so);
2401
0
    if (keys == NULL)
2402
0
        goto done;
2403
0
    args = PyTuple_Pack(1, keys);
2404
0
    if (args == NULL)
2405
0
        goto done;
2406
0
    state = _PyObject_GetState((PyObject *)so);
2407
0
    if (state == NULL)
2408
0
        goto done;
2409
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2410
0
done:
2411
0
    Py_XDECREF(args);
2412
0
    Py_XDECREF(keys);
2413
0
    Py_XDECREF(state);
2414
0
    return result;
2415
0
}
2416
2417
/*[clinic input]
2418
@critical_section
2419
set.__sizeof__
2420
    so: setobject
2421
2422
S.__sizeof__() -> size of S in memory, in bytes.
2423
[clinic start generated code]*/
2424
2425
static PyObject *
2426
set___sizeof___impl(PySetObject *so)
2427
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2428
0
{
2429
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2430
0
    if (so->table != so->smalltable) {
2431
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2432
0
    }
2433
0
    return PyLong_FromSize_t(res);
2434
0
}
2435
2436
static int
2437
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2438
0
{
2439
0
    PySetObject *self = _PySet_CAST(so);
2440
0
    PyObject *iterable = NULL;
2441
2442
0
    if (!_PyArg_NoKeywords("set", kwds))
2443
0
        return -1;
2444
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2445
0
        return -1;
2446
2447
0
    if (Py_REFCNT(self) == 1 && self->fill == 0) {
2448
0
        self->hash = -1;
2449
0
        if (iterable == NULL) {
2450
0
            return 0;
2451
0
        }
2452
0
        return set_update_local(self, iterable);
2453
0
    }
2454
0
    Py_BEGIN_CRITICAL_SECTION(self);
2455
0
    if (self->fill)
2456
0
        set_clear_internal((PyObject*)self);
2457
0
    self->hash = -1;
2458
0
    Py_END_CRITICAL_SECTION();
2459
2460
0
    if (iterable == NULL)
2461
0
        return 0;
2462
0
    return set_update_internal(self, iterable);
2463
0
}
2464
2465
static PyObject*
2466
set_vectorcall(PyObject *type, PyObject * const*args,
2467
               size_t nargsf, PyObject *kwnames)
2468
561k
{
2469
561k
    assert(PyType_Check(type));
2470
2471
561k
    if (!_PyArg_NoKwnames("set", kwnames)) {
2472
0
        return NULL;
2473
0
    }
2474
2475
561k
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2476
561k
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2477
0
        return NULL;
2478
0
    }
2479
2480
561k
    if (nargs) {
2481
16.6k
        return make_new_set(_PyType_CAST(type), args[0]);
2482
16.6k
    }
2483
2484
545k
    return make_new_set(_PyType_CAST(type), NULL);
2485
561k
}
2486
2487
static PySequenceMethods set_as_sequence = {
2488
    set_len,                            /* sq_length */
2489
    0,                                  /* sq_concat */
2490
    0,                                  /* sq_repeat */
2491
    0,                                  /* sq_item */
2492
    0,                                  /* sq_slice */
2493
    0,                                  /* sq_ass_item */
2494
    0,                                  /* sq_ass_slice */
2495
    set_contains,                       /* sq_contains */
2496
};
2497
2498
/* set object ********************************************************/
2499
2500
static PyMethodDef set_methods[] = {
2501
    SET_ADD_METHODDEF
2502
    SET_CLEAR_METHODDEF
2503
    SET___CONTAINS___METHODDEF
2504
    SET_COPY_METHODDEF
2505
    SET_DISCARD_METHODDEF
2506
    SET_DIFFERENCE_MULTI_METHODDEF
2507
    SET_DIFFERENCE_UPDATE_METHODDEF
2508
    SET_INTERSECTION_MULTI_METHODDEF
2509
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2510
    SET_ISDISJOINT_METHODDEF
2511
    SET_ISSUBSET_METHODDEF
2512
    SET_ISSUPERSET_METHODDEF
2513
    SET_POP_METHODDEF
2514
    SET___REDUCE___METHODDEF
2515
    SET_REMOVE_METHODDEF
2516
    SET___SIZEOF___METHODDEF
2517
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2518
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2519
    SET_UNION_METHODDEF
2520
    SET_UPDATE_METHODDEF
2521
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2522
    {NULL,              NULL}   /* sentinel */
2523
};
2524
2525
static PyNumberMethods set_as_number = {
2526
    0,                                  /*nb_add*/
2527
    set_sub,                            /*nb_subtract*/
2528
    0,                                  /*nb_multiply*/
2529
    0,                                  /*nb_remainder*/
2530
    0,                                  /*nb_divmod*/
2531
    0,                                  /*nb_power*/
2532
    0,                                  /*nb_negative*/
2533
    0,                                  /*nb_positive*/
2534
    0,                                  /*nb_absolute*/
2535
    0,                                  /*nb_bool*/
2536
    0,                                  /*nb_invert*/
2537
    0,                                  /*nb_lshift*/
2538
    0,                                  /*nb_rshift*/
2539
    set_and,                            /*nb_and*/
2540
    set_xor,                            /*nb_xor*/
2541
    set_or,                             /*nb_or*/
2542
    0,                                  /*nb_int*/
2543
    0,                                  /*nb_reserved*/
2544
    0,                                  /*nb_float*/
2545
    0,                                  /*nb_inplace_add*/
2546
    set_isub,                           /*nb_inplace_subtract*/
2547
    0,                                  /*nb_inplace_multiply*/
2548
    0,                                  /*nb_inplace_remainder*/
2549
    0,                                  /*nb_inplace_power*/
2550
    0,                                  /*nb_inplace_lshift*/
2551
    0,                                  /*nb_inplace_rshift*/
2552
    set_iand,                           /*nb_inplace_and*/
2553
    set_ixor,                           /*nb_inplace_xor*/
2554
    set_ior,                            /*nb_inplace_or*/
2555
};
2556
2557
PyDoc_STRVAR(set_doc,
2558
"set(iterable=(), /)\n\
2559
--\n\
2560
\n\
2561
Build an unordered collection of unique elements.");
2562
2563
PyTypeObject PySet_Type = {
2564
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2565
    "set",                              /* tp_name */
2566
    sizeof(PySetObject),                /* tp_basicsize */
2567
    0,                                  /* tp_itemsize */
2568
    /* methods */
2569
    set_dealloc,                        /* tp_dealloc */
2570
    0,                                  /* tp_vectorcall_offset */
2571
    0,                                  /* tp_getattr */
2572
    0,                                  /* tp_setattr */
2573
    0,                                  /* tp_as_async */
2574
    set_repr,                           /* tp_repr */
2575
    &set_as_number,                     /* tp_as_number */
2576
    &set_as_sequence,                   /* tp_as_sequence */
2577
    0,                                  /* tp_as_mapping */
2578
    PyObject_HashNotImplemented,        /* tp_hash */
2579
    0,                                  /* tp_call */
2580
    0,                                  /* tp_str */
2581
    PyObject_GenericGetAttr,            /* tp_getattro */
2582
    0,                                  /* tp_setattro */
2583
    0,                                  /* tp_as_buffer */
2584
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2585
        Py_TPFLAGS_BASETYPE |
2586
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2587
    set_doc,                            /* tp_doc */
2588
    set_traverse,                       /* tp_traverse */
2589
    set_clear_internal,                 /* tp_clear */
2590
    set_richcompare,                    /* tp_richcompare */
2591
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2592
    set_iter,                           /* tp_iter */
2593
    0,                                  /* tp_iternext */
2594
    set_methods,                        /* tp_methods */
2595
    0,                                  /* tp_members */
2596
    0,                                  /* tp_getset */
2597
    0,                                  /* tp_base */
2598
    0,                                  /* tp_dict */
2599
    0,                                  /* tp_descr_get */
2600
    0,                                  /* tp_descr_set */
2601
    0,                                  /* tp_dictoffset */
2602
    set_init,                           /* tp_init */
2603
    PyType_GenericAlloc,                /* tp_alloc */
2604
    set_new,                            /* tp_new */
2605
    PyObject_GC_Del,                    /* tp_free */
2606
    .tp_vectorcall = set_vectorcall,
2607
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2608
};
2609
2610
/* frozenset object ********************************************************/
2611
2612
2613
static PyMethodDef frozenset_methods[] = {
2614
    FROZENSET___CONTAINS___METHODDEF
2615
    FROZENSET_COPY_METHODDEF
2616
    SET_DIFFERENCE_MULTI_METHODDEF
2617
    SET_INTERSECTION_MULTI_METHODDEF
2618
    SET_ISDISJOINT_METHODDEF
2619
    SET_ISSUBSET_METHODDEF
2620
    SET_ISSUPERSET_METHODDEF
2621
    SET___REDUCE___METHODDEF
2622
    SET___SIZEOF___METHODDEF
2623
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2624
    SET_UNION_METHODDEF
2625
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2626
    {NULL,              NULL}   /* sentinel */
2627
};
2628
2629
static PyNumberMethods frozenset_as_number = {
2630
    0,                                  /*nb_add*/
2631
    set_sub,                            /*nb_subtract*/
2632
    0,                                  /*nb_multiply*/
2633
    0,                                  /*nb_remainder*/
2634
    0,                                  /*nb_divmod*/
2635
    0,                                  /*nb_power*/
2636
    0,                                  /*nb_negative*/
2637
    0,                                  /*nb_positive*/
2638
    0,                                  /*nb_absolute*/
2639
    0,                                  /*nb_bool*/
2640
    0,                                  /*nb_invert*/
2641
    0,                                  /*nb_lshift*/
2642
    0,                                  /*nb_rshift*/
2643
    set_and,                            /*nb_and*/
2644
    set_xor,                            /*nb_xor*/
2645
    set_or,                             /*nb_or*/
2646
};
2647
2648
PyDoc_STRVAR(frozenset_doc,
2649
"frozenset(iterable=(), /)\n\
2650
--\n\
2651
\n\
2652
Build an immutable unordered collection of unique elements.");
2653
2654
PyTypeObject PyFrozenSet_Type = {
2655
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2656
    "frozenset",                        /* tp_name */
2657
    sizeof(PySetObject),                /* tp_basicsize */
2658
    0,                                  /* tp_itemsize */
2659
    /* methods */
2660
    set_dealloc,                        /* tp_dealloc */
2661
    0,                                  /* tp_vectorcall_offset */
2662
    0,                                  /* tp_getattr */
2663
    0,                                  /* tp_setattr */
2664
    0,                                  /* tp_as_async */
2665
    set_repr,                           /* tp_repr */
2666
    &frozenset_as_number,               /* tp_as_number */
2667
    &set_as_sequence,                   /* tp_as_sequence */
2668
    0,                                  /* tp_as_mapping */
2669
    frozenset_hash,                     /* tp_hash */
2670
    0,                                  /* tp_call */
2671
    0,                                  /* tp_str */
2672
    PyObject_GenericGetAttr,            /* tp_getattro */
2673
    0,                                  /* tp_setattro */
2674
    0,                                  /* tp_as_buffer */
2675
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2676
        Py_TPFLAGS_BASETYPE |
2677
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2678
    frozenset_doc,                      /* tp_doc */
2679
    set_traverse,                       /* tp_traverse */
2680
    set_clear_internal,                 /* tp_clear */
2681
    set_richcompare,                    /* tp_richcompare */
2682
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2683
    set_iter,                           /* tp_iter */
2684
    0,                                  /* tp_iternext */
2685
    frozenset_methods,                  /* tp_methods */
2686
    0,                                  /* tp_members */
2687
    0,                                  /* tp_getset */
2688
    0,                                  /* tp_base */
2689
    0,                                  /* tp_dict */
2690
    0,                                  /* tp_descr_get */
2691
    0,                                  /* tp_descr_set */
2692
    0,                                  /* tp_dictoffset */
2693
    0,                                  /* tp_init */
2694
    PyType_GenericAlloc,                /* tp_alloc */
2695
    frozenset_new,                      /* tp_new */
2696
    PyObject_GC_Del,                    /* tp_free */
2697
    .tp_vectorcall = frozenset_vectorcall,
2698
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2699
};
2700
2701
2702
/***** C API functions *************************************************/
2703
2704
PyObject *
2705
PySet_New(PyObject *iterable)
2706
112k
{
2707
112k
    return make_new_set(&PySet_Type, iterable);
2708
112k
}
2709
2710
PyObject *
2711
PyFrozenSet_New(PyObject *iterable)
2712
1.68k
{
2713
1.68k
    return make_new_set(&PyFrozenSet_Type, iterable);
2714
1.68k
}
2715
2716
Py_ssize_t
2717
PySet_Size(PyObject *anyset)
2718
114
{
2719
114
    if (!PyAnySet_Check(anyset)) {
2720
0
        PyErr_BadInternalCall();
2721
0
        return -1;
2722
0
    }
2723
114
    return set_len(anyset);
2724
114
}
2725
2726
int
2727
PySet_Clear(PyObject *set)
2728
188
{
2729
188
    if (!PySet_Check(set)) {
2730
0
        PyErr_BadInternalCall();
2731
0
        return -1;
2732
0
    }
2733
188
    (void)set_clear(set, NULL);
2734
188
    return 0;
2735
188
}
2736
2737
void
2738
_PySet_ClearInternal(PySetObject *so)
2739
0
{
2740
0
    (void)set_clear_internal((PyObject*)so);
2741
0
}
2742
2743
int
2744
PySet_Contains(PyObject *anyset, PyObject *key)
2745
133k
{
2746
133k
    if (!PyAnySet_Check(anyset)) {
2747
0
        PyErr_BadInternalCall();
2748
0
        return -1;
2749
0
    }
2750
2751
133k
    int rv;
2752
133k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2753
133k
    rv = set_contains_key((PySetObject *)anyset, key);
2754
133k
    Py_END_CRITICAL_SECTION();
2755
133k
    return rv;
2756
133k
}
2757
2758
int
2759
PySet_Discard(PyObject *set, PyObject *key)
2760
73.1k
{
2761
73.1k
    if (!PySet_Check(set)) {
2762
0
        PyErr_BadInternalCall();
2763
0
        return -1;
2764
0
    }
2765
2766
73.1k
    int rv;
2767
73.1k
    Py_BEGIN_CRITICAL_SECTION(set);
2768
73.1k
    rv = set_discard_key((PySetObject *)set, key);
2769
73.1k
    Py_END_CRITICAL_SECTION();
2770
73.1k
    return rv;
2771
73.1k
}
2772
2773
int
2774
PySet_Add(PyObject *anyset, PyObject *key)
2775
46.8k
{
2776
46.8k
    if (!PySet_Check(anyset) &&
2777
1.33k
        (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {
2778
0
        PyErr_BadInternalCall();
2779
0
        return -1;
2780
0
    }
2781
2782
46.8k
    int rv;
2783
46.8k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2784
46.8k
    rv = set_add_key((PySetObject *)anyset, key);
2785
46.8k
    Py_END_CRITICAL_SECTION();
2786
46.8k
    return rv;
2787
46.8k
}
2788
2789
int
2790
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2791
1.28k
{
2792
1.28k
    setentry *entry;
2793
2794
1.28k
    if (!PyAnySet_Check(set)) {
2795
0
        PyErr_BadInternalCall();
2796
0
        return -1;
2797
0
    }
2798
1.28k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2799
302
        return 0;
2800
982
    *key = entry->key;
2801
982
    *hash = entry->hash;
2802
982
    return 1;
2803
1.28k
}
2804
2805
int
2806
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2807
124k
{
2808
124k
    setentry *entry;
2809
2810
124k
    if (!PyAnySet_Check(set)) {
2811
0
        PyErr_BadInternalCall();
2812
0
        return -1;
2813
0
    }
2814
124k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
2815
124k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2816
19.6k
        return 0;
2817
104k
    *key = Py_NewRef(entry->key);
2818
104k
    *hash = entry->hash;
2819
104k
    return 1;
2820
124k
}
2821
2822
PyObject *
2823
PySet_Pop(PyObject *set)
2824
25
{
2825
25
    if (!PySet_Check(set)) {
2826
0
        PyErr_BadInternalCall();
2827
0
        return NULL;
2828
0
    }
2829
25
    return set_pop(set, NULL);
2830
25
}
2831
2832
int
2833
_PySet_Update(PyObject *set, PyObject *iterable)
2834
10
{
2835
10
    if (!PySet_Check(set)) {
2836
0
        PyErr_BadInternalCall();
2837
0
        return -1;
2838
0
    }
2839
10
    return set_update_internal((PySetObject *)set, iterable);
2840
10
}
2841
2842
/* Exported for the gdb plugin's benefit. */
2843
PyObject *_PySet_Dummy = dummy;
2844
2845
/***** Dummy Struct  *************************************************/
2846
2847
static PyObject *
2848
dummy_repr(PyObject *op)
2849
0
{
2850
0
    return PyUnicode_FromString("<dummy key>");
2851
0
}
2852
2853
static void _Py_NO_RETURN
2854
dummy_dealloc(PyObject* ignore)
2855
0
{
2856
0
    Py_FatalError("deallocating <dummy key>");
2857
0
}
2858
2859
static PyTypeObject _PySetDummy_Type = {
2860
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2861
    "<dummy key> type",
2862
    0,
2863
    0,
2864
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
2865
    0,                  /*tp_vectorcall_offset*/
2866
    0,                  /*tp_getattr*/
2867
    0,                  /*tp_setattr*/
2868
    0,                  /*tp_as_async*/
2869
    dummy_repr,         /*tp_repr*/
2870
    0,                  /*tp_as_number*/
2871
    0,                  /*tp_as_sequence*/
2872
    0,                  /*tp_as_mapping*/
2873
    0,                  /*tp_hash */
2874
    0,                  /*tp_call */
2875
    0,                  /*tp_str */
2876
    0,                  /*tp_getattro */
2877
    0,                  /*tp_setattro */
2878
    0,                  /*tp_as_buffer */
2879
    Py_TPFLAGS_DEFAULT, /*tp_flags */
2880
};
2881
2882
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);