Coverage Report

Created: 2025-11-11 06:44

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
2.04M
#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
66.8M
#define LINEAR_PROBES 9
73
#endif
74
75
/* This must be >= 1 */
76
6.10M
#define PERTURB_SHIFT 5
77
78
static setentry *
79
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
80
48.8M
{
81
48.8M
    setentry *table;
82
48.8M
    setentry *entry;
83
48.8M
    size_t perturb = hash;
84
48.8M
    size_t mask = so->mask;
85
48.8M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
86
48.8M
    int probes;
87
48.8M
    int cmp;
88
89
48.8M
    int frozenset = PyFrozenSet_CheckExact(so);
90
91
54.9M
    while (1) {
92
54.9M
        entry = &so->table[i];
93
54.9M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
94
65.9M
        do {
95
65.9M
            if (entry->hash == 0 && entry->key == NULL)
96
33.3M
                return entry;
97
32.6M
            if (entry->hash == hash) {
98
15.5M
                PyObject *startkey = entry->key;
99
15.5M
                assert(startkey != dummy);
100
15.5M
                if (startkey == key)
101
15.5M
                    return entry;
102
3.83k
                if (PyUnicode_CheckExact(startkey)
103
3.83k
                    && PyUnicode_CheckExact(key)
104
1.06k
                    && unicode_eq(startkey, key))
105
1.06k
                    return entry;
106
2.77k
                table = so->table;
107
2.77k
                if (frozenset) {
108
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
109
0
                    if (cmp < 0)
110
0
                        return NULL;
111
2.77k
                } else {
112
                    // incref startkey because it can be removed from the set by the compare
113
2.77k
                    Py_INCREF(startkey);
114
2.77k
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
115
2.77k
                    Py_DECREF(startkey);
116
2.77k
                    if (cmp < 0)
117
0
                        return NULL;
118
2.77k
                    if (table != so->table || entry->key != startkey)
119
0
                        return set_lookkey(so, key, hash);
120
2.77k
                }
121
2.77k
                if (cmp > 0)
122
2.77k
                    return entry;
123
0
                mask = so->mask;
124
0
            }
125
17.0M
            entry++;
126
17.0M
        } while (probes--);
127
6.04M
        perturb >>= PERTURB_SHIFT;
128
6.04M
        i = (i * 5 + 1 + perturb) & mask;
129
6.04M
    }
130
48.8M
}
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
719k
{
137
719k
    setentry *table;
138
719k
    setentry *freeslot;
139
719k
    setentry *entry;
140
719k
    size_t perturb;
141
719k
    size_t mask;
142
719k
    size_t i;                       /* Unsigned for defined overflow behavior */
143
719k
    int probes;
144
719k
    int cmp;
145
146
719k
  restart:
147
148
719k
    mask = so->mask;
149
719k
    i = (size_t)hash & mask;
150
719k
    freeslot = NULL;
151
719k
    perturb = hash;
152
153
780k
    while (1) {
154
780k
        entry = &so->table[i];
155
780k
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
156
898k
        do {
157
898k
            if (entry->hash == 0 && entry->key == NULL)
158
413k
                goto found_unused_or_dummy;
159
484k
            if (entry->hash == hash) {
160
305k
                PyObject *startkey = entry->key;
161
305k
                assert(startkey != dummy);
162
305k
                if (startkey == key)
163
16.6k
                    goto found_active;
164
289k
                if (PyUnicode_CheckExact(startkey)
165
289k
                    && PyUnicode_CheckExact(key)
166
289k
                    && unicode_eq(startkey, key))
167
289k
                    goto found_active;
168
6
                table = so->table;
169
6
                Py_INCREF(startkey);
170
6
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
171
6
                Py_DECREF(startkey);
172
6
                if (cmp > 0)
173
0
                    goto found_active;
174
6
                if (cmp < 0)
175
0
                    goto comparison_error;
176
6
                if (table != so->table || entry->key != startkey)
177
0
                    goto restart;
178
6
                mask = so->mask;
179
6
            }
180
178k
            else if (entry->hash == -1) {
181
0
                assert (entry->key == dummy);
182
0
                freeslot = entry;
183
0
            }
184
178k
            entry++;
185
178k
        } while (probes--);
186
61.4k
        perturb >>= PERTURB_SHIFT;
187
61.4k
        i = (i * 5 + 1 + perturb) & mask;
188
61.4k
    }
189
190
413k
  found_unused_or_dummy:
191
413k
    if (freeslot == NULL)
192
413k
        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
413k
  found_unused:
199
413k
    so->fill++;
200
413k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
201
413k
    entry->key = key;
202
413k
    entry->hash = hash;
203
413k
    if ((size_t)so->fill*5 < mask*3)
204
400k
        return 0;
205
12.7k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
206
207
305k
  found_active:
208
305k
    Py_DECREF(key);
209
305k
    return 0;
210
211
0
  comparison_error:
212
0
    Py_DECREF(key);
213
0
    return -1;
214
413k
}
215
216
static int
217
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
218
717k
{
219
717k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
220
221
717k
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
222
717k
}
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
2.49k
{
243
2.49k
    Py_hash_t hash = _PyObject_HashFast(key);
244
2.49k
    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
2.49k
    return set_add_entry_takeref(so, key, hash);
252
2.49k
}
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
138k
{
265
138k
    setentry *entry;
266
138k
    size_t perturb = hash;
267
138k
    size_t i = (size_t)hash & mask;
268
138k
    size_t j;
269
270
140k
    while (1) {
271
140k
        entry = &table[i];
272
140k
        if (entry->key == NULL)
273
130k
            goto found_null;
274
9.61k
        if (i + LINEAR_PROBES <= mask) {
275
8.62k
            for (j = 0; j < LINEAR_PROBES; j++) {
276
8.62k
                entry++;
277
8.62k
                if (entry->key == NULL)
278
7.59k
                    goto found_null;
279
8.62k
            }
280
7.59k
        }
281
2.01k
        perturb >>= PERTURB_SHIFT;
282
2.01k
        i = (i * 5 + 1 + perturb) & mask;
283
2.01k
    }
284
138k
  found_null:
285
138k
    entry->key = key;
286
138k
    entry->hash = hash;
287
138k
}
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
19.6k
{
300
19.6k
    setentry *oldtable, *newtable, *entry;
301
19.6k
    Py_ssize_t oldmask = so->mask;
302
19.6k
    size_t newmask;
303
19.6k
    int is_oldtable_malloced;
304
19.6k
    setentry small_copy[PySet_MINSIZE];
305
306
19.6k
    assert(minused >= 0);
307
308
    /* Find the smallest table size > minused. */
309
    /* XXX speed-up with intrinsics */
310
19.6k
    size_t newsize = PySet_MINSIZE;
311
61.2k
    while (newsize <= (size_t)minused) {
312
41.5k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
313
41.5k
    }
314
315
    /* Get space for a new table. */
316
19.6k
    oldtable = so->table;
317
19.6k
    assert(oldtable != NULL);
318
19.6k
    is_oldtable_malloced = oldtable != so->smalltable;
319
320
19.6k
    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
19.6k
    else {
340
19.6k
        newtable = PyMem_NEW(setentry, newsize);
341
19.6k
        if (newtable == NULL) {
342
0
            PyErr_NoMemory();
343
0
            return -1;
344
0
        }
345
19.6k
    }
346
347
    /* Make the set empty, using the new table. */
348
19.6k
    assert(newtable != oldtable);
349
19.6k
    memset(newtable, 0, sizeof(setentry) * newsize);
350
19.6k
    so->mask = newsize - 1;
351
19.6k
    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
19.6k
    newmask = (size_t)so->mask;
356
19.6k
    if (so->fill == so->used) {
357
275k
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
358
256k
            if (entry->key != NULL) {
359
129k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
360
129k
            }
361
256k
        }
362
19.6k
    } 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
