blob: f412220e8cc02c8e125f78247105b1748733a09d [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/* ----------------------------------------------
855 * OrderedDict methods
856 */
857
Eric Snow96c6af92015-05-29 22:21:39 -0600858/* fromkeys() */
859
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100860/*[clinic input]
861@classmethod
862OrderedDict.fromkeys
863
864 iterable as seq: object
865 value: object = None
866
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200867Create a new ordered dictionary with keys from iterable and values set to value.
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100868[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600869
870static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100871OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200872/*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600873{
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100874 return _PyDict_FromKeys((PyObject *)type, seq, value);
Eric Snow96c6af92015-05-29 22:21:39 -0600875}
876
877/* __sizeof__() */
878
879/* OrderedDict.__sizeof__() does not have a docstring. */
880PyDoc_STRVAR(odict_sizeof__doc__, "");
881
882static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530883odict_sizeof(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600884{
Serhiy Storchaka0ce7a3a2015-12-22 08:16:18 +0200885 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Serhiy Storchaka6f17e512018-10-20 02:27:45 +0300886 res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
Eric Snow96c6af92015-05-29 22:21:39 -0600887 if (!_odict_EMPTY(od)) {
888 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
889 }
890 return PyLong_FromSsize_t(res);
891}
892
893/* __reduce__() */
894
895PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
896
897static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530898odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600899{
900 _Py_IDENTIFIER(__dict__);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300901 PyObject *dict = NULL, *result = NULL;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300902 PyObject *items_iter, *items, *args = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600903
904 /* capture any instance state */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300905 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
906 if (dict == NULL)
Eric Snowc5e59602015-05-30 11:28:56 -0600907 goto Done;
908 else {
Eric Snow96c6af92015-05-29 22:21:39 -0600909 /* od.__dict__ isn't necessarily a dict... */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300910 Py_ssize_t dict_len = PyObject_Length(dict);
911 if (dict_len == -1)
Eric Snow96c6af92015-05-29 22:21:39 -0600912 goto Done;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300913 if (!dict_len) {
914 /* nothing to pickle in od.__dict__ */
915 Py_CLEAR(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600916 }
917 }
918
919 /* build the result */
Eric Snow96c6af92015-05-29 22:21:39 -0600920 args = PyTuple_New(0);
921 if (args == NULL)
922 goto Done;
923
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200924 items = _PyObject_CallMethodIdNoArgs((PyObject *)od, &PyId_items);
Eric Snow96c6af92015-05-29 22:21:39 -0600925 if (items == NULL)
926 goto Done;
927
928 items_iter = PyObject_GetIter(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300929 Py_DECREF(items);
Eric Snow96c6af92015-05-29 22:21:39 -0600930 if (items_iter == NULL)
931 goto Done;
932
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300933 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300934 Py_DECREF(items_iter);
Eric Snow96c6af92015-05-29 22:21:39 -0600935
936Done:
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300937 Py_XDECREF(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600938 Py_XDECREF(args);
Eric Snow96c6af92015-05-29 22:21:39 -0600939
940 return result;
941}
942
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100943/* setdefault(): Skips __missing__() calls. */
Eric Snow96c6af92015-05-29 22:21:39 -0600944
Eric Snow96c6af92015-05-29 22:21:39 -0600945
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100946/*[clinic input]
947OrderedDict.setdefault
948
949 key: object
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200950 default: object = None
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100951
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200952Insert key with a value of default if key is not in the dictionary.
953
954Return the value for key if key is in the dictionary, else default.
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100955[clinic start generated code]*/
956
Eric Snow96c6af92015-05-29 22:21:39 -0600957static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100958OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200959 PyObject *default_value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200960/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600961{
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100962 PyObject *result = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600963
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100964 if (PyODict_CheckExact(self)) {
965 result = PyODict_GetItemWithError(self, key); /* borrowed */
Eric Snowd1719752015-06-01 23:12:13 -0600966 if (result == NULL) {
967 if (PyErr_Occurred())
968 return NULL;
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100969 assert(_odict_find_node(self, key) == NULL);
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200970 if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
971 result = default_value;
972 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600973 }
974 }
975 else {
Eric Snowd1719752015-06-01 23:12:13 -0600976 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600977 }
978 }
979 else {
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100980 int exists = PySequence_Contains((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -0600981 if (exists < 0) {
Eric Snowd1719752015-06-01 23:12:13 -0600982 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600983 }
984 else if (exists) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100985 result = PyObject_GetItem((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -0600986 }
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200987 else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
988 result = default_value;
989 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600990 }
991 }
992
Eric Snow96c6af92015-05-29 22:21:39 -0600993 return result;
994}
995
996/* pop() */
997
998PyDoc_STRVAR(odict_pop__doc__,
999"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1000 value. If key is not found, d is returned if given, otherwise KeyError\n\
1001 is raised.\n\
1002\n\
1003 ");
1004
1005/* forward */
1006static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1007
1008/* Skips __missing__() calls. */
1009static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001010odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001011{
Eric Snowac02ef32015-06-02 20:42:14 -06001012 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001013 PyObject *key, *failobj = NULL;
1014
Eric Snowac02ef32015-06-02 20:42:14 -06001015 /* borrowed */
1016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1017 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001018 return NULL;
1019 }
1020
1021 return _odict_popkey(od, key, failobj);
1022}
1023
1024static PyObject *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001025_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1026 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -06001027{
1028 _ODictNode *node;
1029 PyObject *value = NULL;
1030
Eric Snow96c6af92015-05-29 22:21:39 -06001031 /* Pop the node first to avoid a possible dict resize (due to
1032 eval loop reentrancy) and complications due to hash collision
1033 resolution. */
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001034 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001035 if (node == NULL) {
1036 if (PyErr_Occurred())
Eric Snowd1719752015-06-01 23:12:13 -06001037 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001038 }
1039 else {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001040 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001041 if (res < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001042 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001043 }
1044 }
1045
1046 /* Now delete the value from the dict. */
Serhiy Storchaka04386832016-10-30 17:17:24 +02001047 if (PyODict_CheckExact(od)) {
1048 if (node != NULL) {
1049 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1050 if (value != NULL) {
1051 Py_INCREF(value);
1052 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1053 Py_DECREF(value);
1054 return NULL;
1055 }
1056 }
1057 }
1058 }
1059 else {
1060 int exists = PySequence_Contains(od, key);
1061 if (exists < 0)
1062 return NULL;
1063 if (exists) {
1064 value = PyObject_GetItem(od, key);
1065 if (value != NULL) {
1066 if (PyObject_DelItem(od, key) == -1) {
1067 Py_CLEAR(value);
1068 }
Eric Snow96c6af92015-05-29 22:21:39 -06001069 }
1070 }
1071 }
1072
1073 /* Apply the fallback value, if necessary. */
1074 if (value == NULL && !PyErr_Occurred()) {
1075 if (failobj) {
1076 value = failobj;
1077 Py_INCREF(failobj);
1078 }
1079 else {
1080 PyErr_SetObject(PyExc_KeyError, key);
1081 }
1082 }
1083
Eric Snow96c6af92015-05-29 22:21:39 -06001084 return value;
1085}
1086
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001087static PyObject *
1088_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1089{
1090 Py_hash_t hash = PyObject_Hash(key);
1091 if (hash == -1)
1092 return NULL;
1093
1094 return _odict_popkey_hash(od, key, failobj, hash);
1095}
1096
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001097
Eric Snow96c6af92015-05-29 22:21:39 -06001098/* popitem() */
1099
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001100/*[clinic input]
1101OrderedDict.popitem
1102
1103 last: bool = True
1104
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001105Remove and return a (key, value) pair from the dictionary.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001106
1107Pairs are returned in LIFO order if last is true or FIFO order if false.
1108[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001109
1110static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001111OrderedDict_popitem_impl(PyODictObject *self, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001112/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001113{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001114 PyObject *key, *value, *item = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001115 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001116
1117 /* pull the item */
1118
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001119 if (_odict_EMPTY(self)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001120 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1121 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001122 }
Eric Snow96c6af92015-05-29 22:21:39 -06001123
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001124 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001125 key = _odictnode_KEY(node);
Eric Snowd1719752015-06-01 23:12:13 -06001126 Py_INCREF(key);
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001127 value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -06001128 if (value == NULL)
1129 return NULL;
1130 item = PyTuple_Pack(2, key, value);
Eric Snowd1719752015-06-01 23:12:13 -06001131 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001132 Py_DECREF(value);
1133 return item;
1134}
1135
1136/* keys() */
1137
1138/* MutableMapping.keys() does not have a docstring. */
1139PyDoc_STRVAR(odict_keys__doc__, "");
1140
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301141static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001142
1143/* values() */
1144
1145/* MutableMapping.values() does not have a docstring. */
1146PyDoc_STRVAR(odict_values__doc__, "");
1147
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301148static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001149
1150/* items() */
1151
1152/* MutableMapping.items() does not have a docstring. */
1153PyDoc_STRVAR(odict_items__doc__, "");
1154
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301155static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001156
1157/* update() */
1158
1159/* MutableMapping.update() does not have a docstring. */
1160PyDoc_STRVAR(odict_update__doc__, "");
1161
1162/* forward */
1163static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1164
1165#define odict_update mutablemapping_update
1166
1167/* clear() */
1168
1169PyDoc_STRVAR(odict_clear__doc__,
1170 "od.clear() -> None. Remove all items from od.");
1171
1172static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301173odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001174{
1175 PyDict_Clear((PyObject *)od);
1176 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001177 Py_RETURN_NONE;
1178}
1179
1180/* copy() */
1181
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001182/* forward */
1183static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1184 Py_hash_t);
1185
Eric Snow96c6af92015-05-29 22:21:39 -06001186PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1187
1188static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301189odict_copy(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001190{
1191 _ODictNode *node;
1192 PyObject *od_copy;
1193
1194 if (PyODict_CheckExact(od))
1195 od_copy = PyODict_New();
1196 else
Victor Stinnerf17c3de2016-12-06 18:46:19 +01001197 od_copy = _PyObject_CallNoArg((PyObject *)Py_TYPE(od));
Eric Snow96c6af92015-05-29 22:21:39 -06001198 if (od_copy == NULL)
1199 return NULL;
1200
1201 if (PyODict_CheckExact(od)) {
1202 _odict_FOREACH(od, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001203 PyObject *key = _odictnode_KEY(node);
1204 PyObject *value = _odictnode_VALUE(node, od);
1205 if (value == NULL) {
1206 if (!PyErr_Occurred())
1207 PyErr_SetObject(PyExc_KeyError, key);
1208 goto fail;
1209 }
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001210 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1211 _odictnode_HASH(node)) != 0)
Eric Snow96c6af92015-05-29 22:21:39 -06001212 goto fail;
1213 }
1214 }
1215 else {
1216 _odict_FOREACH(od, node) {
1217 int res;
1218 PyObject *value = PyObject_GetItem((PyObject *)od,
1219 _odictnode_KEY(node));
1220 if (value == NULL)
1221 goto fail;
1222 res = PyObject_SetItem((PyObject *)od_copy,
1223 _odictnode_KEY(node), value);
1224 Py_DECREF(value);
1225 if (res != 0)
1226 goto fail;
1227 }
1228 }
1229 return od_copy;
1230
1231fail:
1232 Py_DECREF(od_copy);
1233 return NULL;
1234}
1235
1236/* __reversed__() */
1237
1238PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1239
1240#define _odict_ITER_REVERSED 1
1241#define _odict_ITER_KEYS 2
1242#define _odict_ITER_VALUES 4
1243
1244/* forward */
1245static PyObject * odictiter_new(PyODictObject *, int);
1246
1247static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301248odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001249{
Eric Snow96c6af92015-05-29 22:21:39 -06001250 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1251}
1252
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001253
Eric Snow96c6af92015-05-29 22:21:39 -06001254/* move_to_end() */
1255
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001256/*[clinic input]
1257OrderedDict.move_to_end
1258
1259 key: object
1260 last: bool = True
1261
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001262Move an existing element to the end (or beginning if last is false).
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001263
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001264Raise KeyError if the element does not exist.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001265[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001266
1267static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001268OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001269/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001270{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001271 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001272
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001273 if (_odict_EMPTY(self)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001274 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001275 return NULL;
1276 }
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001277 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001278 if (key != _odictnode_KEY(node)) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001279 node = _odict_find_node(self, key);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001280 if (node == NULL) {
1281 if (!PyErr_Occurred())
1282 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowc5e59602015-05-30 11:28:56 -06001283 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001284 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001285 if (last) {
1286 /* Only move if not already the last one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001287 if (node != _odict_LAST(self)) {
1288 _odict_remove_node(self, node);
1289 _odict_add_tail(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001290 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001291 }
1292 else {
1293 /* Only move if not already the first one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001294 if (node != _odict_FIRST(self)) {
1295 _odict_remove_node(self, node);
1296 _odict_add_head(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001297 }
1298 }
1299 }
Eric Snow96c6af92015-05-29 22:21:39 -06001300 Py_RETURN_NONE;
1301}
1302
1303
1304/* tp_methods */
1305
1306static PyMethodDef odict_methods[] = {
1307
Eric Snow96c6af92015-05-29 22:21:39 -06001308 /* overridden dict methods */
Serhiy Storchaka827d49f2018-04-09 19:14:26 +03001309 ORDEREDDICT_FROMKEYS_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001310 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1311 odict_sizeof__doc__},
1312 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1313 odict_reduce__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001314 ORDEREDDICT_SETDEFAULT_METHODDEF
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001315 {"pop", (PyCFunction)(void(*)(void))odict_pop,
Eric Snowac02ef32015-06-02 20:42:14 -06001316 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001317 ORDEREDDICT_POPITEM_METHODDEF
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301318 {"keys", odictkeys_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001319 odict_keys__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301320 {"values", odictvalues_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001321 odict_values__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301322 {"items", odictitems_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001323 odict_items__doc__},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001324 {"update", (PyCFunction)(void(*)(void))odict_update, METH_VARARGS | METH_KEYWORDS,
Eric Snow96c6af92015-05-29 22:21:39 -06001325 odict_update__doc__},
1326 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1327 odict_clear__doc__},
1328 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1329 odict_copy__doc__},
1330
1331 /* new methods */
1332 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1333 odict_reversed__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001334 ORDEREDDICT_MOVE_TO_END_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001335
1336 {NULL, NULL} /* sentinel */
1337};
1338
1339
1340/* ----------------------------------------------
1341 * OrderedDict members
1342 */
1343
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001344/* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001345
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001346static PyGetSetDef odict_getset[] = {
1347 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1348 {NULL}
Eric Snow96c6af92015-05-29 22:21:39 -06001349};
1350
Eric Snow96c6af92015-05-29 22:21:39 -06001351/* ----------------------------------------------
1352 * OrderedDict type slot methods
1353 */
1354
1355/* tp_dealloc */
1356
1357static void
1358odict_dealloc(PyODictObject *self)
1359{
1360 PyObject_GC_UnTrack(self);
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001361 Py_TRASHCAN_BEGIN(self, odict_dealloc)
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001362
Eric Snow96c6af92015-05-29 22:21:39 -06001363 Py_XDECREF(self->od_inst_dict);
1364 if (self->od_weakreflist != NULL)
1365 PyObject_ClearWeakRefs((PyObject *)self);
1366
1367 _odict_clear_nodes(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001368 PyDict_Type.tp_dealloc((PyObject *)self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001369
Jeroen Demeyer351c6742019-05-10 19:21:11 +02001370 Py_TRASHCAN_END
Victor Stinnere1871952016-06-08 10:18:18 +02001371}
Eric Snow96c6af92015-05-29 22:21:39 -06001372
1373/* tp_repr */
1374
1375static PyObject *
1376odict_repr(PyODictObject *self)
1377{
1378 int i;
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001379 PyObject *pieces = NULL, *result = NULL;
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001380
1381 if (PyODict_SIZE(self) == 0)
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001382 return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
Eric Snow96c6af92015-05-29 22:21:39 -06001383
1384 i = Py_ReprEnter((PyObject *)self);
1385 if (i != 0) {
1386 return i > 0 ? PyUnicode_FromString("...") : NULL;
1387 }
1388
Eric Snow96c6af92015-05-29 22:21:39 -06001389 if (PyODict_CheckExact(self)) {
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001390 Py_ssize_t count = 0;
Eric Snowa762af72015-06-01 22:59:08 -06001391 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001392 pieces = PyList_New(PyODict_SIZE(self));
1393 if (pieces == NULL)
1394 goto Done;
1395
1396 _odict_FOREACH(self, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001397 PyObject *pair;
1398 PyObject *key = _odictnode_KEY(node);
1399 PyObject *value = _odictnode_VALUE(node, self);
1400 if (value == NULL) {
1401 if (!PyErr_Occurred())
1402 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowdb4061c2015-06-03 11:09:48 -06001403 goto Done;
Eric Snowa762af72015-06-01 22:59:08 -06001404 }
1405 pair = PyTuple_Pack(2, key, value);
Eric Snow96c6af92015-05-29 22:21:39 -06001406 if (pair == NULL)
1407 goto Done;
1408
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001409 if (count < PyList_GET_SIZE(pieces))
1410 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1411 else {
1412 if (PyList_Append(pieces, pair) < 0) {
1413 Py_DECREF(pair);
1414 goto Done;
1415 }
1416 Py_DECREF(pair);
1417 }
1418 count++;
Eric Snow96c6af92015-05-29 22:21:39 -06001419 }
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001420 if (count < PyList_GET_SIZE(pieces)) {
1421 Py_SET_SIZE(pieces, count);
1422 }
Eric Snow96c6af92015-05-29 22:21:39 -06001423 }
1424 else {
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001425 PyObject *items = _PyObject_CallMethodIdNoArgs((PyObject *)self,
1426 &PyId_items);
Eric Snow96c6af92015-05-29 22:21:39 -06001427 if (items == NULL)
1428 goto Done;
1429 pieces = PySequence_List(items);
1430 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001431 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001432 goto Done;
1433 }
1434
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001435 result = PyUnicode_FromFormat("%s(%R)",
1436 _PyType_Name(Py_TYPE(self)), pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001437
Eric Snow96c6af92015-05-29 22:21:39 -06001438Done:
1439 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001440 Py_ReprLeave((PyObject *)self);
1441 return result;
Victor Stinnere1871952016-06-08 10:18:18 +02001442}
Eric Snow96c6af92015-05-29 22:21:39 -06001443
1444/* tp_doc */
1445
1446PyDoc_STRVAR(odict_doc,
1447 "Dictionary that remembers insertion order");
1448
1449/* tp_traverse */
1450
1451static int
1452odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1453{
Serhiy Storchakad205d012016-01-19 14:46:25 +02001454 _ODictNode *node;
1455
Eric Snow96c6af92015-05-29 22:21:39 -06001456 Py_VISIT(od->od_inst_dict);
1457 Py_VISIT(od->od_weakreflist);
Serhiy Storchakad205d012016-01-19 14:46:25 +02001458 _odict_FOREACH(od, node) {
1459 Py_VISIT(_odictnode_KEY(node));
1460 }
Eric Snow96c6af92015-05-29 22:21:39 -06001461 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1462}
1463
1464/* tp_clear */
1465
1466static int
1467odict_tp_clear(PyODictObject *od)
1468{
Eric Snow96c6af92015-05-29 22:21:39 -06001469 Py_CLEAR(od->od_inst_dict);
1470 Py_CLEAR(od->od_weakreflist);
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001471 PyDict_Clear((PyObject *)od);
1472 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001473 return 0;
1474}
1475
1476/* tp_richcompare */
1477
1478static PyObject *
1479odict_richcompare(PyObject *v, PyObject *w, int op)
1480{
1481 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1482 Py_RETURN_NOTIMPLEMENTED;
1483 }
1484
1485 if (op == Py_EQ || op == Py_NE) {
1486 PyObject *res, *cmp;
1487 int eq;
1488
1489 cmp = PyDict_Type.tp_richcompare(v, w, op);
1490 if (cmp == NULL)
1491 return NULL;
1492 if (!PyODict_Check(w))
1493 return cmp;
1494 if (op == Py_EQ && cmp == Py_False)
1495 return cmp;
1496 if (op == Py_NE && cmp == Py_True)
1497 return cmp;
1498 Py_DECREF(cmp);
1499
1500 /* Try comparing odict keys. */
1501 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1502 if (eq < 0)
1503 return NULL;
1504
1505 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1506 Py_INCREF(res);
1507 return res;
1508 } else {
1509 Py_RETURN_NOTIMPLEMENTED;
1510 }
Victor Stinnere1871952016-06-08 10:18:18 +02001511}
Eric Snow96c6af92015-05-29 22:21:39 -06001512
1513/* tp_iter */
1514
1515static PyObject *
1516odict_iter(PyODictObject *od)
1517{
1518 return odictiter_new(od, _odict_ITER_KEYS);
Victor Stinnere1871952016-06-08 10:18:18 +02001519}
Eric Snow96c6af92015-05-29 22:21:39 -06001520
1521/* tp_init */
1522
1523static int
1524odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1525{
1526 PyObject *res;
1527 Py_ssize_t len = PyObject_Length(args);
1528
1529 if (len == -1)
1530 return -1;
1531 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02001532 const char *msg = "expected at most 1 arguments, got %zd";
Eric Snow96c6af92015-05-29 22:21:39 -06001533 PyErr_Format(PyExc_TypeError, msg, len);
1534 return -1;
1535 }
1536
1537 /* __init__() triggering update() is just the way things are! */
1538 res = odict_update(self, args, kwds);
1539 if (res == NULL) {
1540 return -1;
1541 } else {
1542 Py_DECREF(res);
1543 return 0;
1544 }
Victor Stinnere1871952016-06-08 10:18:18 +02001545}
Eric Snow96c6af92015-05-29 22:21:39 -06001546
Eric Snow96c6af92015-05-29 22:21:39 -06001547/* PyODict_Type */
1548
1549PyTypeObject PyODict_Type = {
1550 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1551 "collections.OrderedDict", /* tp_name */
1552 sizeof(PyODictObject), /* tp_basicsize */
1553 0, /* tp_itemsize */
1554 (destructor)odict_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001555 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001556 0, /* tp_getattr */
1557 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001558 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001559 (reprfunc)odict_repr, /* tp_repr */
1560 0, /* tp_as_number */
1561 0, /* tp_as_sequence */
1562 &odict_as_mapping, /* tp_as_mapping */
1563 0, /* tp_hash */
1564 0, /* tp_call */
1565 0, /* tp_str */
1566 0, /* tp_getattro */
1567 0, /* tp_setattro */
1568 0, /* tp_as_buffer */
1569 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1570 odict_doc, /* tp_doc */
1571 (traverseproc)odict_traverse, /* tp_traverse */
1572 (inquiry)odict_tp_clear, /* tp_clear */
1573 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1574 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1575 (getiterfunc)odict_iter, /* tp_iter */
1576 0, /* tp_iternext */
1577 odict_methods, /* tp_methods */
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001578 0, /* tp_members */
1579 odict_getset, /* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001580 &PyDict_Type, /* tp_base */
1581 0, /* tp_dict */
1582 0, /* tp_descr_get */
1583 0, /* tp_descr_set */
1584 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1585 (initproc)odict_init, /* tp_init */
1586 PyType_GenericAlloc, /* tp_alloc */
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001587 0, /* tp_new */
Eric Snow96c6af92015-05-29 22:21:39 -06001588 0, /* tp_free */
1589};
1590
1591
1592/* ----------------------------------------------
1593 * the public OrderedDict API
1594 */
1595
1596PyObject *
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001597PyODict_New(void)
1598{
1599 return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
Victor Stinnere1871952016-06-08 10:18:18 +02001600}
Eric Snow96c6af92015-05-29 22:21:39 -06001601
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001602static int
1603_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1604 Py_hash_t hash)
1605{
1606 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001607 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001608 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001609 if (res < 0) {
1610 /* Revert setting the value on the dict */
1611 PyObject *exc, *val, *tb;
1612 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001613 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001614 _PyErr_ChainExceptions(exc, val, tb);
1615 }
Eric Snow96c6af92015-05-29 22:21:39 -06001616 }
1617 return res;
Victor Stinnere1871952016-06-08 10:18:18 +02001618}
Eric Snow96c6af92015-05-29 22:21:39 -06001619
1620int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001621PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1622{
1623 Py_hash_t hash = PyObject_Hash(key);
1624 if (hash == -1)
1625 return -1;
1626 return _PyODict_SetItem_KnownHash(od, key, value, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001627}
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001628
1629int
1630PyODict_DelItem(PyObject *od, PyObject *key)
1631{
1632 int res;
1633 Py_hash_t hash = PyObject_Hash(key);
1634 if (hash == -1)
1635 return -1;
1636 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001637 if (res < 0)
1638 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001639 return _PyDict_DelItem_KnownHash(od, key, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001640}
Eric Snow96c6af92015-05-29 22:21:39 -06001641
1642
1643/* -------------------------------------------
1644 * The OrderedDict views (keys/values/items)
1645 */
1646
1647typedef struct {
1648 PyObject_HEAD
1649 int kind;
1650 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001651 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001652 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001653 PyObject *di_current;
1654 PyObject *di_result; /* reusable result tuple for iteritems */
1655} odictiterobject;
1656
1657static void
1658odictiter_dealloc(odictiterobject *di)
1659{
1660 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001661 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001662 Py_XDECREF(di->di_current);
1663 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1664 Py_DECREF(di->di_result);
1665 }
1666 PyObject_GC_Del(di);
1667}
1668
1669static int
1670odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1671{
1672 Py_VISIT(di->di_odict);
1673 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1674 Py_VISIT(di->di_result);
1675 return 0;
1676}
1677
Eric Snowa762af72015-06-01 22:59:08 -06001678/* In order to protect against modifications during iteration, we track
1679 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001680static PyObject *
1681odictiter_nextkey(odictiterobject *di)
1682{
Eric Snowa762af72015-06-01 22:59:08 -06001683 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001684 _ODictNode *node;
1685 int reversed = di->kind & _odict_ITER_REVERSED;
1686
Eric Snowa762af72015-06-01 22:59:08 -06001687 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001688 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001689 if (di->di_current == NULL)
1690 goto done; /* We're already done. */
1691
Eric Snowb952ab42015-06-01 23:35:13 -06001692 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001693 if (di->di_odict->od_state != di->di_state) {
1694 PyErr_SetString(PyExc_RuntimeError,
1695 "OrderedDict mutated during iteration");
1696 goto done;
1697 }
Eric Snowb952ab42015-06-01 23:35:13 -06001698 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1699 PyErr_SetString(PyExc_RuntimeError,
1700 "OrderedDict changed size during iteration");
1701 di->di_size = -1; /* Make this state sticky */
1702 return NULL;
1703 }
1704
Eric Snowa762af72015-06-01 22:59:08 -06001705 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001706 node = _odict_find_node(di->di_odict, di->di_current);
1707 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001708 if (!PyErr_Occurred())
1709 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001710 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001711 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001712 return NULL;
1713 }
1714 key = di->di_current;
1715
1716 /* Advance to the next key. */
1717 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1718 if (node == NULL) {
1719 /* Reached the end. */
1720 di->di_current = NULL;
1721 }
1722 else {
1723 di->di_current = _odictnode_KEY(node);
1724 Py_INCREF(di->di_current);
1725 }
1726
1727 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001728
1729done:
1730 Py_CLEAR(di->di_odict);
1731 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001732}
1733
1734static PyObject *
1735odictiter_iternext(odictiterobject *di)
1736{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001737 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001738 PyObject *key = odictiter_nextkey(di); /* new reference */
1739
1740 if (key == NULL)
1741 return NULL;
1742
1743 /* Handle the keys case. */
1744 if (! (di->kind & _odict_ITER_VALUES)) {
1745 return key;
1746 }
1747
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001748 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1749 if (value == NULL) {
1750 if (!PyErr_Occurred())
1751 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001752 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001753 goto done;
1754 }
1755 Py_INCREF(value);
1756
1757 /* Handle the values case. */
1758 if (!(di->kind & _odict_ITER_KEYS)) {
1759 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001760 return value;
1761 }
Eric Snowa762af72015-06-01 22:59:08 -06001762
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001763 /* Handle the items case. */
1764 result = di->di_result;
1765
1766 if (Py_REFCNT(result) == 1) {
1767 /* not in use so we can reuse it
1768 * (the common case during iteration) */
1769 Py_INCREF(result);
1770 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1771 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1772 }
1773 else {
1774 result = PyTuple_New(2);
1775 if (result == NULL) {
1776 Py_DECREF(key);
1777 Py_DECREF(value);
1778 goto done;
1779 }
1780 }
1781
1782 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1783 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1784 return result;
1785
Eric Snowa762af72015-06-01 22:59:08 -06001786done:
1787 Py_CLEAR(di->di_current);
1788 Py_CLEAR(di->di_odict);
1789 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001790}
1791
1792/* No need for tp_clear because odictiterobject is not mutable. */
1793
1794PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1795
1796static PyObject *
Serhiy Storchaka81524022018-11-27 13:05:02 +02001797odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001798{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001799 _Py_IDENTIFIER(iter);
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001800 /* copy the iterator state */
1801 odictiterobject tmp = *di;
1802 Py_XINCREF(tmp.di_odict);
1803 Py_XINCREF(tmp.di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001804
1805 /* iterate the temporary into a list */
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001806 PyObject *list = PySequence_List((PyObject*)&tmp);
1807 Py_XDECREF(tmp.di_odict);
1808 Py_XDECREF(tmp.di_current);
1809 if (list == NULL) {
Eric Snow96c6af92015-05-29 22:21:39 -06001810 return NULL;
1811 }
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001812 return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
Eric Snow96c6af92015-05-29 22:21:39 -06001813}
1814
1815static PyMethodDef odictiter_methods[] = {
1816 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1817 {NULL, NULL} /* sentinel */
1818};
1819
1820PyTypeObject PyODictIter_Type = {
1821 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1822 "odict_iterator", /* tp_name */
1823 sizeof(odictiterobject), /* tp_basicsize */
1824 0, /* tp_itemsize */
1825 /* methods */
1826 (destructor)odictiter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001827 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001828 0, /* tp_getattr */
1829 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001830 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001831 0, /* tp_repr */
1832 0, /* tp_as_number */
1833 0, /* tp_as_sequence */
1834 0, /* tp_as_mapping */
1835 0, /* tp_hash */
1836 0, /* tp_call */
1837 0, /* tp_str */
1838 PyObject_GenericGetAttr, /* tp_getattro */
1839 0, /* tp_setattro */
1840 0, /* tp_as_buffer */
1841 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1842 0, /* tp_doc */
1843 (traverseproc)odictiter_traverse, /* tp_traverse */
1844 0, /* tp_clear */
1845 0, /* tp_richcompare */
1846 0, /* tp_weaklistoffset */
1847 PyObject_SelfIter, /* tp_iter */
1848 (iternextfunc)odictiter_iternext, /* tp_iternext */
1849 odictiter_methods, /* tp_methods */
1850 0,
1851};
1852
1853static PyObject *
1854odictiter_new(PyODictObject *od, int kind)
1855{
1856 odictiterobject *di;
1857 _ODictNode *node;
1858 int reversed = kind & _odict_ITER_REVERSED;
1859
1860 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1861 if (di == NULL)
1862 return NULL;
1863
1864 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
1865 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1866 if (di->di_result == NULL) {
1867 Py_DECREF(di);
1868 return NULL;
1869 }
1870 }
1871 else
1872 di->di_result = NULL;
1873
1874 di->kind = kind;
1875 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1876 di->di_current = node ? _odictnode_KEY(node) : NULL;
1877 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06001878 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06001879 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001880 di->di_odict = od;
1881 Py_INCREF(od);
1882
1883 _PyObject_GC_TRACK(di);
1884 return (PyObject *)di;
1885}
1886
1887/* keys() */
1888
1889static PyObject *
1890odictkeys_iter(_PyDictViewObject *dv)
1891{
1892 if (dv->dv_dict == NULL) {
1893 Py_RETURN_NONE;
1894 }
1895 return odictiter_new((PyODictObject *)dv->dv_dict,
1896 _odict_ITER_KEYS);
1897}
1898
1899static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301900odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001901{
1902 if (dv->dv_dict == NULL) {
1903 Py_RETURN_NONE;
1904 }
1905 return odictiter_new((PyODictObject *)dv->dv_dict,
1906 _odict_ITER_KEYS|_odict_ITER_REVERSED);
1907}
1908
1909static PyMethodDef odictkeys_methods[] = {
1910 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
1911 {NULL, NULL} /* sentinel */
1912};
1913
1914PyTypeObject PyODictKeys_Type = {
1915 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1916 "odict_keys", /* tp_name */
1917 0, /* tp_basicsize */
1918 0, /* tp_itemsize */
1919 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001920 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001921 0, /* tp_getattr */
1922 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001923 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001924 0, /* tp_repr */
1925 0, /* tp_as_number */
1926 0, /* tp_as_sequence */
1927 0, /* tp_as_mapping */
1928 0, /* tp_hash */
1929 0, /* tp_call */
1930 0, /* tp_str */
1931 0, /* tp_getattro */
1932 0, /* tp_setattro */
1933 0, /* tp_as_buffer */
1934 0, /* tp_flags */
1935 0, /* tp_doc */
1936 0, /* tp_traverse */
1937 0, /* tp_clear */
1938 0, /* tp_richcompare */
1939 0, /* tp_weaklistoffset */
1940 (getiterfunc)odictkeys_iter, /* tp_iter */
1941 0, /* tp_iternext */
1942 odictkeys_methods, /* tp_methods */
1943 0, /* tp_members */
1944 0, /* tp_getset */
1945 &PyDictKeys_Type, /* tp_base */
1946};
1947
1948static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301949odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001950{
1951 return _PyDictView_New(od, &PyODictKeys_Type);
1952}
1953
1954/* items() */
1955
1956static PyObject *
1957odictitems_iter(_PyDictViewObject *dv)
1958{
1959 if (dv->dv_dict == NULL) {
1960 Py_RETURN_NONE;
1961 }
1962 return odictiter_new((PyODictObject *)dv->dv_dict,
1963 _odict_ITER_KEYS|_odict_ITER_VALUES);
1964}
1965
1966static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301967odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001968{
1969 if (dv->dv_dict == NULL) {
1970 Py_RETURN_NONE;
1971 }
1972 return odictiter_new((PyODictObject *)dv->dv_dict,
1973 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
1974}
1975
1976static PyMethodDef odictitems_methods[] = {
1977 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
1978 {NULL, NULL} /* sentinel */
1979};
1980
1981PyTypeObject PyODictItems_Type = {
1982 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1983 "odict_items", /* tp_name */
1984 0, /* tp_basicsize */
1985 0, /* tp_itemsize */
1986 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001987 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001988 0, /* tp_getattr */
1989 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001990 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001991 0, /* tp_repr */
1992 0, /* tp_as_number */
1993 0, /* tp_as_sequence */
1994 0, /* tp_as_mapping */
1995 0, /* tp_hash */
1996 0, /* tp_call */
1997 0, /* tp_str */
1998 0, /* tp_getattro */
1999 0, /* tp_setattro */
2000 0, /* tp_as_buffer */
2001 0, /* tp_flags */
2002 0, /* tp_doc */
2003 0, /* tp_traverse */
2004 0, /* tp_clear */
2005 0, /* tp_richcompare */
2006 0, /* tp_weaklistoffset */
2007 (getiterfunc)odictitems_iter, /* tp_iter */
2008 0, /* tp_iternext */
2009 odictitems_methods, /* tp_methods */
2010 0, /* tp_members */
2011 0, /* tp_getset */
2012 &PyDictItems_Type, /* tp_base */
2013};
2014
2015static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302016odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002017{
2018 return _PyDictView_New(od, &PyODictItems_Type);
2019}
2020
2021/* values() */
2022
2023static PyObject *
2024odictvalues_iter(_PyDictViewObject *dv)
2025{
2026 if (dv->dv_dict == NULL) {
2027 Py_RETURN_NONE;
2028 }
2029 return odictiter_new((PyODictObject *)dv->dv_dict,
2030 _odict_ITER_VALUES);
2031}
2032
2033static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302034odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002035{
2036 if (dv->dv_dict == NULL) {
2037 Py_RETURN_NONE;
2038 }
2039 return odictiter_new((PyODictObject *)dv->dv_dict,
2040 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2041}
2042
2043static PyMethodDef odictvalues_methods[] = {
2044 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2045 {NULL, NULL} /* sentinel */
2046};
2047
2048PyTypeObject PyODictValues_Type = {
2049 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2050 "odict_values", /* tp_name */
2051 0, /* tp_basicsize */
2052 0, /* tp_itemsize */
2053 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002054 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06002055 0, /* tp_getattr */
2056 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002057 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06002058 0, /* tp_repr */
2059 0, /* tp_as_number */
2060 0, /* tp_as_sequence */
2061 0, /* tp_as_mapping */
2062 0, /* tp_hash */
2063 0, /* tp_call */
2064 0, /* tp_str */
2065 0, /* tp_getattro */
2066 0, /* tp_setattro */
2067 0, /* tp_as_buffer */
2068 0, /* tp_flags */
2069 0, /* tp_doc */
2070 0, /* tp_traverse */
2071 0, /* tp_clear */
2072 0, /* tp_richcompare */
2073 0, /* tp_weaklistoffset */
2074 (getiterfunc)odictvalues_iter, /* tp_iter */
2075 0, /* tp_iternext */
2076 odictvalues_methods, /* tp_methods */
2077 0, /* tp_members */
2078 0, /* tp_getset */
2079 &PyDictValues_Type, /* tp_base */
2080};
2081
2082static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302083odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002084{
2085 return _PyDictView_New(od, &PyODictValues_Type);
2086}
2087
2088
2089/* ----------------------------------------------
Martin Panter536d70e2017-01-14 08:23:08 +00002090 MutableMapping implementations
Eric Snow96c6af92015-05-29 22:21:39 -06002091
2092Mapping:
2093
2094============ ===========
2095method uses
2096============ ===========
2097__contains__ __getitem__
2098__eq__ items
2099__getitem__ +
2100__iter__ +
2101__len__ +
2102__ne__ __eq__
2103get __getitem__
2104items ItemsView
2105keys KeysView
2106values ValuesView
2107============ ===========
2108
2109ItemsView uses __len__, __iter__, and __getitem__.
2110KeysView uses __len__, __iter__, and __contains__.
2111ValuesView uses __len__, __iter__, and __getitem__.
2112
2113MutableMapping:
2114
2115============ ===========
2116method uses
2117============ ===========
2118__delitem__ +
2119__setitem__ +
2120clear popitem
2121pop __getitem__
2122 __delitem__
2123popitem __iter__
2124 _getitem__
2125 __delitem__
2126setdefault __getitem__
2127 __setitem__
2128update __setitem__
2129============ ===========
2130*/
2131
2132static int
2133mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2134{
2135 PyObject *pair, *iterator, *unexpected;
2136 int res = 0;
2137
2138 iterator = PyObject_GetIter(pairs);
2139 if (iterator == NULL)
2140 return -1;
2141 PyErr_Clear();
2142
2143 while ((pair = PyIter_Next(iterator)) != NULL) {
2144 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002145 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002146 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002147 if (pair_iterator == NULL)
2148 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002149
2150 key = PyIter_Next(pair_iterator);
2151 if (key == NULL) {
2152 if (!PyErr_Occurred())
2153 PyErr_SetString(PyExc_ValueError,
2154 "need more than 0 values to unpack");
2155 goto Done;
2156 }
2157
2158 value = PyIter_Next(pair_iterator);
2159 if (value == NULL) {
2160 if (!PyErr_Occurred())
2161 PyErr_SetString(PyExc_ValueError,
2162 "need more than 1 value to unpack");
2163 goto Done;
2164 }
2165
2166 unexpected = PyIter_Next(pair_iterator);
2167 if (unexpected != NULL) {
2168 Py_DECREF(unexpected);
2169 PyErr_SetString(PyExc_ValueError,
2170 "too many values to unpack (expected 2)");
2171 goto Done;
2172 }
2173 else if (PyErr_Occurred())
2174 goto Done;
2175
2176 res = PyObject_SetItem(self, key, value);
2177
2178Done:
2179 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002180 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002181 Py_XDECREF(key);
2182 Py_XDECREF(value);
2183 if (PyErr_Occurred())
2184 break;
2185 }
2186 Py_DECREF(iterator);
2187
2188 if (res < 0 || PyErr_Occurred() != NULL)
2189 return -1;
2190 else
2191 return 0;
2192}
2193
2194static PyObject *
2195mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2196{
2197 int res = 0;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002198 Py_ssize_t len;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002199 _Py_IDENTIFIER(keys);
Eric Snow96c6af92015-05-29 22:21:39 -06002200
2201 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002202 assert(args == NULL || PyTuple_Check(args));
2203 len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002204 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02002205 const char *msg = "update() takes at most 1 positional argument (%zd given)";
Eric Snow96c6af92015-05-29 22:21:39 -06002206 PyErr_Format(PyExc_TypeError, msg, len);
2207 return NULL;
2208 }
Eric Snow96c6af92015-05-29 22:21:39 -06002209
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002210 if (len) {
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002211 PyObject *func;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002212 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002213 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002214 Py_INCREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002215 if (PyDict_CheckExact(other)) {
2216 PyObject *items = PyDict_Items(other);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002217 Py_DECREF(other);
2218 if (items == NULL)
2219 return NULL;
2220 res = mutablemapping_add_pairs(self, items);
2221 Py_DECREF(items);
2222 if (res == -1)
2223 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002224 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002225 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002226
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002227 if (_PyObject_LookupAttrId(other, &PyId_keys, &func) < 0) {
2228 Py_DECREF(other);
2229 return NULL;
2230 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002231 if (func != NULL) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002232 PyObject *keys, *iterator, *key;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002233 keys = _PyObject_CallNoArg(func);
2234 Py_DECREF(func);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002235 if (keys == NULL) {
2236 Py_DECREF(other);
2237 return NULL;
2238 }
2239 iterator = PyObject_GetIter(keys);
2240 Py_DECREF(keys);
2241 if (iterator == NULL) {
2242 Py_DECREF(other);
2243 return NULL;
2244 }
2245 while (res == 0 && (key = PyIter_Next(iterator))) {
2246 PyObject *value = PyObject_GetItem(other, key);
2247 if (value != NULL) {
2248 res = PyObject_SetItem(self, key, value);
2249 Py_DECREF(value);
2250 }
2251 else {
2252 res = -1;
2253 }
2254 Py_DECREF(key);
2255 }
2256 Py_DECREF(other);
2257 Py_DECREF(iterator);
2258 if (res != 0 || PyErr_Occurred())
2259 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002260 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002261 }
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002262
2263 if (_PyObject_LookupAttrId(other, &PyId_items, &func) < 0) {
Eric Snow06aed902016-09-09 11:59:08 -07002264 Py_DECREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002265 return NULL;
2266 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002267 if (func != NULL) {
2268 PyObject *items;
2269 Py_DECREF(other);
2270 items = _PyObject_CallNoArg(func);
2271 Py_DECREF(func);
Eric Snow06aed902016-09-09 11:59:08 -07002272 if (items == NULL)
2273 return NULL;
2274 res = mutablemapping_add_pairs(self, items);
2275 Py_DECREF(items);
2276 if (res == -1)
2277 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002278 goto handle_kwargs;
2279 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002280
2281 res = mutablemapping_add_pairs(self, other);
2282 Py_DECREF(other);
2283 if (res != 0)
2284 return NULL;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002285 }
2286
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002287 handle_kwargs:
Benjamin Peterson0718de92015-06-07 00:00:42 -05002288 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002289 assert(kwargs == NULL || PyDict_Check(kwargs));
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02002290 if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002291 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002292 if (items == NULL)
2293 return NULL;
2294 res = mutablemapping_add_pairs(self, items);
2295 Py_DECREF(items);
2296 if (res == -1)
2297 return NULL;
2298 }
Eric Snow96c6af92015-05-29 22:21:39 -06002299
2300 Py_RETURN_NONE;
2301}