Coverage Report

Created: 2026-02-26 06:53

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
21.0k
#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
2.72k
    (node->key)
520
#define _odictnode_HASH(node) \
521
2.55k
    (node->hash)
522
/* borrowed reference */
523
#define _odictnode_VALUE(node, od) \
524
0
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
525
1.94k
#define _odictnode_PREV(node) (node->prev)
526
16.2k
#define _odictnode_NEXT(node) (node->next)
527
528
12.3k
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
529
6.47k
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
530
5.60k
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
531
#define _odict_FOREACH(od, node) \
532
1.41k
    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
7.98k
{
538
7.98k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
539
7.98k
    PyObject *value = NULL;
540
7.98k
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
7.98k
    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
7.98k
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
547
7.98k
#endif
548
7.98k
    if (ix == DKIX_EMPTY) {
549
0
        return keys->dk_nentries;  /* index of new entry */
550
0
    }
551
7.98k
    if (ix < 0)
552
0
        return -1;
553
    /* We use pointer arithmetic to get the entry's index into the table. */
554
7.98k
    return ix;
555
7.98k
}
556
557
7.24k
#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
652
{
563
652
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
564
652
    Py_ssize_t size, i;
565
652
    _ODictNode **fast_nodes, *node;
566
567
    /* Initialize a new "fast nodes" table. */
568
652
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
569
652
    fast_nodes = PyMem_NEW(_ODictNode *, size);
570
652
    if (fast_nodes == NULL) {
571
0
        PyErr_NoMemory();
572
0
        return -1;
573
0
    }
574
7.34k
    for (i = 0; i < size; i++)
575
6.68k
        fast_nodes[i] = NULL;
576
577
    /* Copy the current nodes into the table. */
578
740
    _odict_FOREACH(od, node) {
579
740
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
580
740
                                 _odictnode_HASH(node));
581
740
        if (i < 0) {
582
0
            PyMem_Free(fast_nodes);
583
0
            return -1;
584
0
        }
585
740
        fast_nodes[i] = node;
586
740
    }
587
588
    /* Replace the old fast nodes table. */
589
652
    PyMem_Free(od->od_fast_nodes);
590
652
    od->od_fast_nodes = fast_nodes;
591
652
    od->od_fast_nodes_size = size;
592
652
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
593
652
    return 0;
594
652
}
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
7.24k
{
600
7.24k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
601
7.24k
    PyDictKeysObject *keys;
602
603
7.24k
    assert(key != NULL);
604
7.24k
    keys = ((PyDictObject *)od)->ma_keys;
605
606
    /* Ensure od_fast_nodes and dk_entries are in sync. */
607
7.24k
    if (od->od_resize_sentinel != keys ||
608
6.59k
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
609
652
        int resize_res = _odict_resize(od);
610
652
        if (resize_res < 0)
611
0
            return -1;
612
652
    }
613
614
7.24k
    return _odict_get_index_raw(od, key, hash);
615
7.24k
}
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
2
{
621
2
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
622
2
    Py_ssize_t index;
623
624
2
    if (_odict_EMPTY(od))
625
0
        return NULL;
626
2
    index = _odict_get_index(od, key, hash);
627
2
    if (index < 0)
628
0
        return NULL;
629
2
    assert(od->od_fast_nodes != NULL);
630
2
    return od->od_fast_nodes[index];
631
2
}
632
633
static _ODictNode *
634
_odict_find_node(PyODictObject *od, PyObject *key)
635
5.42k
{
636
5.42k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
637
5.42k
    Py_ssize_t index;
638
5.42k
    Py_hash_t hash;
639
640
5.42k
    if (_odict_EMPTY(od))
641
0
        return NULL;
642
5.42k
    hash = PyObject_Hash(key);
643
5.42k
    if (hash == -1)
644
0
        return NULL;
645
5.42k
    index = _odict_get_index(od, key, hash);
646
5.42k
    if (index < 0)
647
0
        return NULL;
648
5.42k
    assert(od->od_fast_nodes != NULL);
649
5.42k
    return od->od_fast_nodes[index];
650
5.42k
}
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
1.84k
{
669
1.84k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
670
1.84k
    _odictnode_PREV(node) = _odict_LAST(od);
671
1.84k
    _odictnode_NEXT(node) = NULL;
672
1.84k
    if (_odict_LAST(od) == NULL)
673
540
        _odict_FIRST(od) = node;
674
1.30k
    else
675
1.30k
        _odictnode_NEXT(_odict_LAST(od)) = node;
676
1.84k
    _odict_LAST(od) = node;
677
1.84k
    od->od_state++;
678
1.84k
}
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
1.81k
{
684
1.81k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
685
1.81k
    Py_ssize_t i;
686
1.81k
    _ODictNode *node;
687
688
1.81k
    Py_INCREF(key);
689
1.81k
    i = _odict_get_index(od, key, hash);
690
1.81k
    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
1.81k
    assert(od->od_fast_nodes != NULL);
697
1.81k
    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
1.81k
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
705
1.81k
    if (node == NULL) {
706
0
        Py_DECREF(key);
707
0
        PyErr_NoMemory();
708
0
        return -1;
709
0
    }
710
711
1.81k
    _odictnode_KEY(node) = key;
712
1.81k
    _odictnode_HASH(node) = hash;
713
1.81k
    _odict_add_tail(od, node);
714
1.81k
    od->od_fast_nodes[i] = node;
715
1.81k
    return 0;
716
1.81k
}
717
718
/* Putting the decref after the free causes problems. */
719
#define _odictnode_DEALLOC(node) \
720
1.76k
    do { \
721
1.76k
        Py_DECREF(_odictnode_KEY(node)); \
722
1.76k
        PyMem_Free((void *)node); \
723
1.76k
    } 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
