Coverage Report

Created: 2025-07-04 06:49

/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
0
#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
0
    (node->key)
521
#define _odictnode_HASH(node) \
522
0
    (node->hash)
523
/* borrowed reference */
524
#define _odictnode_VALUE(node, od) \
525
0
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
526
0
#define _odictnode_PREV(node) (node->prev)
527
0
#define _odictnode_NEXT(node) (node->next)
528
529
0
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
530
0
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
531
0
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
532
#define _odict_FOREACH(od, node) \
533
0
    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
0
{
539
0
    PyObject *value = NULL;
540
0
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
0
    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
0
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
547
0
#endif
548
0
    if (ix == DKIX_EMPTY) {
549
0
        return keys->dk_nentries;  /* index of new entry */
550
0
    }
551
0
    if (ix < 0)
552
0
        return -1;
553
    /* We use pointer arithmetic to get the entry's index into the table. */
554
0
    return ix;
555
0
}
556
557
0
#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
0
{
563
0
    Py_ssize_t size, i;
564
0
    _ODictNode **fast_nodes, *node;
565
566
    /* Initialize a new "fast nodes" table. */
567
0
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
568
0
    fast_nodes = PyMem_NEW(_ODictNode *, size);
569
0
    if (fast_nodes == NULL) {
570
0
        PyErr_NoMemory();
571
0
        return -1;
572
0
    }
573
0
    for (i = 0; i < size; i++)
574
0
        fast_nodes[i] = NULL;
575
576
    /* Copy the current nodes into the table. */
577
0
    _odict_FOREACH(od, node) {
578
0
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
579
0
                                 _odictnode_HASH(node));
580
0
        if (i < 0) {
581
0
            PyMem_Free(fast_nodes);
582
0
            return -1;
583
0
        }
584
0
        fast_nodes[i] = node;
585
0
    }
586
587
    /* Replace the old fast nodes table. */
588
0
    PyMem_Free(od->od_fast_nodes);
589
0
    od->od_fast_nodes = fast_nodes;
590
0
    od->od_fast_nodes_size = size;
591
0
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
592
0
    return 0;
593
0
}
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
0
{
599
0
    PyDictKeysObject *keys;
600
601
0
    assert(key != NULL);
602
0
    keys = ((PyDictObject *)od)->ma_keys;
603
604
    /* Ensure od_fast_nodes and dk_entries are in sync. */
605
0
    if (od->od_resize_sentinel != keys ||
606
0
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
607
0
        int resize_res = _odict_resize(od);
608
0
        if (resize_res < 0)
609
0
            return -1;
610
0
    }
611
612
0
    return _odict_get_index_raw(od, key, hash);
613
0
}
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
0
{
633
0
    Py_ssize_t index;
634
0
    Py_hash_t hash;
635
636
0
    if (_odict_EMPTY(od))
637
0
        return NULL;
638
0
    hash = PyObject_Hash(key);
639
0
    if (hash == -1)
640
0
        return NULL;
641
0
    index = _odict_get_index(od, key, hash);
642
0
    if (index < 0)
643
0
        return NULL;
644
0
    assert(od->od_fast_nodes != NULL);
645
0
    return od->od_fast_nodes[index];
646
0
}
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
0
{
664
0
    _odictnode_PREV(node) = _odict_LAST(od);
665
0
    _odictnode_NEXT(node) = NULL;
666
0
    if (_odict_LAST(od) == NULL)
667
0
        _odict_FIRST(od) = node;
668
0
    else
669
0
        _odictnode_NEXT(_odict_LAST(od)) = node;
670
0
    _odict_LAST(od) = node;
671
0
    od->od_state++;
672
0
}
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
0
{
678
0
    Py_ssize_t i;
679
0
    _ODictNode *node;
680
681
0
    Py_INCREF(key);
682
0
    i = _odict_get_index(od, key, hash);
683
0
    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
0
    assert(od->od_fast_nodes != NULL);
690
0
    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
0
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
698
0
    if (node == NULL) {
699
0
        Py_DECREF(key);
700
0
        PyErr_NoMemory();
701
0
        return -1;
702
0
    }
703
704
0
    _odictnode_KEY(node) = key;
705
0
    _odictnode_HASH(node) = hash;
706
0
    _odict_add_tail(od, node);
707
0
    od->od_fast_nodes[i] = node;
708
0
    return 0;
709
0
}
710
711
/* Putting the decref after the free causes problems. */
712
#define _odictnode_DEALLOC(node) \
713
0
    do { \
714
0
        Py_DECREF(_odictnode_KEY(node)); \
715
0
        PyMem_Free((void *)node); \
716
0
    } 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
0
{
788
0
    _ODictNode *node, *next;
789
790
0
    PyMem_Free(od->od_fast_nodes);
791
0
    od->od_fast_nodes = NULL;
792
0
    od->od_fast_nodes_size = 0;
793
0
    od->od_resize_sentinel = NULL;
794
795
0
    node = _odict_FIRST(od);
796
0
    _odict_FIRST(od) = NULL;
797
0
    _odict_LAST(od) = NULL;
798
0
    while (node != NULL) {
799
0
        next = _odictnode_NEXT(node);
800
0
        _odictnode_DEALLOC(node);
801
0
        node = next;
802
0
    }
803
0
    od->od_state++;
804
0
}
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
0
{
866
0
    if (w == NULL)
867
0
        return PyODict_DelItem(od, v);
868
0
    else
869
0
        return PyODict_SetItem(od, v, w);
870
0
}
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
@classmethod
939
OrderedDict.fromkeys
940
941
    iterable as seq: object
942
    value: object = None
943
944
Create a new ordered dictionary with keys from iterable and values set to value.
945
[clinic start generated code]*/
946
947
static PyObject *
948
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
949
/*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/
950
0
{
951
0
    return _PyDict_FromKeys((PyObject *)type, seq, value);
952
0
}
953
954
/* __sizeof__() */
955
956
/* OrderedDict.__sizeof__() does not have a docstring. */
957
PyDoc_STRVAR(odict_sizeof__doc__, "");
958
959
static PyObject *
960
odict_sizeof(PyObject *op, PyObject *Py_UNUSED(ignored))
961
0
{
962
0
    PyODictObject *od = _PyODictObject_CAST(op);
963
0
    Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
964
0
    res += sizeof(_ODictNode *) * od->od_fast_nodes_size;  /* od_fast_nodes */
965
0
    if (!_odict_EMPTY(od)) {
966
0
        res += sizeof(_ODictNode) * PyODict_SIZE(od);  /* linked-list */
967
0
    }
968
0
    return PyLong_FromSsize_t(res);
969
0
}
970
971
/* __reduce__() */
972
973
PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
974
975
static PyObject *
976
odict_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
977
0
{
978
0
    register PyODictObject *od = _PyODictObject_CAST(op);
979
0
    PyObject *state, *result = NULL;
980
0
    PyObject *items_iter, *items, *args = NULL;
981
982
    /* capture any instance state */
983
0
    state = _PyObject_GetState((PyObject *)od);
984
0
    if (state == NULL)
985
0
        goto Done;
986
987
    /* build the result */
988
0
    args = PyTuple_New(0);
989
0
    if (args == NULL)
990
0
        goto Done;
991
992
0
    items = PyObject_CallMethodNoArgs((PyObject *)od, &_Py_ID(items));
993
0
    if (items == NULL)
994
0
        goto Done;
995
996
0
    items_iter = PyObject_GetIter(items);
997
0
    Py_DECREF(items);
998
0
    if (items_iter == NULL)
999
0
        goto Done;
1000
1001
0
    result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);
