Coverage Report

Created: 2025-12-07 07:03

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
1.03k
#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
326
    (node->key)
520
#define _odictnode_HASH(node) \
521
326
    (node->hash)
522
/* borrowed reference */
523
#define _odictnode_VALUE(node, od) \
524
0
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
525
176
#define _odictnode_PREV(node) (node->prev)
526
1.01k
#define _odictnode_NEXT(node) (node->next)
527
528
294
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
529
544
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
530
176
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
531
#define _odict_FOREACH(od, node) \
532
188
    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
502
{
538
502
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
539
502
    PyObject *value = NULL;
540
502
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
502
    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
502
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
547
502
#endif
548
502
    if (ix == DKIX_EMPTY) {
549
0
        return keys->dk_nentries;  /* index of new entry */
550
0
    }
551
502
    if (ix < 0)
552
0
        return -1;
553
    /* We use pointer arithmetic to get the entry's index into the table. */
554
502
    return ix;
555
502
}
556
557
352
#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
38
{
563
38
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
564
38
    Py_ssize_t size, i;
565
38
    _ODictNode **fast_nodes, *node;
566
567
    /* Initialize a new "fast nodes" table. */
568
38
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
569
38
    fast_nodes = PyMem_NEW(_ODictNode *, size);
570
38
    if (fast_nodes == NULL) {
571
0
        PyErr_NoMemory();
572
0
        return -1;
573
0
    }
574
646
    for (i = 0; i < size; i++)
575
608
        fast_nodes[i] = NULL;
576
577
    /* Copy the current nodes into the table. */
578
150
    _odict_FOREACH(od, node) {
579
150
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
580
150
                                 _odictnode_HASH(node));
581
150
        if (i < 0) {
582
0
            PyMem_Free(fast_nodes);
583
0
            return -1;
584
0
        }
585
150
        fast_nodes[i] = node;
586
150
    }
587
588
    /* Replace the old fast nodes table. */
589
38
    PyMem_Free(od->od_fast_nodes);
590
38
    od->od_fast_nodes = fast_nodes;
591
38
    od->od_fast_nodes_size = size;
592
38
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
593
38
    return 0;
594
38
}
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
352
{
600
352
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
601
352
    PyDictKeysObject *keys;
602
603
352
    assert(key != NULL);
604
352
    keys = ((PyDictObject *)od)->ma_keys;
605
606
    /* Ensure od_fast_nodes and dk_entries are in sync. */
607
352
    if (od->od_resize_sentinel != keys ||
608
314
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
609
38
        int resize_res = _odict_resize(od);
610
38
        if (resize_res < 0)
611
0
            return -1;
612
38
    }
613
614
352
    return _odict_get_index_raw(od, key, hash);
615
352
}
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
0
{
621
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
622
0
    Py_ssize_t index;
623
624
0
    if (_odict_EMPTY(od))
625
0
        return NULL;
626
0
    index = _odict_get_index(od, key, hash);
627
0
    if (index < 0)
628
0
        return NULL;
629
0
    assert(od->od_fast_nodes != NULL);
630
0
    return od->od_fast_nodes[index];
631
0
}
632
633
static _ODictNode *
634
_odict_find_node(PyODictObject *od, PyObject *key)
635
176
{
636
176
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
637
176
    Py_ssize_t index;
638
176
    Py_hash_t hash;
639
640
176
    if (_odict_EMPTY(od))
641
0
        return NULL;
642
176
    hash = PyObject_Hash(key);
643
176
    if (hash == -1)
644
0
        return NULL;
645
176
    index = _odict_get_index(od, key, hash);
646
176
    if (index < 0)
647
0
        return NULL;
648
176
    assert(od->od_fast_nodes != NULL);
649
176
    return od->od_fast_nodes[index];
650
176
}
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
176
{
669
176
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
670
176
    _odictnode_PREV(node) = _odict_LAST(od);
671
176
    _odictnode_NEXT(node) = NULL;
672
176
    if (_odict_LAST(od) == NULL)
673
16
        _odict_FIRST(od) = node;
674
160
    else
675
160
        _odictnode_NEXT(_odict_LAST(od)) = node;
676
176
    _odict_LAST(od) = node;
677
176
    od->od_state++;
678
176
}
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
176
{
684
176
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
685
176
    Py_ssize_t i;
686
176
    _ODictNode *node;
687
688
176
    Py_INCREF(key);
689
176
    i = _odict_get_index(od, key, hash);
690
176
    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
176
    assert(od->od_fast_nodes != NULL);
697
176
    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
176
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
705
176
    if (node == NULL) {
706
0
        Py_DECREF(key);
707
0
        PyErr_NoMemory();
708
0
        return -1;
709
0
    }
710
711
176
    _odictnode_KEY(node) = key;
712
176
    _odictnode_HASH(node) = hash;
713
176
    _odict_add_tail(od, node);
714
176
    od->od_fast_nodes[i] = node;
715
176
    return 0;
716
176
}
717
718
/* Putting the decref after the free causes problems. */
719
#define _odictnode_DEALLOC(node) \
720
176
    do { \
721
176
        Py_DECREF(_odictnode_KEY(node)); \
722
176
        PyMem_Free((void *)node); \
723
176
    } 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