19.6k
    if (is_oldtable_malloced)
372
2.92k
        PyMem_Free(oldtable);
373
19.6k
    return 0;
374
19.6k
}
375
376
static int
377
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
378
48.7M
{
379
48.7M
    setentry *entry;
380
381
48.7M
    entry = set_lookkey(so, key, hash);
382
48.7M
    if (entry != NULL)
383
48.7M
        return entry->key != NULL;
384
0
    return -1;
385
48.7M
}
386
387
81.1k
#define DISCARD_NOTFOUND 0
388
1.51k
#define DISCARD_FOUND 1
389
390
static int
391
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
392
82.6k
{
393
82.6k
    setentry *entry;
394
82.6k
    PyObject *old_key;
395
396
82.6k
    entry = set_lookkey(so, key, hash);
397
82.6k
    if (entry == NULL)
398
0
        return -1;
399
82.6k
    if (entry->key == NULL)
400
81.1k
        return DISCARD_NOTFOUND;
401
1.51k
    old_key = entry->key;
402
1.51k
    entry->key = dummy;
403
1.51k
    entry->hash = -1;
404
1.51k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
405
1.51k
    Py_DECREF(old_key);
406
1.51k
    return DISCARD_FOUND;
407
82.6k
}
408
409
static int
410
set_add_key(PySetObject *so, PyObject *key)
411
672k
{
412
672k
    Py_hash_t hash = _PyObject_HashFast(key);
413
672k
    if (hash == -1) {
414
0
        set_unhashable_type(key);
415
0
        return -1;
416
0
    }
417
672k
    return set_add_entry(so, key, hash);
418
672k
}
419
420
static int
421
set_contains_key(PySetObject *so, PyObject *key)
422
48.7M
{
423
48.7M
    Py_hash_t hash = _PyObject_HashFast(key);
424
48.7M
    if (hash == -1) {
425
0
        set_unhashable_type(key);
426
0
        return -1;
427
0
    }
428
48.7M
    return set_contains_entry(so, key, hash);
429
48.7M
}
430
431
static int
432
set_discard_key(PySetObject *so, PyObject *key)
433
82.6k
{
434
82.6k
    Py_hash_t hash = _PyObject_HashFast(key);
435
82.6k
    if (hash == -1) {
436
0
        set_unhashable_type(key);
437
0
        return -1;
438
0
    }
439
82.6k
    return set_discard_entry(so, key, hash);
440
82.6k
}
441
442
static void
443
set_empty_to_minsize(PySetObject *so)
444
257
{
445
257
    memset(so->smalltable, 0, sizeof(so->smalltable));
446
257
    so->fill = 0;
447
257
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
448
257
    so->mask = PySet_MINSIZE - 1;
449
257
    so->table = so->smalltable;
450
257
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
451
257
}
452
453
static int
454
set_clear_internal(PyObject *self)
455
257
{
456
257
    PySetObject *so = _PySet_CAST(self);
457
257
    setentry *entry;
458
257
    setentry *table = so->table;
459
257
    Py_ssize_t fill = so->fill;
460
257
    Py_ssize_t used = so->used;
461
257
    int table_is_malloced = table != so->smalltable;
462
257
    setentry small_copy[PySet_MINSIZE];
463
464
257
    assert (PyAnySet_Check(so));
465
257
    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
257
    if (table_is_malloced)
474
0
        set_empty_to_minsize(so);
475
476
257
    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
257
        memcpy(small_copy, table, sizeof(small_copy));
482
257
        table = small_copy;
483
257
        set_empty_to_minsize(so);
484
257
    }
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.18k
    for (entry = table; used > 0; entry++) {
492
929
        if (entry->key && entry->key != dummy) {
493
257
            used--;
494
257
            Py_DECREF(entry->key);
495
257
        }
496
929
    }
