Coverage Report

Created: 2026-05-30 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/odictobject.c
Line
Count
Source
1
/* Ordered Dictionary object implementation.
2
3
This implementation is necessarily explicitly equivalent to the pure Python
4
OrderedDict class in Lib/collections/__init__.py.  The strategy there
5
involves using a doubly-linked-list to capture the order.  We keep to that
6
strategy, using a lower-level linked-list.
7
8
About the Linked-List
9
=====================
10
11
For the linked list we use a basic doubly-linked-list.  Using a circularly-
12
linked-list does have some benefits, but they don't apply so much here
13
since OrderedDict is focused on the ends of the list (for the most part).
14
Furthermore, there are some features of generic linked-lists that we simply
15
don't need for OrderedDict.  Thus a simple custom implementation meets our
16
needs.  Alternatives to our simple approach include the QCIRCLE_*
17
macros from BSD's queue.h, and the linux's list.h.
18
19
Getting O(1) Node Lookup
20
------------------------
21
22
One invariant of Python's OrderedDict is that it preserves time complexity
23
of dict's methods, particularly the O(1) operations.  Simply adding a
24
linked-list on top of dict is not sufficient here; operations for nodes in
25
the middle of the linked-list implicitly require finding the node first.
26
With a simple linked-list like we're using, that is an O(n) operation.
27
Consequently, methods like __delitem__() would change from O(1) to O(n),
28
which is unacceptable.
29
30
In order to preserve O(1) performance for node removal (finding nodes), we
31
must do better than just looping through the linked-list.  Here are options
32
we've considered:
33
34
1. use a second dict to map keys to nodes (a la the pure Python version).
35
2. keep a simple hash table mirroring the order of dict's, mapping each key
36
   to the corresponding node in the linked-list.
37
3. use a version of shared keys (split dict) that allows non-unicode keys.
38
4. have the value stored for each key be a (value, node) pair, and adjust
39
   __getitem__(), get(), etc. accordingly.
40
41
The approach with the least performance impact (time and space) is #2,
42
mirroring the key order of dict's dk_entries with an array of node pointers.
43
While _Py_dict_lookup() does not give us the index into the array,
44
we make use of pointer arithmetic to get that index.  An alternative would
45
be to refactor _Py_dict_lookup() to provide the index, explicitly exposing
46
the implementation detail.  We could even just use a custom lookup function
47
for OrderedDict that facilitates our need.  However, both approaches are
48
significantly more complicated than just using pointer arithmetic.
49
50
The catch with mirroring the hash table ordering is that we have to keep
51
the ordering in sync through any dict resizes.  However, that order only
52
matters during node lookup.  We can simply defer any potential resizing
53
until we need to do a lookup.
54
55
Linked-List Nodes
56
-----------------
57
58
The current implementation stores a pointer to the associated key only.
59
One alternative would be to store a pointer to the PyDictKeyEntry instead.
60
This would save one pointer de-reference per item, which is nice during
61
calls to values() and items().  However, it adds unnecessary overhead
62
otherwise, so we stick with just the key.
63
64
Linked-List API
65
---------------
66
67
As noted, the linked-list implemented here does not have all the bells and
68
whistles.  However, we recognize that the implementation may need to
69
change to accommodate performance improvements or extra functionality.  To
70
that end, we use a simple API to interact with the linked-list.  Here's a
71
summary of the methods/macros:
72
73
Node info:
74
75
* _odictnode_KEY(node)
76
* _odictnode_VALUE(od, node)
77
* _odictnode_PREV(node)
78
* _odictnode_NEXT(node)
79
80
Linked-List info:
81
82
* _odict_FIRST(od)
83
* _odict_LAST(od)
84
* _odict_EMPTY(od)
85
* _odict_FOREACH(od, node) - used in place of `for (node=...)`
86
87
For adding nodes:
88
89
* _odict_add_head(od, node)
90
* _odict_add_tail(od, node)
91
* _odict_add_new_node(od, key, hash)
92
93
For removing nodes:
94
95
* _odict_clear_node(od, node, key, hash)
96
* _odict_clear_nodes(od, clear_each)
97
98
Others:
99
100
* _odict_find_node_hash(od, key, hash)
101
* _odict_find_node(od, key)
102
* _odict_keys_equal(od1, od2)
103
104
And here's a look at how the linked-list relates to the OrderedDict API:
105
106
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
107
method       key val prev next mem  1st last empty iter find add rmv  clr keq
108
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
109
__del__                                      ~                        X
110
__delitem__                    free                     ~        node
111
__eq__       ~                                                            X
112
__iter__     X            X
113
__new__                             X   X
114
__reduce__   X   ~                                 X
115
__repr__     X   X                                 X
116
__reversed__ X       X
117
__setitem__                                                  key
118
__sizeof__                     size          X
119
clear                          ~             ~                        X
120
copy         X   X                                 X
121
items        X   X        X
122
keys         X            X
123
move_to_end  X                      X   X               ~    h/t key
124
pop                            free                              key
125
popitem      X   X             free X   X                        node
126
setdefault       ~                                      ?    ~
127
values           X        X
128
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
129
130
__delitem__ is the only method that directly relies on finding an arbitrary
131
node in the linked-list.  Everything else is iteration or relates to the
132
ends of the linked-list.
133
134
Situation that Endangers Consistency
135
------------------------------------
136
Using a raw linked-list for OrderedDict exposes a key situation that can
137
cause problems.  If a node is stored in a variable, there is a chance that
138
the node may have been deallocated before the variable gets used, thus
139
potentially leading to a segmentation fault.  A key place where this shows
140
up is during iteration through the linked list (via _odict_FOREACH or
141
otherwise).
142
143
A number of solutions are available to resolve this situation:
144
145
* defer looking up the node until as late as possible and certainly after
146
  any code that could possibly result in a deletion;
147
* if the node is needed both before and after a point where the node might
148
  be removed, do a check before using the node at the "after" location to
149
  see if the node is still valid;
150
* like the last one, but simply pull the node again to ensure it's right;
151
* keep the key in the variable instead of the node and then look up the
152
  node using the key at the point where the node is needed (this is what
153
  we do for the iterators).
154
155
Another related problem, preserving consistent ordering during iteration,
156
is described below.  That one is not exclusive to using linked-lists.
157
158
159
Challenges from Subclassing dict
160
================================
161
162
OrderedDict subclasses dict, which is an unusual relationship between two
163
builtin types (other than the base object type).  Doing so results in
164
some complication and deserves further explanation.  There are two things
165
to consider here.  First, in what circumstances or with what adjustments
166
can OrderedDict be used as a drop-in replacement for dict (at the C level)?
167
Second, how can the OrderedDict implementation leverage the dict
168
implementation effectively without introducing unnecessary coupling or
169
inefficiencies?
170
171
This second point is reflected here and in the implementation, so the
172
further focus is on the first point.  It is worth noting that for
173
overridden methods, the dict implementation is deferred to as much as
174
possible.  Furthermore, coupling is limited to as little as is reasonable.
175
176
Concrete API Compatibility
177
--------------------------
178
179
Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
180
problematic.  (See http://bugs.python.org/issue10977.)  The concrete API
181
has a number of hard-coded assumptions tied to the dict implementation.
182
This is, in part, due to performance reasons, which is understandable
183
given the part dict plays in Python.
184
185
Any attempt to replace dict with OrderedDict for any role in the
186
interpreter (e.g. **kwds) faces a challenge.  Such any effort must
187
recognize that the instances in affected locations currently interact with
188
the concrete API.
189
190
Here are some ways to address this challenge:
191
192
1. Change the relevant usage of the concrete API in CPython and add
193
   PyDict_CheckExact() calls to each of the concrete API functions.
194
2. Adjust the relevant concrete API functions to explicitly accommodate
195
   OrderedDict.
196
3. As with #1, add the checks, but improve the abstract API with smart fast
197
   paths for dict and OrderedDict, and refactor CPython to use the abstract
198
   API.  Improvements to the abstract API would be valuable regardless.
199
200
Adding the checks to the concrete API would help make any interpreter
201
switch to OrderedDict less painful for extension modules.  However, this
202
won't work.  The equivalent C API call to `dict.__setitem__(obj, k, v)`
203
is `PyDict_SetItem(obj, k, v)`.  This illustrates how subclasses in C call
204
the base class's methods, since there is no equivalent of super() in the
205
C API.  Calling into Python for parent class API would work, but some
206
extension modules already rely on this feature of the concrete API.
207
208
For reference, here is a breakdown of some of the dict concrete API:
209
210
========================== ============= =======================
211
concrete API               uses          abstract API
212
========================== ============= =======================
213
PyDict_Check                             PyMapping_Check
214
(PyDict_CheckExact)                      -
215
(PyDict_New)                             -
216
(PyDictProxy_New)                        -
217
PyDict_Clear                             -
218
PyDict_Contains                          PySequence_Contains
219
PyDict_Copy                              -
220
PyDict_SetItem                           PyObject_SetItem
221
PyDict_SetItemString                     PyMapping_SetItemString
222
PyDict_DelItem                           PyMapping_DelItem
223
PyDict_DelItemString                     PyMapping_DelItemString
224
PyDict_GetItem                           -
225
PyDict_GetItemWithError                  PyObject_GetItem
226
PyDict_GetItemString                     PyMapping_GetItemString
227
PyDict_Items                             PyMapping_Items
228
PyDict_Keys                              PyMapping_Keys
229
PyDict_Values                            PyMapping_Values
230
PyDict_Size                              PyMapping_Size
231
                                         PyMapping_Length
232
PyDict_Next                              PyIter_Next
233
_PyDict_Next                             -
234
PyDict_Merge                             -
235
PyDict_Update                            -
236
PyDict_MergeFromSeq2                     -
237
PyDict_ClearFreeList                     -
238
-                                        PyMapping_HasKeyString
239
-                                        PyMapping_HasKey
240
========================== ============= =======================
241
242
243
The dict Interface Relative to OrderedDict
244
==========================================
245
246
Since OrderedDict subclasses dict, understanding the various methods and
247
attributes of dict is important for implementing OrderedDict.
248
249
Relevant Type Slots
250
-------------------
251
252
================= ================ =================== ================
253
slot              attribute        object              dict
254
================= ================ =================== ================
255
tp_dealloc        -                object_dealloc      dict_dealloc
256
tp_repr           __repr__         object_repr         dict_repr
257
sq_contains       __contains__     -                   dict_contains
258
mp_length         __len__          -                   dict_length
259
mp_subscript      __getitem__      -                   dict_subscript
260
mp_ass_subscript  __setitem__      -                   dict_ass_sub
261
                  __delitem__
262
tp_hash           __hash__         Py_HashPointer      ..._HashNotImpl
263
tp_str            __str__          object_str          -
264
tp_getattro       __getattribute__ ..._GenericGetAttr  (repeated)
265
                  __getattr__
266
tp_setattro       __setattr__      ..._GenericSetAttr  (disabled)
267
tp_doc            __doc__          (literal)           dictionary_doc
268
tp_traverse       -                -                   dict_traverse
269
tp_clear          -                -                   dict_tp_clear
270
tp_richcompare    __eq__           object_richcompare  dict_richcompare
271
                  __ne__
272
tp_weaklistoffset (__weakref__)    -                   -
273
tp_iter           __iter__         -                   dict_iter
274
tp_dictoffset     (__dict__)       -                   -
275
tp_init           __init__         object_init         dict_init
276
tp_alloc          -                PyType_GenericAlloc (repeated)
277
tp_new            __new__          object_new          dict_new
278
tp_free           -                PyObject_Free       PyObject_GC_Del
279
================= ================ =================== ================
280
281
Relevant Methods
282
----------------
283
284
================ =================== ===============
285
method           object              dict
286
================ =================== ===============
287
__reduce__       object_reduce       -
288
__sizeof__       object_sizeof       dict_sizeof
289
clear            -                   dict_clear
290
copy             -                   dict_copy
291
fromkeys         -                   dict_fromkeys
292
get              -                   dict_get
293
items            -                   dictitems_new
294
keys             -                   dictkeys_new
295
pop              -                   dict_pop
296
popitem          -                   dict_popitem
297
setdefault       -                   dict_setdefault
298
update           -                   dict_update
299
values           -                   dictvalues_new
300
================ =================== ===============
301
302
303
Pure Python OrderedDict
304
=======================
305
306
As already noted, compatibility with the pure Python OrderedDict
307
implementation is a key goal of this C implementation.  To further that
308
goal, here's a summary of how OrderedDict-specific methods are implemented
309
in collections/__init__.py.  Also provided is an indication of which
310
methods directly mutate or iterate the object, as well as any relationship
311
with the underlying linked-list.
312
313
============= ============== == ================ === === ====
314
method        impl used      ll uses             inq mut iter
315
============= ============== == ================ === === ====
316
__contains__  dict           -  -                X
317
__delitem__   OrderedDict    Y  dict.__delitem__     X
318
__eq__        OrderedDict    N  OrderedDict      ~
319
                                dict.__eq__
320
                                __iter__
321
__getitem__   dict           -  -                X
322
__iter__      OrderedDict    Y  -                        X
323
__init__      OrderedDict    N  update
324
__len__       dict           -  -                X
325
__ne__        MutableMapping -  __eq__           ~
326
__reduce__    OrderedDict    N  OrderedDict      ~
327
                                __iter__
328
                                __getitem__
329
__repr__      OrderedDict    N  __class__        ~
330
                                items
331
__reversed__  OrderedDict    Y  -                        X
332
__setitem__   OrderedDict    Y  __contains__         X
333
                                dict.__setitem__
334
__sizeof__    OrderedDict    Y  __len__          ~
335
                                __dict__
336
clear         OrderedDict    Y  dict.clear           X
337
copy          OrderedDict    N  __class__
338
                                __init__
339
fromkeys      OrderedDict    N  __setitem__
340
get           dict           -  -                ~
341
items         MutableMapping -  ItemsView                X
342
keys          MutableMapping -  KeysView                 X
343
move_to_end   OrderedDict    Y  -                    X
344
pop           OrderedDict    N  __contains__         X
345
                                __getitem__
346
                                __delitem__
347
popitem       OrderedDict    Y  dict.pop             X
348
setdefault    OrderedDict    N  __contains__         ~
349
                                __getitem__
350
                                __setitem__
351
update        MutableMapping -  __setitem__          ~
352
values        MutableMapping -  ValuesView               X
353
============= ============== == ================ === === ====
354
355
__reversed__ and move_to_end are both exclusive to OrderedDict.
356
357
358
C OrderedDict Implementation
359
============================
360
361
================= ================
362
slot              impl
363
================= ================
364
tp_dealloc        odict_dealloc
365
tp_repr           odict_repr
366
mp_ass_subscript  odict_ass_sub
367
tp_doc            odict_doc
368
tp_traverse       odict_traverse
369
tp_clear          odict_tp_clear
370
tp_richcompare    odict_richcompare
371
tp_weaklistoffset (offset)
372
tp_iter           odict_iter
373
tp_dictoffset     (offset)
374
tp_init           odict_init
375
tp_alloc          (repeated)
376
================= ================
377
378
================= ================
379
method            impl
380
================= ================
381
__reduce__        odict_reduce
382
__sizeof__        odict_sizeof
383
clear             odict_clear
384
copy              odict_copy
385
fromkeys          odict_fromkeys
386
items             odictitems_new
387
keys              odictkeys_new
388
pop               odict_pop
389
popitem           odict_popitem
390
setdefault        odict_setdefault
391
update            odict_update
392
values            odictvalues_new
393
================= ================
394
395
Inherited unchanged from object/dict:
396
397
================ ==========================
398
method           type field
399
================ ==========================
400
-                tp_free
401
__contains__     tp_as_sequence.sq_contains
402
__getattr__      tp_getattro
403
__getattribute__ tp_getattro
404
__getitem__      tp_as_mapping.mp_subscript
405
__hash__         tp_hash
406
__len__          tp_as_mapping.mp_length
407
__setattr__      tp_setattro
408
__str__          tp_str
409
get              -
410
================ ==========================
411
412
413
Other Challenges
414
================
415
416
Preserving Ordering During Iteration
417
------------------------------------
418
During iteration through an OrderedDict, it is possible that items could
419
get added, removed, or reordered.  For a linked-list implementation, as
420
with some other implementations, that situation may lead to undefined
421
behavior.  The documentation for dict mentions this in the `iter()` section
422
of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
423
In this implementation we follow dict's lead (as does the pure Python
424
implementation) for __iter__(), keys(), values(), and items().
425
426
For internal iteration (using _odict_FOREACH or not), there is still the
427
risk that not all nodes that we expect to be seen in the loop actually get
428
seen.  Thus, we are careful in each of those places to ensure that they
429
are.  This comes, of course, at a small price at each location.  The
430
solutions are much the same as those detailed in the `Situation that
431
Endangers Consistency` section above.
432
433
434
Potential Optimizations
435
=======================
436
437
* Allocate the nodes as a block via od_fast_nodes instead of individually.
438
  - Set node->key to NULL to indicate the node is not-in-use.
439
  - Add _odict_EXISTS()?
440
  - How to maintain consistency across resizes?  Existing node pointers
441
    would be invalidated after a resize, which is particularly problematic
442
    for the iterators.
443
* Use a more stream-lined implementation of update() and, likely indirectly,
444
  __init__().
445
446
*/
447
448
/* TODO
449
450
sooner:
451
- reentrancy (make sure everything is at a thread-safe state when calling
452
  into Python).  I've already checked this multiple times, but want to
453
  make one more pass.
454
- add unit tests for reentrancy?
455
456
later:
457
- make the dict views support the full set API (the pure Python impl does)
458
- implement a fuller MutableMapping API in C?
459
- move the MutableMapping implementation to abstract.c?
460
- optimize mutablemapping_update
461
- use PyObject_Malloc (small object allocator) for odict nodes?
462
- support subclasses better (e.g. in odict_richcompare)
463
464
*/
465
466
#include "Python.h"
467
#include "pycore_call.h"             // _PyObject_CallNoArgs()
468
#include "pycore_ceval.h"            // _PyEval_GetBuiltin()
469
#include "pycore_critical_section.h" //_Py_BEGIN_CRITICAL_SECTION
470
#include "pycore_dict.h"             // _Py_dict_lookup()
471
#include "pycore_object.h"           // _PyObject_GC_UNTRACK()
472
#include "pycore_pyerrors.h"         // _PyErr_ChainExceptions1()
473
#include "pycore_tuple.h"            // _PyTuple_Recycle()
474
#include <stddef.h>                  // offsetof()
475
#include "pycore_weakref.h"          // FT_CLEAR_WEAKREFS()
476
477
#include "clinic/odictobject.c.h"
478
479
/*[clinic input]
480
class OrderedDict "PyODictObject *" "&PyODict_Type"
481
[clinic start generated code]*/
482
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
483
484
485
typedef struct _odictnode _ODictNode;
486
487
/* PyODictObject */
488
struct _odictobject {
489
    PyDictObject od_dict;        /* the underlying dict */
490
    _ODictNode *od_first;        /* first node in the linked list, if any */
491
    _ODictNode *od_last;         /* last node in the linked list, if any */
492
    /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
493
     * by _odict_resize().
494
     * Note that we rely on implementation details of dict for both. */
495
    _ODictNode **od_fast_nodes;  /* hash table that mirrors the dict table */
496
    Py_ssize_t od_fast_nodes_size;
497
    void *od_resize_sentinel;    /* changes if odict should be resized */
498
499
    size_t od_state;             /* incremented whenever the LL changes */
500
    PyObject *od_inst_dict;      /* OrderedDict().__dict__ */
501
    PyObject *od_weakreflist;    /* holds weakrefs to the odict */
502
};
503
504
16.0M
#define _PyODictObject_CAST(op) _Py_CAST(PyODictObject*, (op))
505
506
507
/* ----------------------------------------------
508
 * odict keys (a simple doubly-linked list)
509
 */