1002
0
    Py_DECREF(items_iter);
1003
1004
0
Done:
1005
0
    Py_XDECREF(state);
1006
0
    Py_XDECREF(args);
1007
1008
0
    return result;
1009
0
}
1010
1011
/* setdefault(): Skips __missing__() calls. */
1012
1013
1014
/*[clinic input]
1015
OrderedDict.setdefault
1016
1017
    key: object
1018
    default: object = None
1019
1020
Insert key with a value of default if key is not in the dictionary.
1021
1022
Return the value for key if key is in the dictionary, else default.
1023
[clinic start generated code]*/
1024
1025
static PyObject *
1026
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
1027
                            PyObject *default_value)
1028
/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
1029
0
{
1030
0
    PyObject *result = NULL;
1031
1032
0
    if (PyODict_CheckExact(self)) {
1033
0
        result = PyODict_GetItemWithError(self, key);  /* borrowed */
1034
0
        if (result == NULL) {
1035
0
            if (PyErr_Occurred())
1036
0
                return NULL;
1037
0
            assert(_odict_find_node(self, key) == NULL);
1038
0
            if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
1039
0
                result = Py_NewRef(default_value);
1040
0
            }
1041
0
        }
1042
0
        else {
1043
0
            Py_INCREF(result);
1044
0
        }
1045
0
    }
1046
0
    else {
1047
0
        int exists = PySequence_Contains((PyObject *)self, key);
1048
0
        if (exists < 0) {
1049
0
            return NULL;
1050
0
        }
1051
0
        else if (exists) {
1052
0
            result = PyObject_GetItem((PyObject *)self, key);
1053
0
        }
1054
0
        else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1055
0
            result = Py_NewRef(default_value);
1056
0
        }
1057
0
    }
1058
1059
0
    return result;
1060
0
}
1061
1062
/* pop() */
1063
1064
static PyObject *
1065
_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1066
                   Py_hash_t hash)
1067
0
{
1068
0
    PyObject *value = NULL;
1069
1070
0
    Py_BEGIN_CRITICAL_SECTION(od);
1071
1072
0
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1073
0
    if (node != NULL) {
1074
        /* Pop the node first to avoid a possible dict resize (due to
1075
           eval loop reentrancy) and complications due to hash collision
1076
           resolution. */
1077
0
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1078
0
        if (res < 0) {
1079
0
            goto done;
1080
0
        }
1081
        /* Now delete the value from the dict. */
1082
0
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1083
0
                                  &value) == 0) {
1084
0
            value = Py_NewRef(failobj);
1085
0
        }
1086
0
    }
1087
0
    else if (value == NULL && !PyErr_Occurred()) {
1088
        /* Apply the fallback value, if necessary. */
1089
0
        if (failobj) {
1090
0
            value = Py_NewRef(failobj);
1091
0
        }
1092
0
        else {
1093
0
            PyErr_SetObject(PyExc_KeyError, key);
1094
0
        }
1095
0
    }
1096
0
    Py_END_CRITICAL_SECTION();
1097
0
done:
1098
1099
0
    return value;
1100
0
}
1101
1102
/* Skips __missing__() calls. */
1103
/*[clinic input]
1104
OrderedDict.pop
1105
1106
    key: object
1107
    default: object = NULL
1108
1109
od.pop(key[,default]) -> v, remove specified key and return the corresponding value.
1110
1111
If the key is not found, return the default if given; otherwise,
1112
raise a KeyError.
1113
[clinic start generated code]*/
1114
1115
static PyObject *
1116
OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
1117
                     PyObject *default_value)
1118
/*[clinic end generated code: output=7a6447d104e7494b input=7efe36601007dff7]*/
1119
0
{
1120
0
    Py_hash_t hash = PyObject_Hash(key);
1121
0
    if (hash == -1)
1122
0
        return NULL;
1123
0
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1124
0
}
1125
1126
1127
/* popitem() */
1128
1129
/*[clinic input]
1130
OrderedDict.popitem
1131
1132
    last: bool = True
1133
1134
Remove and return a (key, value) pair from the dictionary.
1135
1136
Pairs are returned in LIFO order if last is true or FIFO order if false.
1137
[clinic start generated code]*/
1138
1139
static PyObject *
1140
OrderedDict_popitem_impl(PyODictObject *self, int last)
1141
/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
1142
0
{
1143
0
    PyObject *key, *value, *item = NULL;
1144
0
    _ODictNode *node;
1145
1146
    /* pull the item */
1147
1148
0
    if (_odict_EMPTY(self)) {
1149
0
        PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1150
0
        return NULL;
1151
0
    }
1152
1153
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1154
0
    key = Py_NewRef(_odictnode_KEY(node));
1155
0
    value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1156
0
    if (value == NULL)
1157
0
        return NULL;
1158
0
    item = PyTuple_Pack(2, key, value);
1159
0
    Py_DECREF(key);
1160
0
    Py_DECREF(value);
1161
0
    return item;
1162
0
}
1163
1164
/* keys() */
1165
1166
/* MutableMapping.keys() does not have a docstring. */
1167
PyDoc_STRVAR(odict_keys__doc__, "");
1168
1169
static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1170
1171
/* values() */
1172
1173
/* MutableMapping.values() does not have a docstring. */
1174
PyDoc_STRVAR(odict_values__doc__, "");
1175
1176
static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1177
1178
/* items() */
1179
1180
/* MutableMapping.items() does not have a docstring. */
1181
PyDoc_STRVAR(odict_items__doc__, "");
1182
1183
static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1184
1185
/* update() */
1186
1187
/* MutableMapping.update() does not have a docstring. */
1188
PyDoc_STRVAR(odict_update__doc__, "");
1189
1190
/* forward */
1191
static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1192
1193
0
#define odict_update mutablemapping_update
1194
1195
/* clear() */
1196
1197
PyDoc_STRVAR(odict_clear__doc__,
1198
             "od.clear() -> None.  Remove all items from od.");