497
498
257
    if (table_is_malloced)
499
0
        PyMem_Free(table);
500
257
    return 0;
501
257
}
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
1.51M
{
519
1.51M
    Py_ssize_t i;
520
1.51M
    Py_ssize_t mask;
521
1.51M
    setentry *entry;
522
523
1.51M
    assert (PyAnySet_Check(so));
524
1.51M
    i = *pos_ptr;
525
1.51M
    assert(i >= 0);
526
1.51M
    mask = so->mask;
527
1.51M
    entry = &so->table[i];
528
4.76M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
529
3.25M
        i++;
530
3.25M
        entry++;
531
3.25M
    }
532
1.51M
    *pos_ptr = i+1;
533
1.51M
    if (i > mask)
534
181k
        return 0;
535
1.51M
    assert(entry != NULL);
536
1.33M
    *entry_ptr = entry;
537
1.33M
    return 1;
538
1.51M
}
539
540
static void
541
set_dealloc(PyObject *self)
542
637k
{
543
637k
    PySetObject *so = _PySet_CAST(self);
544
637k
    setentry *entry;
545
637k
    Py_ssize_t used = so->used;
546
547
    /* bpo-31095: UnTrack is needed before calling any callbacks */
548
637k
    PyObject_GC_UnTrack(so);
549
637k
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
550
551
1.98M
    for (entry = so->table; used > 0; entry++) {
552
1.34M
        if (entry->key && entry->key != dummy) {
553
478k
                used--;
554
478k
                Py_DECREF(entry->key);
555
478k
        }
556
1.34M
    }
557
637k
    if (so->table != so->smalltable)
558
16.0k
        PyMem_Free(so->table);
559
637k
    Py_TYPE(so)->tp_free(so);
560
637k
}
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
250k
{
630
250k
    PySetObject *so = _PySet_CAST(self);
631
250k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
632
250k
}
633
634
static int
635
set_merge_lock_held(PySetObject *so, PyObject *otherset)
636
120k
{
637
120k
    PySetObject *other;
638
120k
    PyObject *key;
639
120k
    Py_ssize_t i;
640
120k
    setentry *so_entry;
641
120k
    setentry *other_entry;
642
643
120k
    assert (PyAnySet_Check(so));
644
120k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
645
120k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
646
647
120k
    other = _PySet_CAST(otherset);
648
120k
    if (other == so || other->used == 0)
649
        /* a.update(a) or a.update(set()); nothing to do */
650
68.5k
        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
51.8k
    if ((so->fill + other->used)*5 >= so->mask*3) {
656
6.86k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
657
0
            return -1;
658
6.86k
    }
659
51.8k
    so_entry = so->table;
660
51.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
51.8k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
665
370k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
666
334k
            key = other_entry->key;
667
334k
            if (key != NULL) {
668
84.9k
                assert(so_entry->key == NULL);
669
84.9k
                so_entry->key = Py_NewRef(key);
670
84.9k
                so_entry->hash = other_entry->hash;
671
84.9k
            }
672
334k
        }
673
35.1k
        so->fill = other->fill;
674
35.1k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
675
35.1k
        return 0;
676
35.1k
    }
677
678
    /* If our table is empty, we can use set_insert_clean() */