510
511
struct _odictnode {
512
    PyObject *key;
513
    Py_hash_t hash;
514
    _ODictNode *next;
515
    _ODictNode *prev;
516
};
517
518
#define _odictnode_KEY(node) \
519
3.55M
    (node->key)
520
#define _odictnode_HASH(node) \
521
31.1k
    (node->hash)
522
/* borrowed reference */
523
#define _odictnode_VALUE(node, od) \
524
0
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
525
1.45M
#define _odictnode_PREV(node) (node->prev)
526
1.98M
#define _odictnode_NEXT(node) (node->next)
527
528
11.2M
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
529
8.30M
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
530
7.15M
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
531
#define _odict_FOREACH(od, node) \
532
24.2k
    for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
533
534
/* Return the index into the hash table, regardless of a valid node. */
535
static Py_ssize_t
536
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
537
3.65M
{
538
3.65M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
539
3.65M
    PyObject *value = NULL;
540
3.65M
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
3.65M
    Py_ssize_t ix;
542
#ifdef Py_GIL_DISABLED
543
    ix = _Py_dict_lookup_threadsafe((PyDictObject *)od, key, hash, &value);
544
    Py_XDECREF(value);
545
#else
546
3.65M
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
547
3.65M
#endif
548
3.65M
    if (ix == DKIX_EMPTY) {
549
0
        return keys->dk_nentries;  /* index of new entry */
550
0
    }
551
3.65M
    if (ix < 0)
552
0
        return -1;
553
    /* We use pointer arithmetic to get the entry's index into the table. */
554
3.65M
    return ix;
555
3.65M
}
556
557
3.65M
#define ONE ((Py_ssize_t)1)
558
559
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
560
static int
561
_odict_resize(PyODictObject *od)
562
22.2k
{
563
22.2k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
564
22.2k
    Py_ssize_t size, i;
565
22.2k
    _ODictNode **fast_nodes, *node;
566
567
    /* Initialize a new "fast nodes" table. */
568
22.2k
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
569
22.2k
    fast_nodes = PyMem_NEW(_ODictNode *, size);
570
22.2k
    if (fast_nodes == NULL) {
571
0
        PyErr_NoMemory();
572
0
        return -1;
573
0
    }
574
201k
    for (i = 0; i < size; i++)
575
178k
        fast_nodes[i] = NULL;
576
577
    /* Copy the current nodes into the table. */
578
22.2k
    _odict_FOREACH(od, node) {
579
560
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
580
560
                                 _odictnode_HASH(node));
581
560
        if (i < 0) {
582
0
            PyMem_Free(fast_nodes);
583
0
            return -1;
584
0
        }
585
560
        fast_nodes[i] = node;
586
560
    }