1199
1200
static PyObject *
1201
odict_clear(PyObject *op, PyObject *Py_UNUSED(ignored))
1202
0
{
1203
0
    register PyODictObject *od = _PyODictObject_CAST(op);
1204
0
    PyDict_Clear(op);
1205
0
    _odict_clear_nodes(od);
1206
0
    Py_RETURN_NONE;
1207
0
}
1208
1209
/* copy() */
1210
1211
/* forward */
1212
static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1213
                                      Py_hash_t);
1214
1215
PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1216
1217
static PyObject *
1218
odict_copy(PyObject *op, PyObject *Py_UNUSED(ignored))
1219
0
{
1220
0
    register PyODictObject *od = _PyODictObject_CAST(op);
1221
0
    _ODictNode *node;
1222
0
    PyObject *od_copy;
1223
1224
0
    if (PyODict_CheckExact(od))
1225
0
        od_copy = PyODict_New();
1226
0
    else
1227
0
        od_copy = _PyObject_CallNoArgs((PyObject *)Py_TYPE(od));
1228
0
    if (od_copy == NULL)
1229
0
        return NULL;
1230
1231
0
    if (PyODict_CheckExact(od)) {
1232
0
        _odict_FOREACH(od, node) {
1233
0
            PyObject *key = _odictnode_KEY(node);
1234
0
            PyObject *value = _odictnode_VALUE(node, od);
1235
0
            if (value == NULL) {
1236
0
                if (!PyErr_Occurred())
1237
0
                    PyErr_SetObject(PyExc_KeyError, key);
1238
0
                goto fail;
1239
0
            }
1240
0
            if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1241
0
                                           _odictnode_HASH(node)) != 0)
1242
0
                goto fail;
1243
0
        }
1244
0
    }
1245
0
    else {
1246
0
        _odict_FOREACH(od, node) {
1247
0
            int res;
1248
0
            PyObject *value = PyObject_GetItem((PyObject *)od,
1249
0
                                               _odictnode_KEY(node));
1250
0
            if (value == NULL)
1251
0
                goto fail;
1252
0
            res = PyObject_SetItem((PyObject *)od_copy,
1253
0
                                   _odictnode_KEY(node), value);
1254
0
            Py_DECREF(value);
1255
0
            if (res != 0)
1256
0
                goto fail;
1257
0
        }
1258
0
    }
1259
0
    return od_copy;
1260
1261
0
fail:
1262
0
    Py_DECREF(od_copy);
1263
0
    return NULL;
1264
0
}
1265
1266
/* __reversed__() */
1267
1268
PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1269
1270
0
#define _odict_ITER_REVERSED 1
1271
0
#define _odict_ITER_KEYS 2
1272
0
#define _odict_ITER_VALUES 4
1273
0
#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES)
1274
1275
/* forward */
1276
static PyObject * odictiter_new(PyODictObject *, int);
1277
1278
static PyObject *
1279
odict_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1280
0
{
1281
0
    PyODictObject *od = _PyODictObject_CAST(op);
1282
0
    return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1283
0
}
1284
1285
1286
/* move_to_end() */
1287
1288
/*[clinic input]
1289
OrderedDict.move_to_end
1290
1291
    key: object
1292
    last: bool = True
1293
1294
Move an existing element to the end (or beginning if last is false).
1295
1296
Raise KeyError if the element does not exist.
1297
[clinic start generated code]*/
1298
1299
static PyObject *
1300
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
1301
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
1302
0
{
1303
0
    _ODictNode *node;
1304
1305
0
    if (_odict_EMPTY(self)) {
1306
0
        PyErr_SetObject(PyExc_KeyError, key);
1307
0
        return NULL;
1308
0
    }
1309
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1310
0
    if (key != _odictnode_KEY(node)) {
1311
0
        node = _odict_find_node(self, key);
1312
0
        if (node == NULL) {
1313
0
            if (!PyErr_Occurred())
1314
0
                PyErr_SetObject(PyExc_KeyError, key);
1315
0
            return NULL;
1316
0
        }
1317
0
        if (last) {
1318
            /* Only move if not already the last one. */
1319
0
            if (node != _odict_LAST(self)) {
1320
0
                _odict_remove_node(self, node);
1321
0
                _odict_add_tail(self, node);
1322
0
            }
1323
0
        }
1324
0
        else {
1325
            /* Only move if not already the first one. */
1326
0
            if (node != _odict_FIRST(self)) {
1327
0
                _odict_remove_node(self, node);
1328
0
                _odict_add_head(self, node);
1329
0
            }
1330
0
        }
1331
0
    }
1332
0
    Py_RETURN_NONE;
1333
0
}
1334
1335
1336
/* tp_methods */
1337
1338
static PyMethodDef odict_methods[] = {
1339
1340
    /* overridden dict methods */
1341
    ORDEREDDICT_FROMKEYS_METHODDEF
1342
    {"__sizeof__",      odict_sizeof,      METH_NOARGS,
1343
     odict_sizeof__doc__},
1344
    {"__reduce__",      odict_reduce,      METH_NOARGS,
1345
     odict_reduce__doc__},
1346
    ORDEREDDICT_SETDEFAULT_METHODDEF
1347
    ORDEREDDICT_POP_METHODDEF
1348
    ORDEREDDICT_POPITEM_METHODDEF
1349
    {"keys",            odictkeys_new,                  METH_NOARGS,
1350
     odict_keys__doc__},
1351
    {"values",          odictvalues_new,                METH_NOARGS,
1352
     odict_values__doc__},
1353
    {"items",           odictitems_new,                 METH_NOARGS,
1354
     odict_items__doc__},
1355
    {"update",          _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,
1356
     odict_update__doc__},
1357
    {"clear",           odict_clear,       METH_NOARGS,
1358
     odict_clear__doc__},
1359
    {"copy",            odict_copy,        METH_NOARGS,
1360
     odict_copy__doc__},
1361
1362
    /* new methods */
1363
    {"__reversed__",    odict_reversed,    METH_NOARGS,
1364
     odict_reversed__doc__},
1365
    ORDEREDDICT_MOVE_TO_END_METHODDEF
1366
1367
    {NULL,              NULL}   /* sentinel */
1368
};
1369
1370
1371
/* ----------------------------------------------
1372
 * OrderedDict members
1373
 */