32
{
729
32
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
730
32
    if (_odict_FIRST(od) == node)
731
32
        _odict_FIRST(od) = _odictnode_NEXT(node);
732
0
    else if (_odictnode_PREV(node) != NULL)
733
0
        _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
734
735
32
    if (_odict_LAST(od) == node)
736
0
        _odict_LAST(od) = _odictnode_PREV(node);
737
32
    else if (_odictnode_NEXT(node) != NULL)
738
32
        _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
739
740
32
    _odictnode_PREV(node) = NULL;
741
32
    _odictnode_NEXT(node) = NULL;
742
32
    od->od_state++;
743
32
}
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
2
{
765
2
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
766
2
    Py_ssize_t i;
767
768
2
    assert(key != NULL);
769
2
    if (_odict_EMPTY(od)) {
770
        /* Let later code decide if this is a KeyError. */
771
0
        return 0;
772
0
    }
773
774
2
    i = _odict_get_index(od, key, hash);
775
2
    if (i < 0)
776
0
        return PyErr_Occurred() ? -1 : 0;
777
778
2
    assert(od->od_fast_nodes != NULL);
779
2
    if (node == NULL)
780
0
        node = od->od_fast_nodes[i];
781
2
    assert(node == od->od_fast_nodes[i]);
782
2
    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
2
    od->od_fast_nodes[i] = NULL;
789
2
    _odict_remove_node(od, node);
790
2
    _odictnode_DEALLOC(node);
791
2
    return 0;
792
2
}
793
794
static void
795
_odict_clear_nodes(PyODictObject *od)
796
564
{
797
564
    _ODictNode *node, *next;
798
799
564
    PyMem_Free(od->od_fast_nodes);
800
564
    od->od_fast_nodes = NULL;
801
564
    od->od_fast_nodes_size = 0;
802
564
    od->od_resize_sentinel = NULL;
803
804
564
    node = _odict_FIRST(od);
805
564
    _odict_FIRST(od) = NULL;
806
564
    _odict_LAST(od) = NULL;
807
2.32k
    while (node != NULL) {
808
1.76k
        next = _odictnode_NEXT(node);
809
1.76k
        _odictnode_DEALLOC(node);
810
1.76k
        node = next;
811
1.76k
    }
812
564
    od->od_state++;
813
564
}
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
1.81k
{
875
1.81k
    if (w == NULL)
876
0
        return PyODict_DelItem(od, v);
877
1.81k
    else
878
1.81k
        return PyODict_SetItem(od, v, w);
879
1.81k
}
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 (!PyDict_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
2
{
1083
2
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1084
1085
2
    PyObject *value = NULL;
1086
2
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1087
2
    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
2
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1092
2
        if (res < 0) {
1093
0
            goto done;
1094
0
        }
1095
        /* Now delete the value from the dict. */
1096
2
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1097
2
                                  &value) == 0) {
1098
0
            value = Py_NewRef(failobj);
1099
0
        }
1100
2
    }
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
2
done:
1111
1112
2
    return value;