587
588
    /* Replace the old fast nodes table. */
589
22.2k
    PyMem_Free(od->od_fast_nodes);
590
22.2k
    od->od_fast_nodes = fast_nodes;
591
22.2k
    od->od_fast_nodes_size = size;
592
22.2k
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
593
22.2k
    return 0;
594
22.2k
}
595
596
/* Return the index into the hash table, regardless of a valid node. */
597
static Py_ssize_t
598
_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
599
3.65M
{
600
3.65M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
601
3.65M
    PyDictKeysObject *keys;
602
603
3.65M
    assert(key != NULL);
604
3.65M
    keys = ((PyDictObject *)od)->ma_keys;
605
606
    /* Ensure od_fast_nodes and dk_entries are in sync. */
607
3.65M
    if (od->od_resize_sentinel != keys ||
608
3.63M
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
609
22.2k
        int resize_res = _odict_resize(od);
610
22.2k
        if (resize_res < 0)
611
0
            return -1;
612
22.2k
    }
613
614
3.65M
    return _odict_get_index_raw(od, key, hash);
615
3.65M
}
616
617
/* Returns NULL if there was some error or the key was not found. */
618
static _ODictNode *
619
_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
620
4
{
621
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
622
4
    Py_ssize_t index;
623
624
4
    if (_odict_EMPTY(od))
625
0
        return NULL;
626
4
    index = _odict_get_index(od, key, hash);
627
4
    if (index < 0)
628
0
        return NULL;
629
4
    assert(od->od_fast_nodes != NULL);
630
4
    return od->od_fast_nodes[index];
631
4
}
632
633
static _ODictNode *
634
_odict_find_node(PyODictObject *od, PyObject *key)
635
3.62M
{
636
3.62M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
637
3.62M
    Py_ssize_t index;
638
3.62M
    Py_hash_t hash;
639
640
3.62M
    if (_odict_EMPTY(od))
641
0
        return NULL;
642
3.62M
    hash = PyObject_Hash(key);
643
3.62M
    if (hash == -1)
644
0
        return NULL;
645
3.62M
    index = _odict_get_index(od, key, hash);
646
3.62M
    if (index < 0)
647
0
        return NULL;
648
3.62M
    assert(od->od_fast_nodes != NULL);
649
3.62M
    return od->od_fast_nodes[index];
650
3.62M
}
651
652
static void
653
_odict_add_head(PyODictObject *od, _ODictNode *node)
654
0
{
655
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
656
0
    _odictnode_PREV(node) = NULL;
657
0
    _odictnode_NEXT(node) = _odict_FIRST(od);
658
0
    if (_odict_FIRST(od) == NULL)
659
0
        _odict_LAST(od) = node;
660
0
    else
661
0
        _odictnode_PREV(_odict_FIRST(od)) = node;
662
0
    _odict_FIRST(od) = node;
663
0
    od->od_state++;
664
0
}
665
666
static void
667
_odict_add_tail(PyODictObject *od, _ODictNode *node)
668
315k
{
669
315k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
670
315k
    _odictnode_PREV(node) = _odict_LAST(od);
671
315k
    _odictnode_NEXT(node) = NULL;
672
315k
    if (_odict_LAST(od) == NULL)
673
22.1k
        _odict_FIRST(od) = node;
674
292k
    else
675
292k
        _odictnode_NEXT(_odict_LAST(od)) = node;
676
315k
    _odict_LAST(od) = node;
677
315k
    od->od_state++;
678
315k
}
679
680
/* adds the node to the end of the list */
681
static int
682
_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
683
30.6k
{
684
30.6k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
685
30.6k
    Py_ssize_t i;
686
30.6k
    _ODictNode *node;
687
688
30.6k
    Py_INCREF(key);
689
30.6k
    i = _odict_get_index(od, key, hash);
690
30.6k
    if (i < 0) {
691
0
        if (!PyErr_Occurred())
692
0
            PyErr_SetObject(PyExc_KeyError, key);
693
0
        Py_DECREF(key);
694
0
        return -1;
695
0
    }
696
30.6k
    assert(od->od_fast_nodes != NULL);
697
30.6k
    if (od->od_fast_nodes[i] != NULL) {
698
        /* We already have a node for the key so there's no need to add one. */
699
0
        Py_DECREF(key);
700
0
        return 0;
701
0
    }
702
703
    /* must not be added yet */
704
30.6k
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
705
30.6k
    if (node == NULL) {
706
0
        Py_DECREF(key);
707
0
        PyErr_NoMemory();
708
0
        return -1;
709
0
    }
710
711
30.6k
    _odictnode_KEY(node) = key;
712
30.6k
    _odictnode_HASH(node) = hash;
713
30.6k
    _odict_add_tail(od, node);
714
30.6k
    od->od_fast_nodes[i] = node;
715
30.6k
    return 0;
716
30.6k
}
717
718
/* Putting the decref after the free causes problems. */
719
#define _odictnode_DEALLOC(node) \
720
30.5k
    do { \
721
30.5k
        Py_DECREF(_odictnode_KEY(node)); \
722
30.5k
        PyMem_Free((void *)node); \
723
30.5k
    } while (0)
724
725
/* Repeated calls on the same node are no-ops. */
726
static void
727
_odict_remove_node(PyODictObject *od, _ODictNode *node)
728
284k
{
729
284k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
730
284k
    if (_odict_FIRST(od) == node)
731
72
        _odict_FIRST(od) = _odictnode_NEXT(node);
732
284k
    else if (_odictnode_PREV(node) != NULL)
733
284k
        _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
734
735
284k
    if (_odict_LAST(od) == node)
736
0
        _odict_LAST(od) = _odictnode_PREV(node);
737
284k
    else if (_odictnode_NEXT(node) != NULL)
738
284k
        _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
739
740
284k
    _odictnode_PREV(node) = NULL;
741
284k
    _odictnode_NEXT(node) = NULL;
742
284k
    od->od_state++;
743
284k
}
744
745
/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
746
   get all sorts of problems here.  In PyODict_DelItem we make sure to
747
   call _odict_clear_node first.
748
749
   This matters in the case of colliding keys.  Suppose we add 3 keys:
750
   [A, B, C], where the hash of C collides with A and the next possible
751
   index in the hash table is occupied by B.  If we remove B then for C
752
   the dict's looknode func will give us the old index of B instead of
753
   the index we got before deleting B.  However, the node for C in
754
   od_fast_nodes is still at the old dict index of C.  Thus to be sure
755
   things don't get out of sync, we clear the node in od_fast_nodes
756
   *before* calling PyDict_DelItem.
757
758
   The same must be done for any other OrderedDict operations where
759
   we modify od_fast_nodes.
760
*/
761
static int
762
_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
763
                  Py_hash_t hash)
764
4
{
765
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
766
4
    Py_ssize_t i;
767
768
4
    assert(key != NULL);
769
4
    if (_odict_EMPTY(od)) {
770
        /* Let later code decide if this is a KeyError. */
771
0
        return 0;
772
0
    }
773
774
4
    i = _odict_get_index(od, key, hash);
775
4
    if (i < 0)
776
0
        return PyErr_Occurred() ? -1 : 0;
777
778
4
    assert(od->od_fast_nodes != NULL);
779
4
    if (node == NULL)
780
0
        node = od->od_fast_nodes[i];
781
4
    assert(node == od->od_fast_nodes[i]);
782
4
    if (node == NULL) {
783
        /* Let later code decide if this is a KeyError. */
784
0
        return 0;
785
0
    }
786
787
    // Now clear the node.
788
4
    od->od_fast_nodes[i] = NULL;
789
4
    _odict_remove_node(od, node);
790
4
    _odictnode_DEALLOC(node);
791
4
    return 0;
792
4
}
793
794
static void
795
_odict_clear_nodes(PyODictObject *od)
796
22.2k
{
797
22.2k
    _ODictNode *node, *next;
798
799
22.2k
    PyMem_Free(od->od_fast_nodes);
800
22.2k
    od->od_fast_nodes = NULL;
801
22.2k
    od->od_fast_nodes_size = 0;
802
22.2k
    od->od_resize_sentinel = NULL;
803
804
22.2k
    node = _odict_FIRST(od);
805
22.2k
    _odict_FIRST(od) = NULL;
806
22.2k
    _odict_LAST(od) = NULL;
807
52.7k
    while (node != NULL) {
808
30.5k
        next = _odictnode_NEXT(node);
809
30.5k
        _odictnode_DEALLOC(node);
810
30.5k
        node = next;
811
30.5k
    }
812
22.2k
    od->od_state++;
813
22.2k
}
814
815
/* There isn't any memory management of nodes past this point. */
816
#undef _odictnode_DEALLOC
817
818
static int
819
_odict_keys_equal(PyODictObject *a, PyODictObject *b)
820
0
{
821
0
    _ODictNode *node_a, *node_b;
822
823
    // keep operands' state to detect undesired mutations
824
0
    const size_t state_a = a->od_state;
825
0
    const size_t state_b = b->od_state;
826
827
0
    node_a = _odict_FIRST(a);
828
0
    node_b = _odict_FIRST(b);
829
0
    while (1) {
830
0
        if (node_a == NULL && node_b == NULL) {
831
            /* success: hit the end of each at the same time */
832
0
            return 1;
833
0
        }
834
0
        else if (node_a == NULL || node_b == NULL) {
835
            /* unequal length */
836
0
            return 0;
837
0
        }
838
0
        else {
839
0
            PyObject *key_a = Py_NewRef(_odictnode_KEY(node_a));
840
0
            PyObject *key_b = Py_NewRef(_odictnode_KEY(node_b));
841
0
            int res = PyObject_RichCompareBool(key_a, key_b, Py_EQ);
842
0
            Py_DECREF(key_a);
843
0
            Py_DECREF(key_b);
844
0
            if (res < 0) {
845
0
                return res;
846
0
            }
847
0
            else if (a->od_state != state_a || b->od_state != state_b) {
848
0
                PyErr_SetString(PyExc_RuntimeError,
849
0
                                "OrderedDict mutated during iteration");
850
0
                return -1;
851
0
            }
852
0
            else if (res == 0) {
853
                // This check comes after the check on the state
854
                // in order for the exception to be set correctly.
855
0
                return 0;
856
0
            }
857
858
            /* otherwise it must match, so move on to the next one */
859
0
            node_a = _odictnode_NEXT(node_a);
860
0
            node_b = _odictnode_NEXT(node_b);
861
0
        }
862
0
    }
863
0
}
864
865
866
/* ----------------------------------------------
867
 * OrderedDict mapping methods
868
 */