679
16.7k
    if (so->fill == 0) {
680
1.07k
        setentry *newtable = so->table;
681
1.07k
        size_t newmask = (size_t)so->mask;
682
1.07k
        so->fill = other->used;
683
1.07k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
684
41.3k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
685
40.2k
            key = other_entry->key;
686
40.2k
            if (key != NULL && key != dummy) {
687
8.52k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
688
8.52k
                                 other_entry->hash);
689
8.52k
            }
690
40.2k
        }
691
1.07k
        return 0;
692
1.07k
    }
693
694
    /* We can't assure there are no duplicates, so do normal insertions */
695
172k
    for (i = 0; i <= other->mask; i++) {
696
156k
        other_entry = &other->table[i];
697
156k
        key = other_entry->key;
698
156k
        if (key != NULL && key != dummy) {
699
44.5k
            if (set_add_entry(so, key, other_entry->hash))
700
0
                return -1;
701
44.5k
        }
702
156k
    }
703
15.6k
    return 0;
704
15.6k
}
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
188
{
720
    /* Make sure the search finger is in bounds */
721
188
    setentry *entry = so->table + (so->finger & so->mask);
722
188
    setentry *limit = so->table + so->mask;
723
188
    PyObject *key;
724
725
188
    if (so->used == 0) {
726
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
727
0
        return NULL;
728
0
    }
729
422
    while (entry->key == NULL || entry->key==dummy) {
730
234
        entry++;
731
234
        if (entry > limit)
732
0
            entry = so->table;
733
234
    }
734
188
    key = entry->key;
735
188
    entry->key = dummy;
736
188
    entry->hash = -1;
737
188
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
738
188
    so->finger = entry - so->table + 1;   /* next place to start */
739
188
    return key;
740
188
}
741
742
static int
743
set_traverse(PyObject *self, visitproc visit, void *arg)
744
160k
{
745
160k
    PySetObject *so = _PySet_CAST(self);
746
160k
    Py_ssize_t pos = 0;
747
160k
    setentry *entry;
748
749
1.39M
    while (set_next(so, &pos, &entry))
750
1.23M
        Py_VISIT(entry->key);
751
160k
    return 0;
752
160k
}
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.57k
{
762
3.57k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
763
3.57k
}
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
168
{
778
168
    PySetObject *so = _PySet_CAST(self);
779
168
    Py_uhash_t hash = 0;
780
168
    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.67k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
793
3.50k
        hash ^= _shuffle_bits(entry->hash);
794
795
    /* Remove the effect of an odd number of NULL entries */
796
168
    if ((so->mask + 1 - so->fill) & 1)
797
66
        hash ^= _shuffle_bits(0);
798
799
    /* Remove the effect of an odd number of dummy entries */
800
168
    if ((so->fill - so->used) & 1)
801
0
        hash ^= _shuffle_bits(-1);
802
803
    /* Factor in the number of active entries */
804
168
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
805
806
    /* Disperse patterns arising in nested frozensets */
807
168
    hash ^= (hash >> 11) ^ (hash >> 25);
808
168
    hash = hash * 69069U + 907133923UL;
809
810
    /* -1 is reserved as an error code */
811
168
    if (hash == (Py_uhash_t)-1)
812
0
        hash = 590923713UL;
813
814
168
    return (Py_hash_t)hash;
815
168
}
816
817
static Py_hash_t
818
frozenset_hash(PyObject *self)
819
280
{
820
280
    PySetObject *so = _PySet_CAST(self);
821
280
    Py_uhash_t hash;
822
823
280
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
824
112
        return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
825
112
    }
826
827
168
    hash = frozenset_hash_impl(self);
828
168
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
829
168
    return hash;
830
280
}
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
245k
{
845
245k
    setiterobject *si = (setiterobject*)self;
846
    /* bpo-31095: UnTrack is needed before calling any callbacks */
847
245k
    _PyObject_GC_UNTRACK(si);
848
245k
    Py_XDECREF(si->si_set);
849
245k
    PyObject_GC_Del(si);
850
245k
}
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
417k
{
900
417k
    setiterobject *si = (setiterobject*)self;
901
417k
    PyObject *key = NULL;
902
417k
    Py_ssize_t i, mask;
903
417k
    setentry *entry;
904
417k
    PySetObject *so = si->si_set;
905
906
417k
    if (so == NULL)
907
0
        return NULL;
908
417k
    assert (PyAnySet_Check(so));
909
910
417k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
911
417k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
912
417k
    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
417k
    Py_BEGIN_CRITICAL_SECTION(so);
920
417k
    i = si->si_pos;
921
417k
    assert(i>=0);
922
417k
    entry = so->table;
923
417k
    mask = so->mask;
924
2.38M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
925
1.96M
        i++;
926
1.96M
    }
927
417k
    if (i <= mask) {
928
172k
        key = Py_NewRef(entry[i].key);
929
172k
    }
930
417k
    Py_END_CRITICAL_SECTION();
931
417k
    si->si_pos = i+1;
