blob: 353afd23d6b5e81fa03c459393a21aa329c8c81e [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
104Used, but specific to the linked-list implementation:
105
106* _odict_free_fast_nodes(od)
107
108And here's a look at how the linked-list relates to the OrderedDict API:
109
110============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
111method key val prev next mem 1st last empty iter find add rmv clr keq
112============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
113__del__ ~ X
114__delitem__ free ~ node
115__eq__ ~ X
116__iter__ X X
117__new__ X X
118__reduce__ X ~ X
119__repr__ X X X
120__reversed__ X X
121__setitem__ key
122__sizeof__ size X
123clear ~ ~ X
124copy X X X
125items X X X
126keys X X
127move_to_end X X X ~ h/t key
128pop free key
129popitem X X free X X node
130setdefault ~ ? ~
131values X X
132============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
133
134__delitem__ is the only method that directly relies on finding an arbitrary
135node in the linked-list. Everything else is iteration or relates to the
136ends of the linked-list.
137
138Situation that Endangers Consistency
139------------------------------------
140Using a raw linked-list for OrderedDict exposes a key situation that can
141cause problems. If a node is stored in a variable, there is a chance that
142the node may have been deallocated before the variable gets used, thus
143potentially leading to a segmentation fault. A key place where this shows
144up is during iteration through the linked list (via _odict_FOREACH or
145otherwise).
146
147A number of solutions are available to resolve this situation:
148
149* defer looking up the node until as late as possible and certainly after
150 any code that could possibly result in a deletion;
151* if the node is needed both before and after a point where the node might
152 be removed, do a check before using the node at the "after" location to
153 see if the node is still valid;
154* like the last one, but simply pull the node again to ensure it's right;
155* keep the key in the variable instead of the node and then look up the
156 node using the key at the point where the node is needed (this is what
157 we do for the iterators).
158
159Another related problem, preserving consistent ordering during iteration,
160is described below. That one is not exclusive to using linked-lists.
161
162
163Challenges from Subclassing dict
164================================
165
166OrderedDict subclasses dict, which is an unusual relationship between two
167builtin types (other than the base object type). Doing so results in
168some complication and deserves further explanation. There are two things
169to consider here. First, in what circumstances or with what adjustments
170can OrderedDict be used as a drop-in replacement for dict (at the C level)?
171Second, how can the OrderedDict implementation leverage the dict
172implementation effectively without introducing unnecessary coupling or
173inefficiencies?
174
175This second point is reflected here and in the implementation, so the
176further focus is on the first point. It is worth noting that for
177overridden methods, the dict implementation is deferred to as much as
178possible. Furthermore, coupling is limited to as little as is reasonable.
179
180Concrete API Compatibility
181--------------------------
182
183Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
184problematic. (See http://bugs.python.org/issue10977.) The concrete API
185has a number of hard-coded assumptions tied to the dict implementation.
186This is, in part, due to performance reasons, which is understandable
187given the part dict plays in Python.
188
189Any attempt to replace dict with OrderedDict for any role in the
190interpreter (e.g. **kwds) faces a challenge. Such any effort must
191recognize that the instances in affected locations currently interact with
192the concrete API.
193
194Here are some ways to address this challenge:
195
1961. Change the relevant usage of the concrete API in CPython and add
Martin Panter69332c12016-08-04 13:07:31 +0000197 PyDict_CheckExact() calls to each of the concrete API functions.
Eric Snow96c6af92015-05-29 22:21:39 -06001982. Adjust the relevant concrete API functions to explicitly accommodate
199 OrderedDict.
2003. As with #1, add the checks, but improve the abstract API with smart fast
201 paths for dict and OrderedDict, and refactor CPython to use the abstract
202 API. Improvements to the abstract API would be valuable regardless.
203
204Adding the checks to the concrete API would help make any interpreter
205switch to OrderedDict less painful for extension modules. However, this
206won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)`
207is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call
208the base class's methods, since there is no equivalent of super() in the
209C API. Calling into Python for parent class API would work, but some
210extension modules already rely on this feature of the concrete API.
211
212For reference, here is a breakdown of some of the dict concrete API:
213
214========================== ============= =======================
215concrete API uses abstract API
216========================== ============= =======================
217PyDict_Check PyMapping_Check
218(PyDict_CheckExact) -
219(PyDict_New) -
220(PyDictProxy_New) -
221PyDict_Clear -
222PyDict_Contains PySequence_Contains
223PyDict_Copy -
224PyDict_SetItem PyObject_SetItem
225PyDict_SetItemString PyMapping_SetItemString
226PyDict_DelItem PyMapping_DelItem
227PyDict_DelItemString PyMapping_DelItemString
228PyDict_GetItem -
229PyDict_GetItemWithError PyObject_GetItem
230_PyDict_GetItemIdWithError -
231PyDict_GetItemString PyMapping_GetItemString
232PyDict_Items PyMapping_Items
233PyDict_Keys PyMapping_Keys
234PyDict_Values PyMapping_Values
235PyDict_Size PyMapping_Size
236 PyMapping_Length
237PyDict_Next PyIter_Next
238_PyDict_Next -
239PyDict_Merge -
240PyDict_Update -
241PyDict_MergeFromSeq2 -
242PyDict_ClearFreeList -
243- PyMapping_HasKeyString
244- PyMapping_HasKey
245========================== ============= =======================
246
247
248The dict Interface Relative to OrderedDict
249==========================================
250
251Since OrderedDict subclasses dict, understanding the various methods and
252attributes of dict is important for implementing OrderedDict.
253
254Relevant Type Slots
255-------------------
256
257================= ================ =================== ================
258slot attribute object dict
259================= ================ =================== ================
260tp_dealloc - object_dealloc dict_dealloc
261tp_repr __repr__ object_repr dict_repr
262sq_contains __contains__ - dict_contains
263mp_length __len__ - dict_length
264mp_subscript __getitem__ - dict_subscript
265mp_ass_subscript __setitem__ - dict_ass_sub
266 __delitem__
267tp_hash __hash__ _Py_HashPointer ..._HashNotImpl
268tp_str __str__ object_str -
269tp_getattro __getattribute__ ..._GenericGetAttr (repeated)
270 __getattr__
271tp_setattro __setattr__ ..._GenericSetAttr (disabled)
272tp_doc __doc__ (literal) dictionary_doc
273tp_traverse - - dict_traverse
274tp_clear - - dict_tp_clear
275tp_richcompare __eq__ object_richcompare dict_richcompare
276 __ne__
277tp_weaklistoffset (__weakref__) - -
278tp_iter __iter__ - dict_iter
279tp_dictoffset (__dict__) - -
280tp_init __init__ object_init dict_init
281tp_alloc - PyType_GenericAlloc (repeated)
282tp_new __new__ object_new dict_new
283tp_free - PyObject_Del PyObject_GC_Del
284================= ================ =================== ================
285
286Relevant Methods
287----------------
288
289================ =================== ===============
290method object dict
291================ =================== ===============
292__reduce__ object_reduce -
293__sizeof__ object_sizeof dict_sizeof
294clear - dict_clear
295copy - dict_copy
296fromkeys - dict_fromkeys
297get - dict_get
298items - dictitems_new
299keys - dictkeys_new
300pop - dict_pop
301popitem - dict_popitem
302setdefault - dict_setdefault
303update - dict_update
304values - dictvalues_new
305================ =================== ===============
306
307
308Pure Python OrderedDict
309=======================
310
311As already noted, compatibility with the pure Python OrderedDict
312implementation is a key goal of this C implementation. To further that
313goal, here's a summary of how OrderedDict-specific methods are implemented
314in collections/__init__.py. Also provided is an indication of which
315methods directly mutate or iterate the object, as well as any relationship
316with the underlying linked-list.
317
318============= ============== == ================ === === ====
319method impl used ll uses inq mut iter
320============= ============== == ================ === === ====
321__contains__ dict - - X
322__delitem__ OrderedDict Y dict.__delitem__ X
323__eq__ OrderedDict N OrderedDict ~
324 dict.__eq__
325 __iter__
326__getitem__ dict - - X
327__iter__ OrderedDict Y - X
328__init__ OrderedDict N update
329__len__ dict - - X
330__ne__ MutableMapping - __eq__ ~
331__reduce__ OrderedDict N OrderedDict ~
332 __iter__
333 __getitem__
334__repr__ OrderedDict N __class__ ~
335 items
336__reversed__ OrderedDict Y - X
337__setitem__ OrderedDict Y __contains__ X
338 dict.__setitem__
339__sizeof__ OrderedDict Y __len__ ~
340 __dict__
341clear OrderedDict Y dict.clear X
342copy OrderedDict N __class__
343 __init__
344fromkeys OrderedDict N __setitem__
345get dict - - ~
346items MutableMapping - ItemsView X
347keys MutableMapping - KeysView X
348move_to_end OrderedDict Y - X
349pop OrderedDict N __contains__ X
350 __getitem__
351 __delitem__
352popitem OrderedDict Y dict.pop X
353setdefault OrderedDict N __contains__ ~
354 __getitem__
355 __setitem__
356update MutableMapping - __setitem__ ~
357values MutableMapping - ValuesView X
358============= ============== == ================ === === ====
359
360__reversed__ and move_to_end are both exclusive to OrderedDict.
361
362
363C OrderedDict Implementation
364============================
365
366================= ================
367slot impl
368================= ================
369tp_dealloc odict_dealloc
370tp_repr odict_repr
371mp_ass_subscript odict_ass_sub
372tp_doc odict_doc
373tp_traverse odict_traverse
374tp_clear odict_tp_clear
375tp_richcompare odict_richcompare
376tp_weaklistoffset (offset)
377tp_iter odict_iter
378tp_dictoffset (offset)
379tp_init odict_init
380tp_alloc (repeated)
381tp_new odict_new
382================= ================
383
384================= ================
385method impl
386================= ================
387__reduce__ odict_reduce
388__sizeof__ odict_sizeof
389clear odict_clear
390copy odict_copy
391fromkeys odict_fromkeys
392items odictitems_new
393keys odictkeys_new
394pop odict_pop
395popitem odict_popitem
396setdefault odict_setdefault
397update odict_update
398values odictvalues_new
399================= ================
400
401Inherited unchanged from object/dict:
402
403================ ==========================
404method type field
405================ ==========================
406- tp_free
407__contains__ tp_as_sequence.sq_contains
408__getattr__ tp_getattro
409__getattribute__ tp_getattro
410__getitem__ tp_as_mapping.mp_subscript
411__hash__ tp_hash
412__len__ tp_as_mapping.mp_length
413__setattr__ tp_setattro
414__str__ tp_str
415get -
416================ ==========================
417
418
419Other Challenges
420================
421
422Preserving Ordering During Iteration
423------------------------------------
424During iteration through an OrderedDict, it is possible that items could
425get added, removed, or reordered. For a linked-list implementation, as
426with some other implementations, that situation may lead to undefined
427behavior. The documentation for dict mentions this in the `iter()` section
428of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
429In this implementation we follow dict's lead (as does the pure Python
430implementation) for __iter__(), keys(), values(), and items().
431
432For internal iteration (using _odict_FOREACH or not), there is still the
433risk that not all nodes that we expect to be seen in the loop actually get
434seen. Thus, we are careful in each of those places to ensure that they
435are. This comes, of course, at a small price at each location. The
436solutions are much the same as those detailed in the `Situation that
437Endangers Consistency` section above.
438
439
440Potential Optimizations
441=======================
442
443* Allocate the nodes as a block via od_fast_nodes instead of individually.
444 - Set node->key to NULL to indicate the node is not-in-use.
445 - Add _odict_EXISTS()?
446 - How to maintain consistency across resizes? Existing node pointers
Robert Krzyzanowski6f19fc62018-07-06 05:54:26 -0500447 would be invalidated after a resize, which is particularly problematic
Eric Snow96c6af92015-05-29 22:21:39 -0600448 for the iterators.
449* Use a more stream-lined implementation of update() and, likely indirectly,
450 __init__().
451
452*/
453
454/* TODO
455
456sooner:
457- reentrancy (make sure everything is at a thread-safe state when calling
458 into Python). I've already checked this multiple times, but want to
459 make one more pass.
460- add unit tests for reentrancy?
461
462later:
463- make the dict views support the full set API (the pure Python impl does)
464- implement a fuller MutableMapping API in C?
465- move the MutableMapping implementation to abstract.c?
466- optimize mutablemapping_update
467- use PyObject_MALLOC (small object allocator) for odict nodes?
468- support subclasses better (e.g. in odict_richcompare)
469
470*/
471
472#include "Python.h"
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600473#include "internal/pystate.h"
Eric Snow96c6af92015-05-29 22:21:39 -0600474#include "structmember.h"
475#include "dict-common.h"
476#include <stddef.h>
477
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100478#include "clinic/odictobject.c.h"
479
480/*[clinic input]
481class OrderedDict "PyODictObject *" "&PyODict_Type"
482[clinic start generated code]*/
483/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
484
Eric Snow96c6af92015-05-29 22:21:39 -0600485
486typedef struct _odictnode _ODictNode;
487
488/* PyODictObject */
489struct _odictobject {
Eric Snow4fabf022015-06-04 00:09:56 -0600490 PyDictObject od_dict; /* the underlying dict */
491 _ODictNode *od_first; /* first node in the linked list, if any */
492 _ODictNode *od_last; /* last node in the linked list, if any */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200493 /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
494 * by _odict_resize().
Eric Snow8c7f9552015-08-07 17:45:12 -0600495 * Note that we rely on implementation details of dict for both. */
496 _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200497 Py_ssize_t od_fast_nodes_size;
498 void *od_resize_sentinel; /* changes if odict should be resized */
Eric Snow8c7f9552015-08-07 17:45:12 -0600499
Eric Snow4fabf022015-06-04 00:09:56 -0600500 size_t od_state; /* incremented whenever the LL changes */
501 PyObject *od_inst_dict; /* OrderedDict().__dict__ */
502 PyObject *od_weakreflist; /* holds weakrefs to the odict */
Eric Snow96c6af92015-05-29 22:21:39 -0600503};
504
505
506/* ----------------------------------------------
507 * odict keys (a simple doubly-linked list)
508 */
509
510struct _odictnode {
511 PyObject *key;
Eric Snow4c729182015-06-03 10:50:37 -0600512 Py_hash_t hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600513 _ODictNode *next;
514 _ODictNode *prev;
515};
516
517#define _odictnode_KEY(node) \
518 (node->key)
Eric Snow4c729182015-06-03 10:50:37 -0600519#define _odictnode_HASH(node) \
520 (node->hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600521/* borrowed reference */
522#define _odictnode_VALUE(node, od) \
Eric Snowa762af72015-06-01 22:59:08 -0600523 PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
Eric Snow96c6af92015-05-29 22:21:39 -0600524#define _odictnode_PREV(node) (node->prev)
525#define _odictnode_NEXT(node) (node->next)
526
527#define _odict_FIRST(od) (((PyODictObject *)od)->od_first)
528#define _odict_LAST(od) (((PyODictObject *)od)->od_last)
529#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
530#define _odict_FOREACH(od, node) \
531 for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
532
Eric Snow8c7f9552015-08-07 17:45:12 -0600533#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size
Eric Snow96c6af92015-05-29 22:21:39 -0600534
Eric Snow96c6af92015-05-29 22:21:39 -0600535static void
536_odict_free_fast_nodes(PyODictObject *od) {
537 if (od->od_fast_nodes) {
538 PyMem_FREE(od->od_fast_nodes);
539 }
540}
541
Eric Snow4c729182015-06-03 10:50:37 -0600542/* Return the index into the hash table, regardless of a valid node. */
543static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200544_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow4c729182015-06-03 10:50:37 -0600545{
INADA Naokiba609772016-12-07 20:41:42 +0900546 PyObject *value = NULL;
Eric Snow4c729182015-06-03 10:50:37 -0600547 PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
Victor Stinner742da042016-09-07 17:40:12 -0700548 Py_ssize_t ix;
Eric Snow4c729182015-06-03 10:50:37 -0600549
INADA Naoki778928b2017-08-03 23:45:15 +0900550 ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value);
Victor Stinner742da042016-09-07 17:40:12 -0700551 if (ix == DKIX_EMPTY) {
552 return keys->dk_nentries; /* index of new entry */
553 }
554 if (ix < 0)
Eric Snow4c729182015-06-03 10:50:37 -0600555 return -1;
556 /* We use pointer arithmetic to get the entry's index into the table. */
Victor Stinner742da042016-09-07 17:40:12 -0700557 return ix;
Eric Snow4c729182015-06-03 10:50:37 -0600558}
559
560/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
Eric Snow96c6af92015-05-29 22:21:39 -0600561static int
562_odict_resize(PyODictObject *od) {
Eric Snow4c729182015-06-03 10:50:37 -0600563 Py_ssize_t size, i;
Eric Snow96c6af92015-05-29 22:21:39 -0600564 _ODictNode **fast_nodes, *node;
565
566 /* Initialize a new "fast nodes" table. */
567 size = ((PyDictObject *)od)->ma_keys->dk_size;
568 fast_nodes = PyMem_NEW(_ODictNode *, size);
569 if (fast_nodes == NULL) {
570 PyErr_NoMemory();
571 return -1;
572 }
573 for (i = 0; i < size; i++)
574 fast_nodes[i] = NULL;
575
576 /* Copy the current nodes into the table. */
Eric Snow96c6af92015-05-29 22:21:39 -0600577 _odict_FOREACH(od, node) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200578 i = _odict_get_index_raw(od, _odictnode_KEY(node),
Victor Stinner742da042016-09-07 17:40:12 -0700579 _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -0600580 if (i < 0) {
Eric Snow96c6af92015-05-29 22:21:39 -0600581 PyMem_FREE(fast_nodes);
582 return -1;
583 }
584 fast_nodes[i] = node;
585 }
Eric Snow96c6af92015-05-29 22:21:39 -0600586
587 /* Replace the old fast nodes table. */
588 _odict_free_fast_nodes(od);
589 od->od_fast_nodes = fast_nodes;
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200590 od->od_fast_nodes_size = size;
591 od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600592 return 0;
593}
594
595/* Return the index into the hash table, regardless of a valid node. */
596static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200597_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600598{
Eric Snow4c729182015-06-03 10:50:37 -0600599 PyDictKeysObject *keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600600
601 assert(key != NULL);
Eric Snow4c729182015-06-03 10:50:37 -0600602 keys = ((PyDictObject *)od)->ma_keys;
603
604 /* Ensure od_fast_nodes and dk_entries are in sync. */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200605 if (od->od_resize_sentinel != keys ||
606 od->od_fast_nodes_size != keys->dk_size) {
Eric Snow4c729182015-06-03 10:50:37 -0600607 int resize_res = _odict_resize(od);
608 if (resize_res < 0)
609 return -1;
610 }
611
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200612 return _odict_get_index_raw(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600613}
614
Eric Snow96c6af92015-05-29 22:21:39 -0600615/* Returns NULL if there was some error or the key was not found. */
616static _ODictNode *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200617_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600618{
619 Py_ssize_t index;
620
621 if (_odict_EMPTY(od))
622 return NULL;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200623 index = _odict_get_index(od, key, hash);
624 if (index < 0)
625 return NULL;
626 return od->od_fast_nodes[index];
627}
628
629static _ODictNode *
630_odict_find_node(PyODictObject *od, PyObject *key)
631{
632 Py_ssize_t index;
633 Py_hash_t hash;
634
635 if (_odict_EMPTY(od))
636 return NULL;
637 hash = PyObject_Hash(key);
638 if (hash == -1)
639 return NULL;
640 index = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600641 if (index < 0)
642 return NULL;
643 return od->od_fast_nodes[index];
644}
645
646static void
647_odict_add_head(PyODictObject *od, _ODictNode *node)
648{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300649 _odictnode_PREV(node) = NULL;
650 _odictnode_NEXT(node) = _odict_FIRST(od);
651 if (_odict_FIRST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600652 _odict_LAST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300653 else
Eric Snow96c6af92015-05-29 22:21:39 -0600654 _odictnode_PREV(_odict_FIRST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300655 _odict_FIRST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600656 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600657}
658
659static void
660_odict_add_tail(PyODictObject *od, _ODictNode *node)
661{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300662 _odictnode_PREV(node) = _odict_LAST(od);
663 _odictnode_NEXT(node) = NULL;
664 if (_odict_LAST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600665 _odict_FIRST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300666 else
Eric Snow96c6af92015-05-29 22:21:39 -0600667 _odictnode_NEXT(_odict_LAST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300668 _odict_LAST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600669 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600670}
671
672/* adds the node to the end of the list */
673static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200674_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600675{
676 Py_ssize_t i;
677 _ODictNode *node;
678
Serhiy Storchakad17427b2015-10-20 18:21:48 +0300679 Py_INCREF(key);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200680 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600681 if (i < 0) {
682 if (!PyErr_Occurred())
683 PyErr_SetObject(PyExc_KeyError, key);
684 Py_DECREF(key);
685 return -1;
686 }
687 else if (od->od_fast_nodes[i] != NULL) {
688 /* We already have a node for the key so there's no need to add one. */
689 Py_DECREF(key);
690 return 0;
691 }
692
693 /* must not be added yet */
694 node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode));
695 if (node == NULL) {
696 Py_DECREF(key);
697 PyErr_NoMemory();
698 return -1;
699 }
700
701 _odictnode_KEY(node) = key;
Eric Snow4c729182015-06-03 10:50:37 -0600702 _odictnode_HASH(node) = hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600703 _odict_add_tail(od, node);
704 od->od_fast_nodes[i] = node;
705 return 0;
706}
707
708/* Putting the decref after the free causes problems. */
709#define _odictnode_DEALLOC(node) \
710 do { \
711 Py_DECREF(_odictnode_KEY(node)); \
712 PyMem_FREE((void *)node); \
713 } while (0)
714
715/* Repeated calls on the same node are no-ops. */
716static void
717_odict_remove_node(PyODictObject *od, _ODictNode *node)
718{
719 if (_odict_FIRST(od) == node)
720 _odict_FIRST(od) = _odictnode_NEXT(node);
721 else if (_odictnode_PREV(node) != NULL)
722 _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
723
724 if (_odict_LAST(od) == node)
725 _odict_LAST(od) = _odictnode_PREV(node);
726 else if (_odictnode_NEXT(node) != NULL)
727 _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
728
729 _odictnode_PREV(node) = NULL;
730 _odictnode_NEXT(node) = NULL;
Eric Snow4fabf022015-06-04 00:09:56 -0600731 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600732}
733
Eric Snow96c6af92015-05-29 22:21:39 -0600734/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
735 get all sorts of problems here. In PyODict_DelItem we make sure to
736 call _odict_clear_node first.
Victor Stinnerca30b022015-09-03 17:50:04 +0200737
Eric Snow96c6af92015-05-29 22:21:39 -0600738 This matters in the case of colliding keys. Suppose we add 3 keys:
739 [A, B, C], where the hash of C collides with A and the next possible
740 index in the hash table is occupied by B. If we remove B then for C
741 the dict's looknode func will give us the old index of B instead of
742 the index we got before deleting B. However, the node for C in
743 od_fast_nodes is still at the old dict index of C. Thus to be sure
744 things don't get out of sync, we clear the node in od_fast_nodes
745 *before* calling PyDict_DelItem.
746
747 The same must be done for any other OrderedDict operations where
748 we modify od_fast_nodes.
749*/
750static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200751_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
752 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600753{
754 Py_ssize_t i;
755
756 assert(key != NULL);
757 if (_odict_EMPTY(od)) {
758 /* Let later code decide if this is a KeyError. */
759 return 0;
760 }
761
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200762 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600763 if (i < 0)
764 return PyErr_Occurred() ? -1 : 0;
765
766 if (node == NULL)
767 node = od->od_fast_nodes[i];
768 assert(node == od->od_fast_nodes[i]);
769 if (node == NULL) {
770 /* Let later code decide if this is a KeyError. */
771 return 0;
772 }
773
774 // Now clear the node.
775 od->od_fast_nodes[i] = NULL;
776 _odict_remove_node(od, node);
777 _odictnode_DEALLOC(node);
778 return 0;
779}
780
781static void
782_odict_clear_nodes(PyODictObject *od)
783{
784 _ODictNode *node, *next;
785
Eric Snow96c6af92015-05-29 22:21:39 -0600786 _odict_free_fast_nodes(od);
787 od->od_fast_nodes = NULL;
Serhiy Storchakad205d012016-01-19 14:46:25 +0200788
789 node = _odict_FIRST(od);
790 _odict_FIRST(od) = NULL;
791 _odict_LAST(od) = NULL;
792 while (node != NULL) {
793 next = _odictnode_NEXT(node);
794 _odictnode_DEALLOC(node);
795 node = next;
796 }
Eric Snow96c6af92015-05-29 22:21:39 -0600797}
798
799/* There isn't any memory management of nodes past this point. */
800#undef _odictnode_DEALLOC
801
802static int
803_odict_keys_equal(PyODictObject *a, PyODictObject *b)
804{
805 _ODictNode *node_a, *node_b;
806
807 node_a = _odict_FIRST(a);
808 node_b = _odict_FIRST(b);
809 while (1) {
810 if (node_a == NULL && node_b == NULL)
811 /* success: hit the end of each at the same time */
812 return 1;
813 else if (node_a == NULL || node_b == NULL)
814 /* unequal length */
815 return 0;
816 else {
817 int res = PyObject_RichCompareBool(
818 (PyObject *)_odictnode_KEY(node_a),
819 (PyObject *)_odictnode_KEY(node_b),
820 Py_EQ);
821 if (res < 0)
822 return res;
823 else if (res == 0)
824 return 0;
825
826 /* otherwise it must match, so move on to the next one */
827 node_a = _odictnode_NEXT(node_a);
828 node_b = _odictnode_NEXT(node_b);
829 }
830 }
831}
832
833
834/* ----------------------------------------------
835 * OrderedDict mapping methods
836 */
837
838/* mp_ass_subscript: __setitem__() and __delitem__() */
839
840static int
841odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)
842{
843 if (w == NULL)
844 return PyODict_DelItem((PyObject *)od, v);
845 else
846 return PyODict_SetItem((PyObject *)od, v, w);
847}
848
849/* tp_as_mapping */
850
851static PyMappingMethods odict_as_mapping = {
852 0, /*mp_length*/
853 0, /*mp_subscript*/
854 (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/
855};
856
857
858/* ----------------------------------------------
859 * OrderedDict methods
860 */
861
Eric Snow96c6af92015-05-29 22:21:39 -0600862/* fromkeys() */
863
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100864/*[clinic input]
865@classmethod
866OrderedDict.fromkeys
867
868 iterable as seq: object
869 value: object = None
870
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200871Create a new ordered dictionary with keys from iterable and values set to value.
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100872[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600873
874static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100875OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200876/*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600877{
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100878 return _PyDict_FromKeys((PyObject *)type, seq, value);
Eric Snow96c6af92015-05-29 22:21:39 -0600879}
880
881/* __sizeof__() */
882
883/* OrderedDict.__sizeof__() does not have a docstring. */
884PyDoc_STRVAR(odict_sizeof__doc__, "");
885
886static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530887odict_sizeof(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600888{
Serhiy Storchaka0ce7a3a2015-12-22 08:16:18 +0200889 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300890 res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
Eric Snow96c6af92015-05-29 22:21:39 -0600891 if (!_odict_EMPTY(od)) {
892 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
893 }
894 return PyLong_FromSsize_t(res);
895}
896
897/* __reduce__() */
898
899PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
900
901static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530902odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -0600903{
904 _Py_IDENTIFIER(__dict__);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300905 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300906 PyObject *dict = NULL, *result = NULL;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300907 PyObject *items_iter, *items, *args = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600908
909 /* capture any instance state */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300910 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
911 if (dict == NULL)
Eric Snowc5e59602015-05-30 11:28:56 -0600912 goto Done;
913 else {
Eric Snow96c6af92015-05-29 22:21:39 -0600914 /* od.__dict__ isn't necessarily a dict... */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300915 Py_ssize_t dict_len = PyObject_Length(dict);
916 if (dict_len == -1)
Eric Snow96c6af92015-05-29 22:21:39 -0600917 goto Done;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300918 if (!dict_len) {
919 /* nothing to pickle in od.__dict__ */
920 Py_CLEAR(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600921 }
922 }
923
924 /* build the result */
Eric Snow96c6af92015-05-29 22:21:39 -0600925 args = PyTuple_New(0);
926 if (args == NULL)
927 goto Done;
928
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300929 items = _PyObject_CallMethodIdObjArgs((PyObject *)od, &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -0600930 if (items == NULL)
931 goto Done;
932
933 items_iter = PyObject_GetIter(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300934 Py_DECREF(items);
Eric Snow96c6af92015-05-29 22:21:39 -0600935 if (items_iter == NULL)
936 goto Done;
937
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300938 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300939 Py_DECREF(items_iter);
Eric Snow96c6af92015-05-29 22:21:39 -0600940
941Done:
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300942 Py_XDECREF(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600943 Py_XDECREF(args);
Eric Snow96c6af92015-05-29 22:21:39 -0600944
945 return result;
946}
947
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100948/* setdefault(): Skips __missing__() calls. */
Eric Snow96c6af92015-05-29 22:21:39 -0600949
Eric Snow96c6af92015-05-29 22:21:39 -0600950
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100951/*[clinic input]
952OrderedDict.setdefault
953
954 key: object
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200955 default: object = None
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100956
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200957Insert key with a value of default if key is not in the dictionary.
958
959Return the value for key if key is in the dictionary, else default.
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100960[clinic start generated code]*/
961
Eric Snow96c6af92015-05-29 22:21:39 -0600962static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100963OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200964 PyObject *default_value)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +0200965/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
Eric Snow96c6af92015-05-29 22:21:39 -0600966{
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100967 PyObject *result = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600968
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100969 if (PyODict_CheckExact(self)) {
970 result = PyODict_GetItemWithError(self, key); /* borrowed */
Eric Snowd1719752015-06-01 23:12:13 -0600971 if (result == NULL) {
972 if (PyErr_Occurred())
973 return NULL;
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100974 assert(_odict_find_node(self, key) == NULL);
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200975 if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
976 result = default_value;
977 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600978 }
979 }
980 else {
Eric Snowd1719752015-06-01 23:12:13 -0600981 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600982 }
983 }
984 else {
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100985 int exists = PySequence_Contains((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -0600986 if (exists < 0) {
Eric Snowd1719752015-06-01 23:12:13 -0600987 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600988 }
989 else if (exists) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +0100990 result = PyObject_GetItem((PyObject *)self, key);
Eric Snow96c6af92015-05-29 22:21:39 -0600991 }
Serhiy Storchakaa70eaf22017-01-19 19:38:13 +0200992 else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
993 result = default_value;
994 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -0600995 }
996 }
997
Eric Snow96c6af92015-05-29 22:21:39 -0600998 return result;
999}
1000
1001/* pop() */
1002
1003PyDoc_STRVAR(odict_pop__doc__,
1004"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1005 value. If key is not found, d is returned if given, otherwise KeyError\n\
1006 is raised.\n\
1007\n\
1008 ");
1009
1010/* forward */
1011static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1012
1013/* Skips __missing__() calls. */
1014static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001015odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001016{
Eric Snowac02ef32015-06-02 20:42:14 -06001017 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001018 PyObject *key, *failobj = NULL;
1019
Eric Snowac02ef32015-06-02 20:42:14 -06001020 /* borrowed */
1021 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1022 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001023 return NULL;
1024 }
1025
1026 return _odict_popkey(od, key, failobj);
1027}
1028
1029static PyObject *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001030_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1031 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -06001032{
1033 _ODictNode *node;
1034 PyObject *value = NULL;
1035
Eric Snow96c6af92015-05-29 22:21:39 -06001036 /* Pop the node first to avoid a possible dict resize (due to
1037 eval loop reentrancy) and complications due to hash collision
1038 resolution. */
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001039 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001040 if (node == NULL) {
1041 if (PyErr_Occurred())
Eric Snowd1719752015-06-01 23:12:13 -06001042 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001043 }
1044 else {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001045 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001046 if (res < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001047 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001048 }
1049 }
1050
1051 /* Now delete the value from the dict. */
Serhiy Storchaka04386832016-10-30 17:17:24 +02001052 if (PyODict_CheckExact(od)) {
1053 if (node != NULL) {
1054 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1055 if (value != NULL) {
1056 Py_INCREF(value);
1057 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1058 Py_DECREF(value);
1059 return NULL;
1060 }
1061 }
1062 }
1063 }
1064 else {
1065 int exists = PySequence_Contains(od, key);
1066 if (exists < 0)
1067 return NULL;
1068 if (exists) {
1069 value = PyObject_GetItem(od, key);
1070 if (value != NULL) {
1071 if (PyObject_DelItem(od, key) == -1) {
1072 Py_CLEAR(value);
1073 }
Eric Snow96c6af92015-05-29 22:21:39 -06001074 }
1075 }
1076 }
1077
1078 /* Apply the fallback value, if necessary. */
1079 if (value == NULL && !PyErr_Occurred()) {
1080 if (failobj) {
1081 value = failobj;
1082 Py_INCREF(failobj);
1083 }
1084 else {
1085 PyErr_SetObject(PyExc_KeyError, key);
1086 }
1087 }
1088
Eric Snow96c6af92015-05-29 22:21:39 -06001089 return value;
1090}
1091
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001092static PyObject *
1093_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1094{
1095 Py_hash_t hash = PyObject_Hash(key);
1096 if (hash == -1)
1097 return NULL;
1098
1099 return _odict_popkey_hash(od, key, failobj, hash);
1100}
1101
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001102
Eric Snow96c6af92015-05-29 22:21:39 -06001103/* popitem() */
1104
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001105/*[clinic input]
1106OrderedDict.popitem
1107
1108 last: bool = True
1109
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001110Remove and return a (key, value) pair from the dictionary.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001111
1112Pairs are returned in LIFO order if last is true or FIFO order if false.
1113[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001114
1115static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001116OrderedDict_popitem_impl(PyODictObject *self, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001117/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001118{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001119 PyObject *key, *value, *item = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001120 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001121
1122 /* pull the item */
1123
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001124 if (_odict_EMPTY(self)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001125 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1126 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001127 }
Eric Snow96c6af92015-05-29 22:21:39 -06001128
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001129 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001130 key = _odictnode_KEY(node);
Eric Snowd1719752015-06-01 23:12:13 -06001131 Py_INCREF(key);
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001132 value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -06001133 if (value == NULL)
1134 return NULL;
1135 item = PyTuple_Pack(2, key, value);
Eric Snowd1719752015-06-01 23:12:13 -06001136 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001137 Py_DECREF(value);
1138 return item;
1139}
1140
1141/* keys() */
1142
1143/* MutableMapping.keys() does not have a docstring. */
1144PyDoc_STRVAR(odict_keys__doc__, "");
1145
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301146static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001147
1148/* values() */
1149
1150/* MutableMapping.values() does not have a docstring. */
1151PyDoc_STRVAR(odict_values__doc__, "");
1152
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301153static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001154
1155/* items() */
1156
1157/* MutableMapping.items() does not have a docstring. */
1158PyDoc_STRVAR(odict_items__doc__, "");
1159
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301160static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
Eric Snow96c6af92015-05-29 22:21:39 -06001161
1162/* update() */
1163
1164/* MutableMapping.update() does not have a docstring. */
1165PyDoc_STRVAR(odict_update__doc__, "");
1166
1167/* forward */
1168static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1169
1170#define odict_update mutablemapping_update
1171
1172/* clear() */
1173
1174PyDoc_STRVAR(odict_clear__doc__,
1175 "od.clear() -> None. Remove all items from od.");
1176
1177static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301178odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001179{
1180 PyDict_Clear((PyObject *)od);
1181 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001182 if (_odict_resize(od) < 0)
1183 return NULL;
1184 Py_RETURN_NONE;
1185}
1186
1187/* copy() */
1188
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001189/* forward */
1190static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1191 Py_hash_t);
1192
Eric Snow96c6af92015-05-29 22:21:39 -06001193PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1194
1195static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301196odict_copy(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001197{
1198 _ODictNode *node;
1199 PyObject *od_copy;
1200
1201 if (PyODict_CheckExact(od))
1202 od_copy = PyODict_New();
1203 else
Victor Stinnerf17c3de2016-12-06 18:46:19 +01001204 od_copy = _PyObject_CallNoArg((PyObject *)Py_TYPE(od));
Eric Snow96c6af92015-05-29 22:21:39 -06001205 if (od_copy == NULL)
1206 return NULL;
1207
1208 if (PyODict_CheckExact(od)) {
1209 _odict_FOREACH(od, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001210 PyObject *key = _odictnode_KEY(node);
1211 PyObject *value = _odictnode_VALUE(node, od);
1212 if (value == NULL) {
1213 if (!PyErr_Occurred())
1214 PyErr_SetObject(PyExc_KeyError, key);
1215 goto fail;
1216 }
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001217 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1218 _odictnode_HASH(node)) != 0)
Eric Snow96c6af92015-05-29 22:21:39 -06001219 goto fail;
1220 }
1221 }
1222 else {
1223 _odict_FOREACH(od, node) {
1224 int res;
1225 PyObject *value = PyObject_GetItem((PyObject *)od,
1226 _odictnode_KEY(node));
1227 if (value == NULL)
1228 goto fail;
1229 res = PyObject_SetItem((PyObject *)od_copy,
1230 _odictnode_KEY(node), value);
1231 Py_DECREF(value);
1232 if (res != 0)
1233 goto fail;
1234 }
1235 }
1236 return od_copy;
1237
1238fail:
1239 Py_DECREF(od_copy);
1240 return NULL;
1241}
1242
1243/* __reversed__() */
1244
1245PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1246
1247#define _odict_ITER_REVERSED 1
1248#define _odict_ITER_KEYS 2
1249#define _odict_ITER_VALUES 4
1250
1251/* forward */
1252static PyObject * odictiter_new(PyODictObject *, int);
1253
1254static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301255odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001256{
Eric Snow96c6af92015-05-29 22:21:39 -06001257 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1258}
1259
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001260
Eric Snow96c6af92015-05-29 22:21:39 -06001261/* move_to_end() */
1262
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001263/*[clinic input]
1264OrderedDict.move_to_end
1265
1266 key: object
1267 last: bool = True
1268
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001269Move an existing element to the end (or beginning if last is false).
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001270
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001271Raise KeyError if the element does not exist.
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001272[clinic start generated code]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001273
1274static PyObject *
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001275OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
Serhiy Storchaka78d9e582017-01-25 00:30:04 +02001276/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
Eric Snow96c6af92015-05-29 22:21:39 -06001277{
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001278 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001279
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001280 if (_odict_EMPTY(self)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001281 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001282 return NULL;
1283 }
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001284 node = last ? _odict_LAST(self) : _odict_FIRST(self);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001285 if (key != _odictnode_KEY(node)) {
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001286 node = _odict_find_node(self, key);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001287 if (node == NULL) {
1288 if (!PyErr_Occurred())
1289 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowc5e59602015-05-30 11:28:56 -06001290 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001291 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001292 if (last) {
1293 /* Only move if not already the last one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001294 if (node != _odict_LAST(self)) {
1295 _odict_remove_node(self, node);
1296 _odict_add_tail(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001297 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001298 }
1299 else {
1300 /* Only move if not already the first one. */
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001301 if (node != _odict_FIRST(self)) {
1302 _odict_remove_node(self, node);
1303 _odict_add_head(self, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001304 }
1305 }
1306 }
Eric Snow96c6af92015-05-29 22:21:39 -06001307 Py_RETURN_NONE;
1308}
1309
1310
1311/* tp_methods */
1312
1313static PyMethodDef odict_methods[] = {
1314
Eric Snow96c6af92015-05-29 22:21:39 -06001315 /* overridden dict methods */
Serhiy Storchaka827d49f2018-04-09 19:14:26 +03001316 ORDEREDDICT_FROMKEYS_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001317 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1318 odict_sizeof__doc__},
1319 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1320 odict_reduce__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001321 ORDEREDDICT_SETDEFAULT_METHODDEF
Eric Snowac02ef32015-06-02 20:42:14 -06001322 {"pop", (PyCFunction)odict_pop,
1323 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001324 ORDEREDDICT_POPITEM_METHODDEF
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301325 {"keys", odictkeys_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001326 odict_keys__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301327 {"values", odictvalues_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001328 odict_values__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301329 {"items", odictitems_new, METH_NOARGS,
Eric Snow96c6af92015-05-29 22:21:39 -06001330 odict_items__doc__},
1331 {"update", (PyCFunction)odict_update, METH_VARARGS | METH_KEYWORDS,
1332 odict_update__doc__},
1333 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1334 odict_clear__doc__},
1335 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1336 odict_copy__doc__},
1337
1338 /* new methods */
1339 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1340 odict_reversed__doc__},
Victor Stinnerb05cbac2017-01-17 03:46:13 +01001341 ORDEREDDICT_MOVE_TO_END_METHODDEF
Eric Snow96c6af92015-05-29 22:21:39 -06001342
1343 {NULL, NULL} /* sentinel */
1344};
1345
1346
1347/* ----------------------------------------------
1348 * OrderedDict members
1349 */
1350
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001351/* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001352
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001353static PyGetSetDef odict_getset[] = {
1354 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1355 {NULL}
Eric Snow96c6af92015-05-29 22:21:39 -06001356};
1357
Eric Snow96c6af92015-05-29 22:21:39 -06001358/* ----------------------------------------------
1359 * OrderedDict type slot methods
1360 */
1361
1362/* tp_dealloc */
1363
1364static void
1365odict_dealloc(PyODictObject *self)
1366{
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001367 PyThreadState *tstate = PyThreadState_GET();
1368
Eric Snow96c6af92015-05-29 22:21:39 -06001369 PyObject_GC_UnTrack(self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001370 Py_TRASHCAN_SAFE_BEGIN(self)
1371
Eric Snow96c6af92015-05-29 22:21:39 -06001372 Py_XDECREF(self->od_inst_dict);
1373 if (self->od_weakreflist != NULL)
1374 PyObject_ClearWeakRefs((PyObject *)self);
1375
1376 _odict_clear_nodes(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001377
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001378 /* Call the base tp_dealloc(). Since it too uses the trashcan mechanism,
1379 * temporarily decrement trash_delete_nesting to prevent triggering it
1380 * and putting the partially deallocated object on the trashcan's
1381 * to-be-deleted-later list.
1382 */
1383 --tstate->trash_delete_nesting;
1384 assert(_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL);
Eric Snow96c6af92015-05-29 22:21:39 -06001385 PyDict_Type.tp_dealloc((PyObject *)self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001386 ++tstate->trash_delete_nesting;
1387
1388 Py_TRASHCAN_SAFE_END(self)
Victor Stinnere1871952016-06-08 10:18:18 +02001389}
Eric Snow96c6af92015-05-29 22:21:39 -06001390
1391/* tp_repr */
1392
1393static PyObject *
1394odict_repr(PyODictObject *self)
1395{
1396 int i;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001397 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001398 PyObject *pieces = NULL, *result = NULL;
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001399
1400 if (PyODict_SIZE(self) == 0)
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001401 return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
Eric Snow96c6af92015-05-29 22:21:39 -06001402
1403 i = Py_ReprEnter((PyObject *)self);
1404 if (i != 0) {
1405 return i > 0 ? PyUnicode_FromString("...") : NULL;
1406 }
1407
Eric Snow96c6af92015-05-29 22:21:39 -06001408 if (PyODict_CheckExact(self)) {
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001409 Py_ssize_t count = 0;
Eric Snowa762af72015-06-01 22:59:08 -06001410 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001411 pieces = PyList_New(PyODict_SIZE(self));
1412 if (pieces == NULL)
1413 goto Done;
1414
1415 _odict_FOREACH(self, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001416 PyObject *pair;
1417 PyObject *key = _odictnode_KEY(node);
1418 PyObject *value = _odictnode_VALUE(node, self);
1419 if (value == NULL) {
1420 if (!PyErr_Occurred())
1421 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowdb4061c2015-06-03 11:09:48 -06001422 goto Done;
Eric Snowa762af72015-06-01 22:59:08 -06001423 }
1424 pair = PyTuple_Pack(2, key, value);
Eric Snow96c6af92015-05-29 22:21:39 -06001425 if (pair == NULL)
1426 goto Done;
1427
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001428 if (count < PyList_GET_SIZE(pieces))
1429 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1430 else {
1431 if (PyList_Append(pieces, pair) < 0) {
1432 Py_DECREF(pair);
1433 goto Done;
1434 }
1435 Py_DECREF(pair);
1436 }
1437 count++;
Eric Snow96c6af92015-05-29 22:21:39 -06001438 }
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001439 if (count < PyList_GET_SIZE(pieces))
Serhiy Storchaka1a5856b2017-04-22 02:48:11 +03001440 Py_SIZE(pieces) = count;
Eric Snow96c6af92015-05-29 22:21:39 -06001441 }
1442 else {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001443 PyObject *items = _PyObject_CallMethodIdObjArgs((PyObject *)self,
1444 &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -06001445 if (items == NULL)
1446 goto Done;
1447 pieces = PySequence_List(items);
1448 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001449 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001450 goto Done;
1451 }
1452
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001453 result = PyUnicode_FromFormat("%s(%R)",
1454 _PyType_Name(Py_TYPE(self)), pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001455
Eric Snow96c6af92015-05-29 22:21:39 -06001456Done:
1457 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001458 Py_ReprLeave((PyObject *)self);
1459 return result;
Victor Stinnere1871952016-06-08 10:18:18 +02001460}
Eric Snow96c6af92015-05-29 22:21:39 -06001461
1462/* tp_doc */
1463
1464PyDoc_STRVAR(odict_doc,
1465 "Dictionary that remembers insertion order");
1466
1467/* tp_traverse */
1468
1469static int
1470odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1471{
Serhiy Storchakad205d012016-01-19 14:46:25 +02001472 _ODictNode *node;
1473
Eric Snow96c6af92015-05-29 22:21:39 -06001474 Py_VISIT(od->od_inst_dict);
1475 Py_VISIT(od->od_weakreflist);
Serhiy Storchakad205d012016-01-19 14:46:25 +02001476 _odict_FOREACH(od, node) {
1477 Py_VISIT(_odictnode_KEY(node));
1478 }
Eric Snow96c6af92015-05-29 22:21:39 -06001479 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1480}
1481
1482/* tp_clear */
1483
1484static int
1485odict_tp_clear(PyODictObject *od)
1486{
1487 PyObject *res;
1488 Py_CLEAR(od->od_inst_dict);
1489 Py_CLEAR(od->od_weakreflist);
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301490 res = odict_clear(od, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -06001491 if (res == NULL)
1492 return -1;
1493 Py_DECREF(res);
1494 return 0;
1495}
1496
1497/* tp_richcompare */
1498
1499static PyObject *
1500odict_richcompare(PyObject *v, PyObject *w, int op)
1501{
1502 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1503 Py_RETURN_NOTIMPLEMENTED;
1504 }
1505
1506 if (op == Py_EQ || op == Py_NE) {
1507 PyObject *res, *cmp;
1508 int eq;
1509
1510 cmp = PyDict_Type.tp_richcompare(v, w, op);
1511 if (cmp == NULL)
1512 return NULL;
1513 if (!PyODict_Check(w))
1514 return cmp;
1515 if (op == Py_EQ && cmp == Py_False)
1516 return cmp;
1517 if (op == Py_NE && cmp == Py_True)
1518 return cmp;
1519 Py_DECREF(cmp);
1520
1521 /* Try comparing odict keys. */
1522 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1523 if (eq < 0)
1524 return NULL;
1525
1526 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1527 Py_INCREF(res);
1528 return res;
1529 } else {
1530 Py_RETURN_NOTIMPLEMENTED;
1531 }
Victor Stinnere1871952016-06-08 10:18:18 +02001532}
Eric Snow96c6af92015-05-29 22:21:39 -06001533
1534/* tp_iter */
1535
1536static PyObject *
1537odict_iter(PyODictObject *od)
1538{
1539 return odictiter_new(od, _odict_ITER_KEYS);
Victor Stinnere1871952016-06-08 10:18:18 +02001540}
Eric Snow96c6af92015-05-29 22:21:39 -06001541
1542/* tp_init */
1543
1544static int
1545odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1546{
1547 PyObject *res;
1548 Py_ssize_t len = PyObject_Length(args);
1549
1550 if (len == -1)
1551 return -1;
1552 if (len > 1) {
Serhiy Storchakae2f92de2017-11-11 13:06:26 +02001553 const char *msg = "expected at most 1 arguments, got %d";
Eric Snow96c6af92015-05-29 22:21:39 -06001554 PyErr_Format(PyExc_TypeError, msg, len);
1555 return -1;
1556 }
1557
1558 /* __init__() triggering update() is just the way things are! */
1559 res = odict_update(self, args, kwds);
1560 if (res == NULL) {
1561 return -1;
1562 } else {
1563 Py_DECREF(res);
1564 return 0;
1565 }
Victor Stinnere1871952016-06-08 10:18:18 +02001566}
Eric Snow96c6af92015-05-29 22:21:39 -06001567
1568/* tp_new */
1569
1570static PyObject *
1571odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1572{
Victor Stinnerca30b022015-09-03 17:50:04 +02001573 PyODictObject *od;
1574
Victor Stinnerca30b022015-09-03 17:50:04 +02001575 od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001576 if (od == NULL)
Victor Stinnerca30b022015-09-03 17:50:04 +02001577 return NULL;
Victor Stinnerca30b022015-09-03 17:50:04 +02001578
Victor Stinnerca30b022015-09-03 17:50:04 +02001579 /* type constructor fills the memory with zeros (see
1580 PyType_GenericAlloc()), there is no need to set them to zero again */
1581 if (_odict_resize(od) < 0) {
1582 Py_DECREF(od);
1583 return NULL;
1584 }
1585
1586 return (PyObject*)od;
Eric Snow96c6af92015-05-29 22:21:39 -06001587}
1588
1589/* PyODict_Type */
1590
1591PyTypeObject PyODict_Type = {
1592 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1593 "collections.OrderedDict", /* tp_name */
1594 sizeof(PyODictObject), /* tp_basicsize */
1595 0, /* tp_itemsize */
1596 (destructor)odict_dealloc, /* tp_dealloc */
1597 0, /* tp_print */
1598 0, /* tp_getattr */
1599 0, /* tp_setattr */
1600 0, /* tp_reserved */
1601 (reprfunc)odict_repr, /* tp_repr */
1602 0, /* tp_as_number */
1603 0, /* tp_as_sequence */
1604 &odict_as_mapping, /* tp_as_mapping */
1605 0, /* tp_hash */
1606 0, /* tp_call */
1607 0, /* tp_str */
1608 0, /* tp_getattro */
1609 0, /* tp_setattro */
1610 0, /* tp_as_buffer */
1611 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1612 odict_doc, /* tp_doc */
1613 (traverseproc)odict_traverse, /* tp_traverse */
1614 (inquiry)odict_tp_clear, /* tp_clear */
1615 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1616 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1617 (getiterfunc)odict_iter, /* tp_iter */
1618 0, /* tp_iternext */
1619 odict_methods, /* tp_methods */
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001620 0, /* tp_members */
1621 odict_getset, /* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001622 &PyDict_Type, /* tp_base */
1623 0, /* tp_dict */
1624 0, /* tp_descr_get */
1625 0, /* tp_descr_set */
1626 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1627 (initproc)odict_init, /* tp_init */
1628 PyType_GenericAlloc, /* tp_alloc */
1629 (newfunc)odict_new, /* tp_new */
1630 0, /* tp_free */
1631};
1632
1633
1634/* ----------------------------------------------
1635 * the public OrderedDict API
1636 */
1637
1638PyObject *
1639PyODict_New(void) {
1640 return odict_new(&PyODict_Type, NULL, NULL);
Victor Stinnere1871952016-06-08 10:18:18 +02001641}
Eric Snow96c6af92015-05-29 22:21:39 -06001642
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001643static int
1644_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1645 Py_hash_t hash)
1646{
1647 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001648 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001649 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001650 if (res < 0) {
1651 /* Revert setting the value on the dict */
1652 PyObject *exc, *val, *tb;
1653 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001654 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001655 _PyErr_ChainExceptions(exc, val, tb);
1656 }
Eric Snow96c6af92015-05-29 22:21:39 -06001657 }
1658 return res;
Victor Stinnere1871952016-06-08 10:18:18 +02001659}
Eric Snow96c6af92015-05-29 22:21:39 -06001660
1661int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001662PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1663{
1664 Py_hash_t hash = PyObject_Hash(key);
1665 if (hash == -1)
1666 return -1;
1667 return _PyODict_SetItem_KnownHash(od, key, value, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001668}
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001669
1670int
1671PyODict_DelItem(PyObject *od, PyObject *key)
1672{
1673 int res;
1674 Py_hash_t hash = PyObject_Hash(key);
1675 if (hash == -1)
1676 return -1;
1677 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001678 if (res < 0)
1679 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001680 return _PyDict_DelItem_KnownHash(od, key, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001681}
Eric Snow96c6af92015-05-29 22:21:39 -06001682
1683
1684/* -------------------------------------------
1685 * The OrderedDict views (keys/values/items)
1686 */
1687
1688typedef struct {
1689 PyObject_HEAD
1690 int kind;
1691 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001692 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001693 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001694 PyObject *di_current;
1695 PyObject *di_result; /* reusable result tuple for iteritems */
1696} odictiterobject;
1697
1698static void
1699odictiter_dealloc(odictiterobject *di)
1700{
1701 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001702 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001703 Py_XDECREF(di->di_current);
1704 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1705 Py_DECREF(di->di_result);
1706 }
1707 PyObject_GC_Del(di);
1708}
1709
1710static int
1711odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1712{
1713 Py_VISIT(di->di_odict);
1714 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1715 Py_VISIT(di->di_result);
1716 return 0;
1717}
1718
Eric Snowa762af72015-06-01 22:59:08 -06001719/* In order to protect against modifications during iteration, we track
1720 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001721static PyObject *
1722odictiter_nextkey(odictiterobject *di)
1723{
Eric Snowa762af72015-06-01 22:59:08 -06001724 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001725 _ODictNode *node;
1726 int reversed = di->kind & _odict_ITER_REVERSED;
1727
Eric Snowa762af72015-06-01 22:59:08 -06001728 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001729 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001730 if (di->di_current == NULL)
1731 goto done; /* We're already done. */
1732
Eric Snowb952ab42015-06-01 23:35:13 -06001733 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001734 if (di->di_odict->od_state != di->di_state) {
1735 PyErr_SetString(PyExc_RuntimeError,
1736 "OrderedDict mutated during iteration");
1737 goto done;
1738 }
Eric Snowb952ab42015-06-01 23:35:13 -06001739 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1740 PyErr_SetString(PyExc_RuntimeError,
1741 "OrderedDict changed size during iteration");
1742 di->di_size = -1; /* Make this state sticky */
1743 return NULL;
1744 }
1745
Eric Snowa762af72015-06-01 22:59:08 -06001746 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001747 node = _odict_find_node(di->di_odict, di->di_current);
1748 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001749 if (!PyErr_Occurred())
1750 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001751 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001752 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001753 return NULL;
1754 }
1755 key = di->di_current;
1756
1757 /* Advance to the next key. */
1758 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1759 if (node == NULL) {
1760 /* Reached the end. */
1761 di->di_current = NULL;
1762 }
1763 else {
1764 di->di_current = _odictnode_KEY(node);
1765 Py_INCREF(di->di_current);
1766 }
1767
1768 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001769
1770done:
1771 Py_CLEAR(di->di_odict);
1772 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001773}
1774
1775static PyObject *
1776odictiter_iternext(odictiterobject *di)
1777{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001778 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001779 PyObject *key = odictiter_nextkey(di); /* new reference */
1780
1781 if (key == NULL)
1782 return NULL;
1783
1784 /* Handle the keys case. */
1785 if (! (di->kind & _odict_ITER_VALUES)) {
1786 return key;
1787 }
1788
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001789 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1790 if (value == NULL) {
1791 if (!PyErr_Occurred())
1792 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001793 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001794 goto done;
1795 }
1796 Py_INCREF(value);
1797
1798 /* Handle the values case. */
1799 if (!(di->kind & _odict_ITER_KEYS)) {
1800 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001801 return value;
1802 }
Eric Snowa762af72015-06-01 22:59:08 -06001803
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001804 /* Handle the items case. */
1805 result = di->di_result;
1806
1807 if (Py_REFCNT(result) == 1) {
1808 /* not in use so we can reuse it
1809 * (the common case during iteration) */
1810 Py_INCREF(result);
1811 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1812 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1813 }
1814 else {
1815 result = PyTuple_New(2);
1816 if (result == NULL) {
1817 Py_DECREF(key);
1818 Py_DECREF(value);
1819 goto done;
1820 }
1821 }
1822
1823 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1824 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1825 return result;
1826
Eric Snowa762af72015-06-01 22:59:08 -06001827done:
1828 Py_CLEAR(di->di_current);
1829 Py_CLEAR(di->di_odict);
1830 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001831}
1832
1833/* No need for tp_clear because odictiterobject is not mutable. */
1834
1835PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1836
1837static PyObject *
1838odictiter_reduce(odictiterobject *di)
1839{
Eric Snowc5e59602015-05-30 11:28:56 -06001840 PyObject *list, *iter;
Eric Snow96c6af92015-05-29 22:21:39 -06001841
1842 list = PyList_New(0);
1843 if (!list)
1844 return NULL;
1845
1846 /* iterate the temporary into a list */
1847 for(;;) {
1848 PyObject *element = odictiter_iternext(di);
1849 if (element) {
1850 if (PyList_Append(list, element)) {
1851 Py_DECREF(element);
1852 Py_DECREF(list);
1853 return NULL;
1854 }
1855 Py_DECREF(element);
1856 }
1857 else {
1858 /* done iterating? */
1859 break;
1860 }
1861 }
1862 if (PyErr_Occurred()) {
1863 Py_DECREF(list);
1864 return NULL;
1865 }
Eric Snowc5e59602015-05-30 11:28:56 -06001866 iter = _PyObject_GetBuiltin("iter");
1867 if (iter == NULL) {
1868 Py_DECREF(list);
1869 return NULL;
1870 }
1871 return Py_BuildValue("N(N)", iter, list);
Eric Snow96c6af92015-05-29 22:21:39 -06001872}
1873
1874static PyMethodDef odictiter_methods[] = {
1875 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1876 {NULL, NULL} /* sentinel */
1877};
1878
1879PyTypeObject PyODictIter_Type = {
1880 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1881 "odict_iterator", /* tp_name */
1882 sizeof(odictiterobject), /* tp_basicsize */
1883 0, /* tp_itemsize */
1884 /* methods */
1885 (destructor)odictiter_dealloc, /* tp_dealloc */
1886 0, /* tp_print */
1887 0, /* tp_getattr */
1888 0, /* tp_setattr */
1889 0, /* tp_reserved */
1890 0, /* tp_repr */
1891 0, /* tp_as_number */
1892 0, /* tp_as_sequence */
1893 0, /* tp_as_mapping */
1894 0, /* tp_hash */
1895 0, /* tp_call */
1896 0, /* tp_str */
1897 PyObject_GenericGetAttr, /* tp_getattro */
1898 0, /* tp_setattro */
1899 0, /* tp_as_buffer */
1900 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1901 0, /* tp_doc */
1902 (traverseproc)odictiter_traverse, /* tp_traverse */
1903 0, /* tp_clear */
1904 0, /* tp_richcompare */
1905 0, /* tp_weaklistoffset */
1906 PyObject_SelfIter, /* tp_iter */
1907 (iternextfunc)odictiter_iternext, /* tp_iternext */
1908 odictiter_methods, /* tp_methods */
1909 0,
1910};
1911
1912static PyObject *
1913odictiter_new(PyODictObject *od, int kind)
1914{
1915 odictiterobject *di;
1916 _ODictNode *node;
1917 int reversed = kind & _odict_ITER_REVERSED;
1918
1919 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1920 if (di == NULL)
1921 return NULL;
1922
1923 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
1924 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1925 if (di->di_result == NULL) {
1926 Py_DECREF(di);
1927 return NULL;
1928 }
1929 }
1930 else
1931 di->di_result = NULL;
1932
1933 di->kind = kind;
1934 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1935 di->di_current = node ? _odictnode_KEY(node) : NULL;
1936 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06001937 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06001938 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001939 di->di_odict = od;
1940 Py_INCREF(od);
1941
1942 _PyObject_GC_TRACK(di);
1943 return (PyObject *)di;
1944}
1945
1946/* keys() */
1947
1948static PyObject *
1949odictkeys_iter(_PyDictViewObject *dv)
1950{
1951 if (dv->dv_dict == NULL) {
1952 Py_RETURN_NONE;
1953 }
1954 return odictiter_new((PyODictObject *)dv->dv_dict,
1955 _odict_ITER_KEYS);
1956}
1957
1958static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301959odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06001960{
1961 if (dv->dv_dict == NULL) {
1962 Py_RETURN_NONE;
1963 }
1964 return odictiter_new((PyODictObject *)dv->dv_dict,
1965 _odict_ITER_KEYS|_odict_ITER_REVERSED);
1966}
1967
1968static PyMethodDef odictkeys_methods[] = {
1969 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
1970 {NULL, NULL} /* sentinel */
1971};
1972
1973PyTypeObject PyODictKeys_Type = {
1974 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1975 "odict_keys", /* tp_name */
1976 0, /* tp_basicsize */
1977 0, /* tp_itemsize */
1978 0, /* tp_dealloc */
1979 0, /* tp_print */
1980 0, /* tp_getattr */
1981 0, /* tp_setattr */
1982 0, /* tp_reserved */
1983 0, /* tp_repr */
1984 0, /* tp_as_number */
1985 0, /* tp_as_sequence */
1986 0, /* tp_as_mapping */
1987 0, /* tp_hash */
1988 0, /* tp_call */
1989 0, /* tp_str */
1990 0, /* tp_getattro */
1991 0, /* tp_setattro */
1992 0, /* tp_as_buffer */
1993 0, /* tp_flags */
1994 0, /* tp_doc */
1995 0, /* tp_traverse */
1996 0, /* tp_clear */
1997 0, /* tp_richcompare */
1998 0, /* tp_weaklistoffset */
1999 (getiterfunc)odictkeys_iter, /* tp_iter */
2000 0, /* tp_iternext */
2001 odictkeys_methods, /* tp_methods */
2002 0, /* tp_members */
2003 0, /* tp_getset */
2004 &PyDictKeys_Type, /* tp_base */
2005};
2006
2007static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302008odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002009{
2010 return _PyDictView_New(od, &PyODictKeys_Type);
2011}
2012
2013/* items() */
2014
2015static PyObject *
2016odictitems_iter(_PyDictViewObject *dv)
2017{
2018 if (dv->dv_dict == NULL) {
2019 Py_RETURN_NONE;
2020 }
2021 return odictiter_new((PyODictObject *)dv->dv_dict,
2022 _odict_ITER_KEYS|_odict_ITER_VALUES);
2023}
2024
2025static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302026odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002027{
2028 if (dv->dv_dict == NULL) {
2029 Py_RETURN_NONE;
2030 }
2031 return odictiter_new((PyODictObject *)dv->dv_dict,
2032 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2033}
2034
2035static PyMethodDef odictitems_methods[] = {
2036 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
2037 {NULL, NULL} /* sentinel */
2038};
2039
2040PyTypeObject PyODictItems_Type = {
2041 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2042 "odict_items", /* tp_name */
2043 0, /* tp_basicsize */
2044 0, /* tp_itemsize */
2045 0, /* tp_dealloc */
2046 0, /* tp_print */
2047 0, /* tp_getattr */
2048 0, /* tp_setattr */
2049 0, /* tp_reserved */
2050 0, /* tp_repr */
2051 0, /* tp_as_number */
2052 0, /* tp_as_sequence */
2053 0, /* tp_as_mapping */
2054 0, /* tp_hash */
2055 0, /* tp_call */
2056 0, /* tp_str */
2057 0, /* tp_getattro */
2058 0, /* tp_setattro */
2059 0, /* tp_as_buffer */
2060 0, /* tp_flags */
2061 0, /* tp_doc */
2062 0, /* tp_traverse */
2063 0, /* tp_clear */
2064 0, /* tp_richcompare */
2065 0, /* tp_weaklistoffset */
2066 (getiterfunc)odictitems_iter, /* tp_iter */
2067 0, /* tp_iternext */
2068 odictitems_methods, /* tp_methods */
2069 0, /* tp_members */
2070 0, /* tp_getset */
2071 &PyDictItems_Type, /* tp_base */
2072};
2073
2074static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302075odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002076{
2077 return _PyDictView_New(od, &PyODictItems_Type);
2078}
2079
2080/* values() */
2081
2082static PyObject *
2083odictvalues_iter(_PyDictViewObject *dv)
2084{
2085 if (dv->dv_dict == NULL) {
2086 Py_RETURN_NONE;
2087 }
2088 return odictiter_new((PyODictObject *)dv->dv_dict,
2089 _odict_ITER_VALUES);
2090}
2091
2092static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302093odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002094{
2095 if (dv->dv_dict == NULL) {
2096 Py_RETURN_NONE;
2097 }
2098 return odictiter_new((PyODictObject *)dv->dv_dict,
2099 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2100}
2101
2102static PyMethodDef odictvalues_methods[] = {
2103 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2104 {NULL, NULL} /* sentinel */
2105};
2106
2107PyTypeObject PyODictValues_Type = {
2108 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2109 "odict_values", /* tp_name */
2110 0, /* tp_basicsize */
2111 0, /* tp_itemsize */
2112 0, /* tp_dealloc */
2113 0, /* tp_print */
2114 0, /* tp_getattr */
2115 0, /* tp_setattr */
2116 0, /* tp_reserved */
2117 0, /* tp_repr */
2118 0, /* tp_as_number */
2119 0, /* tp_as_sequence */
2120 0, /* tp_as_mapping */
2121 0, /* tp_hash */
2122 0, /* tp_call */
2123 0, /* tp_str */
2124 0, /* tp_getattro */
2125 0, /* tp_setattro */
2126 0, /* tp_as_buffer */
2127 0, /* tp_flags */
2128 0, /* tp_doc */
2129 0, /* tp_traverse */
2130 0, /* tp_clear */
2131 0, /* tp_richcompare */
2132 0, /* tp_weaklistoffset */
2133 (getiterfunc)odictvalues_iter, /* tp_iter */
2134 0, /* tp_iternext */
2135 odictvalues_methods, /* tp_methods */
2136 0, /* tp_members */
2137 0, /* tp_getset */
2138 &PyDictValues_Type, /* tp_base */
2139};
2140
2141static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05302142odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
Eric Snow96c6af92015-05-29 22:21:39 -06002143{
2144 return _PyDictView_New(od, &PyODictValues_Type);
2145}
2146
2147
2148/* ----------------------------------------------
Martin Panter536d70e2017-01-14 08:23:08 +00002149 MutableMapping implementations
Eric Snow96c6af92015-05-29 22:21:39 -06002150
2151Mapping:
2152
2153============ ===========
2154method uses
2155============ ===========
2156__contains__ __getitem__
2157__eq__ items
2158__getitem__ +
2159__iter__ +
2160__len__ +
2161__ne__ __eq__
2162get __getitem__
2163items ItemsView
2164keys KeysView
2165values ValuesView
2166============ ===========
2167
2168ItemsView uses __len__, __iter__, and __getitem__.
2169KeysView uses __len__, __iter__, and __contains__.
2170ValuesView uses __len__, __iter__, and __getitem__.
2171
2172MutableMapping:
2173
2174============ ===========
2175method uses
2176============ ===========
2177__delitem__ +
2178__setitem__ +
2179clear popitem
2180pop __getitem__
2181 __delitem__
2182popitem __iter__
2183 _getitem__
2184 __delitem__
2185setdefault __getitem__
2186 __setitem__
2187update __setitem__
2188============ ===========
2189*/
2190
2191static int
2192mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2193{
2194 PyObject *pair, *iterator, *unexpected;
2195 int res = 0;
2196
2197 iterator = PyObject_GetIter(pairs);
2198 if (iterator == NULL)
2199 return -1;
2200 PyErr_Clear();
2201
2202 while ((pair = PyIter_Next(iterator)) != NULL) {
2203 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002204 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002205 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002206 if (pair_iterator == NULL)
2207 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002208
2209 key = PyIter_Next(pair_iterator);
2210 if (key == NULL) {
2211 if (!PyErr_Occurred())
2212 PyErr_SetString(PyExc_ValueError,
2213 "need more than 0 values to unpack");
2214 goto Done;
2215 }
2216
2217 value = PyIter_Next(pair_iterator);
2218 if (value == NULL) {
2219 if (!PyErr_Occurred())
2220 PyErr_SetString(PyExc_ValueError,
2221 "need more than 1 value to unpack");
2222 goto Done;
2223 }
2224
2225 unexpected = PyIter_Next(pair_iterator);
2226 if (unexpected != NULL) {
2227 Py_DECREF(unexpected);
2228 PyErr_SetString(PyExc_ValueError,
2229 "too many values to unpack (expected 2)");
2230 goto Done;
2231 }
2232 else if (PyErr_Occurred())
2233 goto Done;
2234
2235 res = PyObject_SetItem(self, key, value);
2236
2237Done:
2238 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002239 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002240 Py_XDECREF(key);
2241 Py_XDECREF(value);
2242 if (PyErr_Occurred())
2243 break;
2244 }
2245 Py_DECREF(iterator);
2246
2247 if (res < 0 || PyErr_Occurred() != NULL)
2248 return -1;
2249 else
2250 return 0;
2251}
2252
2253static PyObject *
2254mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2255{
2256 int res = 0;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002257 Py_ssize_t len;
2258 _Py_IDENTIFIER(items);
2259 _Py_IDENTIFIER(keys);
Eric Snow96c6af92015-05-29 22:21:39 -06002260
2261 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002262 assert(args == NULL || PyTuple_Check(args));
2263 len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002264 if (len > 1) {
Serhiy Storchakae2f92de2017-11-11 13:06:26 +02002265 const char *msg = "update() takes at most 1 positional argument (%d given)";
Eric Snow96c6af92015-05-29 22:21:39 -06002266 PyErr_Format(PyExc_TypeError, msg, len);
2267 return NULL;
2268 }
Eric Snow96c6af92015-05-29 22:21:39 -06002269
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002270 if (len) {
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002271 PyObject *func;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002272 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002273 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002274 Py_INCREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002275 if (PyDict_CheckExact(other)) {
2276 PyObject *items = PyDict_Items(other);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002277 Py_DECREF(other);
2278 if (items == NULL)
2279 return NULL;
2280 res = mutablemapping_add_pairs(self, items);
2281 Py_DECREF(items);
2282 if (res == -1)
2283 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002284 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002285 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002286
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002287 if (_PyObject_LookupAttrId(other, &PyId_keys, &func) < 0) {
2288 Py_DECREF(other);
2289 return NULL;
2290 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002291 if (func != NULL) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002292 PyObject *keys, *iterator, *key;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002293 keys = _PyObject_CallNoArg(func);
2294 Py_DECREF(func);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002295 if (keys == NULL) {
2296 Py_DECREF(other);
2297 return NULL;
2298 }
2299 iterator = PyObject_GetIter(keys);
2300 Py_DECREF(keys);
2301 if (iterator == NULL) {
2302 Py_DECREF(other);
2303 return NULL;
2304 }
2305 while (res == 0 && (key = PyIter_Next(iterator))) {
2306 PyObject *value = PyObject_GetItem(other, key);
2307 if (value != NULL) {
2308 res = PyObject_SetItem(self, key, value);
2309 Py_DECREF(value);
2310 }
2311 else {
2312 res = -1;
2313 }
2314 Py_DECREF(key);
2315 }
2316 Py_DECREF(other);
2317 Py_DECREF(iterator);
2318 if (res != 0 || PyErr_Occurred())
2319 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002320 goto handle_kwargs;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002321 }
Serhiy Storchakaf320be72018-01-25 10:49:40 +02002322
2323 if (_PyObject_LookupAttrId(other, &PyId_items, &func) < 0) {
Eric Snow06aed902016-09-09 11:59:08 -07002324 Py_DECREF(other);
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002325 return NULL;
2326 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002327 if (func != NULL) {
2328 PyObject *items;
2329 Py_DECREF(other);
2330 items = _PyObject_CallNoArg(func);
2331 Py_DECREF(func);
Eric Snow06aed902016-09-09 11:59:08 -07002332 if (items == NULL)
2333 return NULL;
2334 res = mutablemapping_add_pairs(self, items);
2335 Py_DECREF(items);
2336 if (res == -1)
2337 return NULL;
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002338 goto handle_kwargs;
2339 }
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002340
2341 res = mutablemapping_add_pairs(self, other);
2342 Py_DECREF(other);
2343 if (res != 0)
2344 return NULL;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002345 }
2346
Serhiy Storchaka60c3d352017-11-11 16:19:56 +02002347 handle_kwargs:
Benjamin Peterson0718de92015-06-07 00:00:42 -05002348 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002349 assert(kwargs == NULL || PyDict_Check(kwargs));
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02002350 if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002351 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002352 if (items == NULL)
2353 return NULL;
2354 res = mutablemapping_add_pairs(self, items);
2355 Py_DECREF(items);
2356 if (res == -1)
2357 return NULL;
2358 }
Eric Snow96c6af92015-05-29 22:21:39 -06002359
2360 Py_RETURN_NONE;
2361}