869
870
/* mp_ass_subscript: __setitem__() and __delitem__() */
871
872
static int
873
odict_mp_ass_sub(PyObject *od, PyObject *v, PyObject *w)
874
30.6k
{
875
30.6k
    if (w == NULL)
876
0
        return PyODict_DelItem(od, v);
877
30.6k
    else
878
30.6k
        return PyODict_SetItem(od, v, w);
879
30.6k
}
880
881
/* tp_as_mapping */
882
883
static PyMappingMethods odict_as_mapping = {
884
    0,                                  /*mp_length*/
885
    0,                                  /*mp_subscript*/
886
    odict_mp_ass_sub,                   /*mp_ass_subscript*/
887
};
888
889
890
/* ----------------------------------------------
891
 * OrderedDict number methods
892
 */
893
894
static int mutablemapping_update_arg(PyObject*, PyObject*);
895
896
static PyObject *
897
odict_or(PyObject *left, PyObject *right)
898
0
{
899
0
    PyTypeObject *type;
900
0
    PyObject *other;
901
0
    if (PyODict_Check(left)) {
902
0
        type = Py_TYPE(left);
903
0
        other = right;
904
0
    }
905
0
    else {
906
0
        type = Py_TYPE(right);
907
0
        other = left;
908
0
    }
909
0
    if (!PyAnyDict_Check(other)) {
910
0
        Py_RETURN_NOTIMPLEMENTED;
911
0
    }
912
0
    PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
913
0
    if (!new) {
914
0
        return NULL;
915
0
    }
916
0
    if (mutablemapping_update_arg(new, right) < 0) {
917
0
        Py_DECREF(new);
918
0
        return NULL;
919
0
    }
920
0
    return new;
921
0
}
922
923
static PyObject *
924
odict_inplace_or(PyObject *self, PyObject *other)
925
0
{
926
0
    if (mutablemapping_update_arg(self, other) < 0) {
927
0
        return NULL;
928
0
    }
929
0
    return Py_NewRef(self);
930
0
}
931
932
/* tp_as_number */
933
934
static PyNumberMethods odict_as_number = {
935
    .nb_or = odict_or,
936
    .nb_inplace_or = odict_inplace_or,
937
};
938
939
940
/* ----------------------------------------------
941
 * OrderedDict methods
942
 */
943
944
/* fromkeys() */
945
946
/*[clinic input]
947
@permit_long_summary
948
@classmethod
949
OrderedDict.fromkeys
950
951
    iterable as seq: object
952
    value: object = None
953
954
Create a new ordered dictionary with keys from iterable and values set to value.
955
[clinic start generated code]*/
956
957
static PyObject *
958
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
959
/*[clinic end generated code: output=c10390d452d78d6d input=1277ae0769083848]*/
960
0
{
961
0
    return _PyDict_FromKeys((PyObject *)type, seq, value);
962
0
}
963
964
/*[clinic input]
965
@critical_section
966
OrderedDict.__sizeof__ -> Py_ssize_t
967
[clinic start generated code]*/
968
969
static Py_ssize_t
970
OrderedDict___sizeof___impl(PyODictObject *self)
971
/*[clinic end generated code: output=1a8560db8cf83ac5 input=655e989ae24daa6a]*/
972
0
{
973
0
    Py_ssize_t res = _PyDict_SizeOf_LockHeld((PyDictObject *)self);
974
0
    res += sizeof(_ODictNode *) * self->od_fast_nodes_size;  /* od_fast_nodes */
975
0
    if (!_odict_EMPTY(self)) {
976
0
        res += sizeof(_ODictNode) * PyODict_SIZE(self);  /* linked-list */
977
0
    }
978
0
    return res;
979
0
}
980
981
/*[clinic input]
982
OrderedDict.__reduce__
983
    self as od: self(type="PyODictObject *")
984
985
Return state information for pickling
986
[clinic start generated code]*/
987
988
static PyObject *
989
OrderedDict___reduce___impl(PyODictObject *od)
990
/*[clinic end generated code: output=71eeb81f760a6a8e input=b0467c7ec400fe5e]*/
991
0
{
992
0
    PyObject *state, *result = NULL;
993
0
    PyObject *items_iter, *items, *args = NULL;
994
995
    /* capture any instance state */
996
0
    state = _PyObject_GetState((PyObject *)od);
997
0
    if (state == NULL)
998
0
        goto Done;
999
1000
    /* build the result */
1001
0
    args = PyTuple_New(0);
1002
0
    if (args == NULL)
1003
0
        goto Done;
1004
1005
0
    items = PyObject_CallMethodNoArgs((PyObject *)od, &_Py_ID(items));
1006
0
    if (items == NULL)
1007
0
        goto Done;
1008
1009
0
    items_iter = PyObject_GetIter(items);
1010
0
    Py_DECREF(items);
1011
0
    if (items_iter == NULL)
1012
0
        goto Done;
1013
1014
0
    result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);
1015
0
    Py_DECREF(items_iter);
1016
1017
0
Done:
1018
0
    Py_XDECREF(state);
1019
0
    Py_XDECREF(args);
1020
1021
0
    return result;
1022
0
}
1023
1024
/* setdefault(): Skips __missing__() calls. */
1025
1026
static int PyODict_SetItem_LockHeld(PyObject *self, PyObject *key, PyObject *value);
1027
1028
/*[clinic input]
1029
@critical_section
1030
OrderedDict.setdefault
1031
1032
    key: object
1033
    default: object = None
1034
1035
Insert key with a value of default if key is not in the dictionary.
1036
1037
Return the value for key if key is in the dictionary, else default.
1038
[clinic start generated code]*/
1039
1040
static PyObject *
1041
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
1042
                            PyObject *default_value)
1043
/*[clinic end generated code: output=97537cb7c28464b6 input=d7b93e92734f99b5]*/
1044
0
{
1045
0
    PyObject *result = NULL;
1046
1047
0
    if (PyODict_CheckExact(self)) {
1048
0
        result = PyODict_GetItemWithError(self, key);  /* borrowed */
1049
0
        if (result == NULL) {
1050
0
            if (PyErr_Occurred())
1051
0
                return NULL;
1052
0
            assert(_odict_find_node(self, key) == NULL);
1053
0
            if (PyODict_SetItem_LockHeld((PyObject *)self, key, default_value) >= 0) {
1054
0
                result = Py_NewRef(default_value);
1055
0
            }
1056
0
        }
1057
0
        else {
1058
0
            Py_INCREF(result);
1059
0
        }
1060
0
    }
1061
0
    else {
1062
0
        int exists = PySequence_Contains((PyObject *)self, key);
1063
0
        if (exists < 0) {
1064
0
            return NULL;
1065
0
        }
1066
0
        else if (exists) {
1067
0
            result = PyObject_GetItem((PyObject *)self, key);
1068
0
        }
1069
0
        else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1070
0
            result = Py_NewRef(default_value);
1071
0
        }
1072
0
    }
1073
1074
0
    return result;
1075
0
}
1076
1077
/* pop() */
1078
1079
static PyObject *
1080
_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1081
                   Py_hash_t hash)
1082
4
{
1083
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1084
1085
4
    PyObject *value = NULL;
1086
4
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1087
4
    if (node != NULL) {
1088
        /* Pop the node first to avoid a possible dict resize (due to
1089
           eval loop reentrancy) and complications due to hash collision
1090
           resolution. */
1091
4
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1092
4
        if (res < 0) {
1093
0
            goto done;
1094
0
        }
1095
        /* Now delete the value from the dict. */
1096
4
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1097
4
                                  &value) == 0) {
1098
0
            value = Py_NewRef(failobj);
1099
0
        }
1100
4
    }
1101
0
    else if (value == NULL && !PyErr_Occurred()) {
1102
        /* Apply the fallback value, if necessary. */
1103
0
        if (failobj) {
1104
0
            value = Py_NewRef(failobj);
1105
0
        }
1106
0
        else {
1107
0
            PyErr_SetObject(PyExc_KeyError, key);
1108
0
        }
1109
0
    }
1110
4
done:
1111
1112
4
    return value;
1113
4
}
1114
1115
/* Skips __missing__() calls. */
1116
/*[clinic input]
1117
@critical_section
1118
@permit_long_summary
1119
OrderedDict.pop
1120
1121
    key: object
1122
    default: object = NULL
1123
1124
od.pop(key[,default]) -> v, remove specified key and return the corresponding value.
1125
1126
If the key is not found, return the default if given; otherwise,
1127
raise a KeyError.
1128
[clinic start generated code]*/
1129
1130
static PyObject *
1131
OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
1132
                     PyObject *default_value)
1133
/*[clinic end generated code: output=7a6447d104e7494b input=0742e3c9bf076a72]*/
1134
4
{
1135
4
    Py_hash_t hash = PyObject_Hash(key);
1136
4
    if (hash == -1)
1137
0
        return NULL;
1138
4
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1139
4
}
1140
1141
1142
/* popitem() */
1143
1144
/*[clinic input]
1145
@critical_section
1146
OrderedDict.popitem
1147
1148
    last: bool = True
1149
1150
Remove and return a (key, value) pair from the dictionary.
1151
1152
Pairs are returned in LIFO order if last is true or FIFO order if
1153
false.
1154
[clinic start generated code]*/
1155
1156
static PyObject *
1157
OrderedDict_popitem_impl(PyODictObject *self, int last)
1158
/*[clinic end generated code: output=98e7d986690d49eb input=ebf1cc91579c9e54]*/
1159
0
{
1160
0
    PyObject *key, *value;
1161
0
    _ODictNode *node;
1162
1163
    /* pull the item */
1164
1165
0
    if (_odict_EMPTY(self)) {
1166
0
        PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1167
0
        return NULL;
1168
0
    }
1169
1170
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1171
0
    key = Py_NewRef(_odictnode_KEY(node));
1172
0
    value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1173
0
    if (value == NULL) {
1174
0
        Py_DECREF(key);
1175
0
        return NULL;
1176
0
    }
1177
0
    return _PyTuple_FromPairSteal(key, value);
1178
0
}
1179
1180
/* keys() */
1181
1182
/* MutableMapping.keys() does not have a docstring. */
1183
PyDoc_STRVAR(odict_keys__doc__, "");
1184
1185
static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1186
static int
1187
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1188
                                    Py_hash_t hash); /* forward */