932
417k
    if (key == NULL) {
933
245k
        si->si_set = NULL;
934
245k
        Py_DECREF(so);
935
245k
        return NULL;
936
245k
    }
937
172k
    si->len--;
938
172k
    return key;
939
417k
}
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
245k
{
977
245k
    Py_ssize_t size = set_len(so);
978
245k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
979
245k
    if (si == NULL)
980
0
        return NULL;
981
245k
    si->si_set = (PySetObject*)Py_NewRef(so);
982
245k
    si->si_used = size;
983
245k
    si->si_pos = 0;
984
245k
    si->len = size;
985
245k
    _PyObject_GC_TRACK(si);
986
245k
    return (PyObject *)si;
987
245k
}
988
989
static int
990
set_update_dict_lock_held(PySetObject *so, PyObject *other)
991
137
{
992
137
    assert(PyDict_CheckExact(other));
993
994
137
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
995
137
    _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
137
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1002
137
    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
137
    Py_ssize_t pos = 0;
1009
137
    PyObject *key;
1010
137
    PyObject *value;
1011
137
    Py_hash_t hash;
1012
275
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1013
138
        if (set_add_entry(so, key, hash)) {
1014
0
            return -1;
1015
0
        }
1016
138
    }
1017
137
    return 0;
1018
137
}
1019
1020
static int
1021
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1022
15.0k
{
1023
15.0k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1024
1025
15.0k
    PyObject *it = PyObject_GetIter(other);
1026
15.0k
    if (it == NULL) {
1027
0
        return -1;
1028
0
    }
1029
1030
15.0k
    PyObject *key;
1031
72.0k
    while ((key = PyIter_Next(it)) != NULL) {
1032
57.0k
        if (set_add_key(so, key)) {
1033
0
            Py_DECREF(it);
1034
0
            Py_DECREF(key);
1035
0
            return -1;
1036
0
        }
1037
57.0k
        Py_DECREF(key);
1038
57.0k
    }
1039
15.0k
    Py_DECREF(it);
1040
15.0k
    if (PyErr_Occurred())
1041
0
        return -1;
1042
15.0k
    return 0;
1043
15.0k
}
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
69.4k
{
1061
69.4k
    assert(Py_REFCNT(so) == 1);
1062
69.4k
    if (PyAnySet_Check(other)) {
1063
54.2k
        int rv;
1064
54.2k
        Py_BEGIN_CRITICAL_SECTION(other);
1065
54.2k
        rv = set_merge_lock_held(so, other);
1066
54.2k
        Py_END_CRITICAL_SECTION();
1067
54.2k
        return rv;
1068
54.2k
    }
1069
15.2k
    else if (PyDict_CheckExact(other)) {
1070
137
        int rv;
1071
137
        Py_BEGIN_CRITICAL_SECTION(other);
1072
137
        rv = set_update_dict_lock_held(so, other);
1073
137
        Py_END_CRITICAL_SECTION();
1074
137
        return rv;
1075
137
    }
1076
15.0k
    return set_update_iterable_lock_held(so, other);
1077
69.4k
}
1078
1079
static int
1080
set_update_internal(PySetObject *so, PyObject *other)
1081
66.1k
{
1082
66.1k
    if (PyAnySet_Check(other)) {
1083
66.1k
        if (Py_Is((PyObject *)so, other)) {
1084
0
            return 0;
1085
0
        }
1086
66.1k
        int rv;
1087
66.1k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1088
66.1k
        rv = set_merge_lock_held(so, other);
1089
66.1k
        Py_END_CRITICAL_SECTION2();
1090
66.1k
        return rv;
1091
66.1k
    }
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
66.1k
}
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
640k
{
1140
640k
    assert(PyType_Check(type));
1141
640k
    PySetObject *so;
1142
1143
640k
    so = (PySetObject *)type->tp_alloc(type, 0);
1144
640k
    if (so == NULL)
1145
0
        return NULL;
1146
1147
640k
    so->fill = 0;
1148
640k
    so->used = 0;
1149
640k
    so->mask = PySet_MINSIZE - 1;
1150
640k
    so->table = so->smalltable;
1151
640k
    so->hash = -1;
1152
640k
    so->finger = 0;
1153
640k
    so->weakreflist = NULL;
1154
1155
640k
    if (iterable != NULL) {
1156
69.3k
        if (set_update_local(so, iterable)) {
1157
0
            Py_DECREF(so);
1158
0
            return NULL;
1159
0
        }
1160
69.3k
    }
1161
1162
640k
    return (PyObject *)so;
1163
640k
}
1164
1165
static PyObject *
1166
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1167
187
{
1168
187
    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
187
    return make_new_set(type, iterable);
1175
187
}
1176
1177
static PyObject *
1178
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1179
229
{
1180
229
    if (type != &PyFrozenSet_Type) {
1181
0
        return make_new_set(type, iterable);
1182
0
    }
1183
1184
229
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1185
        /* frozenset(f) is idempotent */
1186
0
        return Py_NewRef(iterable);
1187
0
    }