1113
2
}
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
2
{
1135
2
    Py_hash_t hash = PyObject_Hash(key);
1136
2
    if (hash == -1)
1137
0
        return NULL;
1138
2
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1139
2
}
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 false.
1153
[clinic start generated code]*/
1154
1155
static PyObject *
1156
OrderedDict_popitem_impl(PyODictObject *self, int last)
1157
/*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7]*/
1158
0
{
1159
0
    PyObject *key, *value, *item = NULL;
1160
0
    _ODictNode *node;
1161
1162
    /* pull the item */
1163
1164
0
    if (_odict_EMPTY(self)) {
1165
0
        PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1166
0
        return NULL;
1167
0
    }
1168
1169
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1170
0
    key = Py_NewRef(_odictnode_KEY(node));
1171
0
    value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1172
0
    if (value == NULL)
1173
0
        return NULL;
1174
0
    item = PyTuple_Pack(2, key, value);
1175
0
    Py_DECREF(key);
1176
0
    Py_DECREF(value);
1177
0
    return item;
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
592
#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
9.29k
#define _odict_ITER_REVERSED 1
1294
13.2k
#define _odict_ITER_KEYS 2
1295
15.4k
#define _odict_ITER_VALUES 4
1296
8.36k
#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
173
{
1327
173
    _ODictNode *node;
1328
1329
173
    if (_odict_EMPTY(self)) {
1330
0
        PyErr_SetObject(PyExc_KeyError, key);
1331
0
        return NULL;
1332
0
    }
1333
173
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1334
173
    if (key != _odictnode_KEY(node)) {
1335
165
        node = _odict_find_node(self, key);
1336
165
        if (node == NULL) {
1337
0
            if (!PyErr_Occurred())
1338
0
                PyErr_SetObject(PyExc_KeyError, key);
1339
0
            return NULL;
1340
0
        }
1341
165
        if (last) {
1342
            /* Only move if not already the last one. */
1343
165
            if (node != _odict_LAST(self)) {
1344
30
                _odict_remove_node(self, node);
1345
30
                _odict_add_tail(self, node);
1346
30
            }
1347
165
        }
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
165
    }
1356
173
    Py_RETURN_NONE;
1357
173
}
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
564
{
1410
564
    PyODictObject *self = _PyODictObject_CAST(op);
1411
564
    PyObject_GC_UnTrack(self);
1412
1413
564
    Py_XDECREF(self->od_inst_dict);
1414
564
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1415
1416
564
    _odict_clear_nodes(self);
1417
564
    PyDict_Type.tp_dealloc((PyObject *)self);
1418
564
}
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
6
{
1462
6
    PyODictObject *od = _PyODictObject_CAST(op);
1463
6
    _ODictNode *node;
1464
1465
6
    Py_VISIT(od->od_inst_dict);
1466
12
    _odict_FOREACH(od, node) {
1467
12
        Py_VISIT(_odictnode_KEY(node));
1468
12
    }
1469
6
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1470
6
}
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
304
{
1536
304
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1537
304
}
1538
1539
/* tp_init */
1540
1541
static int
1542
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1543
592
{
1544
592
    PyObject *res;
1545
592
    Py_ssize_t len = PyObject_Length(args);
1546
1547
592
    if (len == -1)
1548
0
        return -1;
1549
592
    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
592
    res = odict_update(self, args, kwds);
1557
592
    if (res == NULL) {
1558
0
        return -1;
1559
592
    } else {
1560
592
        Py_DECREF(res);
1561
592
        return 0;
1562
592
    }
1563
592
}
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
1.81k
{
1624
1.81k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1625
1.81k
    int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
1626
1.81k
    if (res == 0) {
1627
1.81k
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1628
1.81k
        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
1.81k
    }
1635
1.81k
    return res;
1636
1.81k
}
1637
1638
1639
static int
1640
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
1641
1.81k
{
1642
1.81k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1643
1.81k
    Py_hash_t hash = PyObject_Hash(key);
1644
1.81k
    if (hash == -1) {
1645
0
        return -1;
1646
0
    }
1647
1.81k
    return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
1648
1.81k
}
1649
1650
int
1651
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1652
1.81k
{
1653
1.81k
    int res;
1654
1.81k
    Py_BEGIN_CRITICAL_SECTION(od);
1655
1.81k
    res = PyODict_SetItem_LockHeld(od, key, value);
1656
1.81k
    Py_END_CRITICAL_SECTION();
1657
1.81k
    return res;
1658
1.81k
}
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
2.09k
{
1701
2.09k
    odictiterobject *di = (odictiterobject*)op;
1702
2.09k
    _PyObject_GC_UNTRACK(di);
1703
2.09k
    Py_XDECREF(di->di_odict);
1704
2.09k
    Py_XDECREF(di->di_current);
1705
2.09k
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1706
4
        Py_DECREF(di->di_result);
1707
4
    }
1708
2.09k
    PyObject_GC_Del(di);
1709
2.09k
}
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
7.20k
{
1726
7.20k
    assert(di->di_odict != NULL);
1727
7.20k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
1728
7.20k
    PyObject *key = NULL;
1729
7.20k
    _ODictNode *node;
1730
7.20k
    int reversed = di->kind & _odict_ITER_REVERSED;
1731
1732
7.20k
    if (di->di_current == NULL)
1733
1.94k
        goto done;  /* We're already done. */
1734
1735
    /* Check for unsupported changes. */
1736
5.26k
    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
5.26k
    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
5.26k
    node = _odict_find_node(di->di_odict, di->di_current);
1750
5.26k
    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
5.26k
    key = di->di_current;
1758
1759
    /* Advance to the next key. */
1760
5.26k
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1761
5.26k
    if (node == NULL) {
1762
        /* Reached the end. */
1763
1.68k
        di->di_current = NULL;
1764
1.68k
    }
1765
3.57k
    else {
1766
3.57k
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1767
3.57k
    }
1768
1769
5.26k
    return key;
1770
1771
1.94k
done:
1772
1.94k
    Py_CLEAR(di->di_odict);
1773
1.94k
    return key;
1774
5.26k
}
1775
1776
1777
static PyObject *
1778
odictiter_nextkey(odictiterobject *di)
1779
7.21k
{
1780
7.21k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1781
7.21k
    if (di->di_odict == NULL) {
1782
4
        return NULL;
1783
4
    }
1784
7.20k
    PyObject *res;
1785
7.20k
    Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1786
7.20k
    res = odictiter_nextkey_lock_held(di);
1787
7.20k
    Py_END_CRITICAL_SECTION();
1788
7.20k
    return res;
1789
7.21k
}
1790
1791
static PyObject *
1792
odictiter_iternext_lock_held(PyObject *op)
1793
7.21k
{
1794
7.21k
    odictiterobject *di = (odictiterobject*)op;
1795
7.21k
    PyObject *result, *value;
1796
7.21k
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1797
1798
7.21k
    if (key == NULL)
1799
1.95k
        return NULL;
1800
1801
    /* Handle the keys case. */
1802
5.26k
    if (! (di->kind & _odict_ITER_VALUES)) {
1803
720
        return key;
1804
720
    }
1805
1806
4.54k
    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 done;
1811
0
    }