1189
1190
/* values() */
1191
1192
/* MutableMapping.values() does not have a docstring. */
1193
PyDoc_STRVAR(odict_values__doc__, "");
1194
1195
static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1196
1197
/* items() */
1198
1199
/* MutableMapping.items() does not have a docstring. */
1200
PyDoc_STRVAR(odict_items__doc__, "");
1201
1202
static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1203
1204
/* update() */
1205
1206
/* MutableMapping.update() does not have a docstring. */
1207
PyDoc_STRVAR(odict_update__doc__, "");
1208
1209
/* forward */
1210
static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1211
1212
22.2k
#define odict_update mutablemapping_update
1213
1214
/*[clinic input]
1215
@critical_section
1216
OrderedDict.clear
1217
1218
Remove all items from ordered dict.
1219
[clinic start generated code]*/
1220
1221
static PyObject *
1222
OrderedDict_clear_impl(PyODictObject *self)
1223
/*[clinic end generated code: output=a1a76d1322f556c5 input=08b12322e74c535c]*/
1224
0
{
1225
0
    _PyDict_Clear_LockHeld((PyObject *)self);
1226
0
    _odict_clear_nodes(self);
1227
0
    Py_RETURN_NONE;
1228
0
}
1229
1230
/* copy() */
1231
1232
/*[clinic input]
1233
@critical_section
1234
OrderedDict.copy
1235
    self as od: self
1236
1237
A shallow copy of ordered dict.
1238
[clinic start generated code]*/
1239
1240
static PyObject *
1241
OrderedDict_copy_impl(PyObject *od)
1242
/*[clinic end generated code: output=9cdbe7394aecc576 input=e329951ae617ed48]*/
1243
0
{
1244
0
    _ODictNode *node;
1245
0
    PyObject *od_copy;
1246
1247
0
    if (PyODict_CheckExact(od))
1248
0
        od_copy = PyODict_New();
1249
0
    else
1250
0
        od_copy = _PyObject_CallNoArgs((PyObject *)Py_TYPE(od));
1251
0
    if (od_copy == NULL)
1252
0
        return NULL;
1253
1254
0
    if (PyODict_CheckExact(od)) {
1255
0
        _odict_FOREACH(od, node) {
1256
0
            PyObject *key = _odictnode_KEY(node);
1257
0
            PyObject *value = _odictnode_VALUE(node, od);
1258
0
            if (value == NULL) {
1259
0
                if (!PyErr_Occurred())
1260
0
                    PyErr_SetObject(PyExc_KeyError, key);
1261
0
                goto fail;
1262
0
            }
1263
0
            if (_PyODict_SetItem_KnownHash_LockHeld((PyObject *)od_copy, key, value,
1264
0
                                                    _odictnode_HASH(node)) != 0)
1265
0
                goto fail;
1266
0
        }
1267
0
    }
1268
0
    else {
1269
0
        _odict_FOREACH(od, node) {
1270
0
            int res;
1271
0
            PyObject *value = PyObject_GetItem((PyObject *)od,
1272
0
                                               _odictnode_KEY(node));
1273
0
            if (value == NULL)
1274
0
                goto fail;
1275
0
            res = PyObject_SetItem((PyObject *)od_copy,
1276
0
                                   _odictnode_KEY(node), value);
1277
0
            Py_DECREF(value);
1278
0
            if (res != 0)
1279
0
                goto fail;
1280
0
        }
1281
0
    }
1282
0
    return od_copy;
1283
1284
0
fail:
1285
0
    Py_DECREF(od_copy);
1286
0
    return NULL;
1287
0
}
1288
1289
/* __reversed__() */
1290
1291
PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1292
1293
286k
#define _odict_ITER_REVERSED 1
1294
485k
#define _odict_ITER_KEYS 2
1295
567k
#define _odict_ITER_VALUES 4
1296
384k
#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES)
1297
1298
/* forward */
1299
static PyObject * odictiter_new(PyODictObject *, int);
1300
1301
static PyObject *
1302
odict_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1303
0
{
1304
0
    PyODictObject *od = _PyODictObject_CAST(op);
1305
0
    return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1306
0
}
1307
1308
1309
/* move_to_end() */
1310
1311
/*[clinic input]
1312
@critical_section
1313
OrderedDict.move_to_end
1314
1315
    key: object
1316
    last: bool = True
1317
1318
Move an existing element to the end (or beginning if last is false).
1319
1320
Raise KeyError if the element does not exist.
1321
[clinic start generated code]*/
1322
1323
static PyObject *
1324
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
1325
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=09f8bc7053c0f6d4]*/
1326
3.52M
{
1327
3.52M
    _ODictNode *node;
1328
1329
3.52M
    if (_odict_EMPTY(self)) {
1330
0
        PyErr_SetObject(PyExc_KeyError, key);
1331
0
        return NULL;
1332
0
    }
1333
3.52M
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1334
3.52M
    if (key != _odictnode_KEY(node)) {
1335
3.52M
        node = _odict_find_node(self, key);
1336
3.52M
        if (node == NULL) {
1337
0
            if (!PyErr_Occurred())
1338
0
                PyErr_SetObject(PyExc_KeyError, key);
1339
0
            return NULL;
1340
0
        }
1341
3.52M
        if (last) {
1342
            /* Only move if not already the last one. */
1343
3.52M
            if (node != _odict_LAST(self)) {
1344
284k
                _odict_remove_node(self, node);
1345
284k
                _odict_add_tail(self, node);
1346
284k
            }
1347
3.52M
        }
1348
0
        else {
1349
            /* Only move if not already the first one. */
1350
0
            if (node != _odict_FIRST(self)) {
1351
0
                _odict_remove_node(self, node);
1352
0
                _odict_add_head(self, node);
1353
0
            }
1354
0
        }
1355
3.52M
    }
1356
3.52M
    Py_RETURN_NONE;
1357
3.52M
}
1358
1359
1360
/* tp_methods */
1361
1362
static PyMethodDef odict_methods[] = {
1363
1364
    /* overridden dict methods */
1365
    ORDEREDDICT_FROMKEYS_METHODDEF
1366
    ORDEREDDICT___SIZEOF___METHODDEF
1367
    ORDEREDDICT___REDUCE___METHODDEF
1368
    ORDEREDDICT_SETDEFAULT_METHODDEF
1369
    ORDEREDDICT_POP_METHODDEF
1370
    ORDEREDDICT_POPITEM_METHODDEF
1371
    {"keys",            odictkeys_new,                  METH_NOARGS,
1372
     odict_keys__doc__},
1373
    {"values",          odictvalues_new,                METH_NOARGS,
1374
     odict_values__doc__},
1375
    {"items",           odictitems_new,                 METH_NOARGS,
1376
     odict_items__doc__},
1377
    {"update",          _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,
1378
     odict_update__doc__},
1379
     ORDEREDDICT_CLEAR_METHODDEF
1380
     ORDEREDDICT_COPY_METHODDEF
1381
    /* new methods */
1382
    {"__reversed__",    odict_reversed,    METH_NOARGS,
1383
     odict_reversed__doc__},
1384
    ORDEREDDICT_MOVE_TO_END_METHODDEF
1385
1386
    {NULL,              NULL}   /* sentinel */
1387
};
1388
1389
1390
/* ----------------------------------------------
1391
 * OrderedDict members
1392
 */
1393
1394
/* tp_getset */
1395
1396
static PyGetSetDef odict_getset[] = {
1397
    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1398
    {NULL}
1399
};
1400
1401
/* ----------------------------------------------
1402
 * OrderedDict type slot methods
1403
 */
1404
1405
/* tp_dealloc */
1406
1407
static void
1408
odict_dealloc(PyObject *op)
1409
22.2k
{
1410
22.2k
    PyODictObject *self = _PyODictObject_CAST(op);
1411
22.2k
    PyObject_GC_UnTrack(self);
1412
1413
22.2k
    Py_XDECREF(self->od_inst_dict);
1414
22.2k
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1415
1416
22.2k
    _odict_clear_nodes(self);
1417
22.2k
    PyDict_Type.tp_dealloc((PyObject *)self);
1418
22.2k
}
1419
1420
/* tp_repr */
1421
1422
static PyObject *
1423
odict_repr(PyObject *op)
1424
0
{
1425
0
    PyODictObject *self = _PyODictObject_CAST(op);
1426
0
    int i;
1427
0
    PyObject *result = NULL, *dcopy = NULL;
1428
1429
0
    if (PyODict_SIZE(self) == 0)
1430
0
        return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
1431
1432
0
    i = Py_ReprEnter((PyObject *)self);
1433
0
    if (i != 0) {
1434
0
        return i > 0 ? PyUnicode_FromString("...") : NULL;
1435
0
    }
1436
1437
0
    dcopy = PyDict_Copy((PyObject *)self);
1438
0
    if (dcopy == NULL) {
1439
0
        goto Done;
1440
0
    }
1441
1442
0
    result = PyUnicode_FromFormat("%s(%R)",
1443
0
                                  _PyType_Name(Py_TYPE(self)),
1444
0
                                  dcopy);
1445
0
    Py_DECREF(dcopy);
1446
1447
0
Done:
1448
0
    Py_ReprLeave((PyObject *)self);
1449
0
    return result;
1450
0
}
1451
1452
/* tp_doc */
1453
1454
PyDoc_STRVAR(odict_doc,
1455
        "Dictionary that remembers insertion order");
