blob: 220ae92ec929621ce97d8cebd9b96fa597ed695b [file] [log] [blame]
Eric Snow96c6af92015-05-29 22:21:39 -06001/* Ordered Dictionary object implementation.
2
3This implementation is necessarily explicitly equivalent to the pure Python
4OrderedDict class in Lib/collections/__init__.py. The strategy there
5involves using a doubly-linked-list to capture the order. We keep to that
6strategy, using a lower-level linked-list.
7
8About the Linked-List
9=====================
10
11For the linked list we use a basic doubly-linked-list. Using a circularly-
12linked-list does have some benefits, but they don't apply so much here
13since OrderedDict is focused on the ends of the list (for the most part).
14Furthermore, there are some features of generic linked-lists that we simply
15don't need for OrderedDict. Thus a simple custom implementation meets our
16needs. Alternatives to our simple approach include the QCIRCLE_*
17macros from BSD's queue.h, and the linux's list.h.
18
19Getting O(1) Node Lookup
20------------------------
21
22One invariant of Python's OrderedDict is that it preserves time complexity
23of dict's methods, particularly the O(1) operations. Simply adding a
24linked-list on top of dict is not sufficient here; operations for nodes in
25the middle of the linked-list implicitly require finding the node first.
26With a simple linked-list like we're using, that is an O(n) operation.
27Consequently, methods like __delitem__() would change from O(1) to O(n),
28which is unacceptable.
29
30In order to preserve O(1) performance for node removal (finding nodes), we
31must do better than just looping through the linked-list. Here are options
32we've considered:
33
341. use a second dict to map keys to nodes (a la the pure Python version).
352. keep a simple hash table mirroring the order of dict's, mapping each key
36 to the corresponding node in the linked-list.
373. use a version of shared keys (split dict) that allows non-unicode keys.
384. have the value stored for each key be a (value, node) pair, and adjust
39 __getitem__(), get(), etc. accordingly.
40
41The approach with the least performance impact (time and space) is #2,
Benjamin Petersonee178e62016-09-08 11:08:30 -070042mirroring the key order of dict's dk_entries with an array of node pointers.
Eric Snow96c6af92015-05-29 22:21:39 -060043While lookdict() and friends (dk_lookup) don't give us the index into the
44array, we make use of pointer arithmetic to get that index. An alternative
45would be to refactor lookdict() to provide the index, explicitly exposing
46the implementation detail. We could even just use a custom lookup function
47for OrderedDict that facilitates our need. However, both approaches are
48significantly more complicated than just using pointer arithmetic.
49
50The catch with mirroring the hash table ordering is that we have to keep
51the ordering in sync through any dict resizes. However, that order only
52matters during node lookup. We can simply defer any potential resizing
53until we need to do a lookup.
54
55Linked-List Nodes
56-----------------
57
58The current implementation stores a pointer to the associated key only.
59One alternative would be to store a pointer to the PyDictKeyEntry instead.
60This would save one pointer de-reference per item, which is nice during
61calls to values() and items(). However, it adds unnecessary overhead
62otherwise, so we stick with just the key.
63
64Linked-List API
65---------------
66
67As noted, the linked-list implemented here does not have all the bells and
68whistles. However, we recognize that the implementation may need to
69change to accommodate performance improvements or extra functionality. To
Robert Krzyzanowski6f19fc62018-07-06 05:54:26 -050070that end, we use a simple API to interact with the linked-list. Here's a
Eric Snow96c6af92015-05-29 22:21:39 -060071summary of the methods/macros:
72
73Node info:
74
75* _odictnode_KEY(node)
76* _odictnode_VALUE(od, node)
77* _odictnode_PREV(node)
78* _odictnode_NEXT(node)
79
80Linked-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
87For adding nodes:
88
89* _odict_add_head(od, node)
90* _odict_add_tail(od, node)
Serhiy Storchaka19a70e72015-11-13 14:48:36 +020091* _odict_add_new_node(od, key, hash)
Eric Snow96c6af92015-05-29 22:21:39 -060092
93For removing nodes:
94
Serhiy Storchaka19a70e72015-11-13 14:48:36 +020095* _odict_clear_node(od, node, key, hash)
Eric Snow96c6af92015-05-29 22:21:39 -060096* _odict_clear_nodes(od, clear_each)
97
98Others:
99
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200100* _odict_find_node_hash(od, key, hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600101* _odict_find_node(od, key)
102* _odict_keys_equal(od1, od2)
103
Eric Snow96c6af92015-05-29 22:21:39 -0600104And here's a look at how the linked-list relates to the OrderedDict API:
105
106============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
107method 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
119clear ~ ~ X
120copy X X X
121items X X X
122keys X X
123move_to_end X X X ~ h/t key
124pop free key
125popitem X X free X X node
126setdefault ~ ? ~
127values X X
128============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
129
130__delitem__ is the only method that directly relies on finding an arbitrary
131node in the linked-list. Everything else is iteration or relates to the
132ends of the linked-list.
133
134Situation that Endangers Consistency
135------------------------------------
136Using a raw linked-list for OrderedDict exposes a key situation that can
137cause problems. If a node is stored in a variable, there is a chance that
138the node may have been deallocated before the variable gets used, thus
139potentially leading to a segmentation fault. A key place where this shows
140up is during iteration through the linked list (via _odict_FOREACH or
141otherwise).
142
143A 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
155Another related problem, preserving consistent ordering during iteration,
156is described below. That one is not exclusive to using linked-lists.
157
158
159Challenges from Subclassing dict
160================================
161
162OrderedDict subclasses dict, which is an unusual relationship between two
163builtin types (other than the base object type). Doing so results in
164some complication and deserves further explanation. There are two things
165to consider here. First, in what circumstances or with what adjustments
166can OrderedDict be used as a drop-in replacement for dict (at the C level)?
167Second, how can the OrderedDict implementation leverage the dict
168implementation effectively without introducing unnecessary coupling or
169inefficiencies?
170
171This second point is reflected here and in the implementation, so the
172further focus is on the first point. It is worth noting that for
173overridden methods, the dict implementation is deferred to as much as
174possible. Furthermore, coupling is limited to as little as is reasonable.
175
176Concrete API Compatibility
177--------------------------
178
179Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
180problematic. (See http://bugs.python.org/issue10977.) The concrete API
181has a number of hard-coded assumptions tied to the dict implementation.
182This is, in part, due to performance reasons, which is understandable
183given the part dict plays in Python.
184
185Any attempt to replace dict with OrderedDict for any role in the
186interpreter (e.g. **kwds) faces a challenge. Such any effort must
187recognize that the instances in affected locations currently interact with
188the concrete API.
189
190Here are some ways to address this challenge:
191
1921. Change the relevant usage of the concrete API in CPython and add
Martin Panter69332c12016-08-04 13:07:31 +0000193 PyDict_CheckExact() calls to each of the concrete API functions.
Eric Snow96c6af92015-05-29 22:21:39 -06001942. Adjust the relevant concrete API functions to explicitly accommodate
195 OrderedDict.
1963. 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
200Adding the checks to the concrete API would help make any interpreter
201switch to OrderedDict less painful for extension modules. However, this
202won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)`
203is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call
204the base class's methods, since there is no equivalent of super() in the
205C API. Calling into Python for parent class API would work, but some
206extension modules already rely on this feature of the concrete API.
207
208For reference, here is a breakdown of some of the dict concrete API:
209
210========================== ============= =======================
211concrete API uses abstract API
212========================== ============= =======================
213PyDict_Check PyMapping_Check
214(PyDict_CheckExact) -
215(PyDict_New) -
216(PyDictProxy_New) -
217PyDict_Clear -
218PyDict_Contains PySequence_Contains
219PyDict_Copy -
220PyDict_SetItem PyObject_SetItem
221PyDict_SetItemString PyMapping_SetItemString
222PyDict_DelItem PyMapping_DelItem
223PyDict_DelItemString PyMapping_DelItemString
224PyDict_GetItem -
225PyDict_GetItemWithError PyObject_GetItem
226_PyDict_GetItemIdWithError -
227PyDict_GetItemString PyMapping_GetItemString
228PyDict_Items PyMapping_Items
229PyDict_Keys PyMapping_Keys
230PyDict_Values PyMapping_Values
231PyDict_Size PyMapping_Size
232 PyMapping_Length
233PyDict_Next PyIter_Next
234_PyDict_Next -
235PyDict_Merge -
236PyDict_Update -
237PyDict_MergeFromSeq2 -
238PyDict_ClearFreeList -
239- PyMapping_HasKeyString
240- PyMapping_HasKey
241========================== ============= =======================
242
243
244The dict Interface Relative to OrderedDict
245==========================================
246
247Since OrderedDict subclasses dict, understanding the various methods and
248attributes of dict is important for implementing OrderedDict.
249
250Relevant Type Slots
251-------------------
252
253================= ================ =================== ================
254slot attribute object dict
255================= ================ =================== ================
256tp_dealloc - object_dealloc dict_dealloc
257tp_repr __repr__ object_repr dict_repr
258sq_contains __contains__ - dict_contains
259mp_length __len__ - dict_length
260mp_subscript __getitem__ - dict_subscript
261mp_ass_subscript __setitem__ - dict_ass_sub
262 __delitem__
263tp_hash __hash__ _Py_HashPointer ..._HashNotImpl
264tp_str __str__ object_str -
265tp_getattro __getattribute__ ..._GenericGetAttr (repeated)
266 __getattr__
267tp_setattro __setattr__ ..._GenericSetAttr (disabled)
268tp_doc __doc__ (literal) dictionary_doc
269tp_traverse - - dict_traverse
270tp_clear - - dict_tp_clear
271tp_richcompare __eq__ object_richcompare dict_richcompare
272 __ne__
273tp_weaklistoffset (__weakref__) - -
274tp_iter __iter__ - dict_iter
275tp_dictoffset (__dict__) - -
276tp_init __init__ object_init dict_init
277tp_alloc - PyType_GenericAlloc (repeated)
278tp_new __new__ object_new dict_new
279tp_free - PyObject_Del PyObject_GC_Del
280================= ================ =================== ================
281
282Relevant Methods
283----------------
284
285================ =================== ===============
286method object dict
287================ =================== ===============
288__reduce__ object_reduce -
289__sizeof__ object_sizeof dict_sizeof
290clear - dict_clear
291copy - dict_copy
292fromkeys - dict_fromkeys
293get - dict_get
294items - dictitems_new
295keys - dictkeys_new
296pop - dict_pop
297popitem - dict_popitem
298setdefault - dict_setdefault
299update - dict_update
300values - dictvalues_new
301================ =================== ===============
302
303
304Pure Python OrderedDict
305=======================
306
307As already noted, compatibility with the pure Python OrderedDict
308implementation is a key goal of this C implementation. To further that
309goal, here's a summary of how OrderedDict-specific methods are implemented
310in collections/__init__.py. Also provided is an indication of which
311methods directly mutate or iterate the object, as well as any relationship
312with the underlying linked-list.
313
314============= ============== == ================ === === ====
315method 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__
337clear OrderedDict Y dict.clear X
338copy OrderedDict N __class__
339 __init__
340fromkeys OrderedDict N __setitem__
341get dict - - ~
342items MutableMapping - ItemsView X
343keys MutableMapping - KeysView X
344move_to_end OrderedDict Y - X
345pop OrderedDict N __contains__ X
346 __getitem__
347 __delitem__
348popitem OrderedDict Y dict.pop X
349setdefault OrderedDict N __contains__ ~
350 __getitem__
351 __setitem__
352update MutableMapping - __setitem__ ~
353values MutableMapping - ValuesView X
354============= ============== == ================ === === ====
355
356__reversed__ and move_to_end are both exclusive to OrderedDict.
357
358
359C OrderedDict Implementation
360============================
361
362================= ================
363slot impl
364================= ================
365tp_dealloc odict_dealloc
366tp_repr odict_repr
367mp_ass_subscript odict_ass_sub
368tp_doc odict_doc
369tp_traverse odict_traverse
370tp_clear odict_tp_clear
371tp_richcompare odict_richcompare
372tp_weaklistoffset (offset)
373tp_iter odict_iter
374tp_dictoffset (offset)
375tp_init odict_init
376tp_alloc (repeated)
Eric Snow96c6af92015-05-29 22:21:39 -0600377================= ================
378
379================= ================
380method impl
381================= ================
382__reduce__ odict_reduce
383__sizeof__ odict_sizeof
384clear odict_clear
385copy odict_copy
386fromkeys odict_fromkeys
387items odictitems_new
388keys odictkeys_new
389pop odict_pop
390popitem odict_popitem
391setdefault odict_setdefault
392update odict_update
393values odictvalues_new
394================= ================
395
396Inherited unchanged from object/dict:
397
398================ ==========================
399method 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
410get -
411================ ==========================
412
413
414Other Challenges
415================
416
417Preserving Ordering During Iteration
418------------------------------------
419During iteration through an OrderedDict, it is possible that items could
420get added, removed, or reordered. For a linked-list implementation, as
421with some other implementations, that situation may lead to undefined
422behavior. The documentation for dict mentions this in the `iter()` section
423of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
424In this implementation we follow dict's lead (as does the pure Python
425implementation) for __iter__(), keys(), values(), and items().
426
427For internal iteration (using _odict_FOREACH or not), there is still the
428risk that not all nodes that we expect to be seen in the loop actually get
429seen. Thus, we are careful in each of those places to ensure that they
430are. This comes, of course, at a small price at each location. The
431solutions are much the same as those detailed in the `Situation that
432Endangers Consistency` section above.
433
434
435Potential 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
Robert Krzyzanowski6f19fc62018-07-06 05:54:26 -0500442 would be invalidated after a resize, which is particularly problematic
Eric Snow96c6af92015-05-29 22:21:39 -0600443 for the iterators.
444* Use a more stream-lined implementation of update() and, likely indirectly,
445 __init__().
446
447*/
448
449/* TODO
450
451sooner:
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
457later:
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"
Victor Stinnerbcda8f12018-11-21 22:27:47 +0100468#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +0100469#include "pycore_pystate.h"
Eric Snow96c6af92015-05-29 22:21:39 -0600470#include "structmember.h"
471#include "dict-common.h"
472#include <stddef.h>
473
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100474#include "clinic/odictobject.c.h"
475
476/*[clinic input]
477class OrderedDict "PyODictObject *" "&PyODict_Type"
478[clinic start generated code]*/
479/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
480
Eric Snow96c6af92015-05-29 22:21:39 -0600481
482typedef struct _odictnode _ODictNode;
483
484/* PyODictObject */
485struct _odictobject {
Eric Snow4fabf022015-06-04 00:09:56 -0600486 PyDictObject od_dict; /* the underlying dict */
487 _ODictNode *od_first; /* first node in the linked list, if any */
488 _ODictNode *od_last; /* last node in the linked list, if any */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200489 /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
490 * by _odict_resize().
Eric Snow8c7f9552015-08-07 17:45:12 -0600491 * Note that we rely on implementation details of dict for both. */
492 _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200493 Py_ssize_t od_fast_nodes_size;
494 void *od_resize_sentinel; /* changes if odict should be resized */
Eric Snow8c7f9552015-08-07 17:45:12 -0600495
Eric Snow4fabf022015-06-04 00:09:56 -0600496 size_t od_state; /* incremented whenever the LL changes */
497 PyObject *od_inst_dict; /* OrderedDict().__dict__ */
498 PyObject *od_weakreflist; /* holds weakrefs to the odict */
Eric Snow96c6af92015-05-29 22:21:39 -0600499};
500
501
502/* ----------------------------------------------
503 * odict keys (a simple doubly-linked list)
504 */
505
506struct _odictnode {
507 PyObject *key;
Eric Snow4c729182015-06-03 10:50:37 -0600508 Py_hash_t hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600509 _ODictNode *next;
510 _ODictNode *prev;
511};
512
513#define _odictnode_KEY(node) \
514 (node->key)
Eric Snow4c729182015-06-03 10:50:37 -0600515#define _odictnode_HASH(node) \
516 (node->hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600517/* borrowed reference */
518#define _odictnode_VALUE(node, od) \
Eric Snowa762af72015-06-01 22:59:08 -0600519 PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
Eric Snow96c6af92015-05-29 22:21:39 -0600520#define _odictnode_PREV(node) (node->prev)
521#define _odictnode_NEXT(node) (node->next)
522
523#define _odict_FIRST(od) (((PyODictObject *)od)->od_first)
524#define _odict_LAST(od) (((PyODictObject *)od)->od_last)
525#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
526#define _odict_FOREACH(od, node) \
527 for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
528
Hai Shi46874c22020-01-30 17:20:25 -0600529_Py_IDENTIFIER(items);
530
Eric Snow4c729182015-06-03 10:50:37 -0600531/* Return the index into the hash table, regardless of a valid node. */
532static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200533_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow4c729182015-06-03 10:50:37 -0600534{
INADA Naokiba609772016-12-07 20:41:42 +0900535 PyObject *value = NULL;
Eric Snow4c729182015-06-03 10:50:37 -0600536 PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
Victor Stinner742da042016-09-07 17:40:12 -0700537 Py_ssize_t ix;
Eric Snow4c729182015-06-03 10:50:37 -0600538
INADA Naoki778928b2017-08-03 23:45:15 +0900539 ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value);
Victor Stinner742da042016-09-07 17:40:12 -0700540 if (ix == DKIX_EMPTY) {
541 return keys->dk_nentries; /* index of new entry */
542 }
543 if (ix < 0)
Eric Snow4c729182015-06-03 10:50:37 -0600544 return -1;
545 /* We use pointer arithmetic to get the entry's index into the table. */
Victor Stinner742da042016-09-07 17:40:12 -0700546 return ix;
Eric Snow4c729182015-06-03 10:50:37 -0600547}
548
549/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
Eric Snow96c6af92015-05-29 22:21:39 -0600550static int
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300551_odict_resize(PyODictObject *od)
552{
Eric Snow4c729182015-06-03 10:50:37 -0600553 Py_ssize_t size, i;
Eric Snow96c6af92015-05-29 22:21:39 -0600554 _ODictNode **fast_nodes, *node;
555
556 /* Initialize a new "fast nodes" table. */
557 size = ((PyDictObject *)od)->ma_keys->dk_size;
558 fast_nodes = PyMem_NEW(_ODictNode *, size);
559 if (fast_nodes == NULL) {
560 PyErr_NoMemory();
561 return -1;
562 }
563 for (i = 0; i < size; i++)
564 fast_nodes[i] = NULL;
565
566 /* Copy the current nodes into the table. */
Eric Snow96c6af92015-05-29 22:21:39 -0600567 _odict_FOREACH(od, node) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200568 i = _odict_get_index_raw(od, _odictnode_KEY(node),
Victor Stinner742da042016-09-07 17:40:12 -0700569 _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -0600570 if (i < 0) {
Eric Snow96c6af92015-05-29 22:21:39 -0600571 PyMem_FREE(fast_nodes);
572 return -1;
573 }
574 fast_nodes[i] = node;
575 }
Eric Snow96c6af92015-05-29 22:21:39 -0600576
577 /* Replace the old fast nodes table. */
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300578 PyMem_FREE(od->od_fast_nodes);
Eric Snow96c6af92015-05-29 22:21:39 -0600579 od->od_fast_nodes = fast_nodes;
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200580 od->od_fast_nodes_size = size;
581 od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600582 return 0;
583}
584
585/* Return the index into the hash table, regardless of a valid node. */
586static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200587_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600588{
Eric Snow4c729182015-06-03 10:50:37 -0600589 PyDictKeysObject *keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600590
591 assert(key != NULL);
Eric Snow4c729182015-06-03 10:50:37 -0600592 keys = ((PyDictObject *)od)->ma_keys;
593
594 /* Ensure od_fast_nodes and dk_entries are in sync. */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200595 if (od->od_resize_sentinel != keys ||
596 od->od_fast_nodes_size != keys->dk_size) {
Eric Snow4c729182015-06-03 10:50:37 -0600597 int resize_res = _odict_resize(od);
598 if (resize_res < 0)
599 return -1;
600 }
601
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200602 return _odict_get_index_raw(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600603}
604
Eric Snow96c6af92015-05-29 22:21:39 -0600605/* Returns NULL if there was some error or the key was not found. */
606static _ODictNode *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200607_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600608{
609 Py_ssize_t index;
610
611 if (_odict_EMPTY(od))
612 return NULL;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200613 index = _odict_get_index(od, key, hash);
614 if (index < 0)
615 return NULL;
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300616 assert(od->od_fast_nodes != NULL);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200617 return od->od_fast_nodes[index];
618}
619
620static _ODictNode *
621_odict_find_node(PyODictObject *od, PyObject *key)
622{
623 Py_ssize_t index;
624 Py_hash_t hash;
625
626 if (_odict_EMPTY(od))
627 return NULL;
628 hash = PyObject_Hash(key);
629 if (hash == -1)
630 return NULL;
631 index = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600632 if (index < 0)
633 return NULL;
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300634 assert(od->od_fast_nodes != NULL);
Eric Snow96c6af92015-05-29 22:21:39 -0600635 return od->od_fast_nodes[index];
636}
637
638static void
639_odict_add_head(PyODictObject *od, _ODictNode *node)
640{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300641 _odictnode_PREV(node) = NULL;
642 _odictnode_NEXT(node) = _odict_FIRST(od);
643 if (_odict_FIRST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600644 _odict_LAST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300645 else
Eric Snow96c6af92015-05-29 22:21:39 -0600646 _odictnode_PREV(_odict_FIRST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300647 _odict_FIRST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600648 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600649}
650
651static void
652_odict_add_tail(PyODictObject *od, _ODictNode *node)
653{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300654 _odictnode_PREV(node) = _odict_LAST(od);
655 _odictnode_NEXT(node) = NULL;
656 if (_odict_LAST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600657 _odict_FIRST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300658 else
Eric Snow96c6af92015-05-29 22:21:39 -0600659 _odictnode_NEXT(_odict_LAST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300660 _odict_LAST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600661 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600662}
663
664/* adds the node to the end of the list */
665static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200666_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600667{
668 Py_ssize_t i;
669 _ODictNode *node;
670
Serhiy Storchakad17427b2015-10-20 18:21:48 +0300671 Py_INCREF(key);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200672 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600673 if (i < 0) {
674 if (!PyErr_Occurred())
675 PyErr_SetObject(PyExc_KeyError, key);
676 Py_DECREF(key);
677 return -1;
678 }
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300679 assert(od->od_fast_nodes != NULL);
680 if (od->od_fast_nodes[i] != NULL) {
Eric Snow96c6af92015-05-29 22:21:39 -0600681 /* We already have a node for the key so there's no need to add one. */
682 Py_DECREF(key);
683 return 0;
684 }
685
686 /* must not be added yet */
687 node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode));
688 if (node == NULL) {
689 Py_DECREF(key);
690 PyErr_NoMemory();
691 return -1;
692 }
693
694 _odictnode_KEY(node) = key;
Eric Snow4c729182015-06-03 10:50:37 -0600695 _odictnode_HASH(node) = hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600696 _odict_add_tail(od, node);
697 od->od_fast_nodes[i] = node;
698 return 0;
699}
700
701/* Putting the decref after the free causes problems. */
702#define _odictnode_DEALLOC(node) \
703 do { \
704 Py_DECREF(_odictnode_KEY(node)); \
705 PyMem_FREE((void *)node); \
706 } while (0)
707
708/* Repeated calls on the same node are no-ops. */
709static void
710_odict_remove_node(PyODictObject *od, _ODictNode *node)
711{
712 if (_odict_FIRST(od) == node)
713 _odict_FIRST(od) = _odictnode_NEXT(node);
714 else if (_odictnode_PREV(node) != NULL)
715 _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
716
717 if (_odict_LAST(od) == node)
718 _odict_LAST(od) = _odictnode_PREV(node);
719 else if (_odictnode_NEXT(node) != NULL)
720 _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
721
722 _odictnode_PREV(node) = NULL;
723 _odictnode_NEXT(node) = NULL;
Eric Snow4fabf022015-06-04 00:09:56 -0600724 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600725}
726
Eric Snow96c6af92015-05-29 22:21:39 -0600727/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
728 get all sorts of problems here. In PyODict_DelItem we make sure to
729 call _odict_clear_node first.
Victor Stinnerca30b022015-09-03 17:50:04 +0200730
Eric Snow96c6af92015-05-29 22:21:39 -0600731 This matters in the case of colliding keys. Suppose we add 3 keys:
732 [A, B, C], where the hash of C collides with A and the next possible
733 index in the hash table is occupied by B. If we remove B then for C
734 the dict's looknode func will give us the old index of B instead of
735 the index we got before deleting B. However, the node for C in
736 od_fast_nodes is still at the old dict index of C. Thus to be sure
737 things don't get out of sync, we clear the node in od_fast_nodes
738 *before* calling PyDict_DelItem.
739
740 The same must be done for any other OrderedDict operations where
741 we modify od_fast_nodes.
742*/
743static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200744_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
745 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600746{
747 Py_ssize_t i;
748
749 assert(key != NULL);
750 if (_odict_EMPTY(od)) {
751 /* Let later code decide if this is a KeyError. */
752 return 0;
753 }
754
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200755 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600756 if (i < 0)
757 return PyErr_Occurred() ? -1 : 0;
758
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300759 assert(od->od_fast_nodes != NULL);
Eric Snow96c6af92015-05-29 22:21:39 -0600760 if (node == NULL)
761 node = od->od_fast_nodes[i];
762 assert(node == od->od_fast_nodes[i]);
763 if (node == NULL) {
764 /* Let later code decide if this is a KeyError. */
765 return 0;
766 }
767
768 // Now clear the node.
769 od->od_fast_nodes[i] = NULL;
770 _odict_remove_node(od, node);
771 _odictnode_DEALLOC(node);
772 return 0;
773}
774
775static void
776_odict_clear_nodes(PyODictObject *od)
777{
778 _ODictNode *node, *next;
779
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300780 PyMem_FREE(od->od_fast_nodes);
Eric Snow96c6af92015-05-29 22:21:39 -0600781 od->od_fast_nodes = NULL;
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300782 od->od_fast_nodes_size = 0;
783 od->od_resize_sentinel = NULL;
Serhiy Storchakad205d012016-01-19 14:46:25 +0200784
785 node = _odict_FIRST(od);
786 _odict_FIRST(od) = NULL;
787 _odict_LAST(od) = NULL;
788 while (node != NULL) {
789 next = _odictnode_NEXT(node);
790 _odictnode_DEALLOC(node);
791 node = next;
792 }
Eric Snow96c6af92015-05-29 22:21:39 -0600793}
794
795/* There isn't any memory management of nodes past this point. */
796#undef _odictnode_DEALLOC
797
798static int
799_odict_keys_equal(PyODictObject *a, PyODictObject *b)
800{
801 _ODictNode *node_a, *node_b;
802
803 node_a = _odict_FIRST(a);
804 node_b = _odict_FIRST(b);
805 while (1) {
806 if (node_a == NULL && node_b == NULL)
807 /* success: hit the end of each at the same time */
808 return 1;
809 else if (node_a == NULL || node_b == NULL)
810 /* unequal length */
811 return 0;
812 else {
813 int res = PyObject_RichCompareBool(
814 (PyObject *)_odictnode_KEY(node_a),
815 (PyObject *)_odictnode_KEY(node_b),
816 Py_EQ);
817 if (res < 0)
818 return res;
819 else if (res == 0)
820 return 0;
821
822 /* otherwise it must match, so move on to the next one */
823 node_a = _odictnode_NEXT(node_a);
824 node_b = _odictnode_NEXT(node_b);
825 }
826 }
827}
828
829
830/* ----------------------------------------------
831 * OrderedDict mapping methods
832 */
833
834/* mp_ass_subscript: __setitem__() and __delitem__() */
835
836static int
837odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)
838{
839 if (w == NULL)
840 return PyODict_DelItem((PyObject *)od, v);
841 else
842 return PyODict_SetItem((PyObject *)od, v, w);
843}
844
845/* tp_as_mapping */
846
847static PyMappingMethods odict_as_mapping = {
848 0, /*mp_length*/
849 0, /*mp_subscript*/
850 (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/
851};
852
853
854/* ----------------------------------------------
Brandt Bucher6d674a12020-03-13 09:06:04 -0700855 * OrderedDict number methods
856 */
857
858static int mutablemapping_update_arg(PyObject*, PyObject*);
859
860static PyObject *
861odict_or(PyObject *left, PyObject *right)
862{
863 PyTypeObject *type;
864 PyObject *other;
865 if (PyODict_Check(left)) {
866 type = Py_TYPE(left);
867 other = right;
868 }
869 else {
870 type = Py_TYPE(right);
871 other = left;
872 }
873 if (!PyDict_Check(other)) {
874 Py_RETURN_NOTIMPLEMENTED;
875 }
876 PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
877 if (!new) {
878 return NULL;
879 }
880 if (mutablemapping_update_arg(new, right) < 0) {
881 Py_DECREF(new);
882 return NULL;
883 }
884 return new;
885}
886
887static PyObject *
888odict_inplace_or(PyObject *self, PyObject *other)
889{
890 if (mutablemapping_update_arg(self, other) < 0) {
891 return NULL;
892 }
893 Py_INCREF(self);
894 return self;
895}
896
897/* tp_as_number */
898
899static PyNumberMethods odict_as_number = {
900 .nb_or = odict_or,
901 .nb_inplace_or = odict_inplace_or,
902};
903
904
905/* ----------------------------------------------
Eric Snow96c6af92015-05-29 22:21:39 -0600906 * OrderedDict methods
907 */
908
Eric Snow96c6af92015-05-29 22:21:39 -0600909/* fromkeys() */
910
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100911/*[clinic input]
912@classmethod
913OrderedDict.fromkeys
914
915 iterable as seq: object
916 value: object = None
917
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200918Create a new ordered dictionary with keys from iterable and values set to value.
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100919[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600920
921static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100922OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200923/*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600924{
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100925 return _PyDict_FromKeys((PyObject *)type, seq, value);
Eric Snow96c6af92015-05-29 22:21:39 -0600926}
927
928/* __sizeof__() */
929
930/* OrderedDict.__sizeof__() does not have a docstring. */
931PyDoc_STRVAR(odict_sizeof__doc__, "");
932
933static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530934odict_sizeof(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600935{
Serhiy Storchaka0ce7a3a2015-12-22 08:16:18 +0200936 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300937 res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
Eric Snow96c6af92015-05-29 22:21:39 -0600938 if (!_odict_EMPTY(od)) {
939 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
940 }
941 return PyLong_FromSsize_t(res);
942}
943
944/* __reduce__() */
945
946PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
947
948static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530949odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600950{
951 _Py_IDENTIFIER(__dict__);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300952 PyObject *dict = NULL, *result = NULL;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300953 PyObject *items_iter, *items, *args = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600954
955 /* capture any instance state */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300956 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
957 if (dict == NULL)
Eric Snowc5e59602015-05-30 11:28:56 -0600958 goto Done;
959 else {
Eric Snow96c6af92015-05-29 22:21:39 -0600960 /* od.__dict__ isn't necessarily a dict... */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300961 Py_ssize_t dict_len = PyObject_Length(dict);
962 if (dict_len == -1)
Eric Snow96c6af92015-05-29 22:21:39 -0600963 goto Done;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300964 if (!dict_len) {
965 /* nothing to pickle in od.__dict__ */
966 Py_CLEAR(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600967 }
968 }
969
970 /* build the result */
Eric Snow96c6af92015-05-29 22:21:39 -0600971 args = PyTuple_New(0);
972 if (args == NULL)
973 goto Done;
974
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200975 items = _PyObject_CallMethodIdNoArgs((PyObject *)od, &PyId_items);
Eric Snow96c6af92015-05-29 22:21:39 -0600976 if (items == NULL)
977 goto Done;
978
979 items_iter = PyObject_GetIter(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300980 Py_DECREF(items);
Eric Snow96c6af92015-05-29 22:21:39 -0600981 if (items_iter == NULL)
982 goto Done;
983
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300984 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300985 Py_DECREF(items_iter);
Eric Snow96c6af92015-05-29 22:21:39 -0600986
987Done:
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300988 Py_XDECREF(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600989 Py_XDECREF(args);
Eric Snow96c6af92015-05-29 22:21:39 -0600990
991 return result;
992}
993
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100994/* setdefault(): Skips __missing__() calls. */
Eric Snow96c6af92015-05-29 22:21:39 -0600995
Eric Snow96c6af92015-05-29 22:21:39 -0600996
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100997/*[clinic input]
998OrderedDict.setdefault
999
1000 key: object
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +02001001 default: object = None
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001002
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001003Insert key with a value of default if key is not in the dictionary.
1004
1005Return the value for key if key is in the dictionary, else default.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001006[clinic start generated code]*/
1007
Eric Snow96c6af92015-05-29 22:21:39 -06001008static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001009OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +02001010 PyObject *default_value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001011/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001012{
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001013 PyObject *result = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001014
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001015 if (PyODict_CheckExact(self)) {
1016 result = PyODict_GetItemWithError(self, key); /* borrowed */
Eric Snowd1719752015-06-01 23:12:13 -06001017 if (result == NULL) {
1018 if (PyErr_Occurred())
1019 return NULL;
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001020 assert(_odict_find_node(self, key) == NULL);
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +02001021 if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
1022 result = default_value;
1023 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -06001024 }
1025 }
1026 else {
Eric Snowd1719752015-06-01 23:12:13 -06001027 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -06001028 }
1029 }
1030 else {
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001031 int exists = PySequence_Contains((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001032 if (exists < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001033 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001034 }
1035 else if (exists) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001036 result = PyObject_GetItem((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001037 }
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +02001038 else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1039 result = default_value;
1040 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -06001041 }
1042 }
1043
Eric Snow96c6af92015-05-29 22:21:39 -06001044 return result;
1045}
1046
1047/* pop() */
1048
1049PyDoc_STRVAR(odict_pop__doc__,
1050"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1051 value. If key is not found, d is returned if given, otherwise KeyError\n\
1052 is raised.\n\
1053\n\
1054 ");
1055
1056/* forward */
1057static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1058
1059/* Skips __missing__() calls. */
1060static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001061odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001062{
Eric Snowac02ef32015-06-02 20:42:14 -06001063 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001064 PyObject *key, *failobj = NULL;
1065
Eric Snowac02ef32015-06-02 20:42:14 -06001066 /* borrowed */
1067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1068 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001069 return NULL;
1070 }
1071
1072 return _odict_popkey(od, key, failobj);
1073}
1074
1075static PyObject *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001076_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1077 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -06001078{
1079 _ODictNode *node;
1080 PyObject *value = NULL;
1081
Eric Snow96c6af92015-05-29 22:21:39 -06001082 /* Pop the node first to avoid a possible dict resize (due to
1083 eval loop reentrancy) and complications due to hash collision
1084 resolution. */
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001085 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001086 if (node == NULL) {
1087 if (PyErr_Occurred())
Eric Snowd1719752015-06-01 23:12:13 -06001088 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001089 }
1090 else {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001091 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001092 if (res < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001093 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001094 }
1095 }
1096
1097 /* Now delete the value from the dict. */
Serhiy Storchaka04386832016-10-30 17:17:24 +02001098 if (PyODict_CheckExact(od)) {
1099 if (node != NULL) {
1100 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1101 if (value != NULL) {
1102 Py_INCREF(value);
1103 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1104 Py_DECREF(value);
1105 return NULL;
1106 }
1107 }
1108 }
1109 }
1110 else {
1111 int exists = PySequence_Contains(od, key);
1112 if (exists < 0)
1113 return NULL;
1114 if (exists) {
1115 value = PyObject_GetItem(od, key);
1116 if (value != NULL) {
1117 if (PyObject_DelItem(od, key) == -1) {
1118 Py_CLEAR(value);
1119 }
Eric Snow96c6af92015-05-29 22:21:39 -06001120 }
1121 }
1122 }
1123
1124 /* Apply the fallback value, if necessary. */
1125 if (value == NULL && !PyErr_Occurred()) {
1126 if (failobj) {
1127 value = failobj;
1128 Py_INCREF(failobj);
1129 }
1130 else {
1131 PyErr_SetObject(PyExc_KeyError, key);
1132 }
1133 }
1134
Eric Snow96c6af92015-05-29 22:21:39 -06001135 return value;
1136}
1137
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001138static PyObject *
1139_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1140{
1141 Py_hash_t hash = PyObject_Hash(key);
1142 if (hash == -1)
1143 return NULL;
1144
1145 return _odict_popkey_hash(od, key, failobj, hash);
1146}
1147
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001148
Eric Snow96c6af92015-05-29 22:21:39 -06001149/* popitem() */
1150
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001151/*[clinic input]
1152OrderedDict.popitem
1153
1154 last: bool = True
1155
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001156Remove and return a (key, value) pair from the dictionary.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001157
1158Pairs are returned in LIFO order if last is true or FIFO order if false.
1159[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001160
1161static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001162OrderedDict_popitem_impl(PyODictObject *self, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001163/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001164{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001165 PyObject *key, *value, *item = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001166 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001167
1168 /* pull the item */
1169
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001170 if (_odict_EMPTY(self)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001171 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1172 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001173 }
Eric Snow96c6af92015-05-29 22:21:39 -06001174
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001175 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001176 key = _odictnode_KEY(node);
Eric Snowd1719752015-06-01 23:12:13 -06001177 Py_INCREF(key);
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001178 value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -06001179 if (value == NULL)
1180 return NULL;
1181 item = PyTuple_Pack(2, key, value);
Eric Snowd1719752015-06-01 23:12:13 -06001182 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001183 Py_DECREF(value);
1184 return item;
1185}
1186
1187/* keys() */
1188
1189/* MutableMapping.keys() does not have a docstring. */
1190PyDoc_STRVAR(odict_keys__doc__, "");
1191
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301192static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001193
1194/* values() */
1195
1196/* MutableMapping.values() does not have a docstring. */
1197PyDoc_STRVAR(odict_values__doc__, "");
1198
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301199static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001200
1201/* items() */
1202
1203/* MutableMapping.items() does not have a docstring. */
1204PyDoc_STRVAR(odict_items__doc__, "");
1205
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301206static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001207
1208/* update() */
1209
1210/* MutableMapping.update() does not have a docstring. */
1211PyDoc_STRVAR(odict_update__doc__, "");
1212
1213/* forward */
1214static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1215
1216#define odict_update mutablemapping_update
1217
1218/* clear() */
1219
1220PyDoc_STRVAR(odict_clear__doc__,
1221 "od.clear() -> None. Remove all items from od.");
1222
1223static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301224odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001225{
1226 PyDict_Clear((PyObject *)od);
1227 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001228 Py_RETURN_NONE;
1229}
1230
1231/* copy() */
1232
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001233/* forward */
1234static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1235 Py_hash_t);
1236
Eric Snow96c6af92015-05-29 22:21:39 -06001237PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1238
1239static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301240odict_copy(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001241{
1242 _ODictNode *node;
1243 PyObject *od_copy;
1244
1245 if (PyODict_CheckExact(od))
1246 od_copy = PyODict_New();
1247 else
Victor Stinnerf17c3de2016-12-06 18:46:19 +01001248 od_copy = _PyObject_CallNoArg((PyObject *)Py_TYPE(od));
Eric Snow96c6af92015-05-29 22:21:39 -06001249 if (od_copy == NULL)
1250 return NULL;
1251
1252 if (PyODict_CheckExact(od)) {
1253 _odict_FOREACH(od, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001254 PyObject *key = _odictnode_KEY(node);
1255 PyObject *value = _odictnode_VALUE(node, od);
1256 if (value == NULL) {
1257 if (!PyErr_Occurred())
1258 PyErr_SetObject(PyExc_KeyError, key);
1259 goto fail;
1260 }
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001261 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1262 _odictnode_HASH(node)) != 0)
Eric Snow96c6af92015-05-29 22:21:39 -06001263 goto fail;
1264 }
1265 }
1266 else {
1267 _odict_FOREACH(od, node) {
1268 int res;
1269 PyObject *value = PyObject_GetItem((PyObject *)od,
1270 _odictnode_KEY(node));
1271 if (value == NULL)
1272 goto fail;
1273 res = PyObject_SetItem((PyObject *)od_copy,
1274 _odictnode_KEY(node), value);
1275 Py_DECREF(value);
1276 if (res != 0)
1277 goto fail;
1278 }
1279 }
1280 return od_copy;
1281
1282fail:
1283 Py_DECREF(od_copy);
1284 return NULL;
1285}
1286
1287/* __reversed__() */
1288
1289PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1290
1291#define _odict_ITER_REVERSED 1
1292#define _odict_ITER_KEYS 2
1293#define _odict_ITER_VALUES 4
1294
1295/* forward */
1296static PyObject * odictiter_new(PyODictObject *, int);
1297
1298static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301299odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001300{
Eric Snow96c6af92015-05-29 22:21:39 -06001301 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1302}
1303
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001304
Eric Snow96c6af92015-05-29 22:21:39 -06001305/* move_to_end() */
1306
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001307/*[clinic input]
1308OrderedDict.move_to_end
1309
1310 key: object
1311 last: bool = True
1312
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001313Move an existing element to the end (or beginning if last is false).
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001314
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001315Raise KeyError if the element does not exist.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001316[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001317
1318static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001319OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001320/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001321{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001322 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001323
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001324 if (_odict_EMPTY(self)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001325 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001326 return NULL;
1327 }
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001328 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001329 if (key != _odictnode_KEY(node)) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001330 node = _odict_find_node(self, key);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001331 if (node == NULL) {
1332 if (!PyErr_Occurred())
1333 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowc5e59602015-05-30 11:28:56 -06001334 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001335 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001336 if (last) {
1337 /* Only move if not already the last one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001338 if (node != _odict_LAST(self)) {
1339 _odict_remove_node(self, node);
1340 _odict_add_tail(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001341 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001342 }
1343 else {
1344 /* Only move if not already the first one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001345 if (node != _odict_FIRST(self)) {
1346 _odict_remove_node(self, node);
1347 _odict_add_head(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001348 }
1349 }
1350 }
Eric Snow96c6af92015-05-29 22:21:39 -06001351 Py_RETURN_NONE;
1352}
1353
1354
1355/* tp_methods */
1356
1357static PyMethodDef odict_methods[] = {
1358
Eric Snow96c6af92015-05-29 22:21:39 -06001359 /* overridden dict methods */
Serhiy Storchaka827d49f2018-04-09 19:14:26 +03001360 ORDEREDDICT_FROMKEYS_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001361 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1362 odict_sizeof__doc__},
1363 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1364 odict_reduce__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001365 ORDEREDDICT_SETDEFAULT_METHODDEF
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001366 {"pop", (PyCFunction)(void(*)(void))odict_pop,
Eric Snowac02ef32015-06-02 20:42:14 -06001367 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001368 ORDEREDDICT_POPITEM_METHODDEF
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301369 {"keys", odictkeys_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001370 odict_keys__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301371 {"values", odictvalues_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001372 odict_values__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301373 {"items", odictitems_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001374 odict_items__doc__},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001375 {"update", (PyCFunction)(void(*)(void))odict_update, METH_VARARGS | METH_KEYWORDS,
Eric Snow96c6af92015-05-29 22:21:39 -06001376 odict_update__doc__},
1377 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1378 odict_clear__doc__},
1379 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1380 odict_copy__doc__},
1381
1382 /* new methods */
1383 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1384 odict_reversed__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001385 ORDEREDDICT_MOVE_TO_END_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001386
1387 {NULL, NULL} /* sentinel */
1388};
1389
1390
1391/* ----------------------------------------------
1392 * OrderedDict members
1393 */
1394
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001395/* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001396
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001397static PyGetSetDef odict_getset[] = {
1398 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1399 {NULL}
Eric Snow96c6af92015-05-29 22:21:39 -06001400};
1401
Eric Snow96c6af92015-05-29 22:21:39 -06001402/* ----------------------------------------------
1403 * OrderedDict type slot methods
1404 */
1405
1406/* tp_dealloc */
1407
1408static void
1409odict_dealloc(PyODictObject *self)
1410{
1411 PyObject_GC_UnTrack(self);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001412 Py_TRASHCAN_BEGIN(self, odict_dealloc)
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001413
Eric Snow96c6af92015-05-29 22:21:39 -06001414 Py_XDECREF(self->od_inst_dict);
1415 if (self->od_weakreflist != NULL)
1416 PyObject_ClearWeakRefs((PyObject *)self);
1417
1418 _odict_clear_nodes(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001419 PyDict_Type.tp_dealloc((PyObject *)self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001420
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001421 Py_TRASHCAN_END
Victor Stinnere1871952016-06-08 10:18:18 +02001422}
Eric Snow96c6af92015-05-29 22:21:39 -06001423
1424/* tp_repr */
1425
1426static PyObject *
1427odict_repr(PyODictObject *self)
1428{
1429 int i;
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001430 PyObject *pieces = NULL, *result = NULL;
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001431
1432 if (PyODict_SIZE(self) == 0)
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001433 return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
Eric Snow96c6af92015-05-29 22:21:39 -06001434
1435 i = Py_ReprEnter((PyObject *)self);
1436 if (i != 0) {
1437 return i > 0 ? PyUnicode_FromString("...") : NULL;
1438 }
1439
Eric Snow96c6af92015-05-29 22:21:39 -06001440 if (PyODict_CheckExact(self)) {
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001441 Py_ssize_t count = 0;
Eric Snowa762af72015-06-01 22:59:08 -06001442 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001443 pieces = PyList_New(PyODict_SIZE(self));
1444 if (pieces == NULL)
1445 goto Done;
1446
1447 _odict_FOREACH(self, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001448 PyObject *pair;
1449 PyObject *key = _odictnode_KEY(node);
1450 PyObject *value = _odictnode_VALUE(node, self);
1451 if (value == NULL) {
1452 if (!PyErr_Occurred())
1453 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowdb4061c2015-06-03 11:09:48 -06001454 goto Done;
Eric Snowa762af72015-06-01 22:59:08 -06001455 }
1456 pair = PyTuple_Pack(2, key, value);
Eric Snow96c6af92015-05-29 22:21:39 -06001457 if (pair == NULL)
1458 goto Done;
1459
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001460 if (count < PyList_GET_SIZE(pieces))
1461 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1462 else {
1463 if (PyList_Append(pieces, pair) < 0) {
1464 Py_DECREF(pair);
1465 goto Done;
1466 }
1467 Py_DECREF(pair);
1468 }
1469 count++;
Eric Snow96c6af92015-05-29 22:21:39 -06001470 }
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001471 if (count < PyList_GET_SIZE(pieces)) {
1472 Py_SET_SIZE(pieces, count);
1473 }
Eric Snow96c6af92015-05-29 22:21:39 -06001474 }
1475 else {
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001476 PyObject *items = _PyObject_CallMethodIdNoArgs((PyObject *)self,
1477 &PyId_items);
Eric Snow96c6af92015-05-29 22:21:39 -06001478 if (items == NULL)
1479 goto Done;
1480 pieces = PySequence_List(items);
1481 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001482 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001483 goto Done;
1484 }
1485
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001486 result = PyUnicode_FromFormat("%s(%R)",
1487 _PyType_Name(Py_TYPE(self)), pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001488
Eric Snow96c6af92015-05-29 22:21:39 -06001489Done:
1490 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001491 Py_ReprLeave((PyObject *)self);
1492 return result;
Victor Stinnere1871952016-06-08 10:18:18 +02001493}
Eric Snow96c6af92015-05-29 22:21:39 -06001494
1495/* tp_doc */
1496
1497PyDoc_STRVAR(odict_doc,
1498 "Dictionary that remembers insertion order");
1499
1500/* tp_traverse */
1501
1502static int
1503odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1504{
Serhiy Storchakad205d012016-01-19 14:46:25 +02001505 _ODictNode *node;
1506
Eric Snow96c6af92015-05-29 22:21:39 -06001507 Py_VISIT(od->od_inst_dict);
Serhiy Storchakad205d012016-01-19 14:46:25 +02001508 _odict_FOREACH(od, node) {
1509 Py_VISIT(_odictnode_KEY(node));
1510 }
Eric Snow96c6af92015-05-29 22:21:39 -06001511 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1512}
1513
1514/* tp_clear */
1515
1516static int
1517odict_tp_clear(PyODictObject *od)
1518{
Eric Snow96c6af92015-05-29 22:21:39 -06001519 Py_CLEAR(od->od_inst_dict);
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001520 PyDict_Clear((PyObject *)od);
1521 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001522 return 0;
1523}
1524
1525/* tp_richcompare */
1526
1527static PyObject *
1528odict_richcompare(PyObject *v, PyObject *w, int op)
1529{
1530 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1531 Py_RETURN_NOTIMPLEMENTED;
1532 }
1533
1534 if (op == Py_EQ || op == Py_NE) {
1535 PyObject *res, *cmp;
1536 int eq;
1537
1538 cmp = PyDict_Type.tp_richcompare(v, w, op);
1539 if (cmp == NULL)
1540 return NULL;
1541 if (!PyODict_Check(w))
1542 return cmp;
1543 if (op == Py_EQ && cmp == Py_False)
1544 return cmp;
1545 if (op == Py_NE && cmp == Py_True)
1546 return cmp;
1547 Py_DECREF(cmp);
1548
1549 /* Try comparing odict keys. */
1550 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1551 if (eq < 0)
1552 return NULL;
1553
1554 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1555 Py_INCREF(res);
1556 return res;
1557 } else {
1558 Py_RETURN_NOTIMPLEMENTED;
1559 }
Victor Stinnere1871952016-06-08 10:18:18 +02001560}
Eric Snow96c6af92015-05-29 22:21:39 -06001561
1562/* tp_iter */
1563
1564static PyObject *
1565odict_iter(PyODictObject *od)
1566{
1567 return odictiter_new(od, _odict_ITER_KEYS);
Victor Stinnere1871952016-06-08 10:18:18 +02001568}
Eric Snow96c6af92015-05-29 22:21:39 -06001569
1570/* tp_init */
1571
1572static int
1573odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1574{
1575 PyObject *res;
1576 Py_ssize_t len = PyObject_Length(args);
1577
1578 if (len == -1)
1579 return -1;
1580 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02001581 const char *msg = "expected at most 1 arguments, got %zd";
Eric Snow96c6af92015-05-29 22:21:39 -06001582 PyErr_Format(PyExc_TypeError, msg, len);
1583 return -1;
1584 }
1585
1586 /* __init__() triggering update() is just the way things are! */
1587 res = odict_update(self, args, kwds);
1588 if (res == NULL) {
1589 return -1;
1590 } else {
1591 Py_DECREF(res);
1592 return 0;
1593 }
Victor Stinnere1871952016-06-08 10:18:18 +02001594}
Eric Snow96c6af92015-05-29 22:21:39 -06001595
Eric Snow96c6af92015-05-29 22:21:39 -06001596/* PyODict_Type */
1597
1598PyTypeObject PyODict_Type = {
1599 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1600 "collections.OrderedDict", /* tp_name */
1601 sizeof(PyODictObject), /* tp_basicsize */
1602 0, /* tp_itemsize */
1603 (destructor)odict_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001604 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001605 0, /* tp_getattr */
1606 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001607 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001608 (reprfunc)odict_repr, /* tp_repr */
Brandt Bucher6d674a12020-03-13 09:06:04 -07001609 &odict_as_number, /* tp_as_number */
Eric Snow96c6af92015-05-29 22:21:39 -06001610 0, /* tp_as_sequence */
1611 &odict_as_mapping, /* tp_as_mapping */
1612 0, /* tp_hash */
1613 0, /* tp_call */
1614 0, /* tp_str */
1615 0, /* tp_getattro */
1616 0, /* tp_setattro */
1617 0, /* tp_as_buffer */
1618 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1619 odict_doc, /* tp_doc */
1620 (traverseproc)odict_traverse, /* tp_traverse */
1621 (inquiry)odict_tp_clear, /* tp_clear */
1622 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1623 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1624 (getiterfunc)odict_iter, /* tp_iter */
1625 0, /* tp_iternext */
1626 odict_methods, /* tp_methods */
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001627 0, /* tp_members */
1628 odict_getset, /* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001629 &PyDict_Type, /* tp_base */
1630 0, /* tp_dict */
1631 0, /* tp_descr_get */
1632 0, /* tp_descr_set */
1633 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1634 (initproc)odict_init, /* tp_init */
1635 PyType_GenericAlloc, /* tp_alloc */
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001636 0, /* tp_new */
Eric Snow96c6af92015-05-29 22:21:39 -06001637 0, /* tp_free */
1638};
1639
1640
1641/* ----------------------------------------------
1642 * the public OrderedDict API
1643 */
1644
1645PyObject *
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001646PyODict_New(void)
1647{
1648 return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
Victor Stinnere1871952016-06-08 10:18:18 +02001649}
Eric Snow96c6af92015-05-29 22:21:39 -06001650
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001651static int
1652_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1653 Py_hash_t hash)
1654{
1655 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001656 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001657 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001658 if (res < 0) {
1659 /* Revert setting the value on the dict */
1660 PyObject *exc, *val, *tb;
1661 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001662 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001663 _PyErr_ChainExceptions(exc, val, tb);
1664 }
Eric Snow96c6af92015-05-29 22:21:39 -06001665 }
1666 return res;
Victor Stinnere1871952016-06-08 10:18:18 +02001667}
Eric Snow96c6af92015-05-29 22:21:39 -06001668
1669int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001670PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1671{
1672 Py_hash_t hash = PyObject_Hash(key);
1673 if (hash == -1)
1674 return -1;
1675 return _PyODict_SetItem_KnownHash(od, key, value, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001676}
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001677
1678int
1679PyODict_DelItem(PyObject *od, PyObject *key)
1680{
1681 int res;
1682 Py_hash_t hash = PyObject_Hash(key);
1683 if (hash == -1)
1684 return -1;
1685 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001686 if (res < 0)
1687 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001688 return _PyDict_DelItem_KnownHash(od, key, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001689}
Eric Snow96c6af92015-05-29 22:21:39 -06001690
1691
1692/* -------------------------------------------
1693 * The OrderedDict views (keys/values/items)
1694 */
1695
1696typedef struct {
1697 PyObject_HEAD
1698 int kind;
1699 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001700 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001701 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001702 PyObject *di_current;
1703 PyObject *di_result; /* reusable result tuple for iteritems */
1704} odictiterobject;
1705
1706static void
1707odictiter_dealloc(odictiterobject *di)
1708{
1709 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001710 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001711 Py_XDECREF(di->di_current);
1712 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1713 Py_DECREF(di->di_result);
1714 }
1715 PyObject_GC_Del(di);
1716}
1717
1718static int
1719odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1720{
1721 Py_VISIT(di->di_odict);
1722 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1723 Py_VISIT(di->di_result);
1724 return 0;
1725}
1726
Eric Snowa762af72015-06-01 22:59:08 -06001727/* In order to protect against modifications during iteration, we track
1728 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001729static PyObject *
1730odictiter_nextkey(odictiterobject *di)
1731{
Eric Snowa762af72015-06-01 22:59:08 -06001732 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001733 _ODictNode *node;
1734 int reversed = di->kind & _odict_ITER_REVERSED;
1735
Eric Snowa762af72015-06-01 22:59:08 -06001736 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001737 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001738 if (di->di_current == NULL)
1739 goto done; /* We're already done. */
1740
Eric Snowb952ab42015-06-01 23:35:13 -06001741 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001742 if (di->di_odict->od_state != di->di_state) {
1743 PyErr_SetString(PyExc_RuntimeError,
1744 "OrderedDict mutated during iteration");
1745 goto done;
1746 }
Eric Snowb952ab42015-06-01 23:35:13 -06001747 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1748 PyErr_SetString(PyExc_RuntimeError,
1749 "OrderedDict changed size during iteration");
1750 di->di_size = -1; /* Make this state sticky */
1751 return NULL;
1752 }
1753
Eric Snowa762af72015-06-01 22:59:08 -06001754 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001755 node = _odict_find_node(di->di_odict, di->di_current);
1756 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001757 if (!PyErr_Occurred())
1758 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001759 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001760 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001761 return NULL;
1762 }
1763 key = di->di_current;
1764
1765 /* Advance to the next key. */
1766 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1767 if (node == NULL) {
1768 /* Reached the end. */
1769 di->di_current = NULL;
1770 }
1771 else {
1772 di->di_current = _odictnode_KEY(node);
1773 Py_INCREF(di->di_current);
1774 }
1775
1776 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001777
1778done:
1779 Py_CLEAR(di->di_odict);
1780 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001781}
1782
1783static PyObject *
1784odictiter_iternext(odictiterobject *di)
1785{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001786 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001787 PyObject *key = odictiter_nextkey(di); /* new reference */
1788
1789 if (key == NULL)
1790 return NULL;
1791
1792 /* Handle the keys case. */
1793 if (! (di->kind & _odict_ITER_VALUES)) {
1794 return key;
1795 }
1796
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001797 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1798 if (value == NULL) {
1799 if (!PyErr_Occurred())
1800 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001801 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001802 goto done;
1803 }
1804 Py_INCREF(value);
1805
1806 /* Handle the values case. */
1807 if (!(di->kind & _odict_ITER_KEYS)) {
1808 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001809 return value;
1810 }
Eric Snowa762af72015-06-01 22:59:08 -06001811
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001812 /* Handle the items case. */
1813 result = di->di_result;
1814
1815 if (Py_REFCNT(result) == 1) {
1816 /* not in use so we can reuse it
1817 * (the common case during iteration) */
1818 Py_INCREF(result);
1819 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1820 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1821 }
1822 else {
1823 result = PyTuple_New(2);
1824 if (result == NULL) {
1825 Py_DECREF(key);
1826 Py_DECREF(value);
1827 goto done;
1828 }
1829 }
1830
1831 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1832 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1833 return result;
1834
Eric Snowa762af72015-06-01 22:59:08 -06001835done:
1836 Py_CLEAR(di->di_current);
1837 Py_CLEAR(di->di_odict);
1838 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001839}
1840
1841/* No need for tp_clear because odictiterobject is not mutable. */
1842
1843PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1844
1845static PyObject *
Serhiy Storchaka81524022018-11-27 13:05:02 +02001846odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001847{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001848 _Py_IDENTIFIER(iter);
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001849 /* copy the iterator state */
1850 odictiterobject tmp = *di;
1851 Py_XINCREF(tmp.di_odict);
1852 Py_XINCREF(tmp.di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001853
1854 /* iterate the temporary into a list */
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001855 PyObject *list = PySequence_List((PyObject*)&tmp);
1856 Py_XDECREF(tmp.di_odict);
1857 Py_XDECREF(tmp.di_current);
1858 if (list == NULL) {
Eric Snow96c6af92015-05-29 22:21:39 -06001859 return NULL;
1860 }
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001861 return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
Eric Snow96c6af92015-05-29 22:21:39 -06001862}
1863
1864static PyMethodDef odictiter_methods[] = {
1865 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1866 {NULL, NULL} /* sentinel */
1867};
1868
1869PyTypeObject PyODictIter_Type = {
1870 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1871 "odict_iterator", /* tp_name */
1872 sizeof(odictiterobject), /* tp_basicsize */
1873 0, /* tp_itemsize */
1874 /* methods */
1875 (destructor)odictiter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001876 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001877 0, /* tp_getattr */
1878 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001879 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001880 0, /* tp_repr */
1881 0, /* tp_as_number */
1882 0, /* tp_as_sequence */
1883 0, /* tp_as_mapping */
1884 0, /* tp_hash */
1885 0, /* tp_call */
1886 0, /* tp_str */
1887 PyObject_GenericGetAttr, /* tp_getattro */
1888 0, /* tp_setattro */
1889 0, /* tp_as_buffer */
1890 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1891 0, /* tp_doc */
1892 (traverseproc)odictiter_traverse, /* tp_traverse */
1893 0, /* tp_clear */
1894 0, /* tp_richcompare */
1895 0, /* tp_weaklistoffset */
1896 PyObject_SelfIter, /* tp_iter */
1897 (iternextfunc)odictiter_iternext, /* tp_iternext */
1898 odictiter_methods, /* tp_methods */
1899 0,
1900};
1901
1902static PyObject *
1903odictiter_new(PyODictObject *od, int kind)
1904{
1905 odictiterobject *di;
1906 _ODictNode *node;
1907 int reversed = kind & _odict_ITER_REVERSED;
1908
1909 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1910 if (di == NULL)
1911 return NULL;
1912
1913 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
1914 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1915 if (di->di_result == NULL) {
1916 Py_DECREF(di);
1917 return NULL;
1918 }
1919 }
1920 else
1921 di->di_result = NULL;
1922
1923 di->kind = kind;
1924 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1925 di->di_current = node ? _odictnode_KEY(node) : NULL;
1926 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06001927 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06001928 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001929 di->di_odict = od;
1930 Py_INCREF(od);
1931
1932 _PyObject_GC_TRACK(di);
1933 return (PyObject *)di;
1934}
1935
1936/* keys() */
1937
1938static PyObject *
1939odictkeys_iter(_PyDictViewObject *dv)
1940{
1941 if (dv->dv_dict == NULL) {
1942 Py_RETURN_NONE;
1943 }
1944 return odictiter_new((PyODictObject *)dv->dv_dict,
1945 _odict_ITER_KEYS);
1946}
1947
1948static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301949odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001950{
1951 if (dv->dv_dict == NULL) {
1952 Py_RETURN_NONE;
1953 }
1954 return odictiter_new((PyODictObject *)dv->dv_dict,
1955 _odict_ITER_KEYS|_odict_ITER_REVERSED);
1956}
1957
1958static PyMethodDef odictkeys_methods[] = {
1959 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
1960 {NULL, NULL} /* sentinel */
1961};
1962
1963PyTypeObject PyODictKeys_Type = {
1964 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1965 "odict_keys", /* tp_name */
1966 0, /* tp_basicsize */
1967 0, /* tp_itemsize */
1968 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001969 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001970 0, /* tp_getattr */
1971 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001972 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001973 0, /* tp_repr */
1974 0, /* tp_as_number */
1975 0, /* tp_as_sequence */
1976 0, /* tp_as_mapping */
1977 0, /* tp_hash */
1978 0, /* tp_call */
1979 0, /* tp_str */
1980 0, /* tp_getattro */
1981 0, /* tp_setattro */
1982 0, /* tp_as_buffer */
1983 0, /* tp_flags */
1984 0, /* tp_doc */
1985 0, /* tp_traverse */
1986 0, /* tp_clear */
1987 0, /* tp_richcompare */
1988 0, /* tp_weaklistoffset */
1989 (getiterfunc)odictkeys_iter, /* tp_iter */
1990 0, /* tp_iternext */
1991 odictkeys_methods, /* tp_methods */
1992 0, /* tp_members */
1993 0, /* tp_getset */
1994 &PyDictKeys_Type, /* tp_base */
1995};
1996
1997static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301998odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001999{
2000 return _PyDictView_New(od, &PyODictKeys_Type);
2001}
2002
2003/* items() */
2004
2005static PyObject *
2006odictitems_iter(_PyDictViewObject *dv)
2007{
2008 if (dv->dv_dict == NULL) {
2009 Py_RETURN_NONE;
2010 }
2011 return odictiter_new((PyODictObject *)dv->dv_dict,
2012 _odict_ITER_KEYS|_odict_ITER_VALUES);
2013}
2014
2015static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302016odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002017{
2018 if (dv->dv_dict == NULL) {
2019 Py_RETURN_NONE;
2020 }
2021 return odictiter_new((PyODictObject *)dv->dv_dict,
2022 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2023}
2024
2025static PyMethodDef odictitems_methods[] = {
2026 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
2027 {NULL, NULL} /* sentinel */
2028};
2029
2030PyTypeObject PyODictItems_Type = {
2031 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2032 "odict_items", /* tp_name */
2033 0, /* tp_basicsize */
2034 0, /* tp_itemsize */
2035 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002036 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06002037 0, /* tp_getattr */
2038 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002039 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06002040 0, /* tp_repr */
2041 0, /* tp_as_number */
2042 0, /* tp_as_sequence */
2043 0, /* tp_as_mapping */
2044 0, /* tp_hash */
2045 0, /* tp_call */
2046 0, /* tp_str */
2047 0, /* tp_getattro */
2048 0, /* tp_setattro */
2049 0, /* tp_as_buffer */
2050 0, /* tp_flags */
2051 0, /* tp_doc */
2052 0, /* tp_traverse */
2053 0, /* tp_clear */
2054 0, /* tp_richcompare */
2055 0, /* tp_weaklistoffset */
2056 (getiterfunc)odictitems_iter, /* tp_iter */
2057 0, /* tp_iternext */
2058 odictitems_methods, /* tp_methods */
2059 0, /* tp_members */
2060 0, /* tp_getset */
2061 &PyDictItems_Type, /* tp_base */
2062};
2063
2064static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302065odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002066{
2067 return _PyDictView_New(od, &PyODictItems_Type);
2068}
2069
2070/* values() */
2071
2072static PyObject *
2073odictvalues_iter(_PyDictViewObject *dv)
2074{
2075 if (dv->dv_dict == NULL) {
2076 Py_RETURN_NONE;
2077 }
2078 return odictiter_new((PyODictObject *)dv->dv_dict,
2079 _odict_ITER_VALUES);
2080}
2081
2082static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302083odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002084{
2085 if (dv->dv_dict == NULL) {
2086 Py_RETURN_NONE;
2087 }
2088 return odictiter_new((PyODictObject *)dv->dv_dict,
2089 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2090}
2091
2092static PyMethodDef odictvalues_methods[] = {
2093 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2094 {NULL, NULL} /* sentinel */
2095};
2096
2097PyTypeObject PyODictValues_Type = {
2098 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2099 "odict_values", /* tp_name */
2100 0, /* tp_basicsize */
2101 0, /* tp_itemsize */
2102 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002103 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06002104 0, /* tp_getattr */
2105 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002106 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06002107 0, /* tp_repr */
2108 0, /* tp_as_number */
2109 0, /* tp_as_sequence */
2110 0, /* tp_as_mapping */
2111 0, /* tp_hash */
2112 0, /* tp_call */
2113 0, /* tp_str */
2114 0, /* tp_getattro */
2115 0, /* tp_setattro */
2116 0, /* tp_as_buffer */
2117 0, /* tp_flags */
2118 0, /* tp_doc */
2119 0, /* tp_traverse */
2120 0, /* tp_clear */
2121 0, /* tp_richcompare */
2122 0, /* tp_weaklistoffset */
2123 (getiterfunc)odictvalues_iter, /* tp_iter */
2124 0, /* tp_iternext */
2125 odictvalues_methods, /* tp_methods */
2126 0, /* tp_members */
2127 0, /* tp_getset */
2128 &PyDictValues_Type, /* tp_base */
2129};
2130
2131static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302132odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002133{
2134 return _PyDictView_New(od, &PyODictValues_Type);
2135}
2136
2137
2138/* ----------------------------------------------
Martin Panter536d70e2017-01-14 08:23:08 +00002139 MutableMapping implementations
Eric Snow96c6af92015-05-29 22:21:39 -06002140
2141Mapping:
2142
2143============ ===========
2144method uses
2145============ ===========
2146__contains__ __getitem__
2147__eq__ items
2148__getitem__ +
2149__iter__ +
2150__len__ +
2151__ne__ __eq__
2152get __getitem__
2153items ItemsView
2154keys KeysView
2155values ValuesView
2156============ ===========
2157
2158ItemsView uses __len__, __iter__, and __getitem__.
2159KeysView uses __len__, __iter__, and __contains__.
2160ValuesView uses __len__, __iter__, and __getitem__.
2161
2162MutableMapping:
2163
2164============ ===========
2165method uses
2166============ ===========
2167__delitem__ +
2168__setitem__ +
2169clear popitem
2170pop __getitem__
2171 __delitem__
2172popitem __iter__
2173 _getitem__
2174 __delitem__
2175setdefault __getitem__
2176 __setitem__
2177update __setitem__
2178============ ===========
2179*/
2180
2181static int
2182mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2183{
2184 PyObject *pair, *iterator, *unexpected;
2185 int res = 0;
2186
2187 iterator = PyObject_GetIter(pairs);
2188 if (iterator == NULL)
2189 return -1;
2190 PyErr_Clear();
2191
2192 while ((pair = PyIter_Next(iterator)) != NULL) {
2193 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002194 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002195 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002196 if (pair_iterator == NULL)
2197 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002198
2199 key = PyIter_Next(pair_iterator);
2200 if (key == NULL) {
2201 if (!PyErr_Occurred())
2202 PyErr_SetString(PyExc_ValueError,
2203 "need more than 0 values to unpack");
2204 goto Done;
2205 }
2206
2207 value = PyIter_Next(pair_iterator);
2208 if (value == NULL) {
2209 if (!PyErr_Occurred())
2210 PyErr_SetString(PyExc_ValueError,
2211 "need more than 1 value to unpack");
2212 goto Done;
2213 }
2214
2215 unexpected = PyIter_Next(pair_iterator);
2216 if (unexpected != NULL) {
2217 Py_DECREF(unexpected);
2218 PyErr_SetString(PyExc_ValueError,
2219 "too many values to unpack (expected 2)");
2220 goto Done;
2221 }
2222 else if (PyErr_Occurred())
2223 goto Done;
2224
2225 res = PyObject_SetItem(self, key, value);
2226
2227Done:
2228 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002229 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002230 Py_XDECREF(key);
2231 Py_XDECREF(value);
2232 if (PyErr_Occurred())
2233 break;
2234 }
2235 Py_DECREF(iterator);
2236
2237 if (res < 0 || PyErr_Occurred() != NULL)
2238 return -1;
2239 else
2240 return 0;
2241}
2242
Brandt Bucher6d674a12020-03-13 09:06:04 -07002243static int
2244mutablemapping_update_arg(PyObject *self, PyObject *arg)
2245{
2246 int res = 0;
2247 if (PyDict_CheckExact(arg)) {
2248 PyObject *items = PyDict_Items(arg);
2249 if (items == NULL) {
2250 return -1;
2251 }
2252 res = mutablemapping_add_pairs(self, items);
2253 Py_DECREF(items);
2254 return res;
2255 }
2256 _Py_IDENTIFIER(keys);
2257 PyObject *func;
2258 if (_PyObject_LookupAttrId(arg, &PyId_keys, &func) < 0) {
2259 return -1;
2260 }
2261 if (func != NULL) {
2262 PyObject *keys = _PyObject_CallNoArg(func);
2263 Py_DECREF(func);
2264 if (keys == NULL) {
2265 return -1;
2266 }
2267 PyObject *iterator = PyObject_GetIter(keys);
2268 Py_DECREF(keys);
2269 if (iterator == NULL) {
2270 return -1;
2271 }
2272 PyObject *key;
2273 while (res == 0 && (key = PyIter_Next(iterator))) {
2274 PyObject *value = PyObject_GetItem(arg, key);
2275 if (value != NULL) {
2276 res = PyObject_SetItem(self, key, value);
2277 Py_DECREF(value);
2278 }
2279 else {
2280 res = -1;
2281 }
2282 Py_DECREF(key);
2283 }
2284 Py_DECREF(iterator);
2285 if (res != 0 || PyErr_Occurred()) {
2286 return -1;
2287 }
2288 return 0;
2289 }
2290 if (_PyObject_LookupAttrId(arg, &PyId_items, &func) < 0) {
2291 return -1;
2292 }
2293 if (func != NULL) {
2294 PyObject *items = _PyObject_CallNoArg(func);
2295 Py_DECREF(func);
2296 if (items == NULL) {
2297 return -1;
2298 }
2299 res = mutablemapping_add_pairs(self, items);
2300 Py_DECREF(items);
2301 return res;
2302 }
2303 res = mutablemapping_add_pairs(self, arg);
2304 return res;
2305}
2306
Eric Snow96c6af92015-05-29 22:21:39 -06002307static PyObject *
2308mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2309{
Brandt Bucher6d674a12020-03-13 09:06:04 -07002310 int res;
Eric Snow96c6af92015-05-29 22:21:39 -06002311 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002312 assert(args == NULL || PyTuple_Check(args));
Brandt Bucher6d674a12020-03-13 09:06:04 -07002313 Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002314 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02002315 const char *msg = "update() takes at most 1 positional argument (%zd given)";
Eric Snow96c6af92015-05-29 22:21:39 -06002316 PyErr_Format(PyExc_TypeError, msg, len);
2317 return NULL;
2318 }
Eric Snow96c6af92015-05-29 22:21:39 -06002319
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002320 if (len) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002321 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002322 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002323 Py_INCREF(other);
Brandt Bucher6d674a12020-03-13 09:06:04 -07002324 res = mutablemapping_update_arg(self, other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002325 Py_DECREF(other);
Brandt Bucher6d674a12020-03-13 09:06:04 -07002326 if (res < 0) {
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002327 return NULL;
Brandt Bucher6d674a12020-03-13 09:06:04 -07002328 }
Benjamin Peterson0718de92015-06-07 00:00:42 -05002329 }
2330
2331 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002332 assert(kwargs == NULL || PyDict_Check(kwargs));
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02002333 if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002334 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002335 if (items == NULL)
2336 return NULL;
2337 res = mutablemapping_add_pairs(self, items);
2338 Py_DECREF(items);
2339 if (res == -1)
2340 return NULL;
2341 }
Eric Snow96c6af92015-05-29 22:21:39 -06002342
2343 Py_RETURN_NONE;
2344}