1374
1375
/* tp_getset */
1376
1377
static PyGetSetDef odict_getset[] = {
1378
    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1379
    {NULL}
1380
};
1381
1382
/* ----------------------------------------------
1383
 * OrderedDict type slot methods
1384
 */
1385
1386
/* tp_dealloc */
1387
1388
static void
1389
odict_dealloc(PyObject *op)
1390
0
{
1391
0
    PyODictObject *self = _PyODictObject_CAST(op);
1392
0
    PyObject_GC_UnTrack(self);
1393
1394
0
    Py_XDECREF(self->od_inst_dict);
1395
0
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1396
1397
0
    _odict_clear_nodes(self);
1398
0
    PyDict_Type.tp_dealloc((PyObject *)self);
1399
0
}
1400
1401
/* tp_repr */
1402
1403
static PyObject *
1404
odict_repr(PyObject *op)
1405
0
{
1406
0
    PyODictObject *self = _PyODictObject_CAST(op);
1407
0
    int i;
1408
0
    PyObject *result = NULL, *dcopy = NULL;
1409
1410
0
    if (PyODict_SIZE(self) == 0)
1411
0
        return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
1412
1413
0
    i = Py_ReprEnter((PyObject *)self);
1414
0
    if (i != 0) {
1415
0
        return i > 0 ? PyUnicode_FromString("...") : NULL;
1416
0
    }
1417
1418
0
    dcopy = PyDict_Copy((PyObject *)self);
1419
0
    if (dcopy == NULL) {
1420
0
        goto Done;
1421
0
    }
1422
1423
0
    result = PyUnicode_FromFormat("%s(%R)",
1424
0
                                  _PyType_Name(Py_TYPE(self)),
1425
0
                                  dcopy);
1426
0
    Py_DECREF(dcopy);
1427
1428
0
Done:
1429
0
    Py_ReprLeave((PyObject *)self);
1430
0
    return result;
1431
0
}
1432
1433
/* tp_doc */
1434
1435
PyDoc_STRVAR(odict_doc,
1436
        "Dictionary that remembers insertion order");
1437
1438
/* tp_traverse */
1439
1440
static int
1441
odict_traverse(PyObject *op, visitproc visit, void *arg)
1442
0
{
1443
0
    PyODictObject *od = _PyODictObject_CAST(op);
1444
0
    _ODictNode *node;
1445
1446
0
    Py_VISIT(od->od_inst_dict);
1447
0
    _odict_FOREACH(od, node) {
1448
0
        Py_VISIT(_odictnode_KEY(node));
1449
0
    }
1450
0
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1451
0
}
1452
1453
/* tp_clear */
1454
1455
static int
1456
odict_tp_clear(PyObject *op)
1457
0
{
1458
0
    PyODictObject *od = _PyODictObject_CAST(op);
1459
0
    Py_CLEAR(od->od_inst_dict);
1460
0
    PyDict_Clear((PyObject *)od);
1461
0
    _odict_clear_nodes(od);
1462
0
    return 0;
1463
0
}
1464
1465
/* tp_richcompare */
1466
1467
static PyObject *
1468
odict_richcompare(PyObject *v, PyObject *w, int op)
1469
0
{
1470
0
    if (!PyODict_Check(v) || !PyDict_Check(w)) {
1471
0
        Py_RETURN_NOTIMPLEMENTED;
1472
0
    }
1473
1474
0
    if (op == Py_EQ || op == Py_NE) {
1475
0
        PyObject *res, *cmp;
1476
0
        int eq;
1477
1478
0
        cmp = PyDict_Type.tp_richcompare(v, w, op);
1479
0
        if (cmp == NULL)
1480
0
            return NULL;
1481
0
        if (!PyODict_Check(w))
1482
0
            return cmp;
1483
0
        if (op == Py_EQ && cmp == Py_False)
1484
0
            return cmp;
1485
0
        if (op == Py_NE && cmp == Py_True)
1486
0
            return cmp;
1487
0
        Py_DECREF(cmp);
1488
1489
        /* Try comparing odict keys. */
1490
0
        eq = _odict_keys_equal(_PyODictObject_CAST(v), _PyODictObject_CAST(w));
1491
0
        if (eq < 0)
1492
0
            return NULL;
1493
1494
0
        res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1495
0
        return Py_NewRef(res);
1496
0
    } else {
1497
0
        Py_RETURN_NOTIMPLEMENTED;
1498
0
    }
1499
0
}
1500
1501
/* tp_iter */
1502
1503
static PyObject *
1504
odict_iter(PyObject *op)
1505
0
{
1506
0
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1507
0
}
1508
1509
/* tp_init */
1510
1511
static int
1512
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1513
0
{
1514
0
    PyObject *res;
1515
0
    Py_ssize_t len = PyObject_Length(args);
1516
1517
0
    if (len == -1)
1518
0
        return -1;
1519
0
    if (len > 1) {
1520
0
        const char *msg = "expected at most 1 arguments, got %zd";
1521
0
        PyErr_Format(PyExc_TypeError, msg, len);
1522
0
        return -1;
1523
0
    }
1524
1525
    /* __init__() triggering update() is just the way things are! */
1526
0
    res = odict_update(self, args, kwds);
1527
0
    if (res == NULL) {
1528
0
        return -1;
1529
0
    } else {
1530
0
        Py_DECREF(res);
1531
0
        return 0;
1532
0
    }
1533
0
}
1534
1535
/* PyODict_Type */
1536
1537
PyTypeObject PyODict_Type = {
1538
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1539
    "collections.OrderedDict",                  /* tp_name */
1540
    sizeof(PyODictObject),                      /* tp_basicsize */
1541
    0,                                          /* tp_itemsize */
1542
    odict_dealloc,                              /* tp_dealloc */
1543
    0,                                          /* tp_vectorcall_offset */
1544
    0,                                          /* tp_getattr */
1545
    0,                                          /* tp_setattr */
1546
    0,                                          /* tp_as_async */
1547
    odict_repr,                                 /* tp_repr */
1548
    &odict_as_number,                           /* tp_as_number */
1549
    0,                                          /* tp_as_sequence */
1550
    &odict_as_mapping,                          /* tp_as_mapping */
1551
    0,                                          /* tp_hash */
1552
    0,                                          /* tp_call */
1553
    0,                                          /* tp_str */
1554
    0,                                          /* tp_getattro */
1555
    0,                                          /* tp_setattro */
1556
    0,                                          /* tp_as_buffer */
1557
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1558
    odict_doc,                                  /* tp_doc */
1559
    odict_traverse,                             /* tp_traverse */
1560
    odict_tp_clear,                             /* tp_clear */
1561
    odict_richcompare,                          /* tp_richcompare */
1562
    offsetof(PyODictObject, od_weakreflist),    /* tp_weaklistoffset */
1563
    odict_iter,                                 /* tp_iter */
1564
    0,                                          /* tp_iternext */
1565
    odict_methods,                              /* tp_methods */
1566
    0,                                          /* tp_members */
1567
    odict_getset,                               /* tp_getset */
1568
    &PyDict_Type,                               /* tp_base */
1569
    0,                                          /* tp_dict */
1570
    0,                                          /* tp_descr_get */
1571
    0,                                          /* tp_descr_set */
1572
    offsetof(PyODictObject, od_inst_dict),      /* tp_dictoffset */
1573
    odict_init,                                 /* tp_init */
1574
    PyType_GenericAlloc,                        /* tp_alloc */
1575
    0,                                          /* tp_new */
1576
    0,                                          /* tp_free */
1577
};
1578
1579
1580
/* ----------------------------------------------
1581
 * the public OrderedDict API
1582
 */