1812
1813
    /* Handle the values case. */
1814
4.54k
    if (!(di->kind & _odict_ITER_KEYS)) {
1815
4.52k
        Py_DECREF(key);
1816
4.52k
        return value;
1817
4.52k
    }
1818
1819
    /* Handle the items case. */
1820
12
    result = di->di_result;
1821
1822
12
    if (_PyObject_IsUniquelyReferenced(result)) {
1823
        /* not in use so we can reuse it
1824
         * (the common case during iteration) */
1825
12
        Py_INCREF(result);
1826
12
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1827
12
        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
12
        _PyTuple_Recycle(result);
1831
12
    }
1832
0
    else {
1833
0
        result = PyTuple_New(2);
1834
0
        if (result == NULL) {
1835
0
            Py_DECREF(key);
1836
0
            Py_DECREF(value);
1837
0
            goto done;
1838
0
        }
1839
0
    }
1840
1841
12
    PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1842
12
    PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1843
12
    return result;
1844
1845
0
done:
1846
0
    Py_CLEAR(di->di_current);
1847
0
    Py_CLEAR(di->di_odict);
1848
0
    return NULL;
1849
12
}
1850
1851
static PyObject *
1852
odictiter_iternext(PyObject *op)
1853
7.21k
{
1854
7.21k
    PyObject *res;
1855
7.21k
    Py_BEGIN_CRITICAL_SECTION(op);
1856
7.21k
    res = odictiter_iternext_lock_held(op);
1857
7.21k
    Py_END_CRITICAL_SECTION();
1858
7.21k
    return res;
1859
7.21k
}
1860
1861
1862
/* No need for tp_clear because odictiterobject is not mutable. */
1863
1864
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1865
1866
static PyObject *
1867
odictiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1868
0
{
1869
0
    odictiterobject *di = (odictiterobject*)op;
1870
1871
    /* copy the iterator state */
1872
0
    odictiterobject tmp = *di;
1873
0
    Py_XINCREF(tmp.di_odict);
1874
0
    Py_XINCREF(tmp.di_current);
1875
1876
    /* iterate the temporary into a list */
1877
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1878
0
    Py_XDECREF(tmp.di_odict);
1879
0
    Py_XDECREF(tmp.di_current);
1880
0
    if (list == NULL) {
1881
0
        return NULL;
1882
0
    }
1883
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1884
0
}
1885
1886
static PyMethodDef odictiter_methods[] = {
1887
    {"__reduce__", odictiter_reduce, METH_NOARGS, reduce_doc},
1888
    {NULL,              NULL}           /* sentinel */
1889
};
1890
1891
PyTypeObject PyODictIter_Type = {
1892
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1893
    "odict_iterator",                         /* tp_name */
1894
    sizeof(odictiterobject),                  /* tp_basicsize */
1895
    0,                                        /* tp_itemsize */
1896
    /* methods */
1897
    odictiter_dealloc,                        /* tp_dealloc */
1898
    0,                                        /* tp_vectorcall_offset */
1899
    0,                                        /* tp_getattr */
1900
    0,                                        /* tp_setattr */
1901
    0,                                        /* tp_as_async */
1902
    0,                                        /* tp_repr */
1903
    0,                                        /* tp_as_number */
1904
    0,                                        /* tp_as_sequence */
1905
    0,                                        /* tp_as_mapping */
1906
    0,                                        /* tp_hash */
1907
    0,                                        /* tp_call */
1908
    0,                                        /* tp_str */
1909
    PyObject_GenericGetAttr,                  /* tp_getattro */
1910
    0,                                        /* tp_setattro */
1911
    0,                                        /* tp_as_buffer */
1912
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1913
    0,                                        /* tp_doc */
1914
    odictiter_traverse,                       /* tp_traverse */
1915
    0,                                        /* tp_clear */
1916
    0,                                        /* tp_richcompare */
1917
    0,                                        /* tp_weaklistoffset */
1918
    PyObject_SelfIter,                        /* tp_iter */
1919
    odictiter_iternext,                       /* tp_iternext */
1920
    odictiter_methods,                        /* tp_methods */
1921
    0,
1922
};
1923
1924
static PyObject *
1925
odictiter_new(PyODictObject *od, int kind)
1926
2.09k
{
1927
2.09k
    odictiterobject *di;
1928
2.09k
    _ODictNode *node;
1929
2.09k
    int reversed = kind & _odict_ITER_REVERSED;
1930
1931
2.09k
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1932
2.09k
    if (di == NULL)
1933
0
        return NULL;
1934
1935
2.09k
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1936
4
        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1937
4
        if (di->di_result == NULL) {
1938
0
            Py_DECREF(di);
1939
0
            return NULL;
1940
0
        }
1941
4
    }
