blob: 45e089be2871ec1a8424a4660a7fbc89dd692146 [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 }
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001420 if (count < PyList_GET_SIZE(pieces))
Serhiy Storchaka1a5856b2017-04-22 02:48:11 +03001421 Py_SIZE(pieces) = count;
Eric Snow96c6af92015-05-29 22:21:39 -06001422 }
1423 else {
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001424 PyObject *items = _PyObject_CallMethodIdNoArgs((PyObject *)self,
1425 &PyId_items);
Eric Snow96c6af92015-05-29 22:21:39 -06001426 if (items == NULL)
1427 goto Done;
1428 pieces = PySequence_List(items);
1429 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001430 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001431 goto Done;
1432 }
1433
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001434 result = PyUnicode_FromFormat("%s(%R)",
1435 _PyType_Name(Py_TYPE(self)), pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001436
Eric Snow96c6af92015-05-29 22:21:39 -06001437Done:
1438 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001439 Py_ReprLeave((PyObject *)self);
1440 return result;
Victor Stinnere1871952016-06-08 10:18:18 +02001441}
Eric Snow96c6af92015-05-29 22:21:39 -06001442
1443/* tp_doc */
1444
1445PyDoc_STRVAR(odict_doc,
1446 "Dictionary that remembers insertion order");
1447
1448/* tp_traverse */
1449
1450static int
1451odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1452{
Serhiy Storchakad205d012016-01-19 14:46:25 +02001453 _ODictNode *node;
1454
Eric Snow96c6af92015-05-29 22:21:39 -06001455 Py_VISIT(od->od_inst_dict);
1456 Py_VISIT(od->od_weakreflist);
Serhiy Storchakad205d012016-01-19 14:46:25 +02001457 _odict_FOREACH(od, node) {
1458 Py_VISIT(_odictnode_KEY(node));
1459 }
Eric Snow96c6af92015-05-29 22:21:39 -06001460 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1461}
1462
1463/* tp_clear */
1464
1465static int
1466odict_tp_clear(PyODictObject *od)
1467{
Eric Snow96c6af92015-05-29 22:21:39 -06001468 Py_CLEAR(od->od_inst_dict);
1469 Py_CLEAR(od->od_weakreflist);
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001470 PyDict_Clear((PyObject *)od);
1471 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001472 return 0;
1473}
1474
1475/* tp_richcompare */
1476
1477static PyObject *
1478odict_richcompare(PyObject *v, PyObject *w, int op)
1479{
1480 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1481 Py_RETURN_NOTIMPLEMENTED;
1482 }
1483
1484 if (op == Py_EQ || op == Py_NE) {
1485 PyObject *res, *cmp;
1486 int eq;
1487
1488 cmp = PyDict_Type.tp_richcompare(v, w, op);
1489 if (cmp == NULL)
1490 return NULL;
1491 if (!PyODict_Check(w))
1492 return cmp;
1493 if (op == Py_EQ && cmp == Py_False)
1494 return cmp;
1495 if (op == Py_NE && cmp == Py_True)
1496 return cmp;
1497 Py_DECREF(cmp);
1498
1499 /* Try comparing odict keys. */
1500 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1501 if (eq < 0)
1502 return NULL;
1503
1504 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1505 Py_INCREF(res);
1506 return res;
1507 } else {
1508 Py_RETURN_NOTIMPLEMENTED;
1509 }
Victor Stinnere1871952016-06-08 10:18:18 +02001510}
Eric Snow96c6af92015-05-29 22:21:39 -06001511
1512/* tp_iter */
1513
1514static PyObject *
1515odict_iter(PyODictObject *od)
1516{
1517 return odictiter_new(od, _odict_ITER_KEYS);
Victor Stinnere1871952016-06-08 10:18:18 +02001518}
Eric Snow96c6af92015-05-29 22:21:39 -06001519
1520/* tp_init */
1521
1522static int
1523odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1524{
1525 PyObject *res;
1526 Py_ssize_t len = PyObject_Length(args);
1527
1528 if (len == -1)
1529 return -1;
1530 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02001531 const char *msg = "expected at most 1 arguments, got %zd";
Eric Snow96c6af92015-05-29 22:21:39 -06001532 PyErr_Format(PyExc_TypeError, msg, len);
1533 return -1;
1534 }
1535
1536 /* __init__() triggering update() is just the way things are! */
1537 res = odict_update(self, args, kwds);
1538 if (res == NULL) {
1539 return -1;
1540 } else {
1541 Py_DECREF(res);
1542 return 0;
1543 }
Victor Stinnere1871952016-06-08 10:18:18 +02001544}
Eric Snow96c6af92015-05-29 22:21:39 -06001545
Eric Snow96c6af92015-05-29 22:21:39 -06001546/* PyODict_Type */
1547
1548PyTypeObject PyODict_Type = {
1549 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1550 "collections.OrderedDict", /* tp_name */
1551 sizeof(PyODictObject), /* tp_basicsize */
1552 0, /* tp_itemsize */
1553 (destructor)odict_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001554 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001555 0, /* tp_getattr */
1556 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001557 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001558 (reprfunc)odict_repr, /* tp_repr */
1559 0, /* tp_as_number */
1560 0, /* tp_as_sequence */
1561 &odict_as_mapping, /* tp_as_mapping */
1562 0, /* tp_hash */
1563 0, /* tp_call */
1564 0, /* tp_str */
1565 0, /* tp_getattro */
1566 0, /* tp_setattro */
1567 0, /* tp_as_buffer */
1568 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1569 odict_doc, /* tp_doc */
1570 (traverseproc)odict_traverse, /* tp_traverse */
1571 (inquiry)odict_tp_clear, /* tp_clear */
1572 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1573 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1574 (getiterfunc)odict_iter, /* tp_iter */
1575 0, /* tp_iternext */
1576 odict_methods, /* tp_methods */
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001577 0, /* tp_members */
1578 odict_getset, /* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001579 &PyDict_Type, /* tp_base */
1580 0, /* tp_dict */
1581 0, /* tp_descr_get */
1582 0, /* tp_descr_set */
1583 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1584 (initproc)odict_init, /* tp_init */
1585 PyType_GenericAlloc, /* tp_alloc */
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001586 0, /* tp_new */
Eric Snow96c6af92015-05-29 22:21:39 -06001587 0, /* tp_free */
1588};
1589
1590
1591/* ----------------------------------------------
1592 * the public OrderedDict API
1593 */
1594
1595PyObject *
Serhiy Storchaka6f17e512018-10-20 02:27:45 +03001596PyODict_New(void)
1597{
1598 return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
Victor Stinnere1871952016-06-08 10:18:18 +02001599}
Eric Snow96c6af92015-05-29 22:21:39 -06001600
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001601static int
1602_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1603 Py_hash_t hash)
1604{
1605 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001606 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001607 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001608 if (res < 0) {
1609 /* Revert setting the value on the dict */
1610 PyObject *exc, *val, *tb;
1611 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001612 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001613 _PyErr_ChainExceptions(exc, val, tb);
1614 }
Eric Snow96c6af92015-05-29 22:21:39 -06001615 }
1616 return res;
Victor Stinnere1871952016-06-08 10:18:18 +02001617}
Eric Snow96c6af92015-05-29 22:21:39 -06001618
1619int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001620PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1621{
1622 Py_hash_t hash = PyObject_Hash(key);
1623 if (hash == -1)
1624 return -1;
1625 return _PyODict_SetItem_KnownHash(od, key, value, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001626}
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001627
1628int
1629PyODict_DelItem(PyObject *od, PyObject *key)
1630{
1631 int res;
1632 Py_hash_t hash = PyObject_Hash(key);
1633 if (hash == -1)
1634 return -1;
1635 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001636 if (res < 0)
1637 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001638 return _PyDict_DelItem_KnownHash(od, key, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001639}
Eric Snow96c6af92015-05-29 22:21:39 -06001640
1641
1642/* -------------------------------------------
1643 * The OrderedDict views (keys/values/items)
1644 */
1645
1646typedef struct {
1647 PyObject_HEAD
1648 int kind;
1649 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001650 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001651 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001652 PyObject *di_current;
1653 PyObject *di_result; /* reusable result tuple for iteritems */
1654} odictiterobject;
1655
1656static void
1657odictiter_dealloc(odictiterobject *di)
1658{
1659 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001660 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001661 Py_XDECREF(di->di_current);
1662 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1663 Py_DECREF(di->di_result);
1664 }
1665 PyObject_GC_Del(di);
1666}
1667
1668static int
1669odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1670{
1671 Py_VISIT(di->di_odict);
1672 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1673 Py_VISIT(di->di_result);
1674 return 0;
1675}
1676
Eric Snowa762af72015-06-01 22:59:08 -06001677/* In order to protect against modifications during iteration, we track
1678 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001679static PyObject *
1680odictiter_nextkey(odictiterobject *di)
1681{
Eric Snowa762af72015-06-01 22:59:08 -06001682 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001683 _ODictNode *node;
1684 int reversed = di->kind & _odict_ITER_REVERSED;
1685
Eric Snowa762af72015-06-01 22:59:08 -06001686 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001687 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001688 if (di->di_current == NULL)
1689 goto done; /* We're already done. */
1690
Eric Snowb952ab42015-06-01 23:35:13 -06001691 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001692 if (di->di_odict->od_state != di->di_state) {
1693 PyErr_SetString(PyExc_RuntimeError,
1694 "OrderedDict mutated during iteration");
1695 goto done;
1696 }
Eric Snowb952ab42015-06-01 23:35:13 -06001697 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1698 PyErr_SetString(PyExc_RuntimeError,
1699 "OrderedDict changed size during iteration");
1700 di->di_size = -1; /* Make this state sticky */
1701 return NULL;
1702 }
1703
Eric Snowa762af72015-06-01 22:59:08 -06001704 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001705 node = _odict_find_node(di->di_odict, di->di_current);
1706 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001707 if (!PyErr_Occurred())
1708 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001709 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001710 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001711 return NULL;
1712 }
1713 key = di->di_current;
1714
1715 /* Advance to the next key. */
1716 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1717 if (node == NULL) {
1718 /* Reached the end. */
1719 di->di_current = NULL;
1720 }
1721 else {
1722 di->di_current = _odictnode_KEY(node);
1723 Py_INCREF(di->di_current);
1724 }
1725
1726 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001727
1728done:
1729 Py_CLEAR(di->di_odict);
1730 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001731}
1732
1733static PyObject *
1734odictiter_iternext(odictiterobject *di)
1735{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001736 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001737 PyObject *key = odictiter_nextkey(di); /* new reference */
1738
1739 if (key == NULL)
1740 return NULL;
1741
1742 /* Handle the keys case. */
1743 if (! (di->kind & _odict_ITER_VALUES)) {
1744 return key;
1745 }
1746
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001747 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1748 if (value == NULL) {
1749 if (!PyErr_Occurred())
1750 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001751 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001752 goto done;
1753 }
1754 Py_INCREF(value);
1755
1756 /* Handle the values case. */
1757 if (!(di->kind & _odict_ITER_KEYS)) {
1758 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001759 return value;
1760 }
Eric Snowa762af72015-06-01 22:59:08 -06001761
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001762 /* Handle the items case. */
1763 result = di->di_result;
1764
1765 if (Py_REFCNT(result) == 1) {
1766 /* not in use so we can reuse it
1767 * (the common case during iteration) */
1768 Py_INCREF(result);
1769 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1770 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1771 }
1772 else {
1773 result = PyTuple_New(2);
1774 if (result == NULL) {
1775 Py_DECREF(key);
1776 Py_DECREF(value);
1777 goto done;
1778 }
1779 }
1780
1781 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1782 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1783 return result;
1784
Eric Snowa762af72015-06-01 22:59:08 -06001785done:
1786 Py_CLEAR(di->di_current);
1787 Py_CLEAR(di->di_odict);
1788 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001789}
1790
1791/* No need for tp_clear because odictiterobject is not mutable. */
1792
1793PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1794
1795static PyObject *
Serhiy Storchaka81524022018-11-27 13:05:02 +02001796odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001797{
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001798 _Py_IDENTIFIER(iter);
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001799 /* copy the iterator state */
1800 odictiterobject tmp = *di;
1801 Py_XINCREF(tmp.di_odict);
1802 Py_XINCREF(tmp.di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001803
1804 /* iterate the temporary into a list */
Sergey Fedoseeva5259fb2018-10-20 10:20:39 +05001805 PyObject *list = PySequence_List((PyObject*)&tmp);
1806 Py_XDECREF(tmp.di_odict);
1807 Py_XDECREF(tmp.di_current);
1808 if (list == NULL) {
Eric Snow96c6af92015-05-29 22:21:39 -06001809 return NULL;
1810 }
Serhiy Storchakabb86bf42018-12-11 08:28:18 +02001811 return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
Eric Snow96c6af92015-05-29 22:21:39 -06001812}
1813
1814static PyMethodDef odictiter_methods[] = {
1815 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1816 {NULL, NULL} /* sentinel */
1817};
1818
1819PyTypeObject PyODictIter_Type = {
1820 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1821 "odict_iterator", /* tp_name */
1822 sizeof(odictiterobject), /* tp_basicsize */
1823 0, /* tp_itemsize */
1824 /* methods */
1825 (destructor)odictiter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001826 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001827 0, /* tp_getattr */
1828 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001829 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001830 0, /* tp_repr */
1831 0, /* tp_as_number */
1832 0, /* tp_as_sequence */
1833 0, /* tp_as_mapping */
1834 0, /* tp_hash */
1835 0, /* tp_call */
1836 0, /* tp_str */
1837 PyObject_GenericGetAttr, /* tp_getattro */
1838 0, /* tp_setattro */
1839 0, /* tp_as_buffer */
1840 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1841 0, /* tp_doc */
1842 (traverseproc)odictiter_traverse, /* tp_traverse */
1843 0, /* tp_clear */
1844 0, /* tp_richcompare */
1845 0, /* tp_weaklistoffset */
1846 PyObject_SelfIter, /* tp_iter */
1847 (iternextfunc)odictiter_iternext, /* tp_iternext */
1848 odictiter_methods, /* tp_methods */
1849 0,
1850};
1851
1852static PyObject *
1853odictiter_new(PyODictObject *od, int kind)
1854{
1855 odictiterobject *di;
1856 _ODictNode *node;
1857 int reversed = kind & _odict_ITER_REVERSED;
1858
1859 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1860 if (di == NULL)
1861 return NULL;
1862
1863 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
1864 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1865 if (di->di_result == NULL) {
1866 Py_DECREF(di);
1867 return NULL;
1868 }
1869 }
1870 else
1871 di->di_result = NULL;
1872
1873 di->kind = kind;
1874 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1875 di->di_current = node ? _odictnode_KEY(node) : NULL;
1876 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06001877 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06001878 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001879 di->di_odict = od;
1880 Py_INCREF(od);
1881
1882 _PyObject_GC_TRACK(di);
1883 return (PyObject *)di;
1884}
1885
1886/* keys() */
1887
1888static PyObject *
1889odictkeys_iter(_PyDictViewObject *dv)
1890{
1891 if (dv->dv_dict == NULL) {
1892 Py_RETURN_NONE;
1893 }
1894 return odictiter_new((PyODictObject *)dv->dv_dict,
1895 _odict_ITER_KEYS);
1896}
1897
1898static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301899odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001900{
1901 if (dv->dv_dict == NULL) {
1902 Py_RETURN_NONE;
1903 }
1904 return odictiter_new((PyODictObject *)dv->dv_dict,
1905 _odict_ITER_KEYS|_odict_ITER_REVERSED);
1906}
1907
1908static PyMethodDef odictkeys_methods[] = {
1909 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
1910 {NULL, NULL} /* sentinel */
1911};
1912
1913PyTypeObject PyODictKeys_Type = {
1914 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1915 "odict_keys", /* tp_name */
1916 0, /* tp_basicsize */
1917 0, /* tp_itemsize */
1918 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001919 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001920 0, /* tp_getattr */
1921 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001922 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001923 0, /* tp_repr */
1924 0, /* tp_as_number */
1925 0, /* tp_as_sequence */
1926 0, /* tp_as_mapping */
1927 0, /* tp_hash */
1928 0, /* tp_call */
1929 0, /* tp_str */
1930 0, /* tp_getattro */
1931 0, /* tp_setattro */
1932 0, /* tp_as_buffer */
1933 0, /* tp_flags */
1934 0, /* tp_doc */
1935 0, /* tp_traverse */
1936 0, /* tp_clear */
1937 0, /* tp_richcompare */
1938 0, /* tp_weaklistoffset */
1939 (getiterfunc)odictkeys_iter, /* tp_iter */
1940 0, /* tp_iternext */
1941 odictkeys_methods, /* tp_methods */
1942 0, /* tp_members */
1943 0, /* tp_getset */
1944 &PyDictKeys_Type, /* tp_base */
1945};
1946
1947static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301948odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001949{
1950 return _PyDictView_New(od, &PyODictKeys_Type);
1951}
1952
1953/* items() */
1954
1955static PyObject *
1956odictitems_iter(_PyDictViewObject *dv)
1957{
1958 if (dv->dv_dict == NULL) {
1959 Py_RETURN_NONE;
1960 }
1961 return odictiter_new((PyODictObject *)dv->dv_dict,
1962 _odict_ITER_KEYS|_odict_ITER_VALUES);
1963}
1964
1965static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301966odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001967{
1968 if (dv->dv_dict == NULL) {
1969 Py_RETURN_NONE;
1970 }
1971 return odictiter_new((PyODictObject *)dv->dv_dict,
1972 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
1973}
1974
1975static PyMethodDef odictitems_methods[] = {
1976 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
1977 {NULL, NULL} /* sentinel */
1978};
1979
1980PyTypeObject PyODictItems_Type = {
1981 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1982 "odict_items", /* tp_name */
1983 0, /* tp_basicsize */
1984 0, /* tp_itemsize */
1985 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001986 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06001987 0, /* tp_getattr */
1988 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001989 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06001990 0, /* tp_repr */
1991 0, /* tp_as_number */
1992 0, /* tp_as_sequence */
1993 0, /* tp_as_mapping */
1994 0, /* tp_hash */
1995 0, /* tp_call */
1996 0, /* tp_str */
1997 0, /* tp_getattro */
1998 0, /* tp_setattro */
1999 0, /* tp_as_buffer */
2000 0, /* tp_flags */
2001 0, /* tp_doc */
2002 0, /* tp_traverse */
2003 0, /* tp_clear */
2004 0, /* tp_richcompare */
2005 0, /* tp_weaklistoffset */
2006 (getiterfunc)odictitems_iter, /* tp_iter */
2007 0, /* tp_iternext */
2008 odictitems_methods, /* tp_methods */
2009 0, /* tp_members */
2010 0, /* tp_getset */
2011 &PyDictItems_Type, /* tp_base */
2012};
2013
2014static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302015odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002016{
2017 return _PyDictView_New(od, &PyODictItems_Type);
2018}
2019
2020/* values() */
2021
2022static PyObject *
2023odictvalues_iter(_PyDictViewObject *dv)
2024{
2025 if (dv->dv_dict == NULL) {
2026 Py_RETURN_NONE;
2027 }
2028 return odictiter_new((PyODictObject *)dv->dv_dict,
2029 _odict_ITER_VALUES);
2030}
2031
2032static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302033odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002034{
2035 if (dv->dv_dict == NULL) {
2036 Py_RETURN_NONE;
2037 }
2038 return odictiter_new((PyODictObject *)dv->dv_dict,
2039 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2040}
2041
2042static PyMethodDef odictvalues_methods[] = {
2043 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2044 {NULL, NULL} /* sentinel */
2045};
2046
2047PyTypeObject PyODictValues_Type = {
2048 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2049 "odict_values", /* tp_name */
2050 0, /* tp_basicsize */
2051 0, /* tp_itemsize */
2052 0, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002053 0, /* tp_vectorcall_offset */
Eric Snow96c6af92015-05-29 22:21:39 -06002054 0, /* tp_getattr */
2055 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02002056 0, /* tp_as_async */
Eric Snow96c6af92015-05-29 22:21:39 -06002057 0, /* tp_repr */
2058 0, /* tp_as_number */
2059 0, /* tp_as_sequence */
2060 0, /* tp_as_mapping */
2061 0, /* tp_hash */
2062 0, /* tp_call */
2063 0, /* tp_str */
2064 0, /* tp_getattro */
2065 0, /* tp_setattro */
2066 0, /* tp_as_buffer */
2067 0, /* tp_flags */
2068 0, /* tp_doc */
2069 0, /* tp_traverse */
2070 0, /* tp_clear */
2071 0, /* tp_richcompare */
2072 0, /* tp_weaklistoffset */
2073 (getiterfunc)odictvalues_iter, /* tp_iter */
2074 0, /* tp_iternext */
2075 odictvalues_methods, /* tp_methods */
2076 0, /* tp_members */
2077 0, /* tp_getset */
2078 &PyDictValues_Type, /* tp_base */
2079};
2080
2081static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302082odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002083{
2084 return _PyDictView_New(od, &PyODictValues_Type);
2085}
2086
2087
2088/* ----------------------------------------------
Martin Panter536d70e2017-01-14 08:23:08 +00002089 MutableMapping implementations
Eric Snow96c6af92015-05-29 22:21:39 -06002090
2091Mapping:
2092
2093============ ===========
2094method uses
2095============ ===========
2096__contains__ __getitem__
2097__eq__ items
2098__getitem__ +
2099__iter__ +
2100__len__ +
2101__ne__ __eq__
2102get __getitem__
2103items ItemsView
2104keys KeysView
2105values ValuesView
2106============ ===========
2107
2108ItemsView uses __len__, __iter__, and __getitem__.
2109KeysView uses __len__, __iter__, and __contains__.
2110ValuesView uses __len__, __iter__, and __getitem__.
2111
2112MutableMapping:
2113
2114============ ===========
2115method uses
2116============ ===========
2117__delitem__ +
2118__setitem__ +
2119clear popitem
2120pop __getitem__
2121 __delitem__
2122popitem __iter__
2123 _getitem__
2124 __delitem__
2125setdefault __getitem__
2126 __setitem__
2127update __setitem__
2128============ ===========
2129*/
2130
2131static int
2132mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2133{
2134 PyObject *pair, *iterator, *unexpected;
2135 int res = 0;
2136
2137 iterator = PyObject_GetIter(pairs);
2138 if (iterator == NULL)
2139 return -1;
2140 PyErr_Clear();
2141
2142 while ((pair = PyIter_Next(iterator)) != NULL) {
2143 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002144 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002145 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002146 if (pair_iterator == NULL)
2147 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002148
2149 key = PyIter_Next(pair_iterator);
2150 if (key == NULL) {
2151 if (!PyErr_Occurred())
2152 PyErr_SetString(PyExc_ValueError,
2153 "need more than 0 values to unpack");
2154 goto Done;
2155 }
2156
2157 value = PyIter_Next(pair_iterator);
2158 if (value == NULL) {
2159 if (!PyErr_Occurred())
2160 PyErr_SetString(PyExc_ValueError,
2161 "need more than 1 value to unpack");
2162 goto Done;
2163 }
2164
2165 unexpected = PyIter_Next(pair_iterator);
2166 if (unexpected != NULL) {
2167 Py_DECREF(unexpected);
2168 PyErr_SetString(PyExc_ValueError,
2169 "too many values to unpack (expected 2)");
2170 goto Done;
2171 }
2172 else if (PyErr_Occurred())
2173 goto Done;
2174
2175 res = PyObject_SetItem(self, key, value);
2176
2177Done:
2178 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002179 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002180 Py_XDECREF(key);
2181 Py_XDECREF(value);
2182 if (PyErr_Occurred())
2183 break;
2184 }
2185 Py_DECREF(iterator);
2186
2187 if (res < 0 || PyErr_Occurred() != NULL)
2188 return -1;
2189 else
2190 return 0;
2191}
2192
2193static PyObject *
2194mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2195{
2196 int res = 0;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002197 Py_ssize_t len;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002198 _Py_IDENTIFIER(keys);
Eric Snow96c6af92015-05-29 22:21:39 -06002199
2200 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002201 assert(args == NULL || PyTuple_Check(args));
2202 len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002203 if (len > 1) {
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +02002204 const char *msg = "update() takes at most 1 positional argument (%zd given)";
Eric Snow96c6af92015-05-29 22:21:39 -06002205 PyErr_Format(PyExc_TypeError, msg, len);
2206 return NULL;
2207 }
Eric Snow96c6af92015-05-29 22:21:39 -06002208
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002209 if (len) {
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002210 PyObject *func;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002211 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002212 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002213 Py_INCREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002214 if (PyDict_CheckExact(other)) {
2215 PyObject *items = PyDict_Items(other);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002216 Py_DECREF(other);
2217 if (items == NULL)
2218 return NULL;
2219 res = mutablemapping_add_pairs(self, items);
2220 Py_DECREF(items);
2221 if (res == -1)
2222 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002223 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002224 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002225
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002226 if (_PyObject_LookupAttrId(other, &PyId_keys, &func) < 0) {
2227 Py_DECREF(other);
2228 return NULL;
2229 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002230 if (func != NULL) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002231 PyObject *keys, *iterator, *key;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002232 keys = _PyObject_CallNoArg(func);
2233 Py_DECREF(func);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002234 if (keys == NULL) {
2235 Py_DECREF(other);
2236 return NULL;
2237 }
2238 iterator = PyObject_GetIter(keys);
2239 Py_DECREF(keys);
2240 if (iterator == NULL) {
2241 Py_DECREF(other);
2242 return NULL;
2243 }
2244 while (res == 0 && (key = PyIter_Next(iterator))) {
2245 PyObject *value = PyObject_GetItem(other, key);
2246 if (value != NULL) {
2247 res = PyObject_SetItem(self, key, value);
2248 Py_DECREF(value);
2249 }
2250 else {
2251 res = -1;
2252 }
2253 Py_DECREF(key);
2254 }
2255 Py_DECREF(other);
2256 Py_DECREF(iterator);
2257 if (res != 0 || PyErr_Occurred())
2258 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002259 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002260 }
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002261
2262 if (_PyObject_LookupAttrId(other, &PyId_items, &func) < 0) {
Eric Snow06aed902016-09-09 11:59:08 -07002263 Py_DECREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002264 return NULL;
2265 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002266 if (func != NULL) {
2267 PyObject *items;
2268 Py_DECREF(other);
2269 items = _PyObject_CallNoArg(func);
2270 Py_DECREF(func);
Eric Snow06aed902016-09-09 11:59:08 -07002271 if (items == NULL)
2272 return NULL;
2273 res = mutablemapping_add_pairs(self, items);
2274 Py_DECREF(items);
2275 if (res == -1)
2276 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002277 goto handle_kwargs;
2278 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002279
2280 res = mutablemapping_add_pairs(self, other);
2281 Py_DECREF(other);
2282 if (res != 0)
2283 return NULL;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002284 }
2285
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002286 handle_kwargs:
Benjamin Peterson0718de92015-06-07 00:00:42 -05002287 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002288 assert(kwargs == NULL || PyDict_Check(kwargs));
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02002289 if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002290 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002291 if (items == NULL)
2292 return NULL;
2293 res = mutablemapping_add_pairs(self, items);
2294 Py_DECREF(items);
2295 if (res == -1)
2296 return NULL;
2297 }
Eric Snow96c6af92015-05-29 22:21:39 -06002298
2299 Py_RETURN_NONE;
2300}