1583
1584
PyObject *
1585
PyODict_New(void)
1586
0
{
1587
0
    return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
1588
0
}
1589
1590
static int
1591
_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1592
                           Py_hash_t hash)
1593
0
{
1594
0
    int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
1595
0
    if (res == 0) {
1596
0
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1597
0
        if (res < 0) {
1598
            /* Revert setting the value on the dict */
1599
0
            PyObject *exc = PyErr_GetRaisedException();
1600
0
            (void) _PyDict_DelItem_KnownHash(od, key, hash);
1601
0
            _PyErr_ChainExceptions1(exc);
1602
0
        }
1603
0
    }
1604
0
    return res;
1605
0
}
1606
1607
int
1608
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1609
0
{
1610
0
    Py_hash_t hash = PyObject_Hash(key);
1611
0
    if (hash == -1)
1612
0
        return -1;
1613
0
    return _PyODict_SetItem_KnownHash(od, key, value, hash);
1614
0
}
1615
1616
int
1617
PyODict_DelItem(PyObject *od, PyObject *key)
1618
0
{
1619
0
    int res;
1620
0
    Py_hash_t hash = PyObject_Hash(key);
1621
0
    if (hash == -1)
1622
0
        return -1;
1623
0
    res = _odict_clear_node(_PyODictObject_CAST(od), NULL, key, hash);
1624
0
    if (res < 0)
1625
0
        return -1;
1626
0
    return _PyDict_DelItem_KnownHash(od, key, hash);
1627
0
}
1628
1629
1630
/* -------------------------------------------
1631
 * The OrderedDict views (keys/values/items)
1632
 */
1633
1634
typedef struct {
1635
    PyObject_HEAD
1636
    int kind;
1637
    PyODictObject *di_odict;
1638
    Py_ssize_t di_size;
1639
    size_t di_state;
1640
    PyObject *di_current;
1641
    PyObject *di_result; /* reusable result tuple for iteritems */
1642
} odictiterobject;
1643
1644
static void
1645
odictiter_dealloc(PyObject *op)
1646
0
{
1647
0
    odictiterobject *di = (odictiterobject*)op;
1648
0
    _PyObject_GC_UNTRACK(di);
1649
0
    Py_XDECREF(di->di_odict);
1650
0
    Py_XDECREF(di->di_current);
1651
0
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1652
0
        Py_DECREF(di->di_result);
1653
0
    }
1654
0
    PyObject_GC_Del(di);
1655
0
}
1656
1657
static int
1658
odictiter_traverse(PyObject *op, visitproc visit, void *arg)
1659
0
{
1660
0
    odictiterobject *di = (odictiterobject*)op;
1661
0
    Py_VISIT(di->di_odict);
1662
0
    Py_VISIT(di->di_current);  /* A key could be any type, not just str. */
1663
0
    Py_VISIT(di->di_result);
1664
0
    return 0;
1665
0
}
1666
1667
/* In order to protect against modifications during iteration, we track
1668
 * the current key instead of the current node. */