1942
2.08k
    else {
1943
2.08k
        di->di_result = NULL;
1944
2.08k
    }
1945
1946
2.09k
    di->kind = kind;
1947
2.09k
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1948
2.09k
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1949
2.09k
    di->di_size = PyODict_SIZE(od);
1950
2.09k
    di->di_state = od->od_state;
1951
2.09k
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1952
1953
2.09k
    _PyObject_GC_TRACK(di);
1954
2.09k
    return (PyObject *)di;
1955
2.09k
}
1956
1957
/* keys() */
1958
1959
static PyObject *
1960
odictkeys_iter(PyObject *op)
1961
0
{
1962
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1963
0
    if (dv->dv_dict == NULL) {
1964
0
        Py_RETURN_NONE;
1965
0
    }
1966
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1967
0
            _odict_ITER_KEYS);
1968
0
}
1969
1970
static PyObject *
1971
odictkeys_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1972
0
{
1973
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1974
0
    if (dv->dv_dict == NULL) {
1975
0
        Py_RETURN_NONE;
1976
0
    }
1977
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1978
0
            _odict_ITER_KEYS|_odict_ITER_REVERSED);
1979
0
}
1980
1981
static PyMethodDef odictkeys_methods[] = {
1982
    {"__reversed__", odictkeys_reversed, METH_NOARGS, NULL},
1983
    {NULL,          NULL}           /* sentinel */
1984
};
1985
1986
PyTypeObject PyODictKeys_Type = {
1987
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1988
    "odict_keys",                             /* tp_name */
1989
    0,                                        /* tp_basicsize */
1990
    0,                                        /* tp_itemsize */
1991
    0,                                        /* tp_dealloc */
1992
    0,                                        /* tp_vectorcall_offset */
1993
    0,                                        /* tp_getattr */
1994
    0,                                        /* tp_setattr */
1995
    0,                                        /* tp_as_async */
1996
    0,                                        /* tp_repr */
1997
    0,                                        /* tp_as_number */
1998
    0,                                        /* tp_as_sequence */
1999
    0,                                        /* tp_as_mapping */
2000
    0,                                        /* tp_hash */
2001
    0,                                        /* tp_call */
2002
    0,                                        /* tp_str */
2003
    0,                                        /* tp_getattro */
2004
    0,                                        /* tp_setattro */
2005
    0,                                        /* tp_as_buffer */
2006
    0,                                        /* tp_flags */
2007
    0,                                        /* tp_doc */
2008
    0,                                        /* tp_traverse */
2009
    0,                                        /* tp_clear */
2010
    0,                                        /* tp_richcompare */
2011
    0,                                        /* tp_weaklistoffset */
2012
    odictkeys_iter,                           /* tp_iter */
2013
    0,                                        /* tp_iternext */
2014
    odictkeys_methods,                        /* tp_methods */
2015
    0,                                        /* tp_members */
2016
    0,                                        /* tp_getset */
2017
    &PyDictKeys_Type,                         /* tp_base */
2018
};
2019
2020
static PyObject *
2021
odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2022
0
{
2023
0
    return _PyDictView_New(od, &PyODictKeys_Type);
2024
0
}
2025
2026
/* items() */
2027
2028
static PyObject *
2029
odictitems_iter(PyObject *op)
2030
4
{
2031
4
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2032
4
    if (dv->dv_dict == NULL) {
2033
0
        Py_RETURN_NONE;
2034
0
    }
2035
4
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2036
4
            _odict_ITER_KEYS|_odict_ITER_VALUES);