1188
229
    return make_new_set(type, iterable);
1189
229
}
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
229
{
1213
229
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1214
0
        return NULL;
1215
0
    }
1216
1217
229
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1218
229
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1219
0
        return NULL;
1220
0
    }
1221
1222
229
    PyObject *iterable = (nargs ? args[0] : NULL);
1223
229
    return make_new_frozenset(_PyType_CAST(type), iterable);
1224
229
}
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
48
{
1294
48
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1295
48
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1296
48
    if (copy == NULL) {
1297
0
        return NULL;
1298
0
    }
1299
48
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1300
0
        Py_DECREF(copy);
1301
0
        return NULL;
1302
0
    }
1303
48
    return copy;
1304
48
}
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
257
{
1336
257
    set_clear_internal((PyObject*)so);
1337
257
    Py_RETURN_NONE;
1338
257
}
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
38
{
1376
38
    PySetObject *result;
1377
1378
38
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1379
0
        Py_RETURN_NOTIMPLEMENTED;
1380
1381
38
    result = (PySetObject *)set_copy(self, NULL);
1382
38
    if (result == NULL) {
1383
0
        return NULL;
1384
0
    }
1385
38
    if (Py_Is(self, other)) {
1386
0
        return (PyObject *)result;
1387
0
    }
1388
38
    if (set_update_local(result, other)) {
1389
0
        Py_DECREF(result);
1390
0
        return NULL;
1391
0
    }
1392
38
    return (PyObject *)result;
1393
38
}
1394
1395
static PyObject *
1396
set_ior(PyObject *self, PyObject *other)
1397
66.0k
{
1398
66.0k
    if (!PyAnySet_Check(other))
1399
0
        Py_RETURN_NOTIMPLEMENTED;
1400
66.0k
    PySetObject *so = _PySet_CAST(self);
1401
1402
66.0k
    if (set_update_internal(so, other)) {
1403
0
        return NULL;
1404
0
    }
1405
66.0k
    return Py_NewRef(so);
1406
66.0k
}
1407
1408
static PyObject *
1409
set_intersection(PySetObject *so, PyObject *other)
1410
137
{
1411
137
    PySetObject *result;
1412
137
    PyObject *key, *it, *tmp;
1413
137
    Py_hash_t hash;
1414
137
    int rv;
1415
1416
137
    if ((PyObject *)so == other)
1417
0
        return set_copy_impl(so);
1418
1419
137
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1420
137
    if (result == NULL)
1421
0
        return NULL;
1422
1423
137
    if (PyAnySet_Check(other)) {
1424
137
        Py_ssize_t pos = 0;
1425
137
        setentry *entry;
1426
1427
137
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1428
108
            tmp = (PyObject *)so;
1429
108
            so = (PySetObject *)other;
1430
108
            other = tmp;
1431
108
        }
1432
1433
195
        while (set_next((PySetObject *)other, &pos, &entry)) {
1434
58
            key = entry->key;
1435
58
            hash = entry->hash;
1436
58
            Py_INCREF(key);
1437
58
            rv = set_contains_entry(so, key, hash);
1438
58
            if (rv < 0) {
1439
0
                Py_DECREF(result);
1440
0
                Py_DECREF(key);
1441
0
                return NULL;
1442
0
            }
1443
58
            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
58
            Py_DECREF(key);
1451
58
        }
1452
137
        return (PyObject *)result;
1453
137
    }
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
137
{
1567
137
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1568
0
        Py_RETURN_NOTIMPLEMENTED;
1569
137
    PySetObject *so = _PySet_CAST(self);
1570
1571
137
    PyObject *rv;
1572
137
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1573
137
    rv = set_intersection(so, other);
1574
137
    Py_END_CRITICAL_SECTION2();
1575
1576
137
    return rv;
1577
137
}
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
14.4k
{
1612
14.4k
    PyObject *key, *it, *tmp;
1613
14.4k
    int rv;
1614
1615
14.4k
    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
14.4k
    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
14.4k
    it = PyObject_GetIter(other);
1647
14.4k
    if (it == NULL)
1648
0
        return NULL;
1649
1650
20.3k
    while ((key = PyIter_Next(it)) != NULL) {
1651
20.2k
        rv = set_contains_key(so, key);
1652
20.2k
        Py_DECREF(key);
1653
20.2k
        if (rv < 0) {
1654
0
            Py_DECREF(it);
1655
0
            return NULL;
1656
0
        }
1657
20.2k
        if (rv) {
1658
14.2k
            Py_DECREF(it);
1659
14.2k
            Py_RETURN_FALSE;
1660
14.2k
        }
1661
20.2k
    }
1662
170
    Py_DECREF(it);
1663
170
    if (PyErr_Occurred())
1664
0
        return NULL;
1665
170
    Py_RETURN_TRUE;
1666
170
}
1667
1668
static int
1669
set_difference_update_internal(PySetObject *so, PyObject *other)
1670
8
{
1671
8
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1672
8
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1673
1674
8
    if ((PyObject *)so == other)
1675
0
        return set_clear_internal((PyObject*)so);
1676
1677
8
    if (PyAnySet_Check(other)) {
1678
8
        setentry *entry;
1679
8
        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
8
        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
8
        } else {
1690
8
            Py_INCREF(other);
1691
8
        }
1692
1693
17
        while (set_next((PySetObject *)other, &pos, &entry)) {
1694
9
            PyObject *key = entry->key;
1695
9
            Py_INCREF(key);
1696
9
            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
9
            Py_DECREF(key);
1702
9
        }
1703
1704
8
        Py_DECREF(other);
1705
8
    } 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