1669
static PyObject *
1670
odictiter_nextkey(odictiterobject *di)
1671
0
{
1672
0
    PyObject *key = NULL;
1673
0
    _ODictNode *node;
1674
0
    int reversed = di->kind & _odict_ITER_REVERSED;
1675
1676
0
    if (di->di_odict == NULL)
1677
0
        return NULL;
1678
0
    if (di->di_current == NULL)
1679
0
        goto done;  /* We're already done. */
1680
1681
    /* Check for unsupported changes. */
1682
0
    if (di->di_odict->od_state != di->di_state) {
1683
0
        PyErr_SetString(PyExc_RuntimeError,
1684
0
                        "OrderedDict mutated during iteration");
1685
0
        goto done;
1686
0
    }
1687
0
    if (di->di_size != PyODict_SIZE(di->di_odict)) {
1688
0
        PyErr_SetString(PyExc_RuntimeError,
1689
0
                        "OrderedDict changed size during iteration");
1690
0
        di->di_size = -1; /* Make this state sticky */
1691
0
        return NULL;
1692
0
    }
1693
1694
    /* Get the key. */
1695
0
    node = _odict_find_node(di->di_odict, di->di_current);
1696
0
    if (node == NULL) {
1697
0
        if (!PyErr_Occurred())
1698
0
            PyErr_SetObject(PyExc_KeyError, di->di_current);
1699
        /* Must have been deleted. */
1700
0
        Py_CLEAR(di->di_current);
1701
0
        return NULL;
1702
0
    }
1703
0
    key = di->di_current;
1704
1705
    /* Advance to the next key. */
1706
0
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1707
0
    if (node == NULL) {
1708
        /* Reached the end. */
1709
0
        di->di_current = NULL;
1710
0
    }
1711
0
    else {
1712
0
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1713
0
    }
1714
1715
0
    return key;
1716
1717
0
done:
1718
0
    Py_CLEAR(di->di_odict);
1719
0
    return key;
1720
0
}
1721
1722
static PyObject *
1723
odictiter_iternext(PyObject *op)
1724
0
{
1725
0
    odictiterobject *di = (odictiterobject*)op;
1726
0
    PyObject *result, *value;
1727
0
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1728
1729
0
    if (key == NULL)
1730
0
        return NULL;
1731
1732
    /* Handle the keys case. */
1733
0
    if (! (di->kind & _odict_ITER_VALUES)) {
1734
0
        return key;
1735
0
    }
1736
1737
0
    value = PyODict_GetItem((PyObject *)di->di_odict, key);  /* borrowed */
1738
0
    if (value == NULL) {
1739
0
        if (!PyErr_Occurred())
1740
0
            PyErr_SetObject(PyExc_KeyError, key);
1741
0
        Py_DECREF(key);
1742
0
        goto done;
1743
0
    }
1744
0
    Py_INCREF(value);
1745
1746
    /* Handle the values case. */
1747
0
    if (!(di->kind & _odict_ITER_KEYS)) {
1748
0
        Py_DECREF(key);
1749
0
        return value;
1750
0
    }
1751
1752
    /* Handle the items case. */
1753
0
    result = di->di_result;
1754
1755
0
    if (Py_REFCNT(result) == 1) {
1756
        /* not in use so we can reuse it
1757
         * (the common case during iteration) */
1758
0
        Py_INCREF(result);
1759
0
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1760
0
        Py_DECREF(PyTuple_GET_ITEM(result, 1));  /* borrowed */
1761
        // bpo-42536: The GC may have untracked this result tuple. Since we're
1762
        // recycling it, make sure it's tracked again:
1763
0
        _PyTuple_Recycle(result);
1764
0
    }
1765
0
    else {
1766
0
        result = PyTuple_New(2);
1767
0
        if (result == NULL) {
1768
0
            Py_DECREF(key);
1769
0
            Py_DECREF(value);
1770
0
            goto done;
1771
0
        }
1772
0
    }
1773
1774
0
    PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1775
0
    PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1776
0
    return result;
1777
1778
0
done:
1779
0
    Py_CLEAR(di->di_current);
1780
0
    Py_CLEAR(di->di_odict);
1781
0
    return NULL;
1782
0
}
1783
1784
/* No need for tp_clear because odictiterobject is not mutable. */
1785
1786
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1787
1788
static PyObject *
1789
odictiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1790
0
{
1791
0
    odictiterobject *di = (odictiterobject*)op;
1792
1793
    /* copy the iterator state */
1794
0
    odictiterobject tmp = *di;
1795
0
    Py_XINCREF(tmp.di_odict);
1796
0
    Py_XINCREF(tmp.di_current);
1797
1798
    /* iterate the temporary into a list */
1799
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1800
0
    Py_XDECREF(tmp.di_odict);
1801
0
    Py_XDECREF(tmp.di_current);
1802
0
    if (list == NULL) {
1803
0
        return NULL;
1804
0
    }
1805
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1806
0
}
1807
1808
static PyMethodDef odictiter_methods[] = {
1809
    {"__reduce__", odictiter_reduce, METH_NOARGS, reduce_doc},
1810
    {NULL,              NULL}           /* sentinel */
1811
};
1812
1813
PyTypeObject PyODictIter_Type = {
1814
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1815
    "odict_iterator",                         /* tp_name */
1816
    sizeof(odictiterobject),                  /* tp_basicsize */
1817
    0,                                        /* tp_itemsize */
1818
    /* methods */
1819
    odictiter_dealloc,                        /* tp_dealloc */
1820
    0,                                        /* tp_vectorcall_offset */
1821
    0,                                        /* tp_getattr */
1822
    0,                                        /* tp_setattr */
1823
    0,                                        /* tp_as_async */
1824
    0,                                        /* tp_repr */
1825
    0,                                        /* tp_as_number */
1826
    0,                                        /* tp_as_sequence */
1827
    0,                                        /* tp_as_mapping */
1828
    0,                                        /* tp_hash */
1829
    0,                                        /* tp_call */
1830
    0,                                        /* tp_str */
1831
    PyObject_GenericGetAttr,                  /* tp_getattro */
1832
    0,                                        /* tp_setattro */
1833
    0,                                        /* tp_as_buffer */
1834
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1835
    0,                                        /* tp_doc */
1836
    odictiter_traverse,                       /* tp_traverse */
1837
    0,                                        /* tp_clear */
1838
    0,                                        /* tp_richcompare */
1839
    0,                                        /* tp_weaklistoffset */
1840
    PyObject_SelfIter,                        /* tp_iter */
1841
    odictiter_iternext,                       /* tp_iternext */
1842
    odictiter_methods,                        /* tp_methods */
1843
    0,
1844
};
1845
1846
static PyObject *
1847
odictiter_new(PyODictObject *od, int kind)
1848
0
{
1849
0
    odictiterobject *di;
1850
0
    _ODictNode *node;
1851
0
    int reversed = kind & _odict_ITER_REVERSED;
1852
1853
0
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1854
0
    if (di == NULL)
1855
0
        return NULL;
1856
1857
0
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1858
0
        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1859
0
        if (di->di_result == NULL) {
1860
0
            Py_DECREF(di);
1861
0
            return NULL;
1862
0
        }
1863
0
    }
1864
0
    else {
1865
0
        di->di_result = NULL;
1866
0
    }
1867
1868
0
    di->kind = kind;
1869
0
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1870
0
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1871
0
    di->di_size = PyODict_SIZE(od);
1872
0
    di->di_state = od->od_state;
1873
0
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1874
1875
0
    _PyObject_GC_TRACK(di);
1876
0
    return (PyObject *)di;
1877
0
}
1878
1879
/* keys() */
1880
1881
static PyObject *
1882
odictkeys_iter(PyObject *op)
1883
0
{
1884
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1885
0
    if (dv->dv_dict == NULL) {
1886
0
        Py_RETURN_NONE;
1887
0
    }
1888
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1889
0
            _odict_ITER_KEYS);
1890
0
}
1891
1892
static PyObject *
1893
odictkeys_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1894
0
{
1895
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1896
0
    if (dv->dv_dict == NULL) {
1897
0
        Py_RETURN_NONE;
1898
0
    }
1899
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1900
0
            _odict_ITER_KEYS|_odict_ITER_REVERSED);