2037
4
}
2038
2039
static PyObject *
2040
odictitems_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2041
0
{
2042
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2043
0
    if (dv->dv_dict == NULL) {
2044
0
        Py_RETURN_NONE;
2045
0
    }
2046
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2047
0
            _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2048
0
}
2049
2050
static PyMethodDef odictitems_methods[] = {
2051
    {"__reversed__", odictitems_reversed, METH_NOARGS, NULL},
2052
    {NULL,          NULL}           /* sentinel */
2053
};
2054
2055
PyTypeObject PyODictItems_Type = {
2056
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2057
    "odict_items",                            /* tp_name */
2058
    0,                                        /* tp_basicsize */
2059
    0,                                        /* tp_itemsize */
2060
    0,                                        /* tp_dealloc */
2061
    0,                                        /* tp_vectorcall_offset */
2062
    0,                                        /* tp_getattr */
2063
    0,                                        /* tp_setattr */
2064
    0,                                        /* tp_as_async */
2065
    0,                                        /* tp_repr */
2066
    0,                                        /* tp_as_number */
2067
    0,                                        /* tp_as_sequence */
2068
    0,                                        /* tp_as_mapping */
2069
    0,                                        /* tp_hash */
2070
    0,                                        /* tp_call */
2071
    0,                                        /* tp_str */
2072
    0,                                        /* tp_getattro */
2073
    0,                                        /* tp_setattro */
2074
    0,                                        /* tp_as_buffer */
2075
    0,                                        /* tp_flags */
2076
    0,                                        /* tp_doc */
2077
    0,                                        /* tp_traverse */
2078
    0,                                        /* tp_clear */
2079
    0,                                        /* tp_richcompare */
2080
    0,                                        /* tp_weaklistoffset */
2081
    odictitems_iter,                          /* tp_iter */
2082
    0,                                        /* tp_iternext */
2083
    odictitems_methods,                       /* tp_methods */
2084
    0,                                        /* tp_members */
2085
    0,                                        /* tp_getset */
2086
    &PyDictItems_Type,                        /* tp_base */
2087
};
2088
2089
static PyObject *
2090
odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2091
4
{
2092
4
    return _PyDictView_New(od, &PyODictItems_Type);
2093
4
}
2094
2095
/* values() */
2096
2097
static PyObject *
2098
odictvalues_iter(PyObject *op)
2099
1.78k
{
2100
1.78k
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2101
1.78k
    if (dv->dv_dict == NULL) {
2102
0
        Py_RETURN_NONE;
2103
0
    }
2104
1.78k
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2105
1.78k
            _odict_ITER_VALUES);
2106
1.78k
}
2107
2108
static PyObject *
2109
odictvalues_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2110
0
{
2111
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2112
0
    if (dv->dv_dict == NULL) {
2113
0
        Py_RETURN_NONE;
2114
0
    }
2115
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2116
0
            _odict_ITER_VALUES|_odict_ITER_REVERSED);