0
{
729
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
730
0
    if (_odict_FIRST(od) == node)
731
0
        _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
0
    if (_odict_LAST(od) == node)
736
0
        _odict_LAST(od) = _odictnode_PREV(node);
737
0
    else if (_odictnode_NEXT(node) != NULL)
738
0
        _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
739
740
0
    _odictnode_PREV(node) = NULL;
741
0
    _odictnode_NEXT(node) = NULL;
742
0
    od->od_state++;
743
0
}
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
0
{
765
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
766
0
    Py_ssize_t i;
767
768
0
    assert(key != NULL);
769
0
    if (_odict_EMPTY(od)) {
770
        /* Let later code decide if this is a KeyError. */
771
0
        return 0;
772
0
    }
773
774
0
    i = _odict_get_index(od, key, hash);
775
0
    if (i < 0)
776
0
        return PyErr_Occurred() ? -1 : 0;
777
778
0
    assert(od->od_fast_nodes != NULL);
779
0
    if (node == NULL)
780
0
        node = od->od_fast_nodes[i];
781
0
    assert(node == od->od_fast_nodes[i]);
782
0
    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
0
    od->od_fast_nodes[i] = NULL;
789
0
    _odict_remove_node(od, node);
790
0
    _odictnode_DEALLOC(node);
791
0
    return 0;
792
0
}
793
794
static void
795
_odict_clear_nodes(PyODictObject *od)
796
16
{
797
16
    _ODictNode *node, *next;
798
799
16
    PyMem_Free(od->od_fast_nodes);
800
16
    od->od_fast_nodes = NULL;
801
16
    od->od_fast_nodes_size = 0;
802
16
    od->od_resize_sentinel = NULL;
803
804
16
    node = _odict_FIRST(od);
805
16
    _odict_FIRST(od) = NULL;
806
16
    _odict_LAST(od) = NULL;
807
192
    while (node != NULL) {
808
176
        next = _odictnode_NEXT(node);
809
176
        _odictnode_DEALLOC(node);
810
176
        node = next;
811
176
    }
812
16
    od->od_state++;
813
16
}
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
176
{
875
176
    if (w == NULL)
876
0
        return PyODict_DelItem(od, v);
877
176
    else
878
176
        return PyODict_SetItem(od, v, w);
879
176
}
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
0
{
1083
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1084
1085
0
    PyObject *value = NULL;
1086
0
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1087
0
    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
0
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1092
0
        if (res < 0) {
1093
0
            goto done;
1094
0
        }
1095
        /* Now delete the value from the dict. */
1096
0
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1097
0
                                  &value) == 0) {
1098
0
            value = Py_NewRef(failobj);
1099
0
        }
1100
0
    }
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
0
done:
1111
1112
0
    return value;
