blob: f9f1bf362e7e4db4af6ef8fe81f94186bb97ded3 [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
70that end, We use a simple API to interact with the linked-list. Here's a
71summary 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
447 would be invalidate after a resize, which is particularly problematic
448 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"
473#include "structmember.h"
474#include "dict-common.h"
475#include <stddef.h>
476
477
478typedef struct _odictnode _ODictNode;
479
480/* PyODictObject */
481struct _odictobject {
Eric Snow4fabf022015-06-04 00:09:56 -0600482 PyDictObject od_dict; /* the underlying dict */
483 _ODictNode *od_first; /* first node in the linked list, if any */
484 _ODictNode *od_last; /* last node in the linked list, if any */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200485 /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
486 * by _odict_resize().
Eric Snow8c7f9552015-08-07 17:45:12 -0600487 * Note that we rely on implementation details of dict for both. */
488 _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200489 Py_ssize_t od_fast_nodes_size;
490 void *od_resize_sentinel; /* changes if odict should be resized */
Eric Snow8c7f9552015-08-07 17:45:12 -0600491
Eric Snow4fabf022015-06-04 00:09:56 -0600492 size_t od_state; /* incremented whenever the LL changes */
493 PyObject *od_inst_dict; /* OrderedDict().__dict__ */
494 PyObject *od_weakreflist; /* holds weakrefs to the odict */
Eric Snow96c6af92015-05-29 22:21:39 -0600495};
496
497
498/* ----------------------------------------------
499 * odict keys (a simple doubly-linked list)
500 */
501
502struct _odictnode {
503 PyObject *key;
Eric Snow4c729182015-06-03 10:50:37 -0600504 Py_hash_t hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600505 _ODictNode *next;
506 _ODictNode *prev;
507};
508
509#define _odictnode_KEY(node) \
510 (node->key)
Eric Snow4c729182015-06-03 10:50:37 -0600511#define _odictnode_HASH(node) \
512 (node->hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600513/* borrowed reference */
514#define _odictnode_VALUE(node, od) \
Eric Snowa762af72015-06-01 22:59:08 -0600515 PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
Eric Snow96c6af92015-05-29 22:21:39 -0600516#define _odictnode_PREV(node) (node->prev)
517#define _odictnode_NEXT(node) (node->next)
518
519#define _odict_FIRST(od) (((PyODictObject *)od)->od_first)
520#define _odict_LAST(od) (((PyODictObject *)od)->od_last)
521#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
522#define _odict_FOREACH(od, node) \
523 for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
524
Eric Snow8c7f9552015-08-07 17:45:12 -0600525#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size
Eric Snow96c6af92015-05-29 22:21:39 -0600526
Eric Snow96c6af92015-05-29 22:21:39 -0600527static void
528_odict_free_fast_nodes(PyODictObject *od) {
529 if (od->od_fast_nodes) {
530 PyMem_FREE(od->od_fast_nodes);
531 }
532}
533
Eric Snow4c729182015-06-03 10:50:37 -0600534/* Return the index into the hash table, regardless of a valid node. */
535static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200536_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow4c729182015-06-03 10:50:37 -0600537{
538 PyObject **value_addr = NULL;
Eric Snow4c729182015-06-03 10:50:37 -0600539 PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
Victor Stinner742da042016-09-07 17:40:12 -0700540 Py_ssize_t ix;
Eric Snow4c729182015-06-03 10:50:37 -0600541
Victor Stinner742da042016-09-07 17:40:12 -0700542 ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr, NULL);
543 if (ix == DKIX_EMPTY) {
544 return keys->dk_nentries; /* index of new entry */
545 }
546 if (ix < 0)
Eric Snow4c729182015-06-03 10:50:37 -0600547 return -1;
548 /* We use pointer arithmetic to get the entry's index into the table. */
Victor Stinner742da042016-09-07 17:40:12 -0700549 return ix;
Eric Snow4c729182015-06-03 10:50:37 -0600550}
551
552/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
Eric Snow96c6af92015-05-29 22:21:39 -0600553static int
554_odict_resize(PyODictObject *od) {
Eric Snow4c729182015-06-03 10:50:37 -0600555 Py_ssize_t size, i;
Eric Snow96c6af92015-05-29 22:21:39 -0600556 _ODictNode **fast_nodes, *node;
557
558 /* Initialize a new "fast nodes" table. */
559 size = ((PyDictObject *)od)->ma_keys->dk_size;
560 fast_nodes = PyMem_NEW(_ODictNode *, size);
561 if (fast_nodes == NULL) {
562 PyErr_NoMemory();
563 return -1;
564 }
565 for (i = 0; i < size; i++)
566 fast_nodes[i] = NULL;
567
568 /* Copy the current nodes into the table. */
Eric Snow96c6af92015-05-29 22:21:39 -0600569 _odict_FOREACH(od, node) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200570 i = _odict_get_index_raw(od, _odictnode_KEY(node),
Victor Stinner742da042016-09-07 17:40:12 -0700571 _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -0600572 if (i < 0) {
Eric Snow96c6af92015-05-29 22:21:39 -0600573 PyMem_FREE(fast_nodes);
574 return -1;
575 }
576 fast_nodes[i] = node;
577 }
Eric Snow96c6af92015-05-29 22:21:39 -0600578
579 /* Replace the old fast nodes table. */
580 _odict_free_fast_nodes(od);
581 od->od_fast_nodes = fast_nodes;
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200582 od->od_fast_nodes_size = size;
583 od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600584 return 0;
585}
586
587/* Return the index into the hash table, regardless of a valid node. */
588static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200589_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600590{
Eric Snow4c729182015-06-03 10:50:37 -0600591 PyDictKeysObject *keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600592
593 assert(key != NULL);
Eric Snow4c729182015-06-03 10:50:37 -0600594 keys = ((PyDictObject *)od)->ma_keys;
595
596 /* Ensure od_fast_nodes and dk_entries are in sync. */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200597 if (od->od_resize_sentinel != keys ||
598 od->od_fast_nodes_size != keys->dk_size) {
Eric Snow4c729182015-06-03 10:50:37 -0600599 int resize_res = _odict_resize(od);
600 if (resize_res < 0)
601 return -1;
602 }
603
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200604 return _odict_get_index_raw(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600605}
606
Eric Snow96c6af92015-05-29 22:21:39 -0600607/* Returns NULL if there was some error or the key was not found. */
608static _ODictNode *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200609_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600610{
611 Py_ssize_t index;
612
613 if (_odict_EMPTY(od))
614 return NULL;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200615 index = _odict_get_index(od, key, hash);
616 if (index < 0)
617 return NULL;
618 return od->od_fast_nodes[index];
619}
620
621static _ODictNode *
622_odict_find_node(PyODictObject *od, PyObject *key)
623{
624 Py_ssize_t index;
625 Py_hash_t hash;
626
627 if (_odict_EMPTY(od))
628 return NULL;
629 hash = PyObject_Hash(key);
630 if (hash == -1)
631 return NULL;
632 index = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600633 if (index < 0)
634 return NULL;
635 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 }
679 else if (od->od_fast_nodes[i] != NULL) {
680 /* We already have a node for the key so there's no need to add one. */
681 Py_DECREF(key);
682 return 0;
683 }
684
685 /* must not be added yet */
686 node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode));
687 if (node == NULL) {
688 Py_DECREF(key);
689 PyErr_NoMemory();
690 return -1;
691 }
692
693 _odictnode_KEY(node) = key;
Eric Snow4c729182015-06-03 10:50:37 -0600694 _odictnode_HASH(node) = hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600695 _odict_add_tail(od, node);
696 od->od_fast_nodes[i] = node;
697 return 0;
698}
699
700/* Putting the decref after the free causes problems. */
701#define _odictnode_DEALLOC(node) \
702 do { \
703 Py_DECREF(_odictnode_KEY(node)); \
704 PyMem_FREE((void *)node); \
705 } while (0)
706
707/* Repeated calls on the same node are no-ops. */
708static void
709_odict_remove_node(PyODictObject *od, _ODictNode *node)
710{
711 if (_odict_FIRST(od) == node)
712 _odict_FIRST(od) = _odictnode_NEXT(node);
713 else if (_odictnode_PREV(node) != NULL)
714 _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
715
716 if (_odict_LAST(od) == node)
717 _odict_LAST(od) = _odictnode_PREV(node);
718 else if (_odictnode_NEXT(node) != NULL)
719 _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
720
721 _odictnode_PREV(node) = NULL;
722 _odictnode_NEXT(node) = NULL;
Eric Snow4fabf022015-06-04 00:09:56 -0600723 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600724}
725
Eric Snow96c6af92015-05-29 22:21:39 -0600726/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
727 get all sorts of problems here. In PyODict_DelItem we make sure to
728 call _odict_clear_node first.
Victor Stinnerca30b022015-09-03 17:50:04 +0200729
Eric Snow96c6af92015-05-29 22:21:39 -0600730 This matters in the case of colliding keys. Suppose we add 3 keys:
731 [A, B, C], where the hash of C collides with A and the next possible
732 index in the hash table is occupied by B. If we remove B then for C
733 the dict's looknode func will give us the old index of B instead of
734 the index we got before deleting B. However, the node for C in
735 od_fast_nodes is still at the old dict index of C. Thus to be sure
736 things don't get out of sync, we clear the node in od_fast_nodes
737 *before* calling PyDict_DelItem.
738
739 The same must be done for any other OrderedDict operations where
740 we modify od_fast_nodes.
741*/
742static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200743_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
744 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600745{
746 Py_ssize_t i;
747
748 assert(key != NULL);
749 if (_odict_EMPTY(od)) {
750 /* Let later code decide if this is a KeyError. */
751 return 0;
752 }
753
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200754 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600755 if (i < 0)
756 return PyErr_Occurred() ? -1 : 0;
757
758 if (node == NULL)
759 node = od->od_fast_nodes[i];
760 assert(node == od->od_fast_nodes[i]);
761 if (node == NULL) {
762 /* Let later code decide if this is a KeyError. */
763 return 0;
764 }
765
766 // Now clear the node.
767 od->od_fast_nodes[i] = NULL;
768 _odict_remove_node(od, node);
769 _odictnode_DEALLOC(node);
770 return 0;
771}
772
773static void
774_odict_clear_nodes(PyODictObject *od)
775{
776 _ODictNode *node, *next;
777
Eric Snow96c6af92015-05-29 22:21:39 -0600778 _odict_free_fast_nodes(od);
779 od->od_fast_nodes = NULL;
Serhiy Storchakad205d012016-01-19 14:46:25 +0200780
781 node = _odict_FIRST(od);
782 _odict_FIRST(od) = NULL;
783 _odict_LAST(od) = NULL;
784 while (node != NULL) {
785 next = _odictnode_NEXT(node);
786 _odictnode_DEALLOC(node);
787 node = next;
788 }
Eric Snow96c6af92015-05-29 22:21:39 -0600789}
790
791/* There isn't any memory management of nodes past this point. */
792#undef _odictnode_DEALLOC
793
794static int
795_odict_keys_equal(PyODictObject *a, PyODictObject *b)
796{
797 _ODictNode *node_a, *node_b;
798
799 node_a = _odict_FIRST(a);
800 node_b = _odict_FIRST(b);
801 while (1) {
802 if (node_a == NULL && node_b == NULL)
803 /* success: hit the end of each at the same time */
804 return 1;
805 else if (node_a == NULL || node_b == NULL)
806 /* unequal length */
807 return 0;
808 else {
809 int res = PyObject_RichCompareBool(
810 (PyObject *)_odictnode_KEY(node_a),
811 (PyObject *)_odictnode_KEY(node_b),
812 Py_EQ);
813 if (res < 0)
814 return res;
815 else if (res == 0)
816 return 0;
817
818 /* otherwise it must match, so move on to the next one */
819 node_a = _odictnode_NEXT(node_a);
820 node_b = _odictnode_NEXT(node_b);
821 }
822 }
823}
824
825
826/* ----------------------------------------------
827 * OrderedDict mapping methods
828 */
829
830/* mp_ass_subscript: __setitem__() and __delitem__() */
831
832static int
833odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)
834{
835 if (w == NULL)
836 return PyODict_DelItem((PyObject *)od, v);
837 else
838 return PyODict_SetItem((PyObject *)od, v, w);
839}
840
841/* tp_as_mapping */
842
843static PyMappingMethods odict_as_mapping = {
844 0, /*mp_length*/
845 0, /*mp_subscript*/
846 (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/
847};
848
849
850/* ----------------------------------------------
851 * OrderedDict methods
852 */
853
854/* __delitem__() */
855
856PyDoc_STRVAR(odict_delitem__doc__, "od.__delitem__(y) <==> del od[y]");
857
858/* __eq__() */
859
860PyDoc_STRVAR(odict_eq__doc__,
861"od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive \n\
862 while comparison to a regular mapping is order-insensitive.\n\
863 ");
864
865/* forward */
866static PyObject * odict_richcompare(PyObject *v, PyObject *w, int op);
867
868static PyObject *
869odict_eq(PyObject *a, PyObject *b)
870{
871 return odict_richcompare(a, b, Py_EQ);
872}
873
874/* __init__() */
875
876PyDoc_STRVAR(odict_init__doc__,
877"Initialize an ordered dictionary. The signature is the same as\n\
878 regular dictionaries, but keyword arguments are not recommended because\n\
879 their insertion order is arbitrary.\n\
880\n\
881 ");
882
883/* forward */
884static int odict_init(PyObject *self, PyObject *args, PyObject *kwds);
885
886/* __iter__() */
887
888PyDoc_STRVAR(odict_iter__doc__, "od.__iter__() <==> iter(od)");
889
890static PyObject * odict_iter(PyODictObject *self); /* forward */
891
892/* __ne__() */
893
894/* Mapping.__ne__() does not have a docstring. */
895PyDoc_STRVAR(odict_ne__doc__, "");
896
897static PyObject *
898odict_ne(PyObject *a, PyObject *b)
899{
900 return odict_richcompare(a, b, Py_NE);
901}
902
903/* __repr__() */
904
905PyDoc_STRVAR(odict_repr__doc__, "od.__repr__() <==> repr(od)");
906
907static PyObject * odict_repr(PyODictObject *self); /* forward */
908
909/* __setitem__() */
910
911PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y");
912
913/* fromkeys() */
914
915PyDoc_STRVAR(odict_fromkeys__doc__,
916"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\
917 If not specified, the value defaults to None.\n\
918\n\
919 ");
920
921static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -0600922odict_fromkeys(PyObject *cls, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -0600923{
Eric Snowac02ef32015-06-02 20:42:14 -0600924 static char *kwlist[] = {"iterable", "value", 0};
Eric Snow96c6af92015-05-29 22:21:39 -0600925 PyObject *seq;
926 PyObject *value = Py_None;
Eric Snowac02ef32015-06-02 20:42:14 -0600927
928 /* both borrowed */
929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:fromkeys", kwlist,
930 &seq, &value)) {
Eric Snow96c6af92015-05-29 22:21:39 -0600931 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -0600932 }
Eric Snow96c6af92015-05-29 22:21:39 -0600933 return _PyDict_FromKeys(cls, seq, value);
934}
935
936/* __sizeof__() */
937
938/* OrderedDict.__sizeof__() does not have a docstring. */
939PyDoc_STRVAR(odict_sizeof__doc__, "");
940
941static PyObject *
942odict_sizeof(PyODictObject *od)
943{
Serhiy Storchaka0ce7a3a2015-12-22 08:16:18 +0200944 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300945 res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
Eric Snow96c6af92015-05-29 22:21:39 -0600946 if (!_odict_EMPTY(od)) {
947 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
948 }
949 return PyLong_FromSsize_t(res);
950}
951
952/* __reduce__() */
953
954PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
955
956static PyObject *
957odict_reduce(register PyODictObject *od)
958{
959 _Py_IDENTIFIER(__dict__);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300960 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300961 PyObject *dict = NULL, *result = NULL;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300962 PyObject *items_iter, *items, *args = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600963
964 /* capture any instance state */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300965 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
966 if (dict == NULL)
Eric Snowc5e59602015-05-30 11:28:56 -0600967 goto Done;
968 else {
Eric Snow96c6af92015-05-29 22:21:39 -0600969 /* od.__dict__ isn't necessarily a dict... */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300970 Py_ssize_t dict_len = PyObject_Length(dict);
971 if (dict_len == -1)
Eric Snow96c6af92015-05-29 22:21:39 -0600972 goto Done;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300973 if (!dict_len) {
974 /* nothing to pickle in od.__dict__ */
975 Py_CLEAR(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600976 }
977 }
978
979 /* build the result */
Eric Snow96c6af92015-05-29 22:21:39 -0600980 args = PyTuple_New(0);
981 if (args == NULL)
982 goto Done;
983
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300984 items = _PyObject_CallMethodIdObjArgs((PyObject *)od, &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -0600985 if (items == NULL)
986 goto Done;
987
988 items_iter = PyObject_GetIter(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300989 Py_DECREF(items);
Eric Snow96c6af92015-05-29 22:21:39 -0600990 if (items_iter == NULL)
991 goto Done;
992
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300993 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300994 Py_DECREF(items_iter);
Eric Snow96c6af92015-05-29 22:21:39 -0600995
996Done:
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300997 Py_XDECREF(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600998 Py_XDECREF(args);
Eric Snow96c6af92015-05-29 22:21:39 -0600999
1000 return result;
1001}
1002
1003/* setdefault() */
1004
1005PyDoc_STRVAR(odict_setdefault__doc__,
1006 "od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od");
1007
1008/* Skips __missing__() calls. */
1009static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001010odict_setdefault(register PyODictObject *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, *result = NULL;
1014 PyObject *failobj = Py_None;
1015
1016 /* both borrowed */
Eric Snowac02ef32015-06-02 20:42:14 -06001017 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:setdefault", kwlist,
1018 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001019 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001020 }
Eric Snow96c6af92015-05-29 22:21:39 -06001021
1022 if (PyODict_CheckExact(od)) {
Eric Snowd1719752015-06-01 23:12:13 -06001023 result = PyODict_GetItemWithError(od, key); /* borrowed */
1024 if (result == NULL) {
1025 if (PyErr_Occurred())
1026 return NULL;
1027 assert(_odict_find_node(od, key) == NULL);
1028 if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) {
Eric Snow96c6af92015-05-29 22:21:39 -06001029 result = failobj;
1030 Py_INCREF(failobj);
1031 }
1032 }
1033 else {
Eric Snowd1719752015-06-01 23:12:13 -06001034 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -06001035 }
1036 }
1037 else {
1038 int exists = PySequence_Contains((PyObject *)od, key);
1039 if (exists < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001040 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001041 }
1042 else if (exists) {
1043 result = PyObject_GetItem((PyObject *)od, key);
1044 }
1045 else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) {
1046 result = failobj;
1047 Py_INCREF(failobj);
1048 }
1049 }
1050
Eric Snow96c6af92015-05-29 22:21:39 -06001051 return result;
1052}
1053
1054/* pop() */
1055
1056PyDoc_STRVAR(odict_pop__doc__,
1057"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1058 value. If key is not found, d is returned if given, otherwise KeyError\n\
1059 is raised.\n\
1060\n\
1061 ");
1062
1063/* forward */
1064static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1065
1066/* Skips __missing__() calls. */
1067static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001068odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001069{
Eric Snowac02ef32015-06-02 20:42:14 -06001070 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001071 PyObject *key, *failobj = NULL;
1072
Eric Snowac02ef32015-06-02 20:42:14 -06001073 /* borrowed */
1074 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1075 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001076 return NULL;
1077 }
1078
1079 return _odict_popkey(od, key, failobj);
1080}
1081
1082static PyObject *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001083_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1084 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -06001085{
1086 _ODictNode *node;
1087 PyObject *value = NULL;
1088
Eric Snow96c6af92015-05-29 22:21:39 -06001089 /* Pop the node first to avoid a possible dict resize (due to
1090 eval loop reentrancy) and complications due to hash collision
1091 resolution. */
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001092 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001093 if (node == NULL) {
1094 if (PyErr_Occurred())
Eric Snowd1719752015-06-01 23:12:13 -06001095 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001096 }
1097 else {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001098 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001099 if (res < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001100 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001101 }
1102 }
1103
1104 /* Now delete the value from the dict. */
Serhiy Storchaka04386832016-10-30 17:17:24 +02001105 if (PyODict_CheckExact(od)) {
1106 if (node != NULL) {
1107 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1108 if (value != NULL) {
1109 Py_INCREF(value);
1110 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1111 Py_DECREF(value);
1112 return NULL;
1113 }
1114 }
1115 }
1116 }
1117 else {
1118 int exists = PySequence_Contains(od, key);
1119 if (exists < 0)
1120 return NULL;
1121 if (exists) {
1122 value = PyObject_GetItem(od, key);
1123 if (value != NULL) {
1124 if (PyObject_DelItem(od, key) == -1) {
1125 Py_CLEAR(value);
1126 }
Eric Snow96c6af92015-05-29 22:21:39 -06001127 }
1128 }
1129 }
1130
1131 /* Apply the fallback value, if necessary. */
1132 if (value == NULL && !PyErr_Occurred()) {
1133 if (failobj) {
1134 value = failobj;
1135 Py_INCREF(failobj);
1136 }
1137 else {
1138 PyErr_SetObject(PyExc_KeyError, key);
1139 }
1140 }
1141
Eric Snow96c6af92015-05-29 22:21:39 -06001142 return value;
1143}
1144
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001145static PyObject *
1146_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1147{
1148 Py_hash_t hash = PyObject_Hash(key);
1149 if (hash == -1)
1150 return NULL;
1151
1152 return _odict_popkey_hash(od, key, failobj, hash);
1153}
1154
Eric Snow96c6af92015-05-29 22:21:39 -06001155/* popitem() */
1156
1157PyDoc_STRVAR(odict_popitem__doc__,
1158"od.popitem() -> (k, v), return and remove a (key, value) pair.\n\
1159 Pairs are returned in LIFO order if last is true or FIFO order if false.\n\
1160\n\
1161 ");
1162
1163static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001164odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001165{
Eric Snowac02ef32015-06-02 20:42:14 -06001166 static char *kwlist[] = {"last", 0};
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001167 PyObject *key, *value, *item = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001168 _ODictNode *node;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001169 int last = 1;
Eric Snow96c6af92015-05-29 22:21:39 -06001170
1171 /* pull the item */
1172
Eric Snowac02ef32015-06-02 20:42:14 -06001173 /* borrowed */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001174 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:popitem", kwlist,
Eric Snowac02ef32015-06-02 20:42:14 -06001175 &last)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001176 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001177 }
Eric Snow96c6af92015-05-29 22:21:39 -06001178
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001179 if (_odict_EMPTY(od)) {
1180 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1181 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001182 }
Eric Snow96c6af92015-05-29 22:21:39 -06001183
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001184 node = last ? _odict_LAST(od) : _odict_FIRST(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001185 key = _odictnode_KEY(node);
Eric Snowd1719752015-06-01 23:12:13 -06001186 Py_INCREF(key);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001187 value = _odict_popkey_hash(od, key, NULL, _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -06001188 if (value == NULL)
1189 return NULL;
1190 item = PyTuple_Pack(2, key, value);
Eric Snowd1719752015-06-01 23:12:13 -06001191 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001192 Py_DECREF(value);
1193 return item;
1194}
1195
1196/* keys() */
1197
1198/* MutableMapping.keys() does not have a docstring. */
1199PyDoc_STRVAR(odict_keys__doc__, "");
1200
1201static PyObject * odictkeys_new(PyObject *od); /* forward */
1202
1203/* values() */
1204
1205/* MutableMapping.values() does not have a docstring. */
1206PyDoc_STRVAR(odict_values__doc__, "");
1207
1208static PyObject * odictvalues_new(PyObject *od); /* forward */
1209
1210/* items() */
1211
1212/* MutableMapping.items() does not have a docstring. */
1213PyDoc_STRVAR(odict_items__doc__, "");
1214
1215static PyObject * odictitems_new(PyObject *od); /* forward */
1216
1217/* update() */
1218
1219/* MutableMapping.update() does not have a docstring. */
1220PyDoc_STRVAR(odict_update__doc__, "");
1221
1222/* forward */
1223static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1224
1225#define odict_update mutablemapping_update
1226
1227/* clear() */
1228
1229PyDoc_STRVAR(odict_clear__doc__,
1230 "od.clear() -> None. Remove all items from od.");
1231
1232static PyObject *
1233odict_clear(register PyODictObject *od)
1234{
1235 PyDict_Clear((PyObject *)od);
1236 _odict_clear_nodes(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001237 if (_odict_resize(od) < 0)
1238 return NULL;
1239 Py_RETURN_NONE;
1240}
1241
1242/* copy() */
1243
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001244/* forward */
1245static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1246 Py_hash_t);
1247
Eric Snow96c6af92015-05-29 22:21:39 -06001248PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1249
1250static PyObject *
1251odict_copy(register PyODictObject *od)
1252{
1253 _ODictNode *node;
1254 PyObject *od_copy;
1255
1256 if (PyODict_CheckExact(od))
1257 od_copy = PyODict_New();
1258 else
1259 od_copy = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(od), NULL);
1260 if (od_copy == NULL)
1261 return NULL;
1262
1263 if (PyODict_CheckExact(od)) {
1264 _odict_FOREACH(od, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001265 PyObject *key = _odictnode_KEY(node);
1266 PyObject *value = _odictnode_VALUE(node, od);
1267 if (value == NULL) {
1268 if (!PyErr_Occurred())
1269 PyErr_SetObject(PyExc_KeyError, key);
1270 goto fail;
1271 }
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001272 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1273 _odictnode_HASH(node)) != 0)
Eric Snow96c6af92015-05-29 22:21:39 -06001274 goto fail;
1275 }
1276 }
1277 else {
1278 _odict_FOREACH(od, node) {
1279 int res;
1280 PyObject *value = PyObject_GetItem((PyObject *)od,
1281 _odictnode_KEY(node));
1282 if (value == NULL)
1283 goto fail;
1284 res = PyObject_SetItem((PyObject *)od_copy,
1285 _odictnode_KEY(node), value);
1286 Py_DECREF(value);
1287 if (res != 0)
1288 goto fail;
1289 }
1290 }
1291 return od_copy;
1292
1293fail:
1294 Py_DECREF(od_copy);
1295 return NULL;
1296}
1297
1298/* __reversed__() */
1299
1300PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1301
1302#define _odict_ITER_REVERSED 1
1303#define _odict_ITER_KEYS 2
1304#define _odict_ITER_VALUES 4
1305
1306/* forward */
1307static PyObject * odictiter_new(PyODictObject *, int);
1308
1309static PyObject *
1310odict_reversed(PyODictObject *od)
1311{
Eric Snow96c6af92015-05-29 22:21:39 -06001312 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1313}
1314
1315/* move_to_end() */
1316
1317PyDoc_STRVAR(odict_move_to_end__doc__,
1318"Move an existing element to the end (or beginning if last==False).\n\
1319\n\
1320 Raises KeyError if the element does not exist.\n\
1321 When last=True, acts like a fast version of self[key]=self.pop(key).\n\
1322\n\
1323 ");
1324
1325static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001326odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001327{
Eric Snowac02ef32015-06-02 20:42:14 -06001328 static char *kwlist[] = {"key", "last", 0};
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001329 PyObject *key;
1330 int last = 1;
1331 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001332
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|p:move_to_end", kwlist,
Eric Snowac02ef32015-06-02 20:42:14 -06001334 &key, &last)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001335 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001336 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001337
Eric Snow96c6af92015-05-29 22:21:39 -06001338 if (_odict_EMPTY(od)) {
1339 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001340 return NULL;
1341 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001342 node = last ? _odict_LAST(od) : _odict_FIRST(od);
1343 if (key != _odictnode_KEY(node)) {
1344 node = _odict_find_node(od, key);
1345 if (node == NULL) {
1346 if (!PyErr_Occurred())
1347 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowc5e59602015-05-30 11:28:56 -06001348 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001349 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001350 if (last) {
1351 /* Only move if not already the last one. */
1352 if (node != _odict_LAST(od)) {
1353 _odict_remove_node(od, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001354 _odict_add_tail(od, node);
1355 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001356 }
1357 else {
1358 /* Only move if not already the first one. */
1359 if (node != _odict_FIRST(od)) {
1360 _odict_remove_node(od, node);
1361 _odict_add_head(od, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001362 }
1363 }
1364 }
Eric Snow96c6af92015-05-29 22:21:39 -06001365 Py_RETURN_NONE;
1366}
1367
1368
1369/* tp_methods */
1370
1371static PyMethodDef odict_methods[] = {
1372
1373 /* explicitly defined so we can align docstrings with
1374 * collections.OrderedDict */
1375 {"__delitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
1376 odict_delitem__doc__},
1377 {"__eq__", (PyCFunction)odict_eq, METH_NOARGS,
1378 odict_eq__doc__},
1379 {"__init__", (PyCFunction)odict_init, METH_NOARGS,
1380 odict_init__doc__},
1381 {"__iter__", (PyCFunction)odict_iter, METH_NOARGS,
1382 odict_iter__doc__},
1383 {"__ne__", (PyCFunction)odict_ne, METH_NOARGS,
1384 odict_ne__doc__},
1385 {"__repr__", (PyCFunction)odict_repr, METH_NOARGS,
1386 odict_repr__doc__},
1387 {"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
1388 odict_setitem__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001389 {"fromkeys", (PyCFunction)odict_fromkeys,
1390 METH_VARARGS | METH_KEYWORDS | METH_CLASS, odict_fromkeys__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001391
1392 /* overridden dict methods */
1393 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1394 odict_sizeof__doc__},
1395 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1396 odict_reduce__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001397 {"setdefault", (PyCFunction)odict_setdefault,
1398 METH_VARARGS | METH_KEYWORDS, odict_setdefault__doc__},
1399 {"pop", (PyCFunction)odict_pop,
1400 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
1401 {"popitem", (PyCFunction)odict_popitem,
1402 METH_VARARGS | METH_KEYWORDS, odict_popitem__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001403 {"keys", (PyCFunction)odictkeys_new, METH_NOARGS,
1404 odict_keys__doc__},
1405 {"values", (PyCFunction)odictvalues_new, METH_NOARGS,
1406 odict_values__doc__},
1407 {"items", (PyCFunction)odictitems_new, METH_NOARGS,
1408 odict_items__doc__},
1409 {"update", (PyCFunction)odict_update, METH_VARARGS | METH_KEYWORDS,
1410 odict_update__doc__},
1411 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1412 odict_clear__doc__},
1413 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1414 odict_copy__doc__},
1415
1416 /* new methods */
1417 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1418 odict_reversed__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001419 {"move_to_end", (PyCFunction)odict_move_to_end,
1420 METH_VARARGS | METH_KEYWORDS, odict_move_to_end__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001421
1422 {NULL, NULL} /* sentinel */
1423};
1424
1425
1426/* ----------------------------------------------
1427 * OrderedDict members
1428 */
1429
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001430/* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001431
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001432static PyGetSetDef odict_getset[] = {
1433 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1434 {NULL}
Eric Snow96c6af92015-05-29 22:21:39 -06001435};
1436
Eric Snow96c6af92015-05-29 22:21:39 -06001437/* ----------------------------------------------
1438 * OrderedDict type slot methods
1439 */
1440
1441/* tp_dealloc */
1442
1443static void
1444odict_dealloc(PyODictObject *self)
1445{
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001446 PyThreadState *tstate = PyThreadState_GET();
1447
Eric Snow96c6af92015-05-29 22:21:39 -06001448 PyObject_GC_UnTrack(self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001449 Py_TRASHCAN_SAFE_BEGIN(self)
1450
Eric Snow96c6af92015-05-29 22:21:39 -06001451 Py_XDECREF(self->od_inst_dict);
1452 if (self->od_weakreflist != NULL)
1453 PyObject_ClearWeakRefs((PyObject *)self);
1454
1455 _odict_clear_nodes(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001456
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001457 /* Call the base tp_dealloc(). Since it too uses the trashcan mechanism,
1458 * temporarily decrement trash_delete_nesting to prevent triggering it
1459 * and putting the partially deallocated object on the trashcan's
1460 * to-be-deleted-later list.
1461 */
1462 --tstate->trash_delete_nesting;
1463 assert(_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL);
Eric Snow96c6af92015-05-29 22:21:39 -06001464 PyDict_Type.tp_dealloc((PyObject *)self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001465 ++tstate->trash_delete_nesting;
1466
1467 Py_TRASHCAN_SAFE_END(self)
Victor Stinnere1871952016-06-08 10:18:18 +02001468}
Eric Snow96c6af92015-05-29 22:21:39 -06001469
1470/* tp_repr */
1471
1472static PyObject *
1473odict_repr(PyODictObject *self)
1474{
1475 int i;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001476 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001477 PyObject *pieces = NULL, *result = NULL;
1478 const char *classname;
1479
1480 classname = strrchr(Py_TYPE(self)->tp_name, '.');
1481 if (classname == NULL)
1482 classname = Py_TYPE(self)->tp_name;
1483 else
1484 classname++;
1485
1486 if (PyODict_SIZE(self) == 0)
1487 return PyUnicode_FromFormat("%s()", classname);
Eric Snow96c6af92015-05-29 22:21:39 -06001488
1489 i = Py_ReprEnter((PyObject *)self);
1490 if (i != 0) {
1491 return i > 0 ? PyUnicode_FromString("...") : NULL;
1492 }
1493
Eric Snow96c6af92015-05-29 22:21:39 -06001494 if (PyODict_CheckExact(self)) {
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001495 Py_ssize_t count = 0;
Eric Snowa762af72015-06-01 22:59:08 -06001496 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001497 pieces = PyList_New(PyODict_SIZE(self));
1498 if (pieces == NULL)
1499 goto Done;
1500
1501 _odict_FOREACH(self, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001502 PyObject *pair;
1503 PyObject *key = _odictnode_KEY(node);
1504 PyObject *value = _odictnode_VALUE(node, self);
1505 if (value == NULL) {
1506 if (!PyErr_Occurred())
1507 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowdb4061c2015-06-03 11:09:48 -06001508 goto Done;
Eric Snowa762af72015-06-01 22:59:08 -06001509 }
1510 pair = PyTuple_Pack(2, key, value);
Eric Snow96c6af92015-05-29 22:21:39 -06001511 if (pair == NULL)
1512 goto Done;
1513
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001514 if (count < PyList_GET_SIZE(pieces))
1515 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1516 else {
1517 if (PyList_Append(pieces, pair) < 0) {
1518 Py_DECREF(pair);
1519 goto Done;
1520 }
1521 Py_DECREF(pair);
1522 }
1523 count++;
Eric Snow96c6af92015-05-29 22:21:39 -06001524 }
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001525 if (count < PyList_GET_SIZE(pieces))
1526 PyList_GET_SIZE(pieces) = count;
Eric Snow96c6af92015-05-29 22:21:39 -06001527 }
1528 else {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001529 PyObject *items = _PyObject_CallMethodIdObjArgs((PyObject *)self,
1530 &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -06001531 if (items == NULL)
1532 goto Done;
1533 pieces = PySequence_List(items);
1534 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001535 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001536 goto Done;
1537 }
1538
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001539 result = PyUnicode_FromFormat("%s(%R)", classname, pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001540
Eric Snow96c6af92015-05-29 22:21:39 -06001541Done:
1542 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001543 Py_ReprLeave((PyObject *)self);
1544 return result;
Victor Stinnere1871952016-06-08 10:18:18 +02001545}
Eric Snow96c6af92015-05-29 22:21:39 -06001546
1547/* tp_doc */
1548
1549PyDoc_STRVAR(odict_doc,
1550 "Dictionary that remembers insertion order");
1551
1552/* tp_traverse */
1553
1554static int
1555odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1556{
Serhiy Storchakad205d012016-01-19 14:46:25 +02001557 _ODictNode *node;
1558
Eric Snow96c6af92015-05-29 22:21:39 -06001559 Py_VISIT(od->od_inst_dict);
1560 Py_VISIT(od->od_weakreflist);
Serhiy Storchakad205d012016-01-19 14:46:25 +02001561 _odict_FOREACH(od, node) {
1562 Py_VISIT(_odictnode_KEY(node));
1563 }
Eric Snow96c6af92015-05-29 22:21:39 -06001564 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1565}
1566
1567/* tp_clear */
1568
1569static int
1570odict_tp_clear(PyODictObject *od)
1571{
1572 PyObject *res;
1573 Py_CLEAR(od->od_inst_dict);
1574 Py_CLEAR(od->od_weakreflist);
1575 res = odict_clear(od);
1576 if (res == NULL)
1577 return -1;
1578 Py_DECREF(res);
1579 return 0;
1580}
1581
1582/* tp_richcompare */
1583
1584static PyObject *
1585odict_richcompare(PyObject *v, PyObject *w, int op)
1586{
1587 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1588 Py_RETURN_NOTIMPLEMENTED;
1589 }
1590
1591 if (op == Py_EQ || op == Py_NE) {
1592 PyObject *res, *cmp;
1593 int eq;
1594
1595 cmp = PyDict_Type.tp_richcompare(v, w, op);
1596 if (cmp == NULL)
1597 return NULL;
1598 if (!PyODict_Check(w))
1599 return cmp;
1600 if (op == Py_EQ && cmp == Py_False)
1601 return cmp;
1602 if (op == Py_NE && cmp == Py_True)
1603 return cmp;
1604 Py_DECREF(cmp);
1605
1606 /* Try comparing odict keys. */
1607 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1608 if (eq < 0)
1609 return NULL;
1610
1611 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1612 Py_INCREF(res);
1613 return res;
1614 } else {
1615 Py_RETURN_NOTIMPLEMENTED;
1616 }
Victor Stinnere1871952016-06-08 10:18:18 +02001617}
Eric Snow96c6af92015-05-29 22:21:39 -06001618
1619/* tp_iter */
1620
1621static PyObject *
1622odict_iter(PyODictObject *od)
1623{
1624 return odictiter_new(od, _odict_ITER_KEYS);
Victor Stinnere1871952016-06-08 10:18:18 +02001625}
Eric Snow96c6af92015-05-29 22:21:39 -06001626
1627/* tp_init */
1628
1629static int
1630odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1631{
1632 PyObject *res;
1633 Py_ssize_t len = PyObject_Length(args);
1634
1635 if (len == -1)
1636 return -1;
1637 if (len > 1) {
1638 char *msg = "expected at most 1 arguments, got %d";
1639 PyErr_Format(PyExc_TypeError, msg, len);
1640 return -1;
1641 }
1642
1643 /* __init__() triggering update() is just the way things are! */
1644 res = odict_update(self, args, kwds);
1645 if (res == NULL) {
1646 return -1;
1647 } else {
1648 Py_DECREF(res);
1649 return 0;
1650 }
Victor Stinnere1871952016-06-08 10:18:18 +02001651}
Eric Snow96c6af92015-05-29 22:21:39 -06001652
1653/* tp_new */
1654
1655static PyObject *
1656odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1657{
Victor Stinnerca30b022015-09-03 17:50:04 +02001658 PyODictObject *od;
1659
Victor Stinnerca30b022015-09-03 17:50:04 +02001660 od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001661 if (od == NULL)
Victor Stinnerca30b022015-09-03 17:50:04 +02001662 return NULL;
Victor Stinnerca30b022015-09-03 17:50:04 +02001663
Victor Stinnerca30b022015-09-03 17:50:04 +02001664 /* type constructor fills the memory with zeros (see
1665 PyType_GenericAlloc()), there is no need to set them to zero again */
1666 if (_odict_resize(od) < 0) {
1667 Py_DECREF(od);
1668 return NULL;
1669 }
1670
1671 return (PyObject*)od;
Eric Snow96c6af92015-05-29 22:21:39 -06001672}
1673
1674/* PyODict_Type */
1675
1676PyTypeObject PyODict_Type = {
1677 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1678 "collections.OrderedDict", /* tp_name */
1679 sizeof(PyODictObject), /* tp_basicsize */
1680 0, /* tp_itemsize */
1681 (destructor)odict_dealloc, /* tp_dealloc */
1682 0, /* tp_print */
1683 0, /* tp_getattr */
1684 0, /* tp_setattr */
1685 0, /* tp_reserved */
1686 (reprfunc)odict_repr, /* tp_repr */
1687 0, /* tp_as_number */
1688 0, /* tp_as_sequence */
1689 &odict_as_mapping, /* tp_as_mapping */
1690 0, /* tp_hash */
1691 0, /* tp_call */
1692 0, /* tp_str */
1693 0, /* tp_getattro */
1694 0, /* tp_setattro */
1695 0, /* tp_as_buffer */
1696 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1697 odict_doc, /* tp_doc */
1698 (traverseproc)odict_traverse, /* tp_traverse */
1699 (inquiry)odict_tp_clear, /* tp_clear */
1700 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1701 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1702 (getiterfunc)odict_iter, /* tp_iter */
1703 0, /* tp_iternext */
1704 odict_methods, /* tp_methods */
Serhiy Storchakad2962f12016-02-08 16:39:05 +02001705 0, /* tp_members */
1706 odict_getset, /* tp_getset */
Eric Snow96c6af92015-05-29 22:21:39 -06001707 &PyDict_Type, /* tp_base */
1708 0, /* tp_dict */
1709 0, /* tp_descr_get */
1710 0, /* tp_descr_set */
1711 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1712 (initproc)odict_init, /* tp_init */
1713 PyType_GenericAlloc, /* tp_alloc */
1714 (newfunc)odict_new, /* tp_new */
1715 0, /* tp_free */
1716};
1717
1718
1719/* ----------------------------------------------
1720 * the public OrderedDict API
1721 */
1722
1723PyObject *
1724PyODict_New(void) {
1725 return odict_new(&PyODict_Type, NULL, NULL);
Victor Stinnere1871952016-06-08 10:18:18 +02001726}
Eric Snow96c6af92015-05-29 22:21:39 -06001727
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001728static int
1729_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1730 Py_hash_t hash)
1731{
1732 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001733 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001734 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001735 if (res < 0) {
1736 /* Revert setting the value on the dict */
1737 PyObject *exc, *val, *tb;
1738 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001739 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001740 _PyErr_ChainExceptions(exc, val, tb);
1741 }
Eric Snow96c6af92015-05-29 22:21:39 -06001742 }
1743 return res;
Victor Stinnere1871952016-06-08 10:18:18 +02001744}
Eric Snow96c6af92015-05-29 22:21:39 -06001745
1746int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001747PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1748{
1749 Py_hash_t hash = PyObject_Hash(key);
1750 if (hash == -1)
1751 return -1;
1752 return _PyODict_SetItem_KnownHash(od, key, value, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001753}
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001754
1755int
1756PyODict_DelItem(PyObject *od, PyObject *key)
1757{
1758 int res;
1759 Py_hash_t hash = PyObject_Hash(key);
1760 if (hash == -1)
1761 return -1;
1762 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001763 if (res < 0)
1764 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001765 return _PyDict_DelItem_KnownHash(od, key, hash);
Victor Stinnere1871952016-06-08 10:18:18 +02001766}
Eric Snow96c6af92015-05-29 22:21:39 -06001767
1768
1769/* -------------------------------------------
1770 * The OrderedDict views (keys/values/items)
1771 */
1772
1773typedef struct {
1774 PyObject_HEAD
1775 int kind;
1776 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001777 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001778 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001779 PyObject *di_current;
1780 PyObject *di_result; /* reusable result tuple for iteritems */
1781} odictiterobject;
1782
1783static void
1784odictiter_dealloc(odictiterobject *di)
1785{
1786 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001787 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001788 Py_XDECREF(di->di_current);
1789 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1790 Py_DECREF(di->di_result);
1791 }
1792 PyObject_GC_Del(di);
1793}
1794
1795static int
1796odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1797{
1798 Py_VISIT(di->di_odict);
1799 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1800 Py_VISIT(di->di_result);
1801 return 0;
1802}
1803
Eric Snowa762af72015-06-01 22:59:08 -06001804/* In order to protect against modifications during iteration, we track
1805 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001806static PyObject *
1807odictiter_nextkey(odictiterobject *di)
1808{
Eric Snowa762af72015-06-01 22:59:08 -06001809 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001810 _ODictNode *node;
1811 int reversed = di->kind & _odict_ITER_REVERSED;
1812
Eric Snowa762af72015-06-01 22:59:08 -06001813 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001814 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001815 if (di->di_current == NULL)
1816 goto done; /* We're already done. */
1817
Eric Snowb952ab42015-06-01 23:35:13 -06001818 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001819 if (di->di_odict->od_state != di->di_state) {
1820 PyErr_SetString(PyExc_RuntimeError,
1821 "OrderedDict mutated during iteration");
1822 goto done;
1823 }
Eric Snowb952ab42015-06-01 23:35:13 -06001824 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1825 PyErr_SetString(PyExc_RuntimeError,
1826 "OrderedDict changed size during iteration");
1827 di->di_size = -1; /* Make this state sticky */
1828 return NULL;
1829 }
1830
Eric Snowa762af72015-06-01 22:59:08 -06001831 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001832 node = _odict_find_node(di->di_odict, di->di_current);
1833 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001834 if (!PyErr_Occurred())
1835 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001836 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001837 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001838 return NULL;
1839 }
1840 key = di->di_current;
1841
1842 /* Advance to the next key. */
1843 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1844 if (node == NULL) {
1845 /* Reached the end. */
1846 di->di_current = NULL;
1847 }
1848 else {
1849 di->di_current = _odictnode_KEY(node);
1850 Py_INCREF(di->di_current);
1851 }
1852
1853 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001854
1855done:
1856 Py_CLEAR(di->di_odict);
1857 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001858}
1859
1860static PyObject *
1861odictiter_iternext(odictiterobject *di)
1862{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001863 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001864 PyObject *key = odictiter_nextkey(di); /* new reference */
1865
1866 if (key == NULL)
1867 return NULL;
1868
1869 /* Handle the keys case. */
1870 if (! (di->kind & _odict_ITER_VALUES)) {
1871 return key;
1872 }
1873
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001874 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1875 if (value == NULL) {
1876 if (!PyErr_Occurred())
1877 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001878 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001879 goto done;
1880 }
1881 Py_INCREF(value);
1882
1883 /* Handle the values case. */
1884 if (!(di->kind & _odict_ITER_KEYS)) {
1885 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001886 return value;
1887 }
Eric Snowa762af72015-06-01 22:59:08 -06001888
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001889 /* Handle the items case. */
1890 result = di->di_result;
1891
1892 if (Py_REFCNT(result) == 1) {
1893 /* not in use so we can reuse it
1894 * (the common case during iteration) */
1895 Py_INCREF(result);
1896 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1897 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1898 }
1899 else {
1900 result = PyTuple_New(2);
1901 if (result == NULL) {
1902 Py_DECREF(key);
1903 Py_DECREF(value);
1904 goto done;
1905 }
1906 }
1907
1908 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1909 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1910 return result;
1911
Eric Snowa762af72015-06-01 22:59:08 -06001912done:
1913 Py_CLEAR(di->di_current);
1914 Py_CLEAR(di->di_odict);
1915 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001916}
1917
1918/* No need for tp_clear because odictiterobject is not mutable. */
1919
1920PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1921
1922static PyObject *
1923odictiter_reduce(odictiterobject *di)
1924{
Eric Snowc5e59602015-05-30 11:28:56 -06001925 PyObject *list, *iter;
Eric Snow96c6af92015-05-29 22:21:39 -06001926
1927 list = PyList_New(0);
1928 if (!list)
1929 return NULL;
1930
1931 /* iterate the temporary into a list */
1932 for(;;) {
1933 PyObject *element = odictiter_iternext(di);
1934 if (element) {
1935 if (PyList_Append(list, element)) {
1936 Py_DECREF(element);
1937 Py_DECREF(list);
1938 return NULL;
1939 }
1940 Py_DECREF(element);
1941 }
1942 else {
1943 /* done iterating? */
1944 break;
1945 }
1946 }
1947 if (PyErr_Occurred()) {
1948 Py_DECREF(list);
1949 return NULL;
1950 }
Eric Snowc5e59602015-05-30 11:28:56 -06001951 iter = _PyObject_GetBuiltin("iter");
1952 if (iter == NULL) {
1953 Py_DECREF(list);
1954 return NULL;
1955 }
1956 return Py_BuildValue("N(N)", iter, list);
Eric Snow96c6af92015-05-29 22:21:39 -06001957}
1958
1959static PyMethodDef odictiter_methods[] = {
1960 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1961 {NULL, NULL} /* sentinel */
1962};
1963
1964PyTypeObject PyODictIter_Type = {
1965 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1966 "odict_iterator", /* tp_name */
1967 sizeof(odictiterobject), /* tp_basicsize */
1968 0, /* tp_itemsize */
1969 /* methods */
1970 (destructor)odictiter_dealloc, /* tp_dealloc */
1971 0, /* tp_print */
1972 0, /* tp_getattr */
1973 0, /* tp_setattr */
1974 0, /* tp_reserved */
1975 0, /* tp_repr */
1976 0, /* tp_as_number */
1977 0, /* tp_as_sequence */
1978 0, /* tp_as_mapping */
1979 0, /* tp_hash */
1980 0, /* tp_call */
1981 0, /* tp_str */
1982 PyObject_GenericGetAttr, /* tp_getattro */
1983 0, /* tp_setattro */
1984 0, /* tp_as_buffer */
1985 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1986 0, /* tp_doc */
1987 (traverseproc)odictiter_traverse, /* tp_traverse */
1988 0, /* tp_clear */
1989 0, /* tp_richcompare */
1990 0, /* tp_weaklistoffset */
1991 PyObject_SelfIter, /* tp_iter */
1992 (iternextfunc)odictiter_iternext, /* tp_iternext */
1993 odictiter_methods, /* tp_methods */
1994 0,
1995};
1996
1997static PyObject *
1998odictiter_new(PyODictObject *od, int kind)
1999{
2000 odictiterobject *di;
2001 _ODictNode *node;
2002 int reversed = kind & _odict_ITER_REVERSED;
2003
2004 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
2005 if (di == NULL)
2006 return NULL;
2007
2008 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
2009 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
2010 if (di->di_result == NULL) {
2011 Py_DECREF(di);
2012 return NULL;
2013 }
2014 }
2015 else
2016 di->di_result = NULL;
2017
2018 di->kind = kind;
2019 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
2020 di->di_current = node ? _odictnode_KEY(node) : NULL;
2021 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06002022 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06002023 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06002024 di->di_odict = od;
2025 Py_INCREF(od);
2026
2027 _PyObject_GC_TRACK(di);
2028 return (PyObject *)di;
2029}
2030
2031/* keys() */
2032
2033static PyObject *
2034odictkeys_iter(_PyDictViewObject *dv)
2035{
2036 if (dv->dv_dict == NULL) {
2037 Py_RETURN_NONE;
2038 }
2039 return odictiter_new((PyODictObject *)dv->dv_dict,
2040 _odict_ITER_KEYS);
2041}
2042
2043static PyObject *
2044odictkeys_reversed(_PyDictViewObject *dv)
2045{
2046 if (dv->dv_dict == NULL) {
2047 Py_RETURN_NONE;
2048 }
2049 return odictiter_new((PyODictObject *)dv->dv_dict,
2050 _odict_ITER_KEYS|_odict_ITER_REVERSED);
2051}
2052
2053static PyMethodDef odictkeys_methods[] = {
2054 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
2055 {NULL, NULL} /* sentinel */
2056};
2057
2058PyTypeObject PyODictKeys_Type = {
2059 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2060 "odict_keys", /* tp_name */
2061 0, /* tp_basicsize */
2062 0, /* tp_itemsize */
2063 0, /* tp_dealloc */
2064 0, /* tp_print */
2065 0, /* tp_getattr */
2066 0, /* tp_setattr */
2067 0, /* tp_reserved */
2068 0, /* tp_repr */
2069 0, /* tp_as_number */
2070 0, /* tp_as_sequence */
2071 0, /* tp_as_mapping */
2072 0, /* tp_hash */
2073 0, /* tp_call */
2074 0, /* tp_str */
2075 0, /* tp_getattro */
2076 0, /* tp_setattro */
2077 0, /* tp_as_buffer */
2078 0, /* tp_flags */
2079 0, /* tp_doc */
2080 0, /* tp_traverse */
2081 0, /* tp_clear */
2082 0, /* tp_richcompare */
2083 0, /* tp_weaklistoffset */
2084 (getiterfunc)odictkeys_iter, /* tp_iter */
2085 0, /* tp_iternext */
2086 odictkeys_methods, /* tp_methods */
2087 0, /* tp_members */
2088 0, /* tp_getset */
2089 &PyDictKeys_Type, /* tp_base */
2090};
2091
2092static PyObject *
2093odictkeys_new(PyObject *od)
2094{
2095 return _PyDictView_New(od, &PyODictKeys_Type);
2096}
2097
2098/* items() */
2099
2100static PyObject *
2101odictitems_iter(_PyDictViewObject *dv)
2102{
2103 if (dv->dv_dict == NULL) {
2104 Py_RETURN_NONE;
2105 }
2106 return odictiter_new((PyODictObject *)dv->dv_dict,
2107 _odict_ITER_KEYS|_odict_ITER_VALUES);
2108}
2109
2110static PyObject *
2111odictitems_reversed(_PyDictViewObject *dv)
2112{
2113 if (dv->dv_dict == NULL) {
2114 Py_RETURN_NONE;
2115 }
2116 return odictiter_new((PyODictObject *)dv->dv_dict,
2117 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2118}
2119
2120static PyMethodDef odictitems_methods[] = {
2121 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
2122 {NULL, NULL} /* sentinel */
2123};
2124
2125PyTypeObject PyODictItems_Type = {
2126 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2127 "odict_items", /* tp_name */
2128 0, /* tp_basicsize */
2129 0, /* tp_itemsize */
2130 0, /* tp_dealloc */
2131 0, /* tp_print */
2132 0, /* tp_getattr */
2133 0, /* tp_setattr */
2134 0, /* tp_reserved */
2135 0, /* tp_repr */
2136 0, /* tp_as_number */
2137 0, /* tp_as_sequence */
2138 0, /* tp_as_mapping */
2139 0, /* tp_hash */
2140 0, /* tp_call */
2141 0, /* tp_str */
2142 0, /* tp_getattro */
2143 0, /* tp_setattro */
2144 0, /* tp_as_buffer */
2145 0, /* tp_flags */
2146 0, /* tp_doc */
2147 0, /* tp_traverse */
2148 0, /* tp_clear */
2149 0, /* tp_richcompare */
2150 0, /* tp_weaklistoffset */
2151 (getiterfunc)odictitems_iter, /* tp_iter */
2152 0, /* tp_iternext */
2153 odictitems_methods, /* tp_methods */
2154 0, /* tp_members */
2155 0, /* tp_getset */
2156 &PyDictItems_Type, /* tp_base */
2157};
2158
2159static PyObject *
2160odictitems_new(PyObject *od)
2161{
2162 return _PyDictView_New(od, &PyODictItems_Type);
2163}
2164
2165/* values() */
2166
2167static PyObject *
2168odictvalues_iter(_PyDictViewObject *dv)
2169{
2170 if (dv->dv_dict == NULL) {
2171 Py_RETURN_NONE;
2172 }
2173 return odictiter_new((PyODictObject *)dv->dv_dict,
2174 _odict_ITER_VALUES);
2175}
2176
2177static PyObject *
2178odictvalues_reversed(_PyDictViewObject *dv)
2179{
2180 if (dv->dv_dict == NULL) {
2181 Py_RETURN_NONE;
2182 }
2183 return odictiter_new((PyODictObject *)dv->dv_dict,
2184 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2185}
2186
2187static PyMethodDef odictvalues_methods[] = {
2188 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2189 {NULL, NULL} /* sentinel */
2190};
2191
2192PyTypeObject PyODictValues_Type = {
2193 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2194 "odict_values", /* tp_name */
2195 0, /* tp_basicsize */
2196 0, /* tp_itemsize */
2197 0, /* tp_dealloc */
2198 0, /* tp_print */
2199 0, /* tp_getattr */
2200 0, /* tp_setattr */
2201 0, /* tp_reserved */
2202 0, /* tp_repr */
2203 0, /* tp_as_number */
2204 0, /* tp_as_sequence */
2205 0, /* tp_as_mapping */
2206 0, /* tp_hash */
2207 0, /* tp_call */
2208 0, /* tp_str */
2209 0, /* tp_getattro */
2210 0, /* tp_setattro */
2211 0, /* tp_as_buffer */
2212 0, /* tp_flags */
2213 0, /* tp_doc */
2214 0, /* tp_traverse */
2215 0, /* tp_clear */
2216 0, /* tp_richcompare */
2217 0, /* tp_weaklistoffset */
2218 (getiterfunc)odictvalues_iter, /* tp_iter */
2219 0, /* tp_iternext */
2220 odictvalues_methods, /* tp_methods */
2221 0, /* tp_members */
2222 0, /* tp_getset */
2223 &PyDictValues_Type, /* tp_base */
2224};
2225
2226static PyObject *
2227odictvalues_new(PyObject *od)
2228{
2229 return _PyDictView_New(od, &PyODictValues_Type);
2230}
2231
2232
2233/* ----------------------------------------------
Martin Panter536d70e2017-01-14 08:23:08 +00002234 MutableMapping implementations
Eric Snow96c6af92015-05-29 22:21:39 -06002235
2236Mapping:
2237
2238============ ===========
2239method uses
2240============ ===========
2241__contains__ __getitem__
2242__eq__ items
2243__getitem__ +
2244__iter__ +
2245__len__ +
2246__ne__ __eq__
2247get __getitem__
2248items ItemsView
2249keys KeysView
2250values ValuesView
2251============ ===========
2252
2253ItemsView uses __len__, __iter__, and __getitem__.
2254KeysView uses __len__, __iter__, and __contains__.
2255ValuesView uses __len__, __iter__, and __getitem__.
2256
2257MutableMapping:
2258
2259============ ===========
2260method uses
2261============ ===========
2262__delitem__ +
2263__setitem__ +
2264clear popitem
2265pop __getitem__
2266 __delitem__
2267popitem __iter__
2268 _getitem__
2269 __delitem__
2270setdefault __getitem__
2271 __setitem__
2272update __setitem__
2273============ ===========
2274*/
2275
2276static int
2277mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2278{
2279 PyObject *pair, *iterator, *unexpected;
2280 int res = 0;
2281
2282 iterator = PyObject_GetIter(pairs);
2283 if (iterator == NULL)
2284 return -1;
2285 PyErr_Clear();
2286
2287 while ((pair = PyIter_Next(iterator)) != NULL) {
2288 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002289 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002290 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002291 if (pair_iterator == NULL)
2292 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002293
2294 key = PyIter_Next(pair_iterator);
2295 if (key == NULL) {
2296 if (!PyErr_Occurred())
2297 PyErr_SetString(PyExc_ValueError,
2298 "need more than 0 values to unpack");
2299 goto Done;
2300 }
2301
2302 value = PyIter_Next(pair_iterator);
2303 if (value == NULL) {
2304 if (!PyErr_Occurred())
2305 PyErr_SetString(PyExc_ValueError,
2306 "need more than 1 value to unpack");
2307 goto Done;
2308 }
2309
2310 unexpected = PyIter_Next(pair_iterator);
2311 if (unexpected != NULL) {
2312 Py_DECREF(unexpected);
2313 PyErr_SetString(PyExc_ValueError,
2314 "too many values to unpack (expected 2)");
2315 goto Done;
2316 }
2317 else if (PyErr_Occurred())
2318 goto Done;
2319
2320 res = PyObject_SetItem(self, key, value);
2321
2322Done:
2323 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002324 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002325 Py_XDECREF(key);
2326 Py_XDECREF(value);
2327 if (PyErr_Occurred())
2328 break;
2329 }
2330 Py_DECREF(iterator);
2331
2332 if (res < 0 || PyErr_Occurred() != NULL)
2333 return -1;
2334 else
2335 return 0;
2336}
2337
2338static PyObject *
2339mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2340{
2341 int res = 0;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002342 Py_ssize_t len;
2343 _Py_IDENTIFIER(items);
2344 _Py_IDENTIFIER(keys);
Eric Snow96c6af92015-05-29 22:21:39 -06002345
2346 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002347 assert(args == NULL || PyTuple_Check(args));
2348 len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002349 if (len > 1) {
Eric Snow96c6af92015-05-29 22:21:39 -06002350 char *msg = "update() takes at most 1 positional argument (%d given)";
2351 PyErr_Format(PyExc_TypeError, msg, len);
2352 return NULL;
2353 }
Eric Snow96c6af92015-05-29 22:21:39 -06002354
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002355 if (len) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002356 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002357 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002358 Py_INCREF(other);
Eric Snow06aed902016-09-09 11:59:08 -07002359 if PyDict_CheckExact(other) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002360 PyObject *items;
2361 if (PyDict_CheckExact(other))
2362 items = PyDict_Items(other);
2363 else
2364 items = _PyObject_CallMethodId(other, &PyId_items, NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002365 Py_DECREF(other);
2366 if (items == NULL)
2367 return NULL;
2368 res = mutablemapping_add_pairs(self, items);
2369 Py_DECREF(items);
2370 if (res == -1)
2371 return NULL;
2372 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002373 else if (_PyObject_HasAttrId(other, &PyId_keys)) { /* never fails */
Benjamin Peterson0718de92015-06-07 00:00:42 -05002374 PyObject *keys, *iterator, *key;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002375 keys = _PyObject_CallMethodIdObjArgs(other, &PyId_keys, NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002376 if (keys == NULL) {
2377 Py_DECREF(other);
2378 return NULL;
2379 }
2380 iterator = PyObject_GetIter(keys);
2381 Py_DECREF(keys);
2382 if (iterator == NULL) {
2383 Py_DECREF(other);
2384 return NULL;
2385 }
2386 while (res == 0 && (key = PyIter_Next(iterator))) {
2387 PyObject *value = PyObject_GetItem(other, key);
2388 if (value != NULL) {
2389 res = PyObject_SetItem(self, key, value);
2390 Py_DECREF(value);
2391 }
2392 else {
2393 res = -1;
2394 }
2395 Py_DECREF(key);
2396 }
2397 Py_DECREF(other);
2398 Py_DECREF(iterator);
2399 if (res != 0 || PyErr_Occurred())
2400 return NULL;
2401 }
Eric Snow06aed902016-09-09 11:59:08 -07002402 else if (_PyObject_HasAttrId(other, &PyId_items)) { /* never fails */
2403 PyObject *items;
2404 if (PyDict_CheckExact(other))
2405 items = PyDict_Items(other);
2406 else
2407 items = _PyObject_CallMethodId(other, &PyId_items, NULL);
2408 Py_DECREF(other);
2409 if (items == NULL)
2410 return NULL;
2411 res = mutablemapping_add_pairs(self, items);
2412 Py_DECREF(items);
2413 if (res == -1)
2414 return NULL;
2415 }
Benjamin Peterson0718de92015-06-07 00:00:42 -05002416 else {
2417 res = mutablemapping_add_pairs(self, other);
2418 Py_DECREF(other);
2419 if (res != 0)
2420 return NULL;
2421 }
2422 }
2423
2424 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002425 assert(kwargs == NULL || PyDict_Check(kwargs));
2426 len = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002427 if (len > 0) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002428 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002429 if (items == NULL)
2430 return NULL;
2431 res = mutablemapping_add_pairs(self, items);
2432 Py_DECREF(items);
2433 if (res == -1)
2434 return NULL;
2435 }
Eric Snow96c6af92015-05-29 22:21:39 -06002436
2437 Py_RETURN_NONE;
2438}