2117
0
}
2118
2119
static PyMethodDef odictvalues_methods[] = {
2120
    {"__reversed__", odictvalues_reversed, METH_NOARGS, NULL},
2121
    {NULL,          NULL}           /* sentinel */
2122
};
2123
2124
PyTypeObject PyODictValues_Type = {
2125
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2126
    "odict_values",                           /* tp_name */
2127
    0,                                        /* tp_basicsize */
2128
    0,                                        /* tp_itemsize */
2129
    0,                                        /* tp_dealloc */
2130
    0,                                        /* tp_vectorcall_offset */
2131
    0,                                        /* tp_getattr */
2132
    0,                                        /* tp_setattr */
2133
    0,                                        /* tp_as_async */
2134
    0,                                        /* tp_repr */
2135
    0,                                        /* tp_as_number */
2136
    0,                                        /* tp_as_sequence */
2137
    0,                                        /* tp_as_mapping */
2138
    0,                                        /* tp_hash */
2139
    0,                                        /* tp_call */
2140
    0,                                        /* tp_str */
2141
    0,                                        /* tp_getattro */
2142
    0,                                        /* tp_setattro */
2143
    0,                                        /* tp_as_buffer */
2144
    0,                                        /* tp_flags */
2145
    0,                                        /* tp_doc */
2146
    0,                                        /* tp_traverse */
2147
    0,                                        /* tp_clear */
2148
    0,                                        /* tp_richcompare */
2149
    0,                                        /* tp_weaklistoffset */
2150
    odictvalues_iter,                         /* tp_iter */
2151
    0,                                        /* tp_iternext */
2152
    odictvalues_methods,                      /* tp_methods */
2153
    0,                                        /* tp_members */
2154
    0,                                        /* tp_getset */
2155
    &PyDictValues_Type,                       /* tp_base */
2156
};
2157
2158
static PyObject *
2159
odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2160
1.78k
{
2161
1.78k
    return _PyDictView_New(od, &PyODictValues_Type);
2162
1.78k
}
2163
2164
2165
/* ----------------------------------------------
2166
   MutableMapping implementations
2167
2168
Mapping:
2169
2170
============ ===========
2171
method       uses
2172
============ ===========
2173
__contains__ __getitem__
2174
__eq__       items
2175
__getitem__  +
2176
__iter__     +
2177
__len__      +
2178
__ne__       __eq__
2179
get          __getitem__
2180
items        ItemsView
2181
keys         KeysView
2182
values       ValuesView
2183
============ ===========
2184
2185
ItemsView uses __len__, __iter__, and __getitem__.
2186
KeysView uses __len__, __iter__, and __contains__.
2187
ValuesView uses __len__, __iter__, and __getitem__.
2188
2189
MutableMapping:
2190
2191
============ ===========
2192
method       uses
2193
============ ===========
2194
__delitem__  +
2195
__setitem__  +
2196
clear        popitem
2197
pop          __getitem__
2198
             __delitem__
2199
popitem      __iter__
2200
             _getitem__
2201
             __delitem__
2202
setdefault   __getitem__
2203
             __setitem__
2204
update       __setitem__
2205
============ ===========
2206
*/
2207
2208
static int
2209
mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2210
368
{
2211
368
    PyObject *pair, *iterator, *unexpected;
2212
368
    int res = 0;
2213
2214
368
    iterator = PyObject_GetIter(pairs);
2215
368
    if (iterator == NULL)
2216
0
        return -1;
2217
368
    PyErr_Clear();
2218
2219
1.47k
    while ((pair = PyIter_Next(iterator)) != NULL) {
2220
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2221
1.10k
        PyObject *key = NULL, *value = NULL;
2222
1.10k
        PyObject *pair_iterator = PyObject_GetIter(pair);
2223
1.10k
        if (pair_iterator == NULL)
2224
0
            goto Done;
2225
2226
1.10k
        key = PyIter_Next(pair_iterator);
2227
1.10k
        if (key == NULL) {
2228
0
            if (!PyErr_Occurred())
2229
0
                PyErr_SetString(PyExc_ValueError,
2230
0
                                "need more than 0 values to unpack");
2231
0
            goto Done;
2232
0
        }
2233
2234
1.10k
        value = PyIter_Next(pair_iterator);
2235
1.10k
        if (value == NULL) {
2236
0
            if (!PyErr_Occurred())
2237
0
                PyErr_SetString(PyExc_ValueError,
2238
0
                                "need more than 1 value to unpack");
2239
0
            goto Done;
2240
0
        }
2241
2242
1.10k
        unexpected = PyIter_Next(pair_iterator);
2243
1.10k
        if (unexpected != NULL) {
2244
0
            Py_DECREF(unexpected);
2245
0
            PyErr_SetString(PyExc_ValueError,
2246
0
                            "too many values to unpack (expected 2)");
2247
0
            goto Done;
2248
0
        }
2249
1.10k
        else if (PyErr_Occurred())
2250
0
            goto Done;
2251
2252
1.10k
        res = PyObject_SetItem(self, key, value);
2253
2254
1.10k
Done:
2255
1.10k
        Py_DECREF(pair);
2256
1.10k
        Py_XDECREF(pair_iterator);
2257
1.10k
        Py_XDECREF(key);
2258
1.10k
        Py_XDECREF(value);
2259
1.10k
        if (PyErr_Occurred())
2260
0
            break;
2261
1.10k
    }
2262
368
    Py_DECREF(iterator);
2263
2264
368
    if (res < 0 || PyErr_Occurred() != NULL)
2265
0
        return -1;
2266
368
    else
2267
368
        return 0;
2268
368
}
2269
2270
static int
2271
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2272
368
{
2273
368
    int res = 0;
2274
368
    if (PyDict_CheckExact(arg)) {
2275
0
        PyObject *items = PyDict_Items(arg);
2276
0
        if (items == NULL) {
2277
0
            return -1;
2278
0
        }
2279
0
        res = mutablemapping_add_pairs(self, items);
2280
0
        Py_DECREF(items);
2281
0
        return res;
2282
0
    }
2283
368
    PyObject *func;
2284
368
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2285
0
        return -1;
2286
0
    }