8
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1725
8
        return 0;
1726
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1727
8
}
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
8
{
1760
8
    PyObject *result;
1761
1762
8
    result = set_copy_impl(so);
1763
8
    if (result == NULL)
1764
0
        return NULL;
1765
8
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1766
8
        return result;
1767
0
    Py_DECREF(result);
1768
0
    return NULL;
1769
8
}
1770
1771
static PyObject *
1772
set_difference(PySetObject *so, PyObject *other)
1773
10
{
1774
10
    PyObject *result;
1775
10
    PyObject *key;
1776
10
    Py_hash_t hash;
1777
10
    setentry *entry;
1778
10
    Py_ssize_t pos = 0, other_size;
1779
10
    int rv;
1780
1781
10
    if (PyAnySet_Check(other)) {
1782
10
        other_size = PySet_GET_SIZE(other);
1783
10
    }
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
10
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1794
8
        return set_copy_and_difference(so, other);
1795
8
    }
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
10
{
1891
10
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1892
0
        Py_RETURN_NOTIMPLEMENTED;
1893
10
    PySetObject *so = _PySet_CAST(self);
1894
1895
10
    PyObject *rv;
1896
10
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1897
10
    rv = set_difference(so, other);
1898
10
    Py_END_CRITICAL_SECTION2();
1899
10
    return rv;
1900
10
}
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
88
{
2088
88
    setentry *entry;
2089
88
    Py_ssize_t pos = 0;
2090
88
    int rv;
2091
2092
88
    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
88
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2102
0
        Py_RETURN_FALSE;
2103
2104
438
    while (set_next(so, &pos, &entry)) {
2105
350
        PyObject *key = entry->key;
2106
350
        Py_INCREF(key);
2107
350
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2108
350
        Py_DECREF(key);
2109
350
        if (rv < 0) {
2110
0
            return NULL;
2111
0
        }
2112
350
        if (!rv) {
2113
0
            Py_RETURN_FALSE;
2114
0
        }
2115
350
    }
2116
88
    Py_RETURN_TRUE;
2117
88
}
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
88
{
2163
88
    PySetObject *v = _PySet_CAST(self);
2164
88
    PyObject *r1;
2165
88
    int r2;
2166
2167
88
    if(!PyAnySet_Check(w))
2168
0
        Py_RETURN_NOTIMPLEMENTED;
2169
2170
88
    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
48
    case Py_LE:
2189
48
        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
88
    }
2201
88
    Py_RETURN_NOTIMPLEMENTED;