1901
0
}
1902
1903
static PyMethodDef odictkeys_methods[] = {
1904
    {"__reversed__", odictkeys_reversed, METH_NOARGS, NULL},
1905
    {NULL,          NULL}           /* sentinel */
1906
};
1907
1908
PyTypeObject PyODictKeys_Type = {
1909
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1910
    "odict_keys",                             /* tp_name */
1911
    0,                                        /* tp_basicsize */
1912
    0,                                        /* tp_itemsize */
1913
    0,                                        /* tp_dealloc */
1914
    0,                                        /* tp_vectorcall_offset */
1915
    0,                                        /* tp_getattr */
1916
    0,                                        /* tp_setattr */
1917
    0,                                        /* tp_as_async */
1918
    0,                                        /* tp_repr */
1919
    0,                                        /* tp_as_number */
1920
    0,                                        /* tp_as_sequence */
1921
    0,                                        /* tp_as_mapping */
1922
    0,                                        /* tp_hash */
1923
    0,                                        /* tp_call */
1924
    0,                                        /* tp_str */
1925
    0,                                        /* tp_getattro */
1926
    0,                                        /* tp_setattro */
1927
    0,                                        /* tp_as_buffer */
1928
    0,                                        /* tp_flags */
1929
    0,                                        /* tp_doc */
1930
    0,                                        /* tp_traverse */
1931
    0,                                        /* tp_clear */
1932
    0,                                        /* tp_richcompare */
1933
    0,                                        /* tp_weaklistoffset */
1934
    odictkeys_iter,                           /* tp_iter */
1935
    0,                                        /* tp_iternext */
1936
    odictkeys_methods,                        /* tp_methods */
1937
    0,                                        /* tp_members */
1938
    0,                                        /* tp_getset */
1939
    &PyDictKeys_Type,                         /* tp_base */
1940
};
1941
1942
static PyObject *
1943
odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
1944
0
{
1945
0
    return _PyDictView_New(od, &PyODictKeys_Type);
1946
0
}
1947
1948
/* items() */
1949
1950
static PyObject *
1951
odictitems_iter(PyObject *op)
1952
0
{
1953
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1954
0
    if (dv->dv_dict == NULL) {
1955
0
        Py_RETURN_NONE;
1956
0
    }
1957
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1958
0
            _odict_ITER_KEYS|_odict_ITER_VALUES);
1959
0
}
1960
1961
static PyObject *
1962
odictitems_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1963
0
{
1964
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1965
0
    if (dv->dv_dict == NULL) {
1966
0
        Py_RETURN_NONE;
1967
0
    }
1968
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1969
0
            _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
1970
0
}
1971
1972
static PyMethodDef odictitems_methods[] = {
1973
    {"__reversed__", odictitems_reversed, METH_NOARGS, NULL},
1974
    {NULL,          NULL}           /* sentinel */
1975
};
1976
1977
PyTypeObject PyODictItems_Type = {
1978
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1979
    "odict_items",                            /* tp_name */
1980
    0,                                        /* tp_basicsize */
1981
    0,                                        /* tp_itemsize */
1982
    0,                                        /* tp_dealloc */
1983
    0,                                        /* tp_vectorcall_offset */
1984
    0,                                        /* tp_getattr */
1985
    0,                                        /* tp_setattr */
1986
    0,                                        /* tp_as_async */
1987
    0,                                        /* tp_repr */
1988
    0,                                        /* tp_as_number */
1989
    0,                                        /* tp_as_sequence */
1990
    0,                                        /* tp_as_mapping */
1991
    0,                                        /* tp_hash */
1992
    0,                                        /* tp_call */
1993
    0,                                        /* tp_str */
1994
    0,                                        /* tp_getattro */
1995
    0,                                        /* tp_setattro */
1996
    0,                                        /* tp_as_buffer */
1997
    0,                                        /* tp_flags */
1998
    0,                                        /* tp_doc */
1999
    0,                                        /* tp_traverse */
2000
    0,                                        /* tp_clear */
2001
    0,                                        /* tp_richcompare */
2002
    0,                                        /* tp_weaklistoffset */
2003
    odictitems_iter,                          /* tp_iter */
2004
    0,                                        /* tp_iternext */
2005
    odictitems_methods,                       /* tp_methods */
2006
    0,                                        /* tp_members */
2007
    0,                                        /* tp_getset */
2008
    &PyDictItems_Type,                        /* tp_base */
2009
};
2010
2011
static PyObject *
2012
odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2013
0
{
2014
0
    return _PyDictView_New(od, &PyODictItems_Type);
2015
0
}
2016
2017
/* values() */
2018
2019
static PyObject *
2020
odictvalues_iter(PyObject *op)
2021
0
{
2022
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2023
0
    if (dv->dv_dict == NULL) {
2024
0
        Py_RETURN_NONE;
2025
0
    }
2026
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2027
0
            _odict_ITER_VALUES);
2028
0
}
2029
2030
static PyObject *
2031
odictvalues_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2032
0
{
2033
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2034
0
    if (dv->dv_dict == NULL) {
2035
0
        Py_RETURN_NONE;
2036
0
    }
2037
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2038
0
            _odict_ITER_VALUES|_odict_ITER_REVERSED);