1113
0
}
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
0
{
1135
0
    Py_hash_t hash = PyObject_Hash(key);
1136
0
    if (hash == -1)
1137
0
        return NULL;
1138
0
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1139
0
}
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
16
#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
208
#define _odict_ITER_REVERSED 1
1294
240
#define _odict_ITER_KEYS 2
1295
256
#define _odict_ITER_VALUES 4
1296
64
#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
0
{
1327
0
    _ODictNode *node;
1328
1329
0
    if (_odict_EMPTY(self)) {
1330
0
        PyErr_SetObject(PyExc_KeyError, key);
1331
0
        return NULL;
1332
0
    }
1333
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1334
0
    if (key != _odictnode_KEY(node)) {
1335
0
        node = _odict_find_node(self, key);
1336
0
        if (node == NULL) {
1337
0
            if (!PyErr_Occurred())
1338
0
                PyErr_SetObject(PyExc_KeyError, key);
1339
0
            return NULL;
1340
0
        }
1341
0
        if (last) {
1342
            /* Only move if not already the last one. */
1343
0
            if (node != _odict_LAST(self)) {
1344
0
                _odict_remove_node(self, node);
1345
0
                _odict_add_tail(self, node);
1346
0
            }
1347
0
        }
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
0
    }
1356
0
    Py_RETURN_NONE;
1357
0
}
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
16
{
1410
16
    PyODictObject *self = _PyODictObject_CAST(op);
1411
16
    PyObject_GC_UnTrack(self);
1412
1413
16
    Py_XDECREF(self->od_inst_dict);
1414
16
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1415
1416
16
    _odict_clear_nodes(self);
1417
16
    PyDict_Type.tp_dealloc((PyObject *)self);
1418
16
}
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
0
{
1462
0
    PyODictObject *od = _PyODictObject_CAST(op);
1463
0
    _ODictNode *node;
1464
1465
0
    Py_VISIT(od->od_inst_dict);
1466
0
    _odict_FOREACH(od, node) {
1467
0
        Py_VISIT(_odictnode_KEY(node));
1468
0
    }
1469
0
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1470
0
}
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
0
{
1536
0
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1537
0
}
1538
1539
/* tp_init */
1540
1541
static int
1542
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1543
16
{
1544
16
    PyObject *res;
1545
16
    Py_ssize_t len = PyObject_Length(args);
1546
1547
16
    if (len == -1)
1548
0
        return -1;
1549
16
    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
16
    res = odict_update(self, args, kwds);
1557
16
    if (res == NULL) {
1558
0
        return -1;
1559
16
    } else {
1560
16
        Py_DECREF(res);
1561
16
        return 0;
1562
16
    }
1563
16
}
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
176
{
1624
176
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1625
176
    int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
1626
176
    if (res == 0) {
1627
176
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1628
176
        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
176
    }
1635
176
    return res;
1636
176
}
1637
1638
1639
static int
1640
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
1641
176
{
1642
176
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1643
176
    Py_hash_t hash = PyObject_Hash(key);
1644
176
    if (hash == -1) {
1645
0
        return -1;
1646
0
    }
1647
176
    return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
1648
176
}
1649
1650
int
1651
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1652
176
{
1653
176
    int res;
1654
176
    Py_BEGIN_CRITICAL_SECTION(od);
1655
176
    res = PyODict_SetItem_LockHeld(od, key, value);
1656
176
    Py_END_CRITICAL_SECTION();
1657
176
    return res;
1658
176
}
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
16
{
1701
16
    odictiterobject *di = (odictiterobject*)op;
1702
16
    _PyObject_GC_UNTRACK(di);
1703
16
    Py_XDECREF(di->di_odict);
1704
16
    Py_XDECREF(di->di_current);
1705
16
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1706
0
        Py_DECREF(di->di_result);
1707
0
    }
1708
16
    PyObject_GC_Del(di);
1709
16
}
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
192
{
1726
192
    assert(di->di_odict != NULL);
1727
192
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
1728
192
    PyObject *key = NULL;
1729
192
    _ODictNode *node;
1730
192
    int reversed = di->kind & _odict_ITER_REVERSED;
1731
1732
192
    if (di->di_current == NULL)
1733
16
        goto done;  /* We're already done. */
1734
1735
    /* Check for unsupported changes. */
1736
176
    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
176
    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
176
    node = _odict_find_node(di->di_odict, di->di_current);
1750
176
    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
176
    key = di->di_current;
1758
1759
    /* Advance to the next key. */
1760
176
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1761
176
    if (node == NULL) {
1762
        /* Reached the end. */
1763
16
        di->di_current = NULL;
1764
16
    }
1765
160
    else {
1766
160
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1767
160
    }
1768
1769
176
    return key;
1770
1771
16
done:
1772
16
    Py_CLEAR(di->di_odict);
1773
16
    return key;
1774
176
}
1775
1776
1777
static PyObject *
1778
odictiter_nextkey(odictiterobject *di)
1779
192
{
1780
192
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1781
192
    if (di->di_odict == NULL) {
1782
0
        return NULL;
1783
0
    }
1784
192
    PyObject *res;
1785
192
    Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1786
192
    res = odictiter_nextkey_lock_held(di);
1787
192
    Py_END_CRITICAL_SECTION();
1788
192
    return res;
1789
192
}
1790
1791
static PyObject *
1792
odictiter_iternext_lock_held(PyObject *op)
1793
192
{
1794
192
    odictiterobject *di = (odictiterobject*)op;
1795
192
    PyObject *result, *value;
1796
192
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1797
1798
192
    if (key == NULL)
1799
16
        return NULL;
1800
1801
    /* Handle the keys case. */
1802
176
    if (! (di->kind & _odict_ITER_VALUES)) {
1803
0
        return key;
1804
0
    }
1805
1806
176
    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
176
    if (!(di->kind & _odict_ITER_KEYS)) {
1815
176
        Py_DECREF(key);
1816
176
        return value;
1817
176
    }
1818
1819
    /* Handle the items case. */
1820
0
    result = di->di_result;
1821
1822
0
    if (_PyObject_IsUniquelyReferenced(result)) {
1823
        /* not in use so we can reuse it
1824
         * (the common case during iteration) */
1825
0
        Py_INCREF(result);
1826
0
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1827
0
        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
0
        _PyTuple_Recycle(result);
1831
0
    }
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
0
    PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1842
0
    PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1843
0
    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
0
}
1850
1851
static PyObject *
1852
odictiter_iternext(PyObject *op)
1853
192
{
1854
192
    PyObject *res;
1855
192
    Py_BEGIN_CRITICAL_SECTION(op);
1856
192
    res = odictiter_iternext_lock_held(op);
1857
192
    Py_END_CRITICAL_SECTION();
1858
192
    return res;
1859
192
}
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
16
{
1927
16
    odictiterobject *di;
1928
16
    _ODictNode *node;
1929
16
    int reversed = kind & _odict_ITER_REVERSED;
1930
1931
16
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1932
16
    if (di == NULL)
1933
0
        return NULL;
1934
1935
16
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1936
0
        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1937
0
        if (di->di_result == NULL) {
1938
0
            Py_DECREF(di);
1939
0
            return NULL;
1940
0
        }
1941
0
    }