2202
88
}
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
561k
{
2220
561k
    if (set_add_key(so, key))
2221
0
        return NULL;
2222
561k
    Py_RETURN_NONE;
2223
561k
}
2224
2225
static int
2226
set_contains_lock_held(PySetObject *so, PyObject *key)
2227
48.6M
{
2228
48.6M
    int rv;
2229
2230
48.6M
    rv = set_contains_key(so, key);
2231
48.6M
    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
48.6M
    return rv;
2242
48.6M
}
2243
2244
int
2245
_PySet_Contains(PySetObject *so, PyObject *key)
2246
27.8M
{
2247
27.8M
    assert(so);
2248
2249
27.8M
    int rv;
2250
27.8M
    if (PyFrozenSet_CheckExact(so)) {
2251
110k
        rv = set_contains_lock_held(so, key);
2252
27.7M
    } else {
2253
27.7M
        Py_BEGIN_CRITICAL_SECTION(so);
2254
27.7M
        rv = set_contains_lock_held(so, key);
2255
27.7M
        Py_END_CRITICAL_SECTION();
2256
27.7M
    }
2257
27.8M
    return rv;
2258
27.8M
}
2259
2260
static int
2261
set_contains(PyObject *self, PyObject *key)
2262
452
{
2263
452
    PySetObject *so = _PySet_CAST(self);
2264
452
    return _PySet_Contains(so, key);
2265
452
}
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
20.7M
{
2282
20.7M
    long result;
2283
2284
20.7M
    result = set_contains_lock_held(so, key);
2285
20.7M
    if (result < 0)
2286
0
        return NULL;
2287
20.7M
    return PyBool_FromLong(result);
2288
20.7M
}
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
495
{
2304
495
    long result;
2305
2306
495
    result = set_contains_lock_held(so, key);
2307
495
    if (result < 0)
2308
0
        return NULL;
2309
495
    return PyBool_FromLong(result);
2310
495
}
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 (_PyObject_IsUniquelyReferenced((PyObject *)self) && 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
511k
{
2469
511k
    assert(PyType_Check(type));
2470
2471
511k
    if (!_PyArg_NoKwnames("set", kwnames)) {
2472
0
        return NULL;
2473
0
    }
2474
2475
511k
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2476
511k
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2477
0
        return NULL;
2478
0
    }
2479
2480
511k
    if (nargs) {
2481
14.7k
        return make_new_set(_PyType_CAST(type), args[0]);
2482
14.7k
    }
2483
2484
496k
    return make_new_set(_PyType_CAST(type), NULL);
2485
511k
}
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
126k
{
2707
126k
    return make_new_set(&PySet_Type, iterable);
2708
126k
}
2709
2710
PyObject *
2711
PyFrozenSet_New(PyObject *iterable)
2712
2.29k
{
2713
2.29k
    return make_new_set(&PyFrozenSet_Type, iterable);
2714
2.29k
}
2715
2716
Py_ssize_t
2717
PySet_Size(PyObject *anyset)
2718
136
{
2719
136
    if (!PyAnySet_Check(anyset)) {
2720
0
        PyErr_BadInternalCall();
2721
0
        return -1;
2722
0
    }
2723
136
    return set_len(anyset);
2724
136
}
2725
2726
int
2727
PySet_Clear(PyObject *set)
2728
257
{
2729
257
    if (!PySet_Check(set)) {
2730
0
        PyErr_BadInternalCall();
2731
0
        return -1;
2732
0
    }
2733
257
    (void)set_clear(set, NULL);
2734
257
    return 0;
2735
257
}
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
153k
{
2746
153k
    if (!PyAnySet_Check(anyset)) {
2747
0
        PyErr_BadInternalCall();
2748
0
        return -1;
2749
0
    }
2750
2751
153k
    int rv;
2752
153k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2753
153k
    rv = set_contains_key((PySetObject *)anyset, key);
2754
153k
    Py_END_CRITICAL_SECTION();
2755
153k
    return rv;
2756
153k
}
2757
2758
int
2759
PySet_Discard(PyObject *set, PyObject *key)
2760
82.6k
{
2761
82.6k
    if (!PySet_Check(set)) {
2762
0
        PyErr_BadInternalCall();
2763
0
        return -1;
2764
0
    }
2765
2766
82.6k
    int rv;
2767
82.6k
    Py_BEGIN_CRITICAL_SECTION(set);
2768
82.6k
    rv = set_discard_key((PySetObject *)set, key);
2769
82.6k
    Py_END_CRITICAL_SECTION();
2770
82.6k
    return rv;
2771
82.6k
}
2772
2773
int
2774
PySet_Add(PyObject *anyset, PyObject *key)
2775
53.9k
{
2776
53.9k
    if (!PySet_Check(anyset) &&
2777
1.79k
        (!PyFrozenSet_Check(anyset) || !_PyObject_IsUniquelyReferenced(anyset))) {
2778
0
        PyErr_BadInternalCall();
2779
0
        return -1;
2780
0
    }
2781
2782
53.9k
    int rv;
2783
53.9k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2784
53.9k
    rv = set_add_key((PySetObject *)anyset, key);
2785
53.9k
    Py_END_CRITICAL_SECTION();
2786
53.9k
    return rv;
2787
53.9k
}
2788
2789
int
2790
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2791
1.50k
{
2792
1.50k
    setentry *entry;
2793
2794
1.50k
    if (!PyAnySet_Check(set)) {
2795
0
        PyErr_BadInternalCall();
2796
0
        return -1;
2797
0
    }
2798
1.50k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2799
373
        return 0;
2800
1.13k
    *key = entry->key;
2801
1.13k
    *hash = entry->hash;
2802
1.13k
    return 1;
2803
1.50k
}
2804
2805
int
2806
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2807
118k
{
2808
118k
    setentry *entry;
2809
2810
118k
    if (!PyAnySet_Check(set)) {
2811
0
        PyErr_BadInternalCall();
2812
0
        return -1;
2813
0
    }
2814
118k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
2815
118k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2816
19.8k
        return 0;
2817
98.1k
    *key = Py_NewRef(entry->key);
2818
98.1k
    *hash = entry->hash;
2819
98.1k
    return 1;
2820
118k
}
2821
2822
PyObject *
2823
PySet_Pop(PyObject *set)
2824
24
{
2825
24
    if (!PySet_Check(set)) {
2826
0
        PyErr_BadInternalCall();
2827
0
        return NULL;
2828
0
    }
2829
24
    return set_pop(set, NULL);
2830
24
}
2831
2832
int
2833
_PySet_Update(PyObject *set, PyObject *iterable)
2834
13
{
2835
13
    if (!PySet_Check(set)) {
2836
0
        PyErr_BadInternalCall();
2837
0
        return -1;
2838
0
    }
2839
13
    return set_update_internal((PySetObject *)set, iterable);
2840
13
}
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);