2039
0
}
2040
2041
static PyMethodDef odictvalues_methods[] = {
2042
    {"__reversed__", odictvalues_reversed, METH_NOARGS, NULL},
2043
    {NULL,          NULL}           /* sentinel */
2044
};
2045
2046
PyTypeObject PyODictValues_Type = {
2047
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2048
    "odict_values",                           /* tp_name */
2049
    0,                                        /* tp_basicsize */
2050
    0,                                        /* tp_itemsize */
2051
    0,                                        /* tp_dealloc */
2052
    0,                                        /* tp_vectorcall_offset */
2053
    0,                                        /* tp_getattr */
2054
    0,                                        /* tp_setattr */
2055
    0,                                        /* tp_as_async */
2056
    0,                                        /* tp_repr */
2057
    0,                                        /* tp_as_number */
2058
    0,                                        /* tp_as_sequence */
2059
    0,                                        /* tp_as_mapping */
2060
    0,                                        /* tp_hash */
2061
    0,                                        /* tp_call */
2062
    0,                                        /* tp_str */
2063
    0,                                        /* tp_getattro */
2064
    0,                                        /* tp_setattro */
2065
    0,                                        /* tp_as_buffer */
2066
    0,                                        /* tp_flags */
2067
    0,                                        /* tp_doc */
2068
    0,                                        /* tp_traverse */
2069
    0,                                        /* tp_clear */
2070
    0,                                        /* tp_richcompare */
2071
    0,                                        /* tp_weaklistoffset */
2072
    odictvalues_iter,                         /* tp_iter */
2073
    0,                                        /* tp_iternext */
2074
    odictvalues_methods,                      /* tp_methods */
2075
    0,                                        /* tp_members */
2076
    0,                                        /* tp_getset */
2077
    &PyDictValues_Type,                       /* tp_base */
2078
};
2079
2080
static PyObject *
2081
odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2082
0
{
2083
0
    return _PyDictView_New(od, &PyODictValues_Type);
2084
0
}
2085
2086
2087
/* ----------------------------------------------
2088
   MutableMapping implementations
2089
2090
Mapping:
2091
2092
============ ===========
2093
method       uses
2094
============ ===========
2095
__contains__ __getitem__
2096
__eq__       items
2097
__getitem__  +
2098
__iter__     +
2099
__len__      +
2100
__ne__       __eq__
2101
get          __getitem__
2102
items        ItemsView
2103
keys         KeysView
2104
values       ValuesView
2105
============ ===========
2106
2107
ItemsView uses __len__, __iter__, and __getitem__.
2108
KeysView uses __len__, __iter__, and __contains__.
2109
ValuesView uses __len__, __iter__, and __getitem__.
2110
2111
MutableMapping:
2112
2113
============ ===========
2114
method       uses
2115
============ ===========
2116
__delitem__  +
2117
__setitem__  +
2118
clear        popitem
2119
pop          __getitem__
2120
             __delitem__
2121
popitem      __iter__
2122
             _getitem__
2123
             __delitem__
2124
setdefault   __getitem__
2125
             __setitem__
2126
update       __setitem__
2127
============ ===========
2128
*/
2129
2130
static int
2131
mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2132
0
{
2133
0
    PyObject *pair, *iterator, *unexpected;
2134
0
    int res = 0;
2135
2136
0
    iterator = PyObject_GetIter(pairs);
2137
0
    if (iterator == NULL)
2138
0
        return -1;
2139
0
    PyErr_Clear();
2140
2141
0
    while ((pair = PyIter_Next(iterator)) != NULL) {
2142
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2143
0
        PyObject *key = NULL, *value = NULL;
2144
0
        PyObject *pair_iterator = PyObject_GetIter(pair);
2145
0
        if (pair_iterator == NULL)
2146
0
            goto Done;
2147
2148
0
        key = PyIter_Next(pair_iterator);
2149
0
        if (key == NULL) {
2150
0
            if (!PyErr_Occurred())
2151
0
                PyErr_SetString(PyExc_ValueError,
2152
0
                                "need more than 0 values to unpack");
2153
0
            goto Done;
2154
0
        }
2155
2156
0
        value = PyIter_Next(pair_iterator);
2157
0
        if (value == NULL) {
2158
0
            if (!PyErr_Occurred())
2159
0
                PyErr_SetString(PyExc_ValueError,
2160
0
                                "need more than 1 value to unpack");
2161
0
            goto Done;
2162
0
        }
2163
2164
0
        unexpected = PyIter_Next(pair_iterator);
2165
0
        if (unexpected != NULL) {
2166
0
            Py_DECREF(unexpected);
2167
0
            PyErr_SetString(PyExc_ValueError,
2168
0
                            "too many values to unpack (expected 2)");
2169
0
            goto Done;
2170
0
        }
2171
0
        else if (PyErr_Occurred())
2172
0
            goto Done;
2173
2174
0
        res = PyObject_SetItem(self, key, value);
2175
2176
0
Done:
2177
0
        Py_DECREF(pair);
2178
0
        Py_XDECREF(pair_iterator);
2179
0
        Py_XDECREF(key);
2180
0
        Py_XDECREF(value);
2181
0
        if (PyErr_Occurred())
2182
0
            break;
2183
0
    }
2184
0
    Py_DECREF(iterator);
2185
2186
0
    if (res < 0 || PyErr_Occurred() != NULL)
2187
0
        return -1;
2188
0
    else
2189
0
        return 0;
2190
0
}
2191
2192
static int
2193
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2194
0
{
2195
0
    int res = 0;
2196
0
    if (PyDict_CheckExact(arg)) {
2197
0
        PyObject *items = PyDict_Items(arg);
2198
0
        if (items == NULL) {
2199
0
            return -1;
2200
0
        }
2201
0
        res = mutablemapping_add_pairs(self, items);
2202
0
        Py_DECREF(items);
2203
0
        return res;
2204
0
    }
2205
0
    PyObject *func;
2206
0
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2207
0
        return -1;
2208
0
    }
2209
0
    if (func != NULL) {
2210
0
        PyObject *keys = _PyObject_CallNoArgs(func);
2211
0
        Py_DECREF(func);
2212
0
        if (keys == NULL) {
2213
0
            return -1;
2214
0
        }
2215
0
        PyObject *iterator = PyObject_GetIter(keys);
2216
0
        Py_DECREF(keys);
2217
0
        if (iterator == NULL) {
2218
0
            return -1;
2219
0
        }
2220
0
        PyObject *key;
2221
0
        while (res == 0 && (key = PyIter_Next(iterator))) {
2222
0
            PyObject *value = PyObject_GetItem(arg, key);
2223
0
            if (value != NULL) {
2224
0
                res = PyObject_SetItem(self, key, value);
2225
0
                Py_DECREF(value);
2226
0
            }
2227
0
            else {
2228
0
                res = -1;
2229
0
            }
2230
0
            Py_DECREF(key);
2231
0
        }
2232
0
        Py_DECREF(iterator);
2233
0
        if (res != 0 || PyErr_Occurred()) {
2234
0
            return -1;
2235
0
        }
2236
0
        return 0;
2237
0
    }
2238
0
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2239
0
        return -1;
2240
0
    }
2241
0
    if (func != NULL) {
2242
0
        PyObject *items = _PyObject_CallNoArgs(func);
2243
0
        Py_DECREF(func);
2244
0
        if (items == NULL) {
2245
0
            return -1;
2246
0
        }
2247
0
        res = mutablemapping_add_pairs(self, items);
2248
0
        Py_DECREF(items);
2249
0
        return res;
2250
0
    }
2251
0
    res = mutablemapping_add_pairs(self, arg);
2252
0
    return res;
2253
0
}
2254
2255
static PyObject *
2256
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2257
0
{
2258
0
    int res;
2259
    /* first handle args, if any */
2260
0
    assert(args == NULL || PyTuple_Check(args));
2261
0
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2262
0
    if (len > 1) {
2263
0
        const char *msg = "update() takes at most 1 positional argument (%zd given)";
2264
0
        PyErr_Format(PyExc_TypeError, msg, len);
2265
0
        return NULL;
2266
0
    }
2267
2268
0
    if (len) {
2269
0
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2270
0
        assert(other != NULL);
2271
0
        Py_INCREF(other);
2272
0
        res = mutablemapping_update_arg(self, other);
2273
0
        Py_DECREF(other);
2274
0
        if (res < 0) {
2275
0
            return NULL;
2276
0
        }
2277
0
    }
2278
2279
    /* now handle kwargs */
2280
0
    assert(kwargs == NULL || PyDict_Check(kwargs));
2281
0
    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2282
0
        PyObject *items = PyDict_Items(kwargs);
2283
0
        if (items == NULL)
2284
0
            return NULL;
2285
0
        res = mutablemapping_add_pairs(self, items);
2286
0
        Py_DECREF(items);
2287
0
        if (res == -1)
2288
0
            return NULL;
2289
0
    }
2290
2291
0
    Py_RETURN_NONE;
2292
0
}