blob: c15b408dc24041188ed138f3d6f0343411dd5690 [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,
42mirroring the key order of dict's dk_enties with an array of node pointers.
43While 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
197 PyDict_CheckExact() calls to each of the concrete API funcions.
1982. 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;
539 PyDictKeyEntry *ep;
540 PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
542 ep = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr);
543 if (ep == NULL)
544 return -1;
545 /* We use pointer arithmetic to get the entry's index into the table. */
546 return ep - keys->dk_entries;
547}
548
549/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
Eric Snow96c6af92015-05-29 22:21:39 -0600550static int
551_odict_resize(PyODictObject *od) {
Eric Snow4c729182015-06-03 10:50:37 -0600552 Py_ssize_t size, i;
Eric Snow96c6af92015-05-29 22:21:39 -0600553 _ODictNode **fast_nodes, *node;
554
555 /* Initialize a new "fast nodes" table. */
556 size = ((PyDictObject *)od)->ma_keys->dk_size;
557 fast_nodes = PyMem_NEW(_ODictNode *, size);
558 if (fast_nodes == NULL) {
559 PyErr_NoMemory();
560 return -1;
561 }
562 for (i = 0; i < size; i++)
563 fast_nodes[i] = NULL;
564
565 /* Copy the current nodes into the table. */
Eric Snow96c6af92015-05-29 22:21:39 -0600566 _odict_FOREACH(od, node) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200567 i = _odict_get_index_raw(od, _odictnode_KEY(node),
Eric Snow4c729182015-06-03 10:50:37 -0600568 _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -0600569 if (i < 0) {
Eric Snow96c6af92015-05-29 22:21:39 -0600570 PyMem_FREE(fast_nodes);
571 return -1;
572 }
573 fast_nodes[i] = node;
574 }
Eric Snow96c6af92015-05-29 22:21:39 -0600575
576 /* Replace the old fast nodes table. */
577 _odict_free_fast_nodes(od);
578 od->od_fast_nodes = fast_nodes;
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200579 od->od_fast_nodes_size = size;
580 od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600581 return 0;
582}
583
584/* Return the index into the hash table, regardless of a valid node. */
585static Py_ssize_t
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200586_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600587{
Eric Snow4c729182015-06-03 10:50:37 -0600588 PyDictKeysObject *keys;
Eric Snow96c6af92015-05-29 22:21:39 -0600589
590 assert(key != NULL);
Eric Snow4c729182015-06-03 10:50:37 -0600591 keys = ((PyDictObject *)od)->ma_keys;
592
593 /* Ensure od_fast_nodes and dk_entries are in sync. */
Serhiy Storchaka97f46db2015-11-06 12:00:03 +0200594 if (od->od_resize_sentinel != keys ||
595 od->od_fast_nodes_size != keys->dk_size) {
Eric Snow4c729182015-06-03 10:50:37 -0600596 int resize_res = _odict_resize(od);
597 if (resize_res < 0)
598 return -1;
599 }
600
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200601 return _odict_get_index_raw(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600602}
603
Eric Snow96c6af92015-05-29 22:21:39 -0600604/* Returns NULL if there was some error or the key was not found. */
605static _ODictNode *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200606_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600607{
608 Py_ssize_t index;
609
610 if (_odict_EMPTY(od))
611 return NULL;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200612 index = _odict_get_index(od, key, hash);
613 if (index < 0)
614 return NULL;
615 return od->od_fast_nodes[index];
616}
617
618static _ODictNode *
619_odict_find_node(PyODictObject *od, PyObject *key)
620{
621 Py_ssize_t index;
622 Py_hash_t hash;
623
624 if (_odict_EMPTY(od))
625 return NULL;
626 hash = PyObject_Hash(key);
627 if (hash == -1)
628 return NULL;
629 index = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600630 if (index < 0)
631 return NULL;
632 return od->od_fast_nodes[index];
633}
634
635static void
636_odict_add_head(PyODictObject *od, _ODictNode *node)
637{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300638 _odictnode_PREV(node) = NULL;
639 _odictnode_NEXT(node) = _odict_FIRST(od);
640 if (_odict_FIRST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600641 _odict_LAST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300642 else
Eric Snow96c6af92015-05-29 22:21:39 -0600643 _odictnode_PREV(_odict_FIRST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300644 _odict_FIRST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600645 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600646}
647
648static void
649_odict_add_tail(PyODictObject *od, _ODictNode *node)
650{
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300651 _odictnode_PREV(node) = _odict_LAST(od);
652 _odictnode_NEXT(node) = NULL;
653 if (_odict_LAST(od) == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -0600654 _odict_FIRST(od) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300655 else
Eric Snow96c6af92015-05-29 22:21:39 -0600656 _odictnode_NEXT(_odict_LAST(od)) = node;
Serhiy Storchaka992ec462015-10-14 19:21:24 +0300657 _odict_LAST(od) = node;
Eric Snow4fabf022015-06-04 00:09:56 -0600658 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600659}
660
661/* adds the node to the end of the list */
662static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200663_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600664{
665 Py_ssize_t i;
666 _ODictNode *node;
667
Serhiy Storchakad17427b2015-10-20 18:21:48 +0300668 Py_INCREF(key);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200669 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600670 if (i < 0) {
671 if (!PyErr_Occurred())
672 PyErr_SetObject(PyExc_KeyError, key);
673 Py_DECREF(key);
674 return -1;
675 }
676 else if (od->od_fast_nodes[i] != NULL) {
677 /* We already have a node for the key so there's no need to add one. */
678 Py_DECREF(key);
679 return 0;
680 }
681
682 /* must not be added yet */
683 node = (_ODictNode *)PyMem_MALLOC(sizeof(_ODictNode));
684 if (node == NULL) {
685 Py_DECREF(key);
686 PyErr_NoMemory();
687 return -1;
688 }
689
690 _odictnode_KEY(node) = key;
Eric Snow4c729182015-06-03 10:50:37 -0600691 _odictnode_HASH(node) = hash;
Eric Snow96c6af92015-05-29 22:21:39 -0600692 _odict_add_tail(od, node);
693 od->od_fast_nodes[i] = node;
694 return 0;
695}
696
697/* Putting the decref after the free causes problems. */
698#define _odictnode_DEALLOC(node) \
699 do { \
700 Py_DECREF(_odictnode_KEY(node)); \
701 PyMem_FREE((void *)node); \
702 } while (0)
703
704/* Repeated calls on the same node are no-ops. */
705static void
706_odict_remove_node(PyODictObject *od, _ODictNode *node)
707{
708 if (_odict_FIRST(od) == node)
709 _odict_FIRST(od) = _odictnode_NEXT(node);
710 else if (_odictnode_PREV(node) != NULL)
711 _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
712
713 if (_odict_LAST(od) == node)
714 _odict_LAST(od) = _odictnode_PREV(node);
715 else if (_odictnode_NEXT(node) != NULL)
716 _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
717
718 _odictnode_PREV(node) = NULL;
719 _odictnode_NEXT(node) = NULL;
Eric Snow4fabf022015-06-04 00:09:56 -0600720 od->od_state++;
Eric Snow96c6af92015-05-29 22:21:39 -0600721}
722
Eric Snow96c6af92015-05-29 22:21:39 -0600723/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
724 get all sorts of problems here. In PyODict_DelItem we make sure to
725 call _odict_clear_node first.
Victor Stinnerca30b022015-09-03 17:50:04 +0200726
Eric Snow96c6af92015-05-29 22:21:39 -0600727 This matters in the case of colliding keys. Suppose we add 3 keys:
728 [A, B, C], where the hash of C collides with A and the next possible
729 index in the hash table is occupied by B. If we remove B then for C
730 the dict's looknode func will give us the old index of B instead of
731 the index we got before deleting B. However, the node for C in
732 od_fast_nodes is still at the old dict index of C. Thus to be sure
733 things don't get out of sync, we clear the node in od_fast_nodes
734 *before* calling PyDict_DelItem.
735
736 The same must be done for any other OrderedDict operations where
737 we modify od_fast_nodes.
738*/
739static int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200740_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
741 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -0600742{
743 Py_ssize_t i;
744
745 assert(key != NULL);
746 if (_odict_EMPTY(od)) {
747 /* Let later code decide if this is a KeyError. */
748 return 0;
749 }
750
Serhiy Storchaka19a70e72015-11-13 14:48:36 +0200751 i = _odict_get_index(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -0600752 if (i < 0)
753 return PyErr_Occurred() ? -1 : 0;
754
755 if (node == NULL)
756 node = od->od_fast_nodes[i];
757 assert(node == od->od_fast_nodes[i]);
758 if (node == NULL) {
759 /* Let later code decide if this is a KeyError. */
760 return 0;
761 }
762
763 // Now clear the node.
764 od->od_fast_nodes[i] = NULL;
765 _odict_remove_node(od, node);
766 _odictnode_DEALLOC(node);
767 return 0;
768}
769
770static void
771_odict_clear_nodes(PyODictObject *od)
772{
773 _ODictNode *node, *next;
774
775 if (!_odict_EMPTY(od)) {
776 node = _odict_FIRST(od);
777 while (node != NULL) {
778 next = _odictnode_NEXT(node);
779 _odictnode_DEALLOC(node);
780 node = next;
781 }
782 _odict_FIRST(od) = NULL;
783 _odict_LAST(od) = NULL;
784 }
785
786 _odict_free_fast_nodes(od);
787 od->od_fast_nodes = NULL;
788}
789
790/* There isn't any memory management of nodes past this point. */
791#undef _odictnode_DEALLOC
792
793static int
794_odict_keys_equal(PyODictObject *a, PyODictObject *b)
795{
796 _ODictNode *node_a, *node_b;
797
798 node_a = _odict_FIRST(a);
799 node_b = _odict_FIRST(b);
800 while (1) {
801 if (node_a == NULL && node_b == NULL)
802 /* success: hit the end of each at the same time */
803 return 1;
804 else if (node_a == NULL || node_b == NULL)
805 /* unequal length */
806 return 0;
807 else {
808 int res = PyObject_RichCompareBool(
809 (PyObject *)_odictnode_KEY(node_a),
810 (PyObject *)_odictnode_KEY(node_b),
811 Py_EQ);
812 if (res < 0)
813 return res;
814 else if (res == 0)
815 return 0;
816
817 /* otherwise it must match, so move on to the next one */
818 node_a = _odictnode_NEXT(node_a);
819 node_b = _odictnode_NEXT(node_b);
820 }
821 }
822}
823
824
825/* ----------------------------------------------
826 * OrderedDict mapping methods
827 */
828
829/* mp_ass_subscript: __setitem__() and __delitem__() */
830
831static int
832odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)
833{
834 if (w == NULL)
835 return PyODict_DelItem((PyObject *)od, v);
836 else
837 return PyODict_SetItem((PyObject *)od, v, w);
838}
839
840/* tp_as_mapping */
841
842static PyMappingMethods odict_as_mapping = {
843 0, /*mp_length*/
844 0, /*mp_subscript*/
845 (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/
846};
847
848
849/* ----------------------------------------------
850 * OrderedDict methods
851 */
852
853/* __delitem__() */
854
855PyDoc_STRVAR(odict_delitem__doc__, "od.__delitem__(y) <==> del od[y]");
856
857/* __eq__() */
858
859PyDoc_STRVAR(odict_eq__doc__,
860"od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive \n\
861 while comparison to a regular mapping is order-insensitive.\n\
862 ");
863
864/* forward */
865static PyObject * odict_richcompare(PyObject *v, PyObject *w, int op);
866
867static PyObject *
868odict_eq(PyObject *a, PyObject *b)
869{
870 return odict_richcompare(a, b, Py_EQ);
871}
872
873/* __init__() */
874
875PyDoc_STRVAR(odict_init__doc__,
876"Initialize an ordered dictionary. The signature is the same as\n\
877 regular dictionaries, but keyword arguments are not recommended because\n\
878 their insertion order is arbitrary.\n\
879\n\
880 ");
881
882/* forward */
883static int odict_init(PyObject *self, PyObject *args, PyObject *kwds);
884
885/* __iter__() */
886
887PyDoc_STRVAR(odict_iter__doc__, "od.__iter__() <==> iter(od)");
888
889static PyObject * odict_iter(PyODictObject *self); /* forward */
890
891/* __ne__() */
892
893/* Mapping.__ne__() does not have a docstring. */
894PyDoc_STRVAR(odict_ne__doc__, "");
895
896static PyObject *
897odict_ne(PyObject *a, PyObject *b)
898{
899 return odict_richcompare(a, b, Py_NE);
900}
901
902/* __repr__() */
903
904PyDoc_STRVAR(odict_repr__doc__, "od.__repr__() <==> repr(od)");
905
906static PyObject * odict_repr(PyODictObject *self); /* forward */
907
908/* __setitem__() */
909
910PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y");
911
912/* fromkeys() */
913
914PyDoc_STRVAR(odict_fromkeys__doc__,
915"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\
916 If not specified, the value defaults to None.\n\
917\n\
918 ");
919
920static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -0600921odict_fromkeys(PyObject *cls, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -0600922{
Eric Snowac02ef32015-06-02 20:42:14 -0600923 static char *kwlist[] = {"iterable", "value", 0};
Eric Snow96c6af92015-05-29 22:21:39 -0600924 PyObject *seq;
925 PyObject *value = Py_None;
Eric Snowac02ef32015-06-02 20:42:14 -0600926
927 /* both borrowed */
928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:fromkeys", kwlist,
929 &seq, &value)) {
Eric Snow96c6af92015-05-29 22:21:39 -0600930 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -0600931 }
Eric Snow96c6af92015-05-29 22:21:39 -0600932 return _PyDict_FromKeys(cls, seq, value);
933}
934
935/* __sizeof__() */
936
937/* OrderedDict.__sizeof__() does not have a docstring. */
938PyDoc_STRVAR(odict_sizeof__doc__, "");
939
940static PyObject *
941odict_sizeof(PyODictObject *od)
942{
Serhiy Storchaka0ce7a3a2015-12-22 08:16:18 +0200943 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300944 res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
Eric Snow96c6af92015-05-29 22:21:39 -0600945 if (!_odict_EMPTY(od)) {
946 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
947 }
948 return PyLong_FromSsize_t(res);
949}
950
951/* __reduce__() */
952
953PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
954
955static PyObject *
956odict_reduce(register PyODictObject *od)
957{
958 _Py_IDENTIFIER(__dict__);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300959 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300960 PyObject *dict = NULL, *result = NULL;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300961 PyObject *items_iter, *items, *args = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -0600962
963 /* capture any instance state */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300964 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
965 if (dict == NULL)
Eric Snowc5e59602015-05-30 11:28:56 -0600966 goto Done;
967 else {
Eric Snow96c6af92015-05-29 22:21:39 -0600968 /* od.__dict__ isn't necessarily a dict... */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300969 Py_ssize_t dict_len = PyObject_Length(dict);
970 if (dict_len == -1)
Eric Snow96c6af92015-05-29 22:21:39 -0600971 goto Done;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300972 if (!dict_len) {
973 /* nothing to pickle in od.__dict__ */
974 Py_CLEAR(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600975 }
976 }
977
978 /* build the result */
Eric Snow96c6af92015-05-29 22:21:39 -0600979 args = PyTuple_New(0);
980 if (args == NULL)
981 goto Done;
982
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300983 items = _PyObject_CallMethodIdObjArgs((PyObject *)od, &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -0600984 if (items == NULL)
985 goto Done;
986
987 items_iter = PyObject_GetIter(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300988 Py_DECREF(items);
Eric Snow96c6af92015-05-29 22:21:39 -0600989 if (items_iter == NULL)
990 goto Done;
991
Serhiy Storchaka4575beb2015-10-22 20:18:24 +0300992 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300993 Py_DECREF(items_iter);
Eric Snow96c6af92015-05-29 22:21:39 -0600994
995Done:
Serhiy Storchaka8003baf2015-10-18 09:53:17 +0300996 Py_XDECREF(dict);
Eric Snow96c6af92015-05-29 22:21:39 -0600997 Py_XDECREF(args);
Eric Snow96c6af92015-05-29 22:21:39 -0600998
999 return result;
1000}
1001
1002/* setdefault() */
1003
1004PyDoc_STRVAR(odict_setdefault__doc__,
1005 "od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od");
1006
1007/* Skips __missing__() calls. */
1008static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001009odict_setdefault(register PyODictObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001010{
Eric Snowac02ef32015-06-02 20:42:14 -06001011 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001012 PyObject *key, *result = NULL;
1013 PyObject *failobj = Py_None;
1014
1015 /* both borrowed */
Eric Snowac02ef32015-06-02 20:42:14 -06001016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:setdefault", kwlist,
1017 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001018 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001019 }
Eric Snow96c6af92015-05-29 22:21:39 -06001020
1021 if (PyODict_CheckExact(od)) {
Eric Snowd1719752015-06-01 23:12:13 -06001022 result = PyODict_GetItemWithError(od, key); /* borrowed */
1023 if (result == NULL) {
1024 if (PyErr_Occurred())
1025 return NULL;
1026 assert(_odict_find_node(od, key) == NULL);
1027 if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) {
Eric Snow96c6af92015-05-29 22:21:39 -06001028 result = failobj;
1029 Py_INCREF(failobj);
1030 }
1031 }
1032 else {
Eric Snowd1719752015-06-01 23:12:13 -06001033 Py_INCREF(result);
Eric Snow96c6af92015-05-29 22:21:39 -06001034 }
1035 }
1036 else {
1037 int exists = PySequence_Contains((PyObject *)od, key);
1038 if (exists < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001039 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001040 }
1041 else if (exists) {
1042 result = PyObject_GetItem((PyObject *)od, key);
1043 }
1044 else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) {
1045 result = failobj;
1046 Py_INCREF(failobj);
1047 }
1048 }
1049
Eric Snow96c6af92015-05-29 22:21:39 -06001050 return result;
1051}
1052
1053/* pop() */
1054
1055PyDoc_STRVAR(odict_pop__doc__,
1056"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1057 value. If key is not found, d is returned if given, otherwise KeyError\n\
1058 is raised.\n\
1059\n\
1060 ");
1061
1062/* forward */
1063static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1064
1065/* Skips __missing__() calls. */
1066static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001067odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001068{
Eric Snowac02ef32015-06-02 20:42:14 -06001069 static char *kwlist[] = {"key", "default", 0};
Eric Snow96c6af92015-05-29 22:21:39 -06001070 PyObject *key, *failobj = NULL;
1071
Eric Snowac02ef32015-06-02 20:42:14 -06001072 /* borrowed */
1073 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1074 &key, &failobj)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001075 return NULL;
1076 }
1077
1078 return _odict_popkey(od, key, failobj);
1079}
1080
1081static PyObject *
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001082_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1083 Py_hash_t hash)
Eric Snow96c6af92015-05-29 22:21:39 -06001084{
1085 _ODictNode *node;
1086 PyObject *value = NULL;
1087
Eric Snow96c6af92015-05-29 22:21:39 -06001088 /* Pop the node first to avoid a possible dict resize (due to
1089 eval loop reentrancy) and complications due to hash collision
1090 resolution. */
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001091 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001092 if (node == NULL) {
1093 if (PyErr_Occurred())
Eric Snowd1719752015-06-01 23:12:13 -06001094 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001095 }
1096 else {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001097 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001098 if (res < 0) {
Eric Snowd1719752015-06-01 23:12:13 -06001099 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001100 }
1101 }
1102
1103 /* Now delete the value from the dict. */
1104 if (PyODict_CheckExact(od)) {
1105 if (node != NULL) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001106 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1107 if (value != NULL) {
1108 Py_INCREF(value);
1109 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1110 Py_DECREF(value);
1111 return NULL;
1112 }
1113 }
Eric Snow96c6af92015-05-29 22:21:39 -06001114 }
1115 }
1116 else {
1117 int exists = PySequence_Contains(od, key);
1118 if (exists < 0)
Eric Snowd1719752015-06-01 23:12:13 -06001119 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001120 if (exists) {
1121 value = PyObject_GetItem(od, key);
1122 if (value != NULL) {
1123 if (PyObject_DelItem(od, key) == -1) {
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001124 Py_CLEAR(value);
Eric Snow96c6af92015-05-29 22:21:39 -06001125 }
1126 }
1127 }
1128 }
1129
1130 /* Apply the fallback value, if necessary. */
1131 if (value == NULL && !PyErr_Occurred()) {
1132 if (failobj) {
1133 value = failobj;
1134 Py_INCREF(failobj);
1135 }
1136 else {
1137 PyErr_SetObject(PyExc_KeyError, key);
1138 }
1139 }
1140
Eric Snow96c6af92015-05-29 22:21:39 -06001141 return value;
1142}
1143
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001144static PyObject *
1145_odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1146{
1147 Py_hash_t hash = PyObject_Hash(key);
1148 if (hash == -1)
1149 return NULL;
1150
1151 return _odict_popkey_hash(od, key, failobj, hash);
1152}
1153
Eric Snow96c6af92015-05-29 22:21:39 -06001154/* popitem() */
1155
1156PyDoc_STRVAR(odict_popitem__doc__,
1157"od.popitem() -> (k, v), return and remove a (key, value) pair.\n\
1158 Pairs are returned in LIFO order if last is true or FIFO order if false.\n\
1159\n\
1160 ");
1161
1162static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001163odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001164{
Eric Snowac02ef32015-06-02 20:42:14 -06001165 static char *kwlist[] = {"last", 0};
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001166 PyObject *key, *value, *item = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001167 _ODictNode *node;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001168 int last = 1;
Eric Snow96c6af92015-05-29 22:21:39 -06001169
1170 /* pull the item */
1171
Eric Snowac02ef32015-06-02 20:42:14 -06001172 /* borrowed */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001173 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:popitem", kwlist,
Eric Snowac02ef32015-06-02 20:42:14 -06001174 &last)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001175 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001176 }
Eric Snow96c6af92015-05-29 22:21:39 -06001177
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001178 if (_odict_EMPTY(od)) {
1179 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1180 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001181 }
Eric Snow96c6af92015-05-29 22:21:39 -06001182
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001183 node = last ? _odict_LAST(od) : _odict_FIRST(od);
Eric Snow96c6af92015-05-29 22:21:39 -06001184 key = _odictnode_KEY(node);
Eric Snowd1719752015-06-01 23:12:13 -06001185 Py_INCREF(key);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001186 value = _odict_popkey_hash(od, key, NULL, _odictnode_HASH(node));
Eric Snow96c6af92015-05-29 22:21:39 -06001187 if (value == NULL)
1188 return NULL;
1189 item = PyTuple_Pack(2, key, value);
Eric Snowd1719752015-06-01 23:12:13 -06001190 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001191 Py_DECREF(value);
1192 return item;
1193}
1194
1195/* keys() */
1196
1197/* MutableMapping.keys() does not have a docstring. */
1198PyDoc_STRVAR(odict_keys__doc__, "");
1199
1200static PyObject * odictkeys_new(PyObject *od); /* forward */
1201
1202/* values() */
1203
1204/* MutableMapping.values() does not have a docstring. */
1205PyDoc_STRVAR(odict_values__doc__, "");
1206
1207static PyObject * odictvalues_new(PyObject *od); /* forward */
1208
1209/* items() */
1210
1211/* MutableMapping.items() does not have a docstring. */
1212PyDoc_STRVAR(odict_items__doc__, "");
1213
1214static PyObject * odictitems_new(PyObject *od); /* forward */
1215
1216/* update() */
1217
1218/* MutableMapping.update() does not have a docstring. */
1219PyDoc_STRVAR(odict_update__doc__, "");
1220
1221/* forward */
1222static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1223
1224#define odict_update mutablemapping_update
1225
1226/* clear() */
1227
1228PyDoc_STRVAR(odict_clear__doc__,
1229 "od.clear() -> None. Remove all items from od.");
1230
1231static PyObject *
1232odict_clear(register PyODictObject *od)
1233{
1234 PyDict_Clear((PyObject *)od);
1235 _odict_clear_nodes(od);
1236 _odict_FIRST(od) = NULL;
1237 _odict_LAST(od) = NULL;
1238 if (_odict_resize(od) < 0)
1239 return NULL;
1240 Py_RETURN_NONE;
1241}
1242
1243/* copy() */
1244
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001245/* forward */
1246static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1247 Py_hash_t);
1248
Eric Snow96c6af92015-05-29 22:21:39 -06001249PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1250
1251static PyObject *
1252odict_copy(register PyODictObject *od)
1253{
1254 _ODictNode *node;
1255 PyObject *od_copy;
1256
1257 if (PyODict_CheckExact(od))
1258 od_copy = PyODict_New();
1259 else
1260 od_copy = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(od), NULL);
1261 if (od_copy == NULL)
1262 return NULL;
1263
1264 if (PyODict_CheckExact(od)) {
1265 _odict_FOREACH(od, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001266 PyObject *key = _odictnode_KEY(node);
1267 PyObject *value = _odictnode_VALUE(node, od);
1268 if (value == NULL) {
1269 if (!PyErr_Occurred())
1270 PyErr_SetObject(PyExc_KeyError, key);
1271 goto fail;
1272 }
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001273 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1274 _odictnode_HASH(node)) != 0)
Eric Snow96c6af92015-05-29 22:21:39 -06001275 goto fail;
1276 }
1277 }
1278 else {
1279 _odict_FOREACH(od, node) {
1280 int res;
1281 PyObject *value = PyObject_GetItem((PyObject *)od,
1282 _odictnode_KEY(node));
1283 if (value == NULL)
1284 goto fail;
1285 res = PyObject_SetItem((PyObject *)od_copy,
1286 _odictnode_KEY(node), value);
1287 Py_DECREF(value);
1288 if (res != 0)
1289 goto fail;
1290 }
1291 }
1292 return od_copy;
1293
1294fail:
1295 Py_DECREF(od_copy);
1296 return NULL;
1297}
1298
1299/* __reversed__() */
1300
1301PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1302
1303#define _odict_ITER_REVERSED 1
1304#define _odict_ITER_KEYS 2
1305#define _odict_ITER_VALUES 4
1306
1307/* forward */
1308static PyObject * odictiter_new(PyODictObject *, int);
1309
1310static PyObject *
1311odict_reversed(PyODictObject *od)
1312{
Eric Snow96c6af92015-05-29 22:21:39 -06001313 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1314}
1315
1316/* move_to_end() */
1317
1318PyDoc_STRVAR(odict_move_to_end__doc__,
1319"Move an existing element to the end (or beginning if last==False).\n\
1320\n\
1321 Raises KeyError if the element does not exist.\n\
1322 When last=True, acts like a fast version of self[key]=self.pop(key).\n\
1323\n\
1324 ");
1325
1326static PyObject *
Eric Snowac02ef32015-06-02 20:42:14 -06001327odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs)
Eric Snow96c6af92015-05-29 22:21:39 -06001328{
Eric Snowac02ef32015-06-02 20:42:14 -06001329 static char *kwlist[] = {"key", "last", 0};
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001330 PyObject *key;
1331 int last = 1;
1332 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001333
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001334 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|p:move_to_end", kwlist,
Eric Snowac02ef32015-06-02 20:42:14 -06001335 &key, &last)) {
Eric Snow96c6af92015-05-29 22:21:39 -06001336 return NULL;
Eric Snowac02ef32015-06-02 20:42:14 -06001337 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001338
Eric Snow96c6af92015-05-29 22:21:39 -06001339 if (_odict_EMPTY(od)) {
1340 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001341 return NULL;
1342 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001343 node = last ? _odict_LAST(od) : _odict_FIRST(od);
1344 if (key != _odictnode_KEY(node)) {
1345 node = _odict_find_node(od, key);
1346 if (node == NULL) {
1347 if (!PyErr_Occurred())
1348 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowc5e59602015-05-30 11:28:56 -06001349 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001350 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001351 if (last) {
1352 /* Only move if not already the last one. */
1353 if (node != _odict_LAST(od)) {
1354 _odict_remove_node(od, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001355 _odict_add_tail(od, node);
1356 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001357 }
1358 else {
1359 /* Only move if not already the first one. */
1360 if (node != _odict_FIRST(od)) {
1361 _odict_remove_node(od, node);
1362 _odict_add_head(od, node);
Eric Snow96c6af92015-05-29 22:21:39 -06001363 }
1364 }
1365 }
Eric Snow96c6af92015-05-29 22:21:39 -06001366 Py_RETURN_NONE;
1367}
1368
1369
1370/* tp_methods */
1371
1372static PyMethodDef odict_methods[] = {
1373
1374 /* explicitly defined so we can align docstrings with
1375 * collections.OrderedDict */
1376 {"__delitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
1377 odict_delitem__doc__},
1378 {"__eq__", (PyCFunction)odict_eq, METH_NOARGS,
1379 odict_eq__doc__},
1380 {"__init__", (PyCFunction)odict_init, METH_NOARGS,
1381 odict_init__doc__},
1382 {"__iter__", (PyCFunction)odict_iter, METH_NOARGS,
1383 odict_iter__doc__},
1384 {"__ne__", (PyCFunction)odict_ne, METH_NOARGS,
1385 odict_ne__doc__},
1386 {"__repr__", (PyCFunction)odict_repr, METH_NOARGS,
1387 odict_repr__doc__},
1388 {"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
1389 odict_setitem__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001390 {"fromkeys", (PyCFunction)odict_fromkeys,
1391 METH_VARARGS | METH_KEYWORDS | METH_CLASS, odict_fromkeys__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001392
1393 /* overridden dict methods */
1394 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1395 odict_sizeof__doc__},
1396 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1397 odict_reduce__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001398 {"setdefault", (PyCFunction)odict_setdefault,
1399 METH_VARARGS | METH_KEYWORDS, odict_setdefault__doc__},
1400 {"pop", (PyCFunction)odict_pop,
1401 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
1402 {"popitem", (PyCFunction)odict_popitem,
1403 METH_VARARGS | METH_KEYWORDS, odict_popitem__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001404 {"keys", (PyCFunction)odictkeys_new, METH_NOARGS,
1405 odict_keys__doc__},
1406 {"values", (PyCFunction)odictvalues_new, METH_NOARGS,
1407 odict_values__doc__},
1408 {"items", (PyCFunction)odictitems_new, METH_NOARGS,
1409 odict_items__doc__},
1410 {"update", (PyCFunction)odict_update, METH_VARARGS | METH_KEYWORDS,
1411 odict_update__doc__},
1412 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1413 odict_clear__doc__},
1414 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1415 odict_copy__doc__},
1416
1417 /* new methods */
1418 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1419 odict_reversed__doc__},
Eric Snowac02ef32015-06-02 20:42:14 -06001420 {"move_to_end", (PyCFunction)odict_move_to_end,
1421 METH_VARARGS | METH_KEYWORDS, odict_move_to_end__doc__},
Eric Snow96c6af92015-05-29 22:21:39 -06001422
1423 {NULL, NULL} /* sentinel */
1424};
1425
1426
1427/* ----------------------------------------------
1428 * OrderedDict members
1429 */
1430
1431/* tp_members */
1432
1433static PyMemberDef odict_members[] = {
1434 {"__dict__", T_OBJECT, offsetof(PyODictObject, od_inst_dict), READONLY},
1435 {0}
1436};
1437
1438
1439/* ----------------------------------------------
1440 * OrderedDict type slot methods
1441 */
1442
1443/* tp_dealloc */
1444
1445static void
1446odict_dealloc(PyODictObject *self)
1447{
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001448 PyThreadState *tstate = PyThreadState_GET();
1449
Eric Snow96c6af92015-05-29 22:21:39 -06001450 PyObject_GC_UnTrack(self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001451 Py_TRASHCAN_SAFE_BEGIN(self)
1452
Eric Snow96c6af92015-05-29 22:21:39 -06001453 Py_XDECREF(self->od_inst_dict);
1454 if (self->od_weakreflist != NULL)
1455 PyObject_ClearWeakRefs((PyObject *)self);
1456
1457 _odict_clear_nodes(self);
Eric Snow96c6af92015-05-29 22:21:39 -06001458
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001459 /* Call the base tp_dealloc(). Since it too uses the trashcan mechanism,
1460 * temporarily decrement trash_delete_nesting to prevent triggering it
1461 * and putting the partially deallocated object on the trashcan's
1462 * to-be-deleted-later list.
1463 */
1464 --tstate->trash_delete_nesting;
1465 assert(_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL);
Eric Snow96c6af92015-05-29 22:21:39 -06001466 PyDict_Type.tp_dealloc((PyObject *)self);
Serhiy Storchaka14eefe32015-11-01 16:12:34 +02001467 ++tstate->trash_delete_nesting;
1468
1469 Py_TRASHCAN_SAFE_END(self)
Eric Snow96c6af92015-05-29 22:21:39 -06001470};
1471
1472/* tp_repr */
1473
1474static PyObject *
1475odict_repr(PyODictObject *self)
1476{
1477 int i;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001478 _Py_IDENTIFIER(items);
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001479 PyObject *pieces = NULL, *result = NULL;
1480 const char *classname;
1481
1482 classname = strrchr(Py_TYPE(self)->tp_name, '.');
1483 if (classname == NULL)
1484 classname = Py_TYPE(self)->tp_name;
1485 else
1486 classname++;
1487
1488 if (PyODict_SIZE(self) == 0)
1489 return PyUnicode_FromFormat("%s()", classname);
Eric Snow96c6af92015-05-29 22:21:39 -06001490
1491 i = Py_ReprEnter((PyObject *)self);
1492 if (i != 0) {
1493 return i > 0 ? PyUnicode_FromString("...") : NULL;
1494 }
1495
Eric Snow96c6af92015-05-29 22:21:39 -06001496 if (PyODict_CheckExact(self)) {
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001497 Py_ssize_t count = 0;
Eric Snowa762af72015-06-01 22:59:08 -06001498 _ODictNode *node;
Eric Snow96c6af92015-05-29 22:21:39 -06001499 pieces = PyList_New(PyODict_SIZE(self));
1500 if (pieces == NULL)
1501 goto Done;
1502
1503 _odict_FOREACH(self, node) {
Eric Snowa762af72015-06-01 22:59:08 -06001504 PyObject *pair;
1505 PyObject *key = _odictnode_KEY(node);
1506 PyObject *value = _odictnode_VALUE(node, self);
1507 if (value == NULL) {
1508 if (!PyErr_Occurred())
1509 PyErr_SetObject(PyExc_KeyError, key);
Eric Snowdb4061c2015-06-03 11:09:48 -06001510 goto Done;
Eric Snowa762af72015-06-01 22:59:08 -06001511 }
1512 pair = PyTuple_Pack(2, key, value);
Eric Snow96c6af92015-05-29 22:21:39 -06001513 if (pair == NULL)
1514 goto Done;
1515
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001516 if (count < PyList_GET_SIZE(pieces))
1517 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1518 else {
1519 if (PyList_Append(pieces, pair) < 0) {
1520 Py_DECREF(pair);
1521 goto Done;
1522 }
1523 Py_DECREF(pair);
1524 }
1525 count++;
Eric Snow96c6af92015-05-29 22:21:39 -06001526 }
Serhiy Storchaka710cd342015-11-04 22:33:07 +02001527 if (count < PyList_GET_SIZE(pieces))
1528 PyList_GET_SIZE(pieces) = count;
Eric Snow96c6af92015-05-29 22:21:39 -06001529 }
1530 else {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001531 PyObject *items = _PyObject_CallMethodIdObjArgs((PyObject *)self,
1532 &PyId_items, NULL);
Eric Snow96c6af92015-05-29 22:21:39 -06001533 if (items == NULL)
1534 goto Done;
1535 pieces = PySequence_List(items);
1536 Py_DECREF(items);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03001537 if (pieces == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001538 goto Done;
1539 }
1540
Serhiy Storchaka4575beb2015-10-22 20:18:24 +03001541 result = PyUnicode_FromFormat("%s(%R)", classname, pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001542
Eric Snow96c6af92015-05-29 22:21:39 -06001543Done:
1544 Py_XDECREF(pieces);
Eric Snow96c6af92015-05-29 22:21:39 -06001545 Py_ReprLeave((PyObject *)self);
1546 return result;
1547};
1548
1549/* tp_doc */
1550
1551PyDoc_STRVAR(odict_doc,
1552 "Dictionary that remembers insertion order");
1553
1554/* tp_traverse */
1555
1556static int
1557odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1558{
1559 Py_VISIT(od->od_inst_dict);
1560 Py_VISIT(od->od_weakreflist);
1561 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1562}
1563
1564/* tp_clear */
1565
1566static int
1567odict_tp_clear(PyODictObject *od)
1568{
1569 PyObject *res;
1570 Py_CLEAR(od->od_inst_dict);
1571 Py_CLEAR(od->od_weakreflist);
1572 res = odict_clear(od);
1573 if (res == NULL)
1574 return -1;
1575 Py_DECREF(res);
1576 return 0;
1577}
1578
1579/* tp_richcompare */
1580
1581static PyObject *
1582odict_richcompare(PyObject *v, PyObject *w, int op)
1583{
1584 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1585 Py_RETURN_NOTIMPLEMENTED;
1586 }
1587
1588 if (op == Py_EQ || op == Py_NE) {
1589 PyObject *res, *cmp;
1590 int eq;
1591
1592 cmp = PyDict_Type.tp_richcompare(v, w, op);
1593 if (cmp == NULL)
1594 return NULL;
1595 if (!PyODict_Check(w))
1596 return cmp;
1597 if (op == Py_EQ && cmp == Py_False)
1598 return cmp;
1599 if (op == Py_NE && cmp == Py_True)
1600 return cmp;
1601 Py_DECREF(cmp);
1602
1603 /* Try comparing odict keys. */
1604 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1605 if (eq < 0)
1606 return NULL;
1607
1608 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1609 Py_INCREF(res);
1610 return res;
1611 } else {
1612 Py_RETURN_NOTIMPLEMENTED;
1613 }
1614};
1615
1616/* tp_iter */
1617
1618static PyObject *
1619odict_iter(PyODictObject *od)
1620{
1621 return odictiter_new(od, _odict_ITER_KEYS);
1622};
1623
1624/* tp_init */
1625
1626static int
1627odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1628{
1629 PyObject *res;
1630 Py_ssize_t len = PyObject_Length(args);
1631
1632 if (len == -1)
1633 return -1;
1634 if (len > 1) {
1635 char *msg = "expected at most 1 arguments, got %d";
1636 PyErr_Format(PyExc_TypeError, msg, len);
1637 return -1;
1638 }
1639
1640 /* __init__() triggering update() is just the way things are! */
1641 res = odict_update(self, args, kwds);
1642 if (res == NULL) {
1643 return -1;
1644 } else {
1645 Py_DECREF(res);
1646 return 0;
1647 }
1648};
1649
1650/* tp_new */
1651
1652static PyObject *
1653odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1654{
Victor Stinnerca30b022015-09-03 17:50:04 +02001655 PyObject *dict;
1656 PyODictObject *od;
1657
1658 dict = PyDict_New();
1659 if (dict == NULL)
1660 return NULL;
1661
1662 od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
1663 if (od == NULL) {
1664 Py_DECREF(dict);
1665 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001666 }
Victor Stinnerca30b022015-09-03 17:50:04 +02001667
1668 od->od_inst_dict = dict;
1669 /* type constructor fills the memory with zeros (see
1670 PyType_GenericAlloc()), there is no need to set them to zero again */
1671 if (_odict_resize(od) < 0) {
1672 Py_DECREF(od);
1673 return NULL;
1674 }
1675
1676 return (PyObject*)od;
Eric Snow96c6af92015-05-29 22:21:39 -06001677}
1678
1679/* PyODict_Type */
1680
1681PyTypeObject PyODict_Type = {
1682 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1683 "collections.OrderedDict", /* tp_name */
1684 sizeof(PyODictObject), /* tp_basicsize */
1685 0, /* tp_itemsize */
1686 (destructor)odict_dealloc, /* tp_dealloc */
1687 0, /* tp_print */
1688 0, /* tp_getattr */
1689 0, /* tp_setattr */
1690 0, /* tp_reserved */
1691 (reprfunc)odict_repr, /* tp_repr */
1692 0, /* tp_as_number */
1693 0, /* tp_as_sequence */
1694 &odict_as_mapping, /* tp_as_mapping */
1695 0, /* tp_hash */
1696 0, /* tp_call */
1697 0, /* tp_str */
1698 0, /* tp_getattro */
1699 0, /* tp_setattro */
1700 0, /* tp_as_buffer */
1701 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1702 odict_doc, /* tp_doc */
1703 (traverseproc)odict_traverse, /* tp_traverse */
1704 (inquiry)odict_tp_clear, /* tp_clear */
1705 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1706 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1707 (getiterfunc)odict_iter, /* tp_iter */
1708 0, /* tp_iternext */
1709 odict_methods, /* tp_methods */
1710 odict_members, /* tp_members */
1711 0, /* tp_getset */
1712 &PyDict_Type, /* tp_base */
1713 0, /* tp_dict */
1714 0, /* tp_descr_get */
1715 0, /* tp_descr_set */
1716 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1717 (initproc)odict_init, /* tp_init */
1718 PyType_GenericAlloc, /* tp_alloc */
1719 (newfunc)odict_new, /* tp_new */
1720 0, /* tp_free */
1721};
1722
1723
1724/* ----------------------------------------------
1725 * the public OrderedDict API
1726 */
1727
1728PyObject *
1729PyODict_New(void) {
1730 return odict_new(&PyODict_Type, NULL, NULL);
1731};
1732
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001733static int
1734_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1735 Py_hash_t hash)
1736{
1737 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001738 if (res == 0) {
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001739 res = _odict_add_new_node((PyODictObject *)od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001740 if (res < 0) {
1741 /* Revert setting the value on the dict */
1742 PyObject *exc, *val, *tb;
1743 PyErr_Fetch(&exc, &val, &tb);
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001744 (void) _PyDict_DelItem_KnownHash(od, key, hash);
Serhiy Storchakad5f353e2015-11-06 11:07:11 +02001745 _PyErr_ChainExceptions(exc, val, tb);
1746 }
Eric Snow96c6af92015-05-29 22:21:39 -06001747 }
1748 return res;
1749};
1750
1751int
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001752PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1753{
1754 Py_hash_t hash = PyObject_Hash(key);
1755 if (hash == -1)
1756 return -1;
1757 return _PyODict_SetItem_KnownHash(od, key, value, hash);
1758};
1759
1760int
1761PyODict_DelItem(PyObject *od, PyObject *key)
1762{
1763 int res;
1764 Py_hash_t hash = PyObject_Hash(key);
1765 if (hash == -1)
1766 return -1;
1767 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001768 if (res < 0)
1769 return -1;
Serhiy Storchaka19a70e72015-11-13 14:48:36 +02001770 return _PyDict_DelItem_KnownHash(od, key, hash);
Eric Snow96c6af92015-05-29 22:21:39 -06001771};
1772
1773
1774/* -------------------------------------------
1775 * The OrderedDict views (keys/values/items)
1776 */
1777
1778typedef struct {
1779 PyObject_HEAD
1780 int kind;
1781 PyODictObject *di_odict;
Eric Snowb952ab42015-06-01 23:35:13 -06001782 Py_ssize_t di_size;
Eric Snow4fabf022015-06-04 00:09:56 -06001783 size_t di_state;
Eric Snow96c6af92015-05-29 22:21:39 -06001784 PyObject *di_current;
1785 PyObject *di_result; /* reusable result tuple for iteritems */
1786} odictiterobject;
1787
1788static void
1789odictiter_dealloc(odictiterobject *di)
1790{
1791 _PyObject_GC_UNTRACK(di);
Eric Snowa762af72015-06-01 22:59:08 -06001792 Py_XDECREF(di->di_odict);
Eric Snow96c6af92015-05-29 22:21:39 -06001793 Py_XDECREF(di->di_current);
1794 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1795 Py_DECREF(di->di_result);
1796 }
1797 PyObject_GC_Del(di);
1798}
1799
1800static int
1801odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1802{
1803 Py_VISIT(di->di_odict);
1804 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1805 Py_VISIT(di->di_result);
1806 return 0;
1807}
1808
Eric Snowa762af72015-06-01 22:59:08 -06001809/* In order to protect against modifications during iteration, we track
1810 * the current key instead of the current node. */
Eric Snow96c6af92015-05-29 22:21:39 -06001811static PyObject *
1812odictiter_nextkey(odictiterobject *di)
1813{
Eric Snowa762af72015-06-01 22:59:08 -06001814 PyObject *key = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001815 _ODictNode *node;
1816 int reversed = di->kind & _odict_ITER_REVERSED;
1817
Eric Snowa762af72015-06-01 22:59:08 -06001818 if (di->di_odict == NULL)
Eric Snow96c6af92015-05-29 22:21:39 -06001819 return NULL;
Eric Snowa762af72015-06-01 22:59:08 -06001820 if (di->di_current == NULL)
1821 goto done; /* We're already done. */
1822
Eric Snowb952ab42015-06-01 23:35:13 -06001823 /* Check for unsupported changes. */
Eric Snow4fabf022015-06-04 00:09:56 -06001824 if (di->di_odict->od_state != di->di_state) {
1825 PyErr_SetString(PyExc_RuntimeError,
1826 "OrderedDict mutated during iteration");
1827 goto done;
1828 }
Eric Snowb952ab42015-06-01 23:35:13 -06001829 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1830 PyErr_SetString(PyExc_RuntimeError,
1831 "OrderedDict changed size during iteration");
1832 di->di_size = -1; /* Make this state sticky */
1833 return NULL;
1834 }
1835
Eric Snowa762af72015-06-01 22:59:08 -06001836 /* Get the key. */
Eric Snow96c6af92015-05-29 22:21:39 -06001837 node = _odict_find_node(di->di_odict, di->di_current);
1838 if (node == NULL) {
Serhiy Storchakab45b7b22015-11-04 22:05:38 +02001839 if (!PyErr_Occurred())
1840 PyErr_SetObject(PyExc_KeyError, di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001841 /* Must have been deleted. */
Eric Snowe3dfa9e2015-05-30 12:51:15 -06001842 Py_CLEAR(di->di_current);
Eric Snow96c6af92015-05-29 22:21:39 -06001843 return NULL;
1844 }
1845 key = di->di_current;
1846
1847 /* Advance to the next key. */
1848 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1849 if (node == NULL) {
1850 /* Reached the end. */
1851 di->di_current = NULL;
1852 }
1853 else {
1854 di->di_current = _odictnode_KEY(node);
1855 Py_INCREF(di->di_current);
1856 }
1857
1858 return key;
Eric Snowa762af72015-06-01 22:59:08 -06001859
1860done:
1861 Py_CLEAR(di->di_odict);
1862 return key;
Eric Snow96c6af92015-05-29 22:21:39 -06001863}
1864
1865static PyObject *
1866odictiter_iternext(odictiterobject *di)
1867{
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001868 PyObject *result, *value;
Eric Snow96c6af92015-05-29 22:21:39 -06001869 PyObject *key = odictiter_nextkey(di); /* new reference */
1870
1871 if (key == NULL)
1872 return NULL;
1873
1874 /* Handle the keys case. */
1875 if (! (di->kind & _odict_ITER_VALUES)) {
1876 return key;
1877 }
1878
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001879 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1880 if (value == NULL) {
1881 if (!PyErr_Occurred())
1882 PyErr_SetObject(PyExc_KeyError, key);
Eric Snow96c6af92015-05-29 22:21:39 -06001883 Py_DECREF(key);
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001884 goto done;
1885 }
1886 Py_INCREF(value);
1887
1888 /* Handle the values case. */
1889 if (!(di->kind & _odict_ITER_KEYS)) {
1890 Py_DECREF(key);
Eric Snow96c6af92015-05-29 22:21:39 -06001891 return value;
1892 }
Eric Snowa762af72015-06-01 22:59:08 -06001893
Serhiy Storchaka9c967612015-11-06 10:39:51 +02001894 /* Handle the items case. */
1895 result = di->di_result;
1896
1897 if (Py_REFCNT(result) == 1) {
1898 /* not in use so we can reuse it
1899 * (the common case during iteration) */
1900 Py_INCREF(result);
1901 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1902 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1903 }
1904 else {
1905 result = PyTuple_New(2);
1906 if (result == NULL) {
1907 Py_DECREF(key);
1908 Py_DECREF(value);
1909 goto done;
1910 }
1911 }
1912
1913 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1914 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1915 return result;
1916
Eric Snowa762af72015-06-01 22:59:08 -06001917done:
1918 Py_CLEAR(di->di_current);
1919 Py_CLEAR(di->di_odict);
1920 return NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06001921}
1922
1923/* No need for tp_clear because odictiterobject is not mutable. */
1924
1925PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1926
1927static PyObject *
1928odictiter_reduce(odictiterobject *di)
1929{
Eric Snowc5e59602015-05-30 11:28:56 -06001930 PyObject *list, *iter;
Eric Snow96c6af92015-05-29 22:21:39 -06001931
1932 list = PyList_New(0);
1933 if (!list)
1934 return NULL;
1935
1936 /* iterate the temporary into a list */
1937 for(;;) {
1938 PyObject *element = odictiter_iternext(di);
1939 if (element) {
1940 if (PyList_Append(list, element)) {
1941 Py_DECREF(element);
1942 Py_DECREF(list);
1943 return NULL;
1944 }
1945 Py_DECREF(element);
1946 }
1947 else {
1948 /* done iterating? */
1949 break;
1950 }
1951 }
1952 if (PyErr_Occurred()) {
1953 Py_DECREF(list);
1954 return NULL;
1955 }
Eric Snowc5e59602015-05-30 11:28:56 -06001956 iter = _PyObject_GetBuiltin("iter");
1957 if (iter == NULL) {
1958 Py_DECREF(list);
1959 return NULL;
1960 }
1961 return Py_BuildValue("N(N)", iter, list);
Eric Snow96c6af92015-05-29 22:21:39 -06001962}
1963
1964static PyMethodDef odictiter_methods[] = {
1965 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1966 {NULL, NULL} /* sentinel */
1967};
1968
1969PyTypeObject PyODictIter_Type = {
1970 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1971 "odict_iterator", /* tp_name */
1972 sizeof(odictiterobject), /* tp_basicsize */
1973 0, /* tp_itemsize */
1974 /* methods */
1975 (destructor)odictiter_dealloc, /* tp_dealloc */
1976 0, /* tp_print */
1977 0, /* tp_getattr */
1978 0, /* tp_setattr */
1979 0, /* tp_reserved */
1980 0, /* tp_repr */
1981 0, /* tp_as_number */
1982 0, /* tp_as_sequence */
1983 0, /* tp_as_mapping */
1984 0, /* tp_hash */
1985 0, /* tp_call */
1986 0, /* tp_str */
1987 PyObject_GenericGetAttr, /* tp_getattro */
1988 0, /* tp_setattro */
1989 0, /* tp_as_buffer */
1990 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1991 0, /* tp_doc */
1992 (traverseproc)odictiter_traverse, /* tp_traverse */
1993 0, /* tp_clear */
1994 0, /* tp_richcompare */
1995 0, /* tp_weaklistoffset */
1996 PyObject_SelfIter, /* tp_iter */
1997 (iternextfunc)odictiter_iternext, /* tp_iternext */
1998 odictiter_methods, /* tp_methods */
1999 0,
2000};
2001
2002static PyObject *
2003odictiter_new(PyODictObject *od, int kind)
2004{
2005 odictiterobject *di;
2006 _ODictNode *node;
2007 int reversed = kind & _odict_ITER_REVERSED;
2008
2009 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
2010 if (di == NULL)
2011 return NULL;
2012
2013 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
2014 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
2015 if (di->di_result == NULL) {
2016 Py_DECREF(di);
2017 return NULL;
2018 }
2019 }
2020 else
2021 di->di_result = NULL;
2022
2023 di->kind = kind;
2024 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
2025 di->di_current = node ? _odictnode_KEY(node) : NULL;
2026 Py_XINCREF(di->di_current);
Eric Snowb952ab42015-06-01 23:35:13 -06002027 di->di_size = PyODict_SIZE(od);
Eric Snow4fabf022015-06-04 00:09:56 -06002028 di->di_state = od->od_state;
Eric Snow96c6af92015-05-29 22:21:39 -06002029 di->di_odict = od;
2030 Py_INCREF(od);
2031
2032 _PyObject_GC_TRACK(di);
2033 return (PyObject *)di;
2034}
2035
2036/* keys() */
2037
2038static PyObject *
2039odictkeys_iter(_PyDictViewObject *dv)
2040{
2041 if (dv->dv_dict == NULL) {
2042 Py_RETURN_NONE;
2043 }
2044 return odictiter_new((PyODictObject *)dv->dv_dict,
2045 _odict_ITER_KEYS);
2046}
2047
2048static PyObject *
2049odictkeys_reversed(_PyDictViewObject *dv)
2050{
2051 if (dv->dv_dict == NULL) {
2052 Py_RETURN_NONE;
2053 }
2054 return odictiter_new((PyODictObject *)dv->dv_dict,
2055 _odict_ITER_KEYS|_odict_ITER_REVERSED);
2056}
2057
2058static PyMethodDef odictkeys_methods[] = {
2059 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
2060 {NULL, NULL} /* sentinel */
2061};
2062
2063PyTypeObject PyODictKeys_Type = {
2064 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2065 "odict_keys", /* tp_name */
2066 0, /* tp_basicsize */
2067 0, /* tp_itemsize */
2068 0, /* tp_dealloc */
2069 0, /* tp_print */
2070 0, /* tp_getattr */
2071 0, /* tp_setattr */
2072 0, /* tp_reserved */
2073 0, /* tp_repr */
2074 0, /* tp_as_number */
2075 0, /* tp_as_sequence */
2076 0, /* tp_as_mapping */
2077 0, /* tp_hash */
2078 0, /* tp_call */
2079 0, /* tp_str */
2080 0, /* tp_getattro */
2081 0, /* tp_setattro */
2082 0, /* tp_as_buffer */
2083 0, /* tp_flags */
2084 0, /* tp_doc */
2085 0, /* tp_traverse */
2086 0, /* tp_clear */
2087 0, /* tp_richcompare */
2088 0, /* tp_weaklistoffset */
2089 (getiterfunc)odictkeys_iter, /* tp_iter */
2090 0, /* tp_iternext */
2091 odictkeys_methods, /* tp_methods */
2092 0, /* tp_members */
2093 0, /* tp_getset */
2094 &PyDictKeys_Type, /* tp_base */
2095};
2096
2097static PyObject *
2098odictkeys_new(PyObject *od)
2099{
2100 return _PyDictView_New(od, &PyODictKeys_Type);
2101}
2102
2103/* items() */
2104
2105static PyObject *
2106odictitems_iter(_PyDictViewObject *dv)
2107{
2108 if (dv->dv_dict == NULL) {
2109 Py_RETURN_NONE;
2110 }
2111 return odictiter_new((PyODictObject *)dv->dv_dict,
2112 _odict_ITER_KEYS|_odict_ITER_VALUES);
2113}
2114
2115static PyObject *
2116odictitems_reversed(_PyDictViewObject *dv)
2117{
2118 if (dv->dv_dict == NULL) {
2119 Py_RETURN_NONE;
2120 }
2121 return odictiter_new((PyODictObject *)dv->dv_dict,
2122 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2123}
2124
2125static PyMethodDef odictitems_methods[] = {
2126 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
2127 {NULL, NULL} /* sentinel */
2128};
2129
2130PyTypeObject PyODictItems_Type = {
2131 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2132 "odict_items", /* tp_name */
2133 0, /* tp_basicsize */
2134 0, /* tp_itemsize */
2135 0, /* tp_dealloc */
2136 0, /* tp_print */
2137 0, /* tp_getattr */
2138 0, /* tp_setattr */
2139 0, /* tp_reserved */
2140 0, /* tp_repr */
2141 0, /* tp_as_number */
2142 0, /* tp_as_sequence */
2143 0, /* tp_as_mapping */
2144 0, /* tp_hash */
2145 0, /* tp_call */
2146 0, /* tp_str */
2147 0, /* tp_getattro */
2148 0, /* tp_setattro */
2149 0, /* tp_as_buffer */
2150 0, /* tp_flags */
2151 0, /* tp_doc */
2152 0, /* tp_traverse */
2153 0, /* tp_clear */
2154 0, /* tp_richcompare */
2155 0, /* tp_weaklistoffset */
2156 (getiterfunc)odictitems_iter, /* tp_iter */
2157 0, /* tp_iternext */
2158 odictitems_methods, /* tp_methods */
2159 0, /* tp_members */
2160 0, /* tp_getset */
2161 &PyDictItems_Type, /* tp_base */
2162};
2163
2164static PyObject *
2165odictitems_new(PyObject *od)
2166{
2167 return _PyDictView_New(od, &PyODictItems_Type);
2168}
2169
2170/* values() */
2171
2172static PyObject *
2173odictvalues_iter(_PyDictViewObject *dv)
2174{
2175 if (dv->dv_dict == NULL) {
2176 Py_RETURN_NONE;
2177 }
2178 return odictiter_new((PyODictObject *)dv->dv_dict,
2179 _odict_ITER_VALUES);
2180}
2181
2182static PyObject *
2183odictvalues_reversed(_PyDictViewObject *dv)
2184{
2185 if (dv->dv_dict == NULL) {
2186 Py_RETURN_NONE;
2187 }
2188 return odictiter_new((PyODictObject *)dv->dv_dict,
2189 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2190}
2191
2192static PyMethodDef odictvalues_methods[] = {
2193 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2194 {NULL, NULL} /* sentinel */
2195};
2196
2197PyTypeObject PyODictValues_Type = {
2198 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2199 "odict_values", /* tp_name */
2200 0, /* tp_basicsize */
2201 0, /* tp_itemsize */
2202 0, /* tp_dealloc */
2203 0, /* tp_print */
2204 0, /* tp_getattr */
2205 0, /* tp_setattr */
2206 0, /* tp_reserved */
2207 0, /* tp_repr */
2208 0, /* tp_as_number */
2209 0, /* tp_as_sequence */
2210 0, /* tp_as_mapping */
2211 0, /* tp_hash */
2212 0, /* tp_call */
2213 0, /* tp_str */
2214 0, /* tp_getattro */
2215 0, /* tp_setattro */
2216 0, /* tp_as_buffer */
2217 0, /* tp_flags */
2218 0, /* tp_doc */
2219 0, /* tp_traverse */
2220 0, /* tp_clear */
2221 0, /* tp_richcompare */
2222 0, /* tp_weaklistoffset */
2223 (getiterfunc)odictvalues_iter, /* tp_iter */
2224 0, /* tp_iternext */
2225 odictvalues_methods, /* tp_methods */
2226 0, /* tp_members */
2227 0, /* tp_getset */
2228 &PyDictValues_Type, /* tp_base */
2229};
2230
2231static PyObject *
2232odictvalues_new(PyObject *od)
2233{
2234 return _PyDictView_New(od, &PyODictValues_Type);
2235}
2236
2237
2238/* ----------------------------------------------
2239 MutableMappping implementations
2240
2241Mapping:
2242
2243============ ===========
2244method uses
2245============ ===========
2246__contains__ __getitem__
2247__eq__ items
2248__getitem__ +
2249__iter__ +
2250__len__ +
2251__ne__ __eq__
2252get __getitem__
2253items ItemsView
2254keys KeysView
2255values ValuesView
2256============ ===========
2257
2258ItemsView uses __len__, __iter__, and __getitem__.
2259KeysView uses __len__, __iter__, and __contains__.
2260ValuesView uses __len__, __iter__, and __getitem__.
2261
2262MutableMapping:
2263
2264============ ===========
2265method uses
2266============ ===========
2267__delitem__ +
2268__setitem__ +
2269clear popitem
2270pop __getitem__
2271 __delitem__
2272popitem __iter__
2273 _getitem__
2274 __delitem__
2275setdefault __getitem__
2276 __setitem__
2277update __setitem__
2278============ ===========
2279*/
2280
2281static int
2282mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2283{
2284 PyObject *pair, *iterator, *unexpected;
2285 int res = 0;
2286
2287 iterator = PyObject_GetIter(pairs);
2288 if (iterator == NULL)
2289 return -1;
2290 PyErr_Clear();
2291
2292 while ((pair = PyIter_Next(iterator)) != NULL) {
2293 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
Eric Snowc5e59602015-05-30 11:28:56 -06002294 PyObject *key = NULL, *value = NULL;
Eric Snow96c6af92015-05-29 22:21:39 -06002295 PyObject *pair_iterator = PyObject_GetIter(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002296 if (pair_iterator == NULL)
2297 goto Done;
Eric Snow96c6af92015-05-29 22:21:39 -06002298
2299 key = PyIter_Next(pair_iterator);
2300 if (key == NULL) {
2301 if (!PyErr_Occurred())
2302 PyErr_SetString(PyExc_ValueError,
2303 "need more than 0 values to unpack");
2304 goto Done;
2305 }
2306
2307 value = PyIter_Next(pair_iterator);
2308 if (value == NULL) {
2309 if (!PyErr_Occurred())
2310 PyErr_SetString(PyExc_ValueError,
2311 "need more than 1 value to unpack");
2312 goto Done;
2313 }
2314
2315 unexpected = PyIter_Next(pair_iterator);
2316 if (unexpected != NULL) {
2317 Py_DECREF(unexpected);
2318 PyErr_SetString(PyExc_ValueError,
2319 "too many values to unpack (expected 2)");
2320 goto Done;
2321 }
2322 else if (PyErr_Occurred())
2323 goto Done;
2324
2325 res = PyObject_SetItem(self, key, value);
2326
2327Done:
2328 Py_DECREF(pair);
Eric Snowc5e59602015-05-30 11:28:56 -06002329 Py_XDECREF(pair_iterator);
Eric Snow96c6af92015-05-29 22:21:39 -06002330 Py_XDECREF(key);
2331 Py_XDECREF(value);
2332 if (PyErr_Occurred())
2333 break;
2334 }
2335 Py_DECREF(iterator);
2336
2337 if (res < 0 || PyErr_Occurred() != NULL)
2338 return -1;
2339 else
2340 return 0;
2341}
2342
2343static PyObject *
2344mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2345{
2346 int res = 0;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002347 Py_ssize_t len;
2348 _Py_IDENTIFIER(items);
2349 _Py_IDENTIFIER(keys);
Eric Snow96c6af92015-05-29 22:21:39 -06002350
2351 /* first handle args, if any */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002352 assert(args == NULL || PyTuple_Check(args));
2353 len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
Benjamin Peterson99e96f22015-06-06 23:20:32 -05002354 if (len > 1) {
Eric Snow96c6af92015-05-29 22:21:39 -06002355 char *msg = "update() takes at most 1 positional argument (%d given)";
2356 PyErr_Format(PyExc_TypeError, msg, len);
2357 return NULL;
2358 }
Eric Snow96c6af92015-05-29 22:21:39 -06002359
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002360 if (len) {
Benjamin Peterson0718de92015-06-07 00:00:42 -05002361 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002362 assert(other != NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002363 Py_INCREF(other);
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002364 if (PyDict_CheckExact(other) ||
2365 _PyObject_HasAttrId(other, &PyId_items)) { /* never fails */
2366 PyObject *items;
2367 if (PyDict_CheckExact(other))
2368 items = PyDict_Items(other);
2369 else
2370 items = _PyObject_CallMethodId(other, &PyId_items, NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002371 Py_DECREF(other);
2372 if (items == NULL)
2373 return NULL;
2374 res = mutablemapping_add_pairs(self, items);
2375 Py_DECREF(items);
2376 if (res == -1)
2377 return NULL;
2378 }
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002379 else if (_PyObject_HasAttrId(other, &PyId_keys)) { /* never fails */
Benjamin Peterson0718de92015-06-07 00:00:42 -05002380 PyObject *keys, *iterator, *key;
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002381 keys = _PyObject_CallMethodIdObjArgs(other, &PyId_keys, NULL);
Benjamin Peterson0718de92015-06-07 00:00:42 -05002382 if (keys == NULL) {
2383 Py_DECREF(other);
2384 return NULL;
2385 }
2386 iterator = PyObject_GetIter(keys);
2387 Py_DECREF(keys);
2388 if (iterator == NULL) {
2389 Py_DECREF(other);
2390 return NULL;
2391 }
2392 while (res == 0 && (key = PyIter_Next(iterator))) {
2393 PyObject *value = PyObject_GetItem(other, key);
2394 if (value != NULL) {
2395 res = PyObject_SetItem(self, key, value);
2396 Py_DECREF(value);
2397 }
2398 else {
2399 res = -1;
2400 }
2401 Py_DECREF(key);
2402 }
2403 Py_DECREF(other);
2404 Py_DECREF(iterator);
2405 if (res != 0 || PyErr_Occurred())
2406 return NULL;
2407 }
2408 else {
2409 res = mutablemapping_add_pairs(self, other);
2410 Py_DECREF(other);
2411 if (res != 0)
2412 return NULL;
2413 }
2414 }
2415
2416 /* now handle kwargs */
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002417 assert(kwargs == NULL || PyDict_Check(kwargs));
2418 len = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
Benjamin Peterson0718de92015-06-07 00:00:42 -05002419 if (len > 0) {
Serhiy Storchaka8003baf2015-10-18 09:53:17 +03002420 PyObject *items = PyDict_Items(kwargs);
Eric Snow96c6af92015-05-29 22:21:39 -06002421 if (items == NULL)
2422 return NULL;
2423 res = mutablemapping_add_pairs(self, items);
2424 Py_DECREF(items);
2425 if (res == -1)
2426 return NULL;
2427 }
Eric Snow96c6af92015-05-29 22:21:39 -06002428
2429 Py_RETURN_NONE;
2430}