2287
368
    if (func != NULL) {
2288
0
        PyObject *keys = _PyObject_CallNoArgs(func);
2289
0
        Py_DECREF(func);
2290
0
        if (keys == NULL) {
2291
0
            return -1;
2292
0
        }
2293
0
        PyObject *iterator = PyObject_GetIter(keys);
2294
0
        Py_DECREF(keys);
2295
0
        if (iterator == NULL) {
2296
0
            return -1;
2297
0
        }
2298
0
        PyObject *key;
2299
0
        while (res == 0 && (key = PyIter_Next(iterator))) {
2300
0
            PyObject *value = PyObject_GetItem(arg, key);
2301
0
            if (value != NULL) {
2302
0
                res = PyObject_SetItem(self, key, value);
2303
0
                Py_DECREF(value);
2304
0
            }
2305
0
            else {
2306
0
                res = -1;
2307
0
            }
2308
0
            Py_DECREF(key);
2309
0
        }
2310
0
        Py_DECREF(iterator);
2311
0
        if (res != 0 || PyErr_Occurred()) {
2312
0
            return -1;
2313
0
        }
2314
0
        return 0;
2315
0
    }
2316
368
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2317
0
        return -1;
2318
0
    }
2319
368
    if (func != NULL) {
2320
0
        PyObject *items = _PyObject_CallNoArgs(func);
2321
0
        Py_DECREF(func);
2322
0
        if (items == NULL) {
2323
0
            return -1;
2324
0
        }
2325
0
        res = mutablemapping_add_pairs(self, items);
2326
0
        Py_DECREF(items);
2327
0
        return res;
2328
0
    }
2329
368
    res = mutablemapping_add_pairs(self, arg);
2330
368
    return res;
2331
368
}
2332
2333
static PyObject *
2334
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2335
592
{
2336
592
    int res;
2337
    /* first handle args, if any */
2338
592
    assert(args == NULL || PyTuple_Check(args));
2339
592
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2340
592
    if (len > 1) {
2341
0
        const char *msg = "update() takes at most 1 positional argument (%zd given)";
2342
0
        PyErr_Format(PyExc_TypeError, msg, len);
2343
0
        return NULL;
2344
0
    }
2345
2346
592
    if (len) {
2347
368
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2348
368
        assert(other != NULL);
2349
368
        Py_INCREF(other);
2350
368
        res = mutablemapping_update_arg(self, other);
2351
368
        Py_DECREF(other);
2352
368
        if (res < 0) {
2353
0
            return NULL;
2354
0
        }
2355
368
    }
2356
2357
    /* now handle kwargs */
2358
592
    assert(kwargs == NULL || PyDict_Check(kwargs));
2359
592
    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2360
0
        PyObject *items = PyDict_Items(kwargs);
2361
0
        if (items == NULL)
2362
0
            return NULL;
2363
0
        res = mutablemapping_add_pairs(self, items);
2364
0
        Py_DECREF(items);
2365
0
        if (res == -1)
2366
0
            return NULL;
2367
0
    }
2368
2369
592
    Py_RETURN_NONE;
2370
592
}