1456
1457
/* tp_traverse */
1458
1459
static int
1460
odict_traverse(PyObject *op, visitproc visit, void *arg)
1461
432
{
1462
432
    PyODictObject *od = _PyODictObject_CAST(op);
1463
432
    _ODictNode *node;
1464
1465
432
    Py_VISIT(od->od_inst_dict);
1466
1.05k
    _odict_FOREACH(od, node) {
1467
1.05k
        Py_VISIT(_odictnode_KEY(node));
1468
1.05k
    }
1469
432
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1470
432
}
1471
1472
/* tp_clear */
1473
1474
static int
1475
odict_tp_clear(PyObject *op)
1476
0
{
1477
0
    PyODictObject *od = _PyODictObject_CAST(op);
1478
0
    Py_CLEAR(od->od_inst_dict);
1479
    // cannot use lock held variant as critical section is not held here
1480
0
    PyDict_Clear(op);
1481
0
    _odict_clear_nodes(od);
1482
0
    return 0;
1483
0
}
1484
1485
/* tp_richcompare */
1486
1487
static PyObject *
1488
odict_richcompare_lock_held(PyObject *v, PyObject *w, int op)
1489
0
{
1490
0
    if (!PyODict_Check(v) || !PyDict_Check(w)) {
1491
0
        Py_RETURN_NOTIMPLEMENTED;
1492
0
    }
1493
1494
0
    if (op == Py_EQ || op == Py_NE) {
1495
0
        PyObject *res, *cmp;
1496
0
        int eq;
1497
1498
0
        cmp = PyDict_Type.tp_richcompare(v, w, op);
1499
0
        if (cmp == NULL)
1500
0
            return NULL;
1501
0
        if (!PyODict_Check(w))
1502
0
            return cmp;
1503
0
        if (op == Py_EQ && cmp == Py_False)
1504
0
            return cmp;
1505
0
        if (op == Py_NE && cmp == Py_True)
1506
0
            return cmp;
1507
0
        Py_DECREF(cmp);
1508
1509
        /* Try comparing odict keys. */
1510
0
        eq = _odict_keys_equal(_PyODictObject_CAST(v), _PyODictObject_CAST(w));
1511
0
        if (eq < 0)
1512
0
            return NULL;
1513
1514
0
        res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1515
0
        return Py_NewRef(res);
1516
0
    } else {
1517
0
        Py_RETURN_NOTIMPLEMENTED;
1518
0
    }
1519
0
}
1520
1521
static PyObject *
1522
odict_richcompare(PyObject *v, PyObject *w, int op)
1523
0
{
1524
0
    PyObject *res;
1525
0
    Py_BEGIN_CRITICAL_SECTION2(v, w);
1526
0
    res = odict_richcompare_lock_held(v, w, op);
1527
0
    Py_END_CRITICAL_SECTION2();
1528
0
    return res;
1529
0
}
1530
1531
/* tp_iter */
1532
1533
static PyObject *
1534
odict_iter(PyObject *op)
1535
14.7k
{
1536
14.7k
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1537
14.7k
}
1538
1539
/* tp_init */
1540
1541
static int
1542
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1543
22.2k
{
1544
22.2k
    PyObject *res;
1545
22.2k
    Py_ssize_t len = PyObject_Length(args);
1546
1547
22.2k
    if (len == -1)
1548
0
        return -1;
1549
22.2k
    if (len > 1) {
1550
0
        const char *msg = "expected at most 1 argument, got %zd";
1551
0
        PyErr_Format(PyExc_TypeError, msg, len);
1552
0
        return -1;
1553
0
    }
1554
1555
    /* __init__() triggering update() is just the way things are! */
1556
22.2k
    res = odict_update(self, args, kwds);
1557
22.2k
    if (res == NULL) {
1558
0
        return -1;
1559
22.2k
    } else {
1560
22.2k
        Py_DECREF(res);
1561
22.2k
        return 0;
1562
22.2k
    }
1563
22.2k
}
1564
1565
/* PyODict_Type */
1566
1567
PyTypeObject PyODict_Type = {
1568
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1569
    "collections.OrderedDict",                  /* tp_name */
1570
    sizeof(PyODictObject),                      /* tp_basicsize */
1571
    0,                                          /* tp_itemsize */
1572
    odict_dealloc,                              /* tp_dealloc */
1573
    0,                                          /* tp_vectorcall_offset */
1574
    0,                                          /* tp_getattr */
1575
    0,                                          /* tp_setattr */
1576
    0,                                          /* tp_as_async */
1577
    odict_repr,                                 /* tp_repr */
1578
    &odict_as_number,                           /* tp_as_number */
1579
    0,                                          /* tp_as_sequence */
1580
    &odict_as_mapping,                          /* tp_as_mapping */
1581
    0,                                          /* tp_hash */
1582
    0,                                          /* tp_call */
1583
    0,                                          /* tp_str */
1584
    0,                                          /* tp_getattro */
1585
    0,                                          /* tp_setattro */
1586
    0,                                          /* tp_as_buffer */
1587
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1588
    odict_doc,                                  /* tp_doc */
1589
    odict_traverse,                             /* tp_traverse */
1590
    odict_tp_clear,                             /* tp_clear */
1591
    odict_richcompare,                          /* tp_richcompare */
1592
    offsetof(PyODictObject, od_weakreflist),    /* tp_weaklistoffset */
1593
    odict_iter,                                 /* tp_iter */
1594
    0,                                          /* tp_iternext */
1595
    odict_methods,                              /* tp_methods */
1596
    0,                                          /* tp_members */
1597
    odict_getset,                               /* tp_getset */
1598
    &PyDict_Type,                               /* tp_base */
1599
    0,                                          /* tp_dict */
1600
    0,                                          /* tp_descr_get */
1601
    0,                                          /* tp_descr_set */
1602
    offsetof(PyODictObject, od_inst_dict),      /* tp_dictoffset */
1603
    odict_init,                                 /* tp_init */
1604
    PyType_GenericAlloc,                        /* tp_alloc */
1605
    0,                                          /* tp_new */
1606
    0,                                          /* tp_free */
1607
};
1608
1609
1610
/* ----------------------------------------------
1611
 * the public OrderedDict API
1612
 */
1613
1614
PyObject *
1615
PyODict_New(void)
1616
0
{
1617
0
    return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
1618
0
}
1619
1620
static int
1621
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1622
                                    Py_hash_t hash)
1623
30.6k
{
1624
30.6k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1625
30.6k
    int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
1626
30.6k
    if (res == 0) {
1627
30.6k
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1628
30.6k
        if (res < 0) {
1629
            /* Revert setting the value on the dict */
1630
0
            PyObject *exc = PyErr_GetRaisedException();
1631
0
            (void) _PyDict_DelItem_KnownHash(od, key, hash);
1632
0
            _PyErr_ChainExceptions1(exc);
1633
0
        }
1634
30.6k
    }
1635
30.6k
    return res;
1636
30.6k
}
1637
1638
1639
static int
1640
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
1641
30.6k
{
1642
30.6k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1643
30.6k
    Py_hash_t hash = PyObject_Hash(key);
1644
30.6k
    if (hash == -1) {
1645
0
        return -1;
1646
0
    }
1647
30.6k
    return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
1648
30.6k
}
1649
1650
int
1651
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1652
30.6k
{
1653
30.6k
    int res;
1654
30.6k
    Py_BEGIN_CRITICAL_SECTION(od);
1655
30.6k
    res = PyODict_SetItem_LockHeld(od, key, value);
1656
30.6k
    Py_END_CRITICAL_SECTION();
1657
30.6k
    return res;
1658
30.6k
}
1659
1660
int
1661
PyODict_DelItem_LockHeld(PyObject *od, PyObject *key)
1662
0
{
1663
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1664
0
    int res;
1665
0
    Py_hash_t hash = PyObject_Hash(key);
1666
0
    if (hash == -1)
1667
0
        return -1;
1668
0
    res = _odict_clear_node(_PyODictObject_CAST(od), NULL, key, hash);
1669
0
    if (res < 0)
1670
0
        return -1;
1671
0
    return _PyDict_DelItem_KnownHash_LockHeld(od, key, hash);
1672
0
}
1673
1674
int
1675
PyODict_DelItem(PyObject *od, PyObject *key)
1676
0
{
1677
0
    int res;
1678
0
    Py_BEGIN_CRITICAL_SECTION(od);
1679
0
    res = PyODict_DelItem_LockHeld(od, key);
1680
0
    Py_END_CRITICAL_SECTION();
1681
0
    return res;
1682
0
}
1683
1684
/* -------------------------------------------
1685
 * The OrderedDict views (keys/values/items)
1686
 */
1687
1688
typedef struct {
1689
    PyObject_HEAD
1690
    int kind;
1691
    PyODictObject *di_odict;
1692
    Py_ssize_t di_size;
1693
    size_t di_state;
1694
    PyObject *di_current;
1695
    PyObject *di_result; /* reusable result tuple for iteritems */
1696
} odictiterobject;
1697
1698
static void
1699
odictiter_dealloc(PyObject *op)
1700
96.1k
{
1701
96.1k
    odictiterobject *di = (odictiterobject*)op;
1702
96.1k
    _PyObject_GC_UNTRACK(di);
1703
96.1k
    Py_XDECREF(di->di_odict);
1704
96.1k
    Py_XDECREF(di->di_current);
1705
96.1k
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1706
8
        Py_DECREF(di->di_result);
1707
8
    }
1708
96.1k
    PyObject_GC_Del(di);
1709
96.1k
}
1710
1711
static int
1712
odictiter_traverse(PyObject *op, visitproc visit, void *arg)
1713
0
{
1714
0
    odictiterobject *di = (odictiterobject*)op;
1715
0
    Py_VISIT(di->di_odict);
1716
0
    Py_VISIT(di->di_current);  /* A key could be any type, not just str. */
1717
0
    Py_VISIT(di->di_result);
1718
0
    return 0;
1719
0
}
1720
1721
/* In order to protect against modifications during iteration, we track
1722
 * the current key instead of the current node. */
