Coverage Report

Created: 2025-08-26 06:26

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