1942
16
    else {
1943
16
        di->di_result = NULL;
1944
16
    }
1945
1946
16
    di->kind = kind;
1947
16
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1948
16
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1949
16
    di->di_size = PyODict_SIZE(od);
1950
16
    di->di_state = od->od_state;
1951
16
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1952
1953
16
    _PyObject_GC_TRACK(di);
1954
16
    return (PyObject *)di;
1955
16
}
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
0
{
2031
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2032
0
    if (dv->dv_dict == NULL) {
2033
0
        Py_RETURN_NONE;
2034
0
    }
2035
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2036
0
            _odict_ITER_KEYS|_odict_ITER_VALUES);
2037
0
}
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
0
{
2092
0
    return _PyDictView_New(od, &PyODictItems_Type);
2093
0
}
2094
2095
/* values() */
2096
2097
static PyObject *
2098
odictvalues_iter(PyObject *op)
2099
16
{
2100
16
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2101
16
    if (dv->dv_dict == NULL) {
2102
0
        Py_RETURN_NONE;
2103
0
    }
2104
16
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2105
16
            _odict_ITER_VALUES);
2106
16
}
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
16
{
2161
16
    return _PyDictView_New(od, &PyODictValues_Type);
2162
16
}
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
8
{
2211
8
    PyObject *pair, *iterator, *unexpected;
2212
8
    int res = 0;
2213
2214
8
    iterator = PyObject_GetIter(pairs);
2215
8
    if (iterator == NULL)
2216
0
        return -1;
2217
8
    PyErr_Clear();
2218
2219
100
    while ((pair = PyIter_Next(iterator)) != NULL) {
2220
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2221
92
        PyObject *key = NULL, *value = NULL;
2222
92
        PyObject *pair_iterator = PyObject_GetIter(pair);
2223
92
        if (pair_iterator == NULL)
2224
0
            goto Done;
2225
2226
92
        key = PyIter_Next(pair_iterator);
2227
92
        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
92
        value = PyIter_Next(pair_iterator);
2235
92
        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
92
        unexpected = PyIter_Next(pair_iterator);
2243
92
        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
92
        else if (PyErr_Occurred())
2250
0
            goto Done;
2251
2252
92
        res = PyObject_SetItem(self, key, value);
2253
2254
92
Done:
2255
92
        Py_DECREF(pair);
2256
92
        Py_XDECREF(pair_iterator);
2257
92
        Py_XDECREF(key);
2258
92
        Py_XDECREF(value);
2259
92
        if (PyErr_Occurred())
2260
0
            break;
2261
92
    }
2262
8
    Py_DECREF(iterator);
2263
2264
8
    if (res < 0 || PyErr_Occurred() != NULL)
2265
0
        return -1;
2266
8
    else
2267
8
        return 0;
2268
8
}
2269
2270
static int
2271
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2272
8
{
2273
8
    int res = 0;
2274
8
    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
8
    PyObject *func;
2284
8
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2285
0
        return -1;
2286
0
    }
2287
8
    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
8
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2317
0
        return -1;
2318
0
    }
2319
8
    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
8
    res = mutablemapping_add_pairs(self, arg);
2330
8
    return res;
2331
8
}
2332
2333
static PyObject *
2334
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2335
16
{
2336
16
    int res;
2337
    /* first handle args, if any */
2338
16
    assert(args == NULL || PyTuple_Check(args));
2339
16
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2340
16
    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
16
    if (len) {
2347
8
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2348
8
        assert(other != NULL);
2349
8
        Py_INCREF(other);
2350
8
        res = mutablemapping_update_arg(self, other);
2351
8
        Py_DECREF(other);
2352
8
        if (res < 0) {
2353
0
            return NULL;
2354
0
        }
2355
8
    }
2356
2357
    /* now handle kwargs */
2358
16
    assert(kwargs == NULL || PyDict_Check(kwargs));
2359
16
    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
16
    Py_RETURN_NONE;
2370
16
}