1723
static PyObject *
1724
odictiter_nextkey_lock_held(odictiterobject *di)
1725
190k
{
1726
190k
    assert(di->di_odict != NULL);
1727
190k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
1728
190k
    PyObject *key = NULL;
1729
190k
    _ODictNode *node;
1730
190k
    int reversed = di->kind & _odict_ITER_REVERSED;
1731
1732
190k
    if (di->di_current == NULL)
1733
88.7k
        goto done;  /* We're already done. */
1734
1735
    /* Check for unsupported changes. */
1736
101k
    if (di->di_odict->od_state != di->di_state) {
1737
0
        PyErr_SetString(PyExc_RuntimeError,
1738
0
                        "OrderedDict mutated during iteration");
1739
0
        goto done;
1740
0
    }
1741
101k
    if (di->di_size != PyODict_SIZE(di->di_odict)) {
1742
0
        PyErr_SetString(PyExc_RuntimeError,
1743
0
                        "OrderedDict changed size during iteration");
1744
0
        di->di_size = -1; /* Make this state sticky */
1745
0
        return NULL;
1746
0
    }
1747
1748
    /* Get the key. */
1749
101k
    node = _odict_find_node(di->di_odict, di->di_current);
1750
101k
    if (node == NULL) {
1751
0
        if (!PyErr_Occurred())
1752
0
            PyErr_SetObject(PyExc_KeyError, di->di_current);
1753
        /* Must have been deleted. */
1754
0
        Py_CLEAR(di->di_current);
1755
0
        return NULL;
1756
0
    }
1757
101k
    key = di->di_current;
1758
1759
    /* Advance to the next key. */
1760
101k
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1761
101k
    if (node == NULL) {
1762
        /* Reached the end. */
1763
88.2k
        di->di_current = NULL;
1764
88.2k
    }
1765
13.0k
    else {
1766
13.0k
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1767
13.0k
    }
1768
1769
101k
    return key;
1770
1771
88.7k
done:
1772
88.7k
    Py_CLEAR(di->di_odict);
1773
88.7k
    return key;
1774
101k
}
1775
1776
1777
static PyObject *
1778
odictiter_nextkey(odictiterobject *di)
1779
190k
{
1780
190k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1781
190k
    if (di->di_odict == NULL) {
1782
8
        return NULL;
1783
8
    }
1784
190k
    PyObject *res;
1785
190k
    Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1786
190k
    res = odictiter_nextkey_lock_held(di);
1787
190k
    Py_END_CRITICAL_SECTION();
1788
190k
    return res;
1789
190k
}
1790
1791
static PyObject *
1792
odictiter_iternext_lock_held(PyObject *op)
1793
190k
{
1794
190k
    odictiterobject *di = (odictiterobject*)op;
1795
190k
    PyObject *result, *value;
1796
190k
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1797
1798
190k
    if (key == NULL)
1799
88.7k
        return NULL;
1800
1801
    /* Handle the keys case. */
1802
101k
    if (! (di->kind & _odict_ITER_VALUES)) {
1803
15.6k
        return key;
1804
15.6k
    }
1805
1806
85.6k
    if (PyDict_GetItemRef((PyObject *)di->di_odict, key, &value) != 1) {
1807
0
        if (!PyErr_Occurred())
1808
0
            PyErr_SetObject(PyExc_KeyError, key);
1809
0
        Py_DECREF(key);
1810
0
        goto error;
1811
0
    }
1812
1813
    /* Handle the values case. */
1814
85.6k
    if (!(di->kind & _odict_ITER_KEYS)) {
1815
85.6k
        Py_DECREF(key);
1816
85.6k
        return value;
1817
85.6k
    }
1818
1819
    /* Handle the items case. */
1820
24
    result = di->di_result;
1821
1822
24
    if (_PyObject_IsUniquelyReferenced(result)) {
1823
        /* not in use so we can reuse it
1824
         * (the common case during iteration) */
1825
24
        Py_INCREF(result);
1826
24
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1827
24
        Py_DECREF(PyTuple_GET_ITEM(result, 1));  /* borrowed */
1828
        // bpo-42536: The GC may have untracked this result tuple. Since we're
1829
        // recycling it, make sure it's tracked again:
1830
24
        _PyTuple_Recycle(result);
1831
24
        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1832
24
        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1833
24
    }
1834
0
    else {
1835
0
        result = _PyTuple_FromPairSteal(key, value);
1836
0
        if (result == NULL) {
1837
0
            goto error;
1838
0
        }
1839
0
    }
1840
1841
24
    return result;
1842
1843
0
error:
1844
0
    Py_CLEAR(di->di_current);
1845
0
    Py_CLEAR(di->di_odict);
1846
0
    return NULL;
1847
24
}
1848
1849
static PyObject *
1850
odictiter_iternext(PyObject *op)
1851
190k
{
1852
190k
    PyObject *res;
1853
190k
    Py_BEGIN_CRITICAL_SECTION(op);
1854
190k
    res = odictiter_iternext_lock_held(op);
1855
190k
    Py_END_CRITICAL_SECTION();
1856
190k
    return res;
1857
190k
}
1858
1859
1860
/* No need for tp_clear because odictiterobject is not mutable. */
1861
1862
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1863
1864
static PyObject *
1865
odictiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1866
0
{
1867
0
    odictiterobject *di = (odictiterobject*)op;
1868
1869
    /* copy the iterator state */
1870
0
    odictiterobject tmp = *di;
1871
0
    Py_XINCREF(tmp.di_odict);
1872
0
    Py_XINCREF(tmp.di_current);
1873
1874
    /* iterate the temporary into a list */
1875
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1876
0
    Py_XDECREF(tmp.di_odict);
1877
0
    Py_XDECREF(tmp.di_current);
1878
0
    if (list == NULL) {
1879
0
        return NULL;
1880
0
    }
1881
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1882
0
}
1883
1884
static PyMethodDef odictiter_methods[] = {
1885
    {"__reduce__", odictiter_reduce, METH_NOARGS, reduce_doc},
1886
    {NULL,              NULL}           /* sentinel */
1887
};
1888
1889
PyTypeObject PyODictIter_Type = {
1890
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1891
    "odict_iterator",                         /* tp_name */
1892
    sizeof(odictiterobject),                  /* tp_basicsize */
1893
    0,                                        /* tp_itemsize */
1894
    /* methods */
1895
    odictiter_dealloc,                        /* tp_dealloc */
1896
    0,                                        /* tp_vectorcall_offset */
1897
    0,                                        /* tp_getattr */
1898
    0,                                        /* tp_setattr */
1899
    0,                                        /* tp_as_async */
1900
    0,                                        /* tp_repr */
1901
    0,                                        /* tp_as_number */
1902
    0,                                        /* tp_as_sequence */
1903
    0,                                        /* tp_as_mapping */
1904
    0,                                        /* tp_hash */
1905
    0,                                        /* tp_call */
1906
    0,                                        /* tp_str */
1907
    PyObject_GenericGetAttr,                  /* tp_getattro */
1908
    0,                                        /* tp_setattro */
1909
    0,                                        /* tp_as_buffer */
1910
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1911
    0,                                        /* tp_doc */
1912
    odictiter_traverse,                       /* tp_traverse */
1913
    0,                                        /* tp_clear */
1914
    0,                                        /* tp_richcompare */
1915
    0,                                        /* tp_weaklistoffset */
1916
    PyObject_SelfIter,                        /* tp_iter */
1917
    odictiter_iternext,                       /* tp_iternext */
1918
    odictiter_methods,                        /* tp_methods */
1919
    0,
1920
};
1921
1922
static PyObject *
1923
odictiter_new(PyODictObject *od, int kind)
1924
96.1k
{
1925
96.1k
    odictiterobject *di;
1926
96.1k
    _ODictNode *node;
1927
96.1k
    int reversed = kind & _odict_ITER_REVERSED;
1928
1929
96.1k
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1930
96.1k
    if (di == NULL)
1931
0
        return NULL;
1932
1933
96.1k
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1934
8
        di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None);
1935
8
        if (di->di_result == NULL) {
1936
0
            Py_DECREF(di);
1937
0
            return NULL;
1938
0
        }
1939
8
    }
1940
96.1k
    else {
1941
96.1k
        di->di_result = NULL;
1942
96.1k
    }
1943
1944
96.1k
    di->kind = kind;
1945
96.1k
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1946
96.1k
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1947
96.1k
    di->di_size = PyODict_SIZE(od);
1948
96.1k
    di->di_state = od->od_state;
1949
96.1k
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1950
1951
96.1k
    _PyObject_GC_TRACK(di);
1952
96.1k
    return (PyObject *)di;
1953
96.1k
}
1954
1955
/* keys() */
1956
1957
static PyObject *
1958
odictkeys_iter(PyObject *op)
1959
0
{
1960
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1961
0
    if (dv->dv_dict == NULL) {
1962
0
        Py_RETURN_NONE;
1963
0
    }
1964
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1965
0
            _odict_ITER_KEYS);
1966
0
}
1967
1968
static PyObject *
1969
odictkeys_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1970
0
{
1971
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1972
0
    if (dv->dv_dict == NULL) {
1973
0
        Py_RETURN_NONE;
1974
0
    }
1975
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1976
0
            _odict_ITER_KEYS|_odict_ITER_REVERSED);
1977
0
}
1978
1979
static PyMethodDef odictkeys_methods[] = {
1980
    {"__reversed__", odictkeys_reversed, METH_NOARGS, NULL},
1981
    {NULL,          NULL}           /* sentinel */
1982
};
1983
1984
PyTypeObject PyODictKeys_Type = {
1985
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1986
    "odict_keys",                             /* tp_name */
1987
    0,                                        /* tp_basicsize */
1988
    0,                                        /* tp_itemsize */
1989
    0,                                        /* tp_dealloc */
1990
    0,                                        /* tp_vectorcall_offset */
1991
    0,                                        /* tp_getattr */
1992
    0,                                        /* tp_setattr */
1993
    0,                                        /* tp_as_async */
1994
    0,                                        /* tp_repr */
1995
    0,                                        /* tp_as_number */
1996
    0,                                        /* tp_as_sequence */
1997
    0,                                        /* tp_as_mapping */
1998
    0,                                        /* tp_hash */
1999
    0,                                        /* tp_call */
2000
    0,                                        /* tp_str */
2001
    0,                                        /* tp_getattro */
2002
    0,                                        /* tp_setattro */
2003
    0,                                        /* tp_as_buffer */
2004
    0,                                        /* tp_flags */
2005
    0,                                        /* tp_doc */
2006
    0,                                        /* tp_traverse */
2007
    0,                                        /* tp_clear */
2008
    0,                                        /* tp_richcompare */
2009
    0,                                        /* tp_weaklistoffset */
2010
    odictkeys_iter,                           /* tp_iter */
2011
    0,                                        /* tp_iternext */
2012
    odictkeys_methods,                        /* tp_methods */
2013
    0,                                        /* tp_members */
2014
    0,                                        /* tp_getset */
2015
    &PyDictKeys_Type,                         /* tp_base */
2016
};
2017
2018
static PyObject *
2019
odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2020
0
{
2021
0
    return _PyDictView_New(od, &PyODictKeys_Type);
2022
0
}
2023
2024
/* items() */
2025
2026
static PyObject *
2027
odictitems_iter(PyObject *op)
2028
8
{
2029
8
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2030
8
    if (dv->dv_dict == NULL) {
2031
0
        Py_RETURN_NONE;
2032
0
    }
2033
8
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2034
8
            _odict_ITER_KEYS|_odict_ITER_VALUES);
2035
8
}
2036
2037
static PyObject *
2038
odictitems_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2039
0
{
2040
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2041
0
    if (dv->dv_dict == NULL) {
2042
0
        Py_RETURN_NONE;
2043
0
    }
2044
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2045
0
            _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2046
0
}
2047
2048
static PyMethodDef odictitems_methods[] = {
2049
    {"__reversed__", odictitems_reversed, METH_NOARGS, NULL},
2050
    {NULL,          NULL}           /* sentinel */
2051
};
2052
2053
PyTypeObject PyODictItems_Type = {
2054
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2055
    "odict_items",                            /* tp_name */
2056
    0,                                        /* tp_basicsize */
2057
    0,                                        /* tp_itemsize */
2058
    0,                                        /* tp_dealloc */
2059
    0,                                        /* tp_vectorcall_offset */
2060
    0,                                        /* tp_getattr */
2061
    0,                                        /* tp_setattr */
2062
    0,                                        /* tp_as_async */
2063
    0,                                        /* tp_repr */
2064
    0,                                        /* tp_as_number */
2065
    0,                                        /* tp_as_sequence */
2066
    0,                                        /* tp_as_mapping */
2067
    0,                                        /* tp_hash */
2068
    0,                                        /* tp_call */
2069
    0,                                        /* tp_str */
2070
    0,                                        /* tp_getattro */
2071
    0,                                        /* tp_setattro */
2072
    0,                                        /* tp_as_buffer */
2073
    0,                                        /* tp_flags */
2074
    0,                                        /* tp_doc */
2075
    0,                                        /* tp_traverse */
2076
    0,                                        /* tp_clear */
2077
    0,                                        /* tp_richcompare */
2078
    0,                                        /* tp_weaklistoffset */
2079
    odictitems_iter,                          /* tp_iter */
2080
    0,                                        /* tp_iternext */
2081
    odictitems_methods,                       /* tp_methods */
2082
    0,                                        /* tp_members */
2083
    0,                                        /* tp_getset */
2084
    &PyDictItems_Type,                        /* tp_base */
2085
};
2086
2087
static PyObject *
2088
odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2089
8
{
2090
8
    return _PyDictView_New(od, &PyODictItems_Type);
2091
8
}
2092
2093
/* values() */
2094
2095
static PyObject *
2096
odictvalues_iter(PyObject *op)
2097
81.3k
{
2098
81.3k
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2099
81.3k
    if (dv->dv_dict == NULL) {
2100
0
        Py_RETURN_NONE;
2101
0
    }
2102
81.3k
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2103
81.3k
            _odict_ITER_VALUES);
2104
81.3k
}
2105
2106
static PyObject *
2107
odictvalues_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2108
0
{
2109
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2110
0
    if (dv->dv_dict == NULL) {
2111
0
        Py_RETURN_NONE;
2112
0
    }
2113
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2114
0
            _odict_ITER_VALUES|_odict_ITER_REVERSED);
2115
0
}
2116
2117
static PyMethodDef odictvalues_methods[] = {
2118
    {"__reversed__", odictvalues_reversed, METH_NOARGS, NULL},
2119
    {NULL,          NULL}           /* sentinel */
2120
};
2121
2122
PyTypeObject PyODictValues_Type = {
2123
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2124
    "odict_values",                           /* tp_name */
2125
    0,                                        /* tp_basicsize */
2126
    0,                                        /* tp_itemsize */
2127
    0,                                        /* tp_dealloc */
2128
    0,                                        /* tp_vectorcall_offset */
2129
    0,                                        /* tp_getattr */
2130
    0,                                        /* tp_setattr */
2131
    0,                                        /* tp_as_async */
2132
    0,                                        /* tp_repr */
2133
    0,                                        /* tp_as_number */
2134
    0,                                        /* tp_as_sequence */
2135
    0,                                        /* tp_as_mapping */
2136
    0,                                        /* tp_hash */
2137
    0,                                        /* tp_call */
2138
    0,                                        /* tp_str */
2139
    0,                                        /* tp_getattro */
2140
    0,                                        /* tp_setattro */
2141
    0,                                        /* tp_as_buffer */
2142
    0,                                        /* tp_flags */
2143
    0,                                        /* tp_doc */
2144
    0,                                        /* tp_traverse */
2145
    0,                                        /* tp_clear */
2146
    0,                                        /* tp_richcompare */
2147
    0,                                        /* tp_weaklistoffset */
2148
    odictvalues_iter,                         /* tp_iter */
2149
    0,                                        /* tp_iternext */
2150
    odictvalues_methods,                      /* tp_methods */
2151
    0,                                        /* tp_members */
2152
    0,                                        /* tp_getset */
2153
    &PyDictValues_Type,                       /* tp_base */
2154
};
2155
2156
static PyObject *
2157
odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2158
81.3k
{
2159
81.3k
    return _PyDictView_New(od, &PyODictValues_Type);
2160
81.3k
}
2161
2162
2163
/* ----------------------------------------------
2164
   MutableMapping implementations
2165
2166
Mapping:
2167
2168
============ ===========
2169
method       uses
2170
============ ===========
2171
__contains__ __getitem__
2172
__eq__       items
2173
__getitem__  +
2174
__iter__     +
2175
__len__      +
2176
__ne__       __eq__
2177
get          __getitem__
2178
items        ItemsView
2179
keys         KeysView
2180
values       ValuesView
2181
============ ===========
2182
2183
ItemsView uses __len__, __iter__, and __getitem__.
2184
KeysView uses __len__, __iter__, and __contains__.
2185
ValuesView uses __len__, __iter__, and __getitem__.
2186
2187
MutableMapping:
2188
2189
============ ===========
2190
method       uses
2191
============ ===========
2192
__delitem__  +
2193
__setitem__  +
2194
clear        popitem
2195
pop          __getitem__
2196
             __delitem__
2197
popitem      __iter__
2198
             _getitem__
2199
             __delitem__
2200
setdefault   __getitem__
2201
             __setitem__
2202
update       __setitem__
2203
============ ===========
2204
*/
2205
2206
static int
2207
mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2208
14.8k
{
2209
14.8k
    PyObject *pair, *iterator, *unexpected;
2210
14.8k
    int res = 0;
2211
2212
14.8k
    iterator = PyObject_GetIter(pairs);
2213
14.8k
    if (iterator == NULL)
2214
0
        return -1;
2215
14.8k
    PyErr_Clear();
2216
2217
37.5k
    while ((pair = PyIter_Next(iterator)) != NULL) {
2218
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2219
22.7k
        PyObject *key = NULL, *value = NULL;
2220
22.7k
        PyObject *pair_iterator = PyObject_GetIter(pair);
2221
22.7k
        if (pair_iterator == NULL)
2222
0
            goto Done;
2223
2224
22.7k
        key = PyIter_Next(pair_iterator);
2225
22.7k
        if (key == NULL) {
2226
0
            if (!PyErr_Occurred())
2227
0
                PyErr_SetString(PyExc_ValueError,
2228
0
                                "need more than 0 values to unpack");
2229
0
            goto Done;
2230
0
        }
2231
2232
22.7k
        value = PyIter_Next(pair_iterator);
2233
22.7k
        if (value == NULL) {
2234
0
            if (!PyErr_Occurred())
2235
0
                PyErr_SetString(PyExc_ValueError,
2236
0
                                "need more than 1 value to unpack");
2237
0
            goto Done;
2238
0
        }
2239
2240
22.7k
        unexpected = PyIter_Next(pair_iterator);
2241
22.7k
        if (unexpected != NULL) {
2242
0
            Py_DECREF(unexpected);
2243
0
            PyErr_SetString(PyExc_ValueError,
2244
0
                            "too many values to unpack (expected 2)");
2245
0
            goto Done;
2246
0
        }
2247
22.7k
        else if (PyErr_Occurred())
2248
0
            goto Done;
2249
2250
22.7k
        res = PyObject_SetItem(self, key, value);
2251
2252
22.7k
Done:
2253
22.7k
        Py_DECREF(pair);
2254
22.7k
        Py_XDECREF(pair_iterator);
2255
22.7k
        Py_XDECREF(key);
2256
22.7k
        Py_XDECREF(value);
2257
22.7k
        if (PyErr_Occurred())
2258
0
            break;
2259
22.7k
    }
2260
14.8k
    Py_DECREF(iterator);
2261
2262
14.8k
    if (res < 0 || PyErr_Occurred() != NULL)
2263
0
        return -1;
2264
14.8k
    else
2265
14.8k
        return 0;
2266
14.8k
}
2267
2268
static int
2269
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2270
14.8k
{
2271
14.8k
    int res = 0;
2272
14.8k
    if (PyAnyDict_CheckExact(arg)) {
2273
0
        PyObject *items = PyDict_Items(arg);
2274
0
        if (items == NULL) {
2275
0
            return -1;
2276
0
        }
2277
0
        res = mutablemapping_add_pairs(self, items);
2278
0
        Py_DECREF(items);
2279
0
        return res;
2280
0
    }
2281
14.8k
    PyObject *func;
2282
14.8k
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2283
0
        return -1;
2284
0
    }
2285
14.8k
    if (func != NULL) {
2286
0
        PyObject *keys = _PyObject_CallNoArgs(func);
2287
0
        Py_DECREF(func);
2288
0
        if (keys == NULL) {
2289
0
            return -1;
2290
0
        }
2291
0
        PyObject *iterator = PyObject_GetIter(keys);
2292
0
        Py_DECREF(keys);
2293
0
        if (iterator == NULL) {
2294
0
            return -1;
2295
0
        }
2296
0
        PyObject *key;
2297
0
        while (res == 0 && (key = PyIter_Next(iterator))) {
2298
0
            PyObject *value = PyObject_GetItem(arg, key);
2299
0
            if (value != NULL) {
2300
0
                res = PyObject_SetItem(self, key, value);
2301
0
                Py_DECREF(value);
2302
0
            }
2303
0
            else {
2304
0
                res = -1;
2305
0
            }
2306
0
            Py_DECREF(key);
2307
0
        }
2308
0
        Py_DECREF(iterator);
2309
0
        if (res != 0 || PyErr_Occurred()) {
2310
0
            return -1;
2311
0
        }
2312
0
        return 0;
2313
0
    }
2314
14.8k
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2315
0
        return -1;
2316
0
    }
2317
14.8k
    if (func != NULL) {
2318
0
        PyObject *items = _PyObject_CallNoArgs(func);
2319
0
        Py_DECREF(func);
2320
0
        if (items == NULL) {
2321
0
            return -1;
2322
0
        }
2323
0
        res = mutablemapping_add_pairs(self, items);
2324
0
        Py_DECREF(items);
2325
0
        return res;
2326
0
    }
2327
14.8k
    res = mutablemapping_add_pairs(self, arg);
2328
14.8k
    return res;
2329
14.8k
}
2330
2331
static PyObject *
2332
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2333
22.2k
{
2334
22.2k
    int res;
2335
    /* first handle args, if any */
2336
22.2k
    assert(args == NULL || PyTuple_Check(args));
2337
22.2k
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2338
22.2k
    if (len > 1) {
2339
0
        const char *msg = "update() takes at most 1 positional argument (%zd given)";
2340
0
        PyErr_Format(PyExc_TypeError, msg, len);
2341
0
        return NULL;
2342
0
    }
2343
2344
22.2k
    if (len) {
2345
14.8k
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2346
14.8k
        assert(other != NULL);
2347
14.8k
        Py_INCREF(other);
2348
14.8k
        res = mutablemapping_update_arg(self, other);
2349
14.8k
        Py_DECREF(other);
2350
14.8k
        if (res < 0) {
2351
0
            return NULL;
2352
0
        }
2353
14.8k
    }
2354
2355
    /* now handle kwargs */
2356
22.2k
    assert(kwargs == NULL || PyDict_Check(kwargs));
2357
22.2k
    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2358
0
        PyObject *items = PyDict_Items(kwargs);
2359
0
        if (items == NULL)
2360
0
            return NULL;
2361
0
        res = mutablemapping_add_pairs(self, items);
2362
0
        Py_DECREF(items);
2363
0
        if (res == -1)
2364
0
            return NULL;
2365
0
    }
2366
2367
22.2k
    Py_RETURN_NONE;
2368
22.2k
}