1 /* Ordered Dictionary object implementation.
2
3 This implementation is necessarily explicitly equivalent to the pure Python
4 OrderedDict class in Lib/collections/__init__.py. The strategy there
5 involves using a doubly-linked-list to capture the order. We keep to that
6 strategy, using a lower-level linked-list.
7
8 About the Linked-List
9 =====================
10
11 For the linked list we use a basic doubly-linked-list. Using a circularly-
12 linked-list does have some benefits, but they don't apply so much here
13 since OrderedDict is focused on the ends of the list (for the most part).
14 Furthermore, there are some features of generic linked-lists that we simply
15 don't need for OrderedDict. Thus a simple custom implementation meets our
16 needs. Alternatives to our simple approach include the QCIRCLE_*
17 macros from BSD's queue.h, and the linux's list.h.
18
19 Getting O(1) Node Lookup
20 ------------------------
21
22 One invariant of Python's OrderedDict is that it preserves time complexity
23 of dict's methods, particularly the O(1) operations. Simply adding a
24 linked-list on top of dict is not sufficient here; operations for nodes in
25 the middle of the linked-list implicitly require finding the node first.
26 With a simple linked-list like we're using, that is an O(n) operation.
27 Consequently, methods like __delitem__() would change from O(1) to O(n),
28 which is unacceptable.
29
30 In order to preserve O(1) performance for node removal (finding nodes), we
31 must do better than just looping through the linked-list. Here are options
32 we've considered:
33
34 1. use a second dict to map keys to nodes (a la the pure Python version).
35 2. keep a simple hash table mirroring the order of dict's, mapping each key
36 to the corresponding node in the linked-list.
37 3. use a version of shared keys (split dict) that allows non-unicode keys.
38 4. have the value stored for each key be a (value, node) pair, and adjust
39 __getitem__(), get(), etc. accordingly.
40
41 The approach with the least performance impact (time and space) is #2,
42 mirroring the key order of dict's dk_entries with an array of node pointers.
43 While lookdict() and friends (dk_lookup) don't give us the index into the
44 array, we make use of pointer arithmetic to get that index. An alternative
45 would be to refactor lookdict() to provide the index, explicitly exposing
46 the implementation detail. We could even just use a custom lookup function
47 for OrderedDict that facilitates our need. However, both approaches are
48 significantly more complicated than just using pointer arithmetic.
49
50 The catch with mirroring the hash table ordering is that we have to keep
51 the ordering in sync through any dict resizes. However, that order only
52 matters during node lookup. We can simply defer any potential resizing
53 until we need to do a lookup.
54
55 Linked-List Nodes
56 -----------------
57
58 The current implementation stores a pointer to the associated key only.
59 One alternative would be to store a pointer to the PyDictKeyEntry instead.
60 This would save one pointer de-reference per item, which is nice during
61 calls to values() and items(). However, it adds unnecessary overhead
62 otherwise, so we stick with just the key.
63
64 Linked-List API
65 ---------------
66
67 As noted, the linked-list implemented here does not have all the bells and
68 whistles. However, we recognize that the implementation may need to
69 change to accommodate performance improvements or extra functionality. To
70 that end, we use a simple API to interact with the linked-list. Here's a
71 summary of the methods/macros:
72
73 Node info:
74
75 * _odictnode_KEY(node)
76 * _odictnode_VALUE(od, node)
77 * _odictnode_PREV(node)
78 * _odictnode_NEXT(node)
79
80 Linked-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
87 For adding nodes:
88
89 * _odict_add_head(od, node)
90 * _odict_add_tail(od, node)
91 * _odict_add_new_node(od, key, hash)
92
93 For removing nodes:
94
95 * _odict_clear_node(od, node, key, hash)
96 * _odict_clear_nodes(od, clear_each)
97
98 Others:
99
100 * _odict_find_node_hash(od, key, hash)
101 * _odict_find_node(od, key)
102 * _odict_keys_equal(od1, od2)
103
104 And here's a look at how the linked-list relates to the OrderedDict API:
105
106 ============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
107 method key val prev next mem 1st last empty iter find add rmv clr keq
108 ============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
109 __del__ ~ X
110 __delitem__ free ~ node
111 __eq__ ~ X
112 __iter__ X X
113 __new__ X X
114 __reduce__ X ~ X
115 __repr__ X X X
116 __reversed__ X X
117 __setitem__ key
118 __sizeof__ size X
119 clear ~ ~ X
120 copy X X X
121 items X X X
122 keys X X
123 move_to_end X X X ~ h/t key
124 pop free key
125 popitem X X free X X node
126 setdefault ~ ? ~
127 values X X
128 ============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
129
130 __delitem__ is the only method that directly relies on finding an arbitrary
131 node in the linked-list. Everything else is iteration or relates to the
132 ends of the linked-list.
133
134 Situation that Endangers Consistency
135 ------------------------------------
136 Using a raw linked-list for OrderedDict exposes a key situation that can
137 cause problems. If a node is stored in a variable, there is a chance that
138 the node may have been deallocated before the variable gets used, thus
139 potentially leading to a segmentation fault. A key place where this shows
140 up is during iteration through the linked list (via _odict_FOREACH or
141 otherwise).
142
143 A number of solutions are available to resolve this situation:
144
145 * defer looking up the node until as late as possible and certainly after
146 any code that could possibly result in a deletion;
147 * if the node is needed both before and after a point where the node might
148 be removed, do a check before using the node at the "after" location to
149 see if the node is still valid;
150 * like the last one, but simply pull the node again to ensure it's right;
151 * keep the key in the variable instead of the node and then look up the
152 node using the key at the point where the node is needed (this is what
153 we do for the iterators).
154
155 Another related problem, preserving consistent ordering during iteration,
156 is described below. That one is not exclusive to using linked-lists.
157
158
159 Challenges from Subclassing dict
160 ================================
161
162 OrderedDict subclasses dict, which is an unusual relationship between two
163 builtin types (other than the base object type). Doing so results in
164 some complication and deserves further explanation. There are two things
165 to consider here. First, in what circumstances or with what adjustments
166 can OrderedDict be used as a drop-in replacement for dict (at the C level)?
167 Second, how can the OrderedDict implementation leverage the dict
168 implementation effectively without introducing unnecessary coupling or
169 inefficiencies?
170
171 This second point is reflected here and in the implementation, so the
172 further focus is on the first point. It is worth noting that for
173 overridden methods, the dict implementation is deferred to as much as
174 possible. Furthermore, coupling is limited to as little as is reasonable.
175
176 Concrete API Compatibility
177 --------------------------
178
179 Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
180 problematic. (See http://bugs.python.org/issue10977.) The concrete API
181 has a number of hard-coded assumptions tied to the dict implementation.
182 This is, in part, due to performance reasons, which is understandable
183 given the part dict plays in Python.
184
185 Any attempt to replace dict with OrderedDict for any role in the
186 interpreter (e.g. **kwds) faces a challenge. Such any effort must
187 recognize that the instances in affected locations currently interact with
188 the concrete API.
189
190 Here are some ways to address this challenge:
191
192 1. Change the relevant usage of the concrete API in CPython and add
193 PyDict_CheckExact() calls to each of the concrete API functions.
194 2. Adjust the relevant concrete API functions to explicitly accommodate
195 OrderedDict.
196 3. As with #1, add the checks, but improve the abstract API with smart fast
197 paths for dict and OrderedDict, and refactor CPython to use the abstract
198 API. Improvements to the abstract API would be valuable regardless.
199
200 Adding the checks to the concrete API would help make any interpreter
201 switch to OrderedDict less painful for extension modules. However, this
202 won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)`
203 is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call
204 the base class's methods, since there is no equivalent of super() in the
205 C API. Calling into Python for parent class API would work, but some
206 extension modules already rely on this feature of the concrete API.
207
208 For reference, here is a breakdown of some of the dict concrete API:
209
210 ========================== ============= =======================
211 concrete API uses abstract API
212 ========================== ============= =======================
213 PyDict_Check PyMapping_Check
214 (PyDict_CheckExact) -
215 (PyDict_New) -
216 (PyDictProxy_New) -
217 PyDict_Clear -
218 PyDict_Contains PySequence_Contains
219 PyDict_Copy -
220 PyDict_SetItem PyObject_SetItem
221 PyDict_SetItemString PyMapping_SetItemString
222 PyDict_DelItem PyMapping_DelItem
223 PyDict_DelItemString PyMapping_DelItemString
224 PyDict_GetItem -
225 PyDict_GetItemWithError PyObject_GetItem
226 _PyDict_GetItemIdWithError -
227 PyDict_GetItemString PyMapping_GetItemString
228 PyDict_Items PyMapping_Items
229 PyDict_Keys PyMapping_Keys
230 PyDict_Values PyMapping_Values
231 PyDict_Size PyMapping_Size
232 PyMapping_Length
233 PyDict_Next PyIter_Next
234 _PyDict_Next -
235 PyDict_Merge -
236 PyDict_Update -
237 PyDict_MergeFromSeq2 -
238 PyDict_ClearFreeList -
239 - PyMapping_HasKeyString
240 - PyMapping_HasKey
241 ========================== ============= =======================
242
243
244 The dict Interface Relative to OrderedDict
245 ==========================================
246
247 Since OrderedDict subclasses dict, understanding the various methods and
248 attributes of dict is important for implementing OrderedDict.
249
250 Relevant Type Slots
251 -------------------
252
253 ================= ================ =================== ================
254 slot attribute object dict
255 ================= ================ =================== ================
256 tp_dealloc - object_dealloc dict_dealloc
257 tp_repr __repr__ object_repr dict_repr
258 sq_contains __contains__ - dict_contains
259 mp_length __len__ - dict_length
260 mp_subscript __getitem__ - dict_subscript
261 mp_ass_subscript __setitem__ - dict_ass_sub
262 __delitem__
263 tp_hash __hash__ _Py_HashPointer ..._HashNotImpl
264 tp_str __str__ object_str -
265 tp_getattro __getattribute__ ..._GenericGetAttr (repeated)
266 __getattr__
267 tp_setattro __setattr__ ..._GenericSetAttr (disabled)
268 tp_doc __doc__ (literal) dictionary_doc
269 tp_traverse - - dict_traverse
270 tp_clear - - dict_tp_clear
271 tp_richcompare __eq__ object_richcompare dict_richcompare
272 __ne__
273 tp_weaklistoffset (__weakref__) - -
274 tp_iter __iter__ - dict_iter
275 tp_dictoffset (__dict__) - -
276 tp_init __init__ object_init dict_init
277 tp_alloc - PyType_GenericAlloc (repeated)
278 tp_new __new__ object_new dict_new
279 tp_free - PyObject_Del PyObject_GC_Del
280 ================= ================ =================== ================
281
282 Relevant Methods
283 ----------------
284
285 ================ =================== ===============
286 method object dict
287 ================ =================== ===============
288 __reduce__ object_reduce -
289 __sizeof__ object_sizeof dict_sizeof
290 clear - dict_clear
291 copy - dict_copy
292 fromkeys - dict_fromkeys
293 get - dict_get
294 items - dictitems_new
295 keys - dictkeys_new
296 pop - dict_pop
297 popitem - dict_popitem
298 setdefault - dict_setdefault
299 update - dict_update
300 values - dictvalues_new
301 ================ =================== ===============
302
303
304 Pure Python OrderedDict
305 =======================
306
307 As already noted, compatibility with the pure Python OrderedDict
308 implementation is a key goal of this C implementation. To further that
309 goal, here's a summary of how OrderedDict-specific methods are implemented
310 in collections/__init__.py. Also provided is an indication of which
311 methods directly mutate or iterate the object, as well as any relationship
312 with the underlying linked-list.
313
314 ============= ============== == ================ === === ====
315 method impl used ll uses inq mut iter
316 ============= ============== == ================ === === ====
317 __contains__ dict - - X
318 __delitem__ OrderedDict Y dict.__delitem__ X
319 __eq__ OrderedDict N OrderedDict ~
320 dict.__eq__
321 __iter__
322 __getitem__ dict - - X
323 __iter__ OrderedDict Y - X
324 __init__ OrderedDict N update
325 __len__ dict - - X
326 __ne__ MutableMapping - __eq__ ~
327 __reduce__ OrderedDict N OrderedDict ~
328 __iter__
329 __getitem__
330 __repr__ OrderedDict N __class__ ~
331 items
332 __reversed__ OrderedDict Y - X
333 __setitem__ OrderedDict Y __contains__ X
334 dict.__setitem__
335 __sizeof__ OrderedDict Y __len__ ~
336 __dict__
337 clear OrderedDict Y dict.clear X
338 copy OrderedDict N __class__
339 __init__
340 fromkeys OrderedDict N __setitem__
341 get dict - - ~
342 items MutableMapping - ItemsView X
343 keys MutableMapping - KeysView X
344 move_to_end OrderedDict Y - X
345 pop OrderedDict N __contains__ X
346 __getitem__
347 __delitem__
348 popitem OrderedDict Y dict.pop X
349 setdefault OrderedDict N __contains__ ~
350 __getitem__
351 __setitem__
352 update MutableMapping - __setitem__ ~
353 values MutableMapping - ValuesView X
354 ============= ============== == ================ === === ====
355
356 __reversed__ and move_to_end are both exclusive to OrderedDict.
357
358
359 C OrderedDict Implementation
360 ============================
361
362 ================= ================
363 slot impl
364 ================= ================
365 tp_dealloc odict_dealloc
366 tp_repr odict_repr
367 mp_ass_subscript odict_ass_sub
368 tp_doc odict_doc
369 tp_traverse odict_traverse
370 tp_clear odict_tp_clear
371 tp_richcompare odict_richcompare
372 tp_weaklistoffset (offset)
373 tp_iter odict_iter
374 tp_dictoffset (offset)
375 tp_init odict_init
376 tp_alloc (repeated)
377 ================= ================
378
379 ================= ================
380 method impl
381 ================= ================
382 __reduce__ odict_reduce
383 __sizeof__ odict_sizeof
384 clear odict_clear
385 copy odict_copy
386 fromkeys odict_fromkeys
387 items odictitems_new
388 keys odictkeys_new
389 pop odict_pop
390 popitem odict_popitem
391 setdefault odict_setdefault
392 update odict_update
393 values odictvalues_new
394 ================= ================
395
396 Inherited unchanged from object/dict:
397
398 ================ ==========================
399 method type field
400 ================ ==========================
401 - tp_free
402 __contains__ tp_as_sequence.sq_contains
403 __getattr__ tp_getattro
404 __getattribute__ tp_getattro
405 __getitem__ tp_as_mapping.mp_subscript
406 __hash__ tp_hash
407 __len__ tp_as_mapping.mp_length
408 __setattr__ tp_setattro
409 __str__ tp_str
410 get -
411 ================ ==========================
412
413
414 Other Challenges
415 ================
416
417 Preserving Ordering During Iteration
418 ------------------------------------
419 During iteration through an OrderedDict, it is possible that items could
420 get added, removed, or reordered. For a linked-list implementation, as
421 with some other implementations, that situation may lead to undefined
422 behavior. The documentation for dict mentions this in the `iter()` section
423 of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
424 In this implementation we follow dict's lead (as does the pure Python
425 implementation) for __iter__(), keys(), values(), and items().
426
427 For internal iteration (using _odict_FOREACH or not), there is still the
428 risk that not all nodes that we expect to be seen in the loop actually get
429 seen. Thus, we are careful in each of those places to ensure that they
430 are. This comes, of course, at a small price at each location. The
431 solutions are much the same as those detailed in the `Situation that
432 Endangers Consistency` section above.
433
434
435 Potential Optimizations
436 =======================
437
438 * Allocate the nodes as a block via od_fast_nodes instead of individually.
439 - Set node->key to NULL to indicate the node is not-in-use.
440 - Add _odict_EXISTS()?
441 - How to maintain consistency across resizes? Existing node pointers
442 would be invalidated after a resize, which is particularly problematic
443 for the iterators.
444 * Use a more stream-lined implementation of update() and, likely indirectly,
445 __init__().
446
447 */
448
449 /* TODO
450
451 sooner:
452 - reentrancy (make sure everything is at a thread-safe state when calling
453 into Python). I've already checked this multiple times, but want to
454 make one more pass.
455 - add unit tests for reentrancy?
456
457 later:
458 - make the dict views support the full set API (the pure Python impl does)
459 - implement a fuller MutableMapping API in C?
460 - move the MutableMapping implementation to abstract.c?
461 - optimize mutablemapping_update
462 - use PyObject_MALLOC (small object allocator) for odict nodes?
463 - support subclasses better (e.g. in odict_richcompare)
464
465 */
466
467 #include "Python.h"
468 #include "pycore_object.h"
469 #include <stddef.h> // offsetof()
470 #include "dict-common.h"
471 #include <stddef.h>
472
473 #include "clinic/odictobject.c.h"
474
475 /*[clinic input]
476 class OrderedDict "PyODictObject *" "&PyODict_Type"
477 [clinic start generated code]*/
478 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
479
480
481 typedef struct _odictnode _ODictNode;
482
483 /* PyODictObject */
484 struct _odictobject {
485 PyDictObject od_dict; /* the underlying dict */
486 _ODictNode *od_first; /* first node in the linked list, if any */
487 _ODictNode *od_last; /* last node in the linked list, if any */
488 /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
489 * by _odict_resize().
490 * Note that we rely on implementation details of dict for both. */
491 _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */
492 Py_ssize_t od_fast_nodes_size;
493 void *od_resize_sentinel; /* changes if odict should be resized */
494
495 size_t od_state; /* incremented whenever the LL changes */
496 PyObject *od_inst_dict; /* OrderedDict().__dict__ */
497 PyObject *od_weakreflist; /* holds weakrefs to the odict */
498 };
499
500
501 /* ----------------------------------------------
502 * odict keys (a simple doubly-linked list)
503 */
504
505 struct _odictnode {
506 PyObject *key;
507 Py_hash_t hash;
508 _ODictNode *next;
509 _ODictNode *prev;
510 };
511
512 #define _odictnode_KEY(node) \
513 (node->key)
514 #define _odictnode_HASH(node) \
515 (node->hash)
516 /* borrowed reference */
517 #define _odictnode_VALUE(node, od) \
518 PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
519 #define _odictnode_PREV(node) (node->prev)
520 #define _odictnode_NEXT(node) (node->next)
521
522 #define _odict_FIRST(od) (((PyODictObject *)od)->od_first)
523 #define _odict_LAST(od) (((PyODictObject *)od)->od_last)
524 #define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
525 #define _odict_FOREACH(od, node) \
526 for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
527
528 _Py_IDENTIFIER(items);
529
530 /* Return the index into the hash table, regardless of a valid node. */
531 static Py_ssize_t
_odict_get_index_raw(PyODictObject * od,PyObject * key,Py_hash_t hash)532 _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
533 {
534 PyObject *value = NULL;
535 PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
536 Py_ssize_t ix;
537
538 ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value);
539 if (ix == DKIX_EMPTY) {
540 return keys->dk_nentries; /* index of new entry */
541 }
542 if (ix < 0)
543 return -1;
544 /* We use pointer arithmetic to get the entry's index into the table. */
545 return ix;
546 }
547
548 /* Replace od->od_fast_nodes with a new table matching the size of dict's. */
549 static int
_odict_resize(PyODictObject * od)550 _odict_resize(PyODictObject *od)
551 {
552 Py_ssize_t size, i;
553 _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. */
566 _odict_FOREACH(od, node) {
567 i = _odict_get_index_raw(od, _odictnode_KEY(node),
568 _odictnode_HASH(node));
569 if (i < 0) {
570 PyMem_FREE(fast_nodes);
571 return -1;
572 }
573 fast_nodes[i] = node;
574 }
575
576 /* Replace the old fast nodes table. */
577 PyMem_FREE(od->od_fast_nodes);
578 od->od_fast_nodes = fast_nodes;
579 od->od_fast_nodes_size = size;
580 od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
581 return 0;
582 }
583
584 /* Return the index into the hash table, regardless of a valid node. */
585 static Py_ssize_t
_odict_get_index(PyODictObject * od,PyObject * key,Py_hash_t hash)586 _odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
587 {
588 PyDictKeysObject *keys;
589
590 assert(key != NULL);
591 keys = ((PyDictObject *)od)->ma_keys;
592
593 /* Ensure od_fast_nodes and dk_entries are in sync. */
594 if (od->od_resize_sentinel != keys ||
595 od->od_fast_nodes_size != keys->dk_size) {
596 int resize_res = _odict_resize(od);
597 if (resize_res < 0)
598 return -1;
599 }
600
601 return _odict_get_index_raw(od, key, hash);
602 }
603
604 /* Returns NULL if there was some error or the key was not found. */
605 static _ODictNode *
_odict_find_node_hash(PyODictObject * od,PyObject * key,Py_hash_t hash)606 _odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
607 {
608 Py_ssize_t index;
609
610 if (_odict_EMPTY(od))
611 return NULL;
612 index = _odict_get_index(od, key, hash);
613 if (index < 0)
614 return NULL;
615 assert(od->od_fast_nodes != NULL);
616 return od->od_fast_nodes[index];
617 }
618
619 static _ODictNode *
_odict_find_node(PyODictObject * od,PyObject * key)620 _odict_find_node(PyODictObject *od, PyObject *key)
621 {
622 Py_ssize_t index;
623 Py_hash_t hash;
624
625 if (_odict_EMPTY(od))
626 return NULL;
627 hash = PyObject_Hash(key);
628 if (hash == -1)
629 return NULL;
630 index = _odict_get_index(od, key, hash);
631 if (index < 0)
632 return NULL;
633 assert(od->od_fast_nodes != NULL);
634 return od->od_fast_nodes[index];
635 }
636
637 static void
_odict_add_head(PyODictObject * od,_ODictNode * node)638 _odict_add_head(PyODictObject *od, _ODictNode *node)
639 {
640 _odictnode_PREV(node) = NULL;
641 _odictnode_NEXT(node) = _odict_FIRST(od);
642 if (_odict_FIRST(od) == NULL)
643 _odict_LAST(od) = node;
644 else
645 _odictnode_PREV(_odict_FIRST(od)) = node;
646 _odict_FIRST(od) = node;
647 od->od_state++;
648 }
649
650 static void
_odict_add_tail(PyODictObject * od,_ODictNode * node)651 _odict_add_tail(PyODictObject *od, _ODictNode *node)
652 {
653 _odictnode_PREV(node) = _odict_LAST(od);
654 _odictnode_NEXT(node) = NULL;
655 if (_odict_LAST(od) == NULL)
656 _odict_FIRST(od) = node;
657 else
658 _odictnode_NEXT(_odict_LAST(od)) = node;
659 _odict_LAST(od) = node;
660 od->od_state++;
661 }
662
663 /* adds the node to the end of the list */
664 static int
_odict_add_new_node(PyODictObject * od,PyObject * key,Py_hash_t hash)665 _odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
666 {
667 Py_ssize_t i;
668 _ODictNode *node;
669
670 Py_INCREF(key);
671 i = _odict_get_index(od, key, hash);
672 if (i < 0) {
673 if (!PyErr_Occurred())
674 PyErr_SetObject(PyExc_KeyError, key);
675 Py_DECREF(key);
676 return -1;
677 }
678 assert(od->od_fast_nodes != NULL);
679 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;
694 _odictnode_HASH(node) = hash;
695 _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. */
708 static void
_odict_remove_node(PyODictObject * od,_ODictNode * node)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;
723 od->od_state++;
724 }
725
726 /* 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.
729
730 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 */
742 static int
_odict_clear_node(PyODictObject * od,_ODictNode * node,PyObject * key,Py_hash_t hash)743 _odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
744 Py_hash_t hash)
745 {
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
754 i = _odict_get_index(od, key, hash);
755 if (i < 0)
756 return PyErr_Occurred() ? -1 : 0;
757
758 assert(od->od_fast_nodes != NULL);
759 if (node == NULL)
760 node = od->od_fast_nodes[i];
761 assert(node == od->od_fast_nodes[i]);
762 if (node == NULL) {
763 /* Let later code decide if this is a KeyError. */
764 return 0;
765 }
766
767 // Now clear the node.
768 od->od_fast_nodes[i] = NULL;
769 _odict_remove_node(od, node);
770 _odictnode_DEALLOC(node);
771 return 0;
772 }
773
774 static void
_odict_clear_nodes(PyODictObject * od)775 _odict_clear_nodes(PyODictObject *od)
776 {
777 _ODictNode *node, *next;
778
779 PyMem_FREE(od->od_fast_nodes);
780 od->od_fast_nodes = NULL;
781 od->od_fast_nodes_size = 0;
782 od->od_resize_sentinel = NULL;
783
784 node = _odict_FIRST(od);
785 _odict_FIRST(od) = NULL;
786 _odict_LAST(od) = NULL;
787 while (node != NULL) {
788 next = _odictnode_NEXT(node);
789 _odictnode_DEALLOC(node);
790 node = next;
791 }
792 }
793
794 /* There isn't any memory management of nodes past this point. */
795 #undef _odictnode_DEALLOC
796
797 static int
_odict_keys_equal(PyODictObject * a,PyODictObject * b)798 _odict_keys_equal(PyODictObject *a, PyODictObject *b)
799 {
800 _ODictNode *node_a, *node_b;
801
802 node_a = _odict_FIRST(a);
803 node_b = _odict_FIRST(b);
804 while (1) {
805 if (node_a == NULL && node_b == NULL)
806 /* success: hit the end of each at the same time */
807 return 1;
808 else if (node_a == NULL || node_b == NULL)
809 /* unequal length */
810 return 0;
811 else {
812 int res = PyObject_RichCompareBool(
813 (PyObject *)_odictnode_KEY(node_a),
814 (PyObject *)_odictnode_KEY(node_b),
815 Py_EQ);
816 if (res < 0)
817 return res;
818 else if (res == 0)
819 return 0;
820
821 /* otherwise it must match, so move on to the next one */
822 node_a = _odictnode_NEXT(node_a);
823 node_b = _odictnode_NEXT(node_b);
824 }
825 }
826 }
827
828
829 /* ----------------------------------------------
830 * OrderedDict mapping methods
831 */
832
833 /* mp_ass_subscript: __setitem__() and __delitem__() */
834
835 static int
odict_mp_ass_sub(PyODictObject * od,PyObject * v,PyObject * w)836 odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)
837 {
838 if (w == NULL)
839 return PyODict_DelItem((PyObject *)od, v);
840 else
841 return PyODict_SetItem((PyObject *)od, v, w);
842 }
843
844 /* tp_as_mapping */
845
846 static PyMappingMethods odict_as_mapping = {
847 0, /*mp_length*/
848 0, /*mp_subscript*/
849 (objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/
850 };
851
852
853 /* ----------------------------------------------
854 * OrderedDict number methods
855 */
856
857 static int mutablemapping_update_arg(PyObject*, PyObject*);
858
859 static PyObject *
odict_or(PyObject * left,PyObject * right)860 odict_or(PyObject *left, PyObject *right)
861 {
862 PyTypeObject *type;
863 PyObject *other;
864 if (PyODict_Check(left)) {
865 type = Py_TYPE(left);
866 other = right;
867 }
868 else {
869 type = Py_TYPE(right);
870 other = left;
871 }
872 if (!PyDict_Check(other)) {
873 Py_RETURN_NOTIMPLEMENTED;
874 }
875 PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
876 if (!new) {
877 return NULL;
878 }
879 if (mutablemapping_update_arg(new, right) < 0) {
880 Py_DECREF(new);
881 return NULL;
882 }
883 return new;
884 }
885
886 static PyObject *
odict_inplace_or(PyObject * self,PyObject * other)887 odict_inplace_or(PyObject *self, PyObject *other)
888 {
889 if (mutablemapping_update_arg(self, other) < 0) {
890 return NULL;
891 }
892 Py_INCREF(self);
893 return self;
894 }
895
896 /* tp_as_number */
897
898 static PyNumberMethods odict_as_number = {
899 .nb_or = odict_or,
900 .nb_inplace_or = odict_inplace_or,
901 };
902
903
904 /* ----------------------------------------------
905 * OrderedDict methods
906 */
907
908 /* fromkeys() */
909
910 /*[clinic input]
911 @classmethod
912 OrderedDict.fromkeys
913
914 iterable as seq: object
915 value: object = None
916
917 Create a new ordered dictionary with keys from iterable and values set to value.
918 [clinic start generated code]*/
919
920 static PyObject *
OrderedDict_fromkeys_impl(PyTypeObject * type,PyObject * seq,PyObject * value)921 OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
922 /*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/
923 {
924 return _PyDict_FromKeys((PyObject *)type, seq, value);
925 }
926
927 /* __sizeof__() */
928
929 /* OrderedDict.__sizeof__() does not have a docstring. */
930 PyDoc_STRVAR(odict_sizeof__doc__, "");
931
932 static PyObject *
odict_sizeof(PyODictObject * od,PyObject * Py_UNUSED (ignored))933 odict_sizeof(PyODictObject *od, PyObject *Py_UNUSED(ignored))
934 {
935 Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
936 res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
937 if (!_odict_EMPTY(od)) {
938 res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
939 }
940 return PyLong_FromSsize_t(res);
941 }
942
943 /* __reduce__() */
944
945 PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
946
947 static PyObject *
odict_reduce(register PyODictObject * od,PyObject * Py_UNUSED (ignored))948 odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
949 {
950 _Py_IDENTIFIER(__dict__);
951 PyObject *dict = NULL, *result = NULL;
952 PyObject *items_iter, *items, *args = NULL;
953
954 /* capture any instance state */
955 dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
956 if (dict == NULL)
957 goto Done;
958 else {
959 /* od.__dict__ isn't necessarily a dict... */
960 Py_ssize_t dict_len = PyObject_Length(dict);
961 if (dict_len == -1)
962 goto Done;
963 if (!dict_len) {
964 /* nothing to pickle in od.__dict__ */
965 Py_CLEAR(dict);
966 }
967 }
968
969 /* build the result */
970 args = PyTuple_New(0);
971 if (args == NULL)
972 goto Done;
973
974 items = _PyObject_CallMethodIdNoArgs((PyObject *)od, &PyId_items);
975 if (items == NULL)
976 goto Done;
977
978 items_iter = PyObject_GetIter(items);
979 Py_DECREF(items);
980 if (items_iter == NULL)
981 goto Done;
982
983 result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
984 Py_DECREF(items_iter);
985
986 Done:
987 Py_XDECREF(dict);
988 Py_XDECREF(args);
989
990 return result;
991 }
992
993 /* setdefault(): Skips __missing__() calls. */
994
995
996 /*[clinic input]
997 OrderedDict.setdefault
998
999 key: object
1000 default: object = None
1001
1002 Insert key with a value of default if key is not in the dictionary.
1003
1004 Return the value for key if key is in the dictionary, else default.
1005 [clinic start generated code]*/
1006
1007 static PyObject *
OrderedDict_setdefault_impl(PyODictObject * self,PyObject * key,PyObject * default_value)1008 OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
1009 PyObject *default_value)
1010 /*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
1011 {
1012 PyObject *result = NULL;
1013
1014 if (PyODict_CheckExact(self)) {
1015 result = PyODict_GetItemWithError(self, key); /* borrowed */
1016 if (result == NULL) {
1017 if (PyErr_Occurred())
1018 return NULL;
1019 assert(_odict_find_node(self, key) == NULL);
1020 if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
1021 result = default_value;
1022 Py_INCREF(result);
1023 }
1024 }
1025 else {
1026 Py_INCREF(result);
1027 }
1028 }
1029 else {
1030 int exists = PySequence_Contains((PyObject *)self, key);
1031 if (exists < 0) {
1032 return NULL;
1033 }
1034 else if (exists) {
1035 result = PyObject_GetItem((PyObject *)self, key);
1036 }
1037 else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1038 result = default_value;
1039 Py_INCREF(result);
1040 }
1041 }
1042
1043 return result;
1044 }
1045
1046 /* pop() */
1047
1048 PyDoc_STRVAR(odict_pop__doc__,
1049 "od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\
1050 value. If key is not found, d is returned if given, otherwise KeyError\n\
1051 is raised.\n\
1052 \n\
1053 ");
1054
1055 /* forward */
1056 static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *);
1057
1058 /* Skips __missing__() calls. */
1059 static PyObject *
odict_pop(PyObject * od,PyObject * args,PyObject * kwargs)1060 odict_pop(PyObject *od, PyObject *args, PyObject *kwargs)
1061 {
1062 static char *kwlist[] = {"key", "default", 0};
1063 PyObject *key, *failobj = NULL;
1064
1065 /* borrowed */
1066 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist,
1067 &key, &failobj)) {
1068 return NULL;
1069 }
1070
1071 return _odict_popkey(od, key, failobj);
1072 }
1073
1074 static PyObject *
_odict_popkey_hash(PyObject * od,PyObject * key,PyObject * failobj,Py_hash_t hash)1075 _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1076 Py_hash_t hash)
1077 {
1078 _ODictNode *node;
1079 PyObject *value = NULL;
1080
1081 /* Pop the node first to avoid a possible dict resize (due to
1082 eval loop reentrancy) and complications due to hash collision
1083 resolution. */
1084 node = _odict_find_node_hash((PyODictObject *)od, key, hash);
1085 if (node == NULL) {
1086 if (PyErr_Occurred())
1087 return NULL;
1088 }
1089 else {
1090 int res = _odict_clear_node((PyODictObject *)od, node, key, hash);
1091 if (res < 0) {
1092 return NULL;
1093 }
1094 }
1095
1096 /* Now delete the value from the dict. */
1097 if (PyODict_CheckExact(od)) {
1098 if (node != NULL) {
1099 value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
1100 if (value != NULL) {
1101 Py_INCREF(value);
1102 if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
1103 Py_DECREF(value);
1104 return NULL;
1105 }
1106 }
1107 }
1108 }
1109 else {
1110 int exists = PySequence_Contains(od, key);
1111 if (exists < 0)
1112 return NULL;
1113 if (exists) {
1114 value = PyObject_GetItem(od, key);
1115 if (value != NULL) {
1116 if (PyObject_DelItem(od, key) == -1) {
1117 Py_CLEAR(value);
1118 }
1119 }
1120 }
1121 }
1122
1123 /* Apply the fallback value, if necessary. */
1124 if (value == NULL && !PyErr_Occurred()) {
1125 if (failobj) {
1126 value = failobj;
1127 Py_INCREF(failobj);
1128 }
1129 else {
1130 PyErr_SetObject(PyExc_KeyError, key);
1131 }
1132 }
1133
1134 return value;
1135 }
1136
1137 static PyObject *
_odict_popkey(PyObject * od,PyObject * key,PyObject * failobj)1138 _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
1139 {
1140 Py_hash_t hash = PyObject_Hash(key);
1141 if (hash == -1)
1142 return NULL;
1143
1144 return _odict_popkey_hash(od, key, failobj, hash);
1145 }
1146
1147
1148 /* popitem() */
1149
1150 /*[clinic input]
1151 OrderedDict.popitem
1152
1153 last: bool = True
1154
1155 Remove and return a (key, value) pair from the dictionary.
1156
1157 Pairs are returned in LIFO order if last is true or FIFO order if false.
1158 [clinic start generated code]*/
1159
1160 static PyObject *
OrderedDict_popitem_impl(PyODictObject * self,int last)1161 OrderedDict_popitem_impl(PyODictObject *self, int last)
1162 /*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
1163 {
1164 PyObject *key, *value, *item = NULL;
1165 _ODictNode *node;
1166
1167 /* pull the item */
1168
1169 if (_odict_EMPTY(self)) {
1170 PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1171 return NULL;
1172 }
1173
1174 node = last ? _odict_LAST(self) : _odict_FIRST(self);
1175 key = _odictnode_KEY(node);
1176 Py_INCREF(key);
1177 value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1178 if (value == NULL)
1179 return NULL;
1180 item = PyTuple_Pack(2, key, value);
1181 Py_DECREF(key);
1182 Py_DECREF(value);
1183 return item;
1184 }
1185
1186 /* keys() */
1187
1188 /* MutableMapping.keys() does not have a docstring. */
1189 PyDoc_STRVAR(odict_keys__doc__, "");
1190
1191 static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
1192
1193 /* values() */
1194
1195 /* MutableMapping.values() does not have a docstring. */
1196 PyDoc_STRVAR(odict_values__doc__, "");
1197
1198 static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
1199
1200 /* items() */
1201
1202 /* MutableMapping.items() does not have a docstring. */
1203 PyDoc_STRVAR(odict_items__doc__, "");
1204
1205 static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
1206
1207 /* update() */
1208
1209 /* MutableMapping.update() does not have a docstring. */
1210 PyDoc_STRVAR(odict_update__doc__, "");
1211
1212 /* forward */
1213 static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1214
1215 #define odict_update mutablemapping_update
1216
1217 /* clear() */
1218
1219 PyDoc_STRVAR(odict_clear__doc__,
1220 "od.clear() -> None. Remove all items from od.");
1221
1222 static PyObject *
odict_clear(register PyODictObject * od,PyObject * Py_UNUSED (ignored))1223 odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
1224 {
1225 PyDict_Clear((PyObject *)od);
1226 _odict_clear_nodes(od);
1227 Py_RETURN_NONE;
1228 }
1229
1230 /* copy() */
1231
1232 /* forward */
1233 static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
1234 Py_hash_t);
1235
1236 PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
1237
1238 static PyObject *
odict_copy(register PyODictObject * od,PyObject * Py_UNUSED (ignored))1239 odict_copy(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
1240 {
1241 _ODictNode *node;
1242 PyObject *od_copy;
1243
1244 if (PyODict_CheckExact(od))
1245 od_copy = PyODict_New();
1246 else
1247 od_copy = _PyObject_CallNoArg((PyObject *)Py_TYPE(od));
1248 if (od_copy == NULL)
1249 return NULL;
1250
1251 if (PyODict_CheckExact(od)) {
1252 _odict_FOREACH(od, node) {
1253 PyObject *key = _odictnode_KEY(node);
1254 PyObject *value = _odictnode_VALUE(node, od);
1255 if (value == NULL) {
1256 if (!PyErr_Occurred())
1257 PyErr_SetObject(PyExc_KeyError, key);
1258 goto fail;
1259 }
1260 if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
1261 _odictnode_HASH(node)) != 0)
1262 goto fail;
1263 }
1264 }
1265 else {
1266 _odict_FOREACH(od, node) {
1267 int res;
1268 PyObject *value = PyObject_GetItem((PyObject *)od,
1269 _odictnode_KEY(node));
1270 if (value == NULL)
1271 goto fail;
1272 res = PyObject_SetItem((PyObject *)od_copy,
1273 _odictnode_KEY(node), value);
1274 Py_DECREF(value);
1275 if (res != 0)
1276 goto fail;
1277 }
1278 }
1279 return od_copy;
1280
1281 fail:
1282 Py_DECREF(od_copy);
1283 return NULL;
1284 }
1285
1286 /* __reversed__() */
1287
1288 PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1289
1290 #define _odict_ITER_REVERSED 1
1291 #define _odict_ITER_KEYS 2
1292 #define _odict_ITER_VALUES 4
1293
1294 /* forward */
1295 static PyObject * odictiter_new(PyODictObject *, int);
1296
1297 static PyObject *
odict_reversed(PyODictObject * od,PyObject * Py_UNUSED (ignored))1298 odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))
1299 {
1300 return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1301 }
1302
1303
1304 /* move_to_end() */
1305
1306 /*[clinic input]
1307 OrderedDict.move_to_end
1308
1309 key: object
1310 last: bool = True
1311
1312 Move an existing element to the end (or beginning if last is false).
1313
1314 Raise KeyError if the element does not exist.
1315 [clinic start generated code]*/
1316
1317 static PyObject *
OrderedDict_move_to_end_impl(PyODictObject * self,PyObject * key,int last)1318 OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
1319 /*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
1320 {
1321 _ODictNode *node;
1322
1323 if (_odict_EMPTY(self)) {
1324 PyErr_SetObject(PyExc_KeyError, key);
1325 return NULL;
1326 }
1327 node = last ? _odict_LAST(self) : _odict_FIRST(self);
1328 if (key != _odictnode_KEY(node)) {
1329 node = _odict_find_node(self, key);
1330 if (node == NULL) {
1331 if (!PyErr_Occurred())
1332 PyErr_SetObject(PyExc_KeyError, key);
1333 return NULL;
1334 }
1335 if (last) {
1336 /* Only move if not already the last one. */
1337 if (node != _odict_LAST(self)) {
1338 _odict_remove_node(self, node);
1339 _odict_add_tail(self, node);
1340 }
1341 }
1342 else {
1343 /* Only move if not already the first one. */
1344 if (node != _odict_FIRST(self)) {
1345 _odict_remove_node(self, node);
1346 _odict_add_head(self, node);
1347 }
1348 }
1349 }
1350 Py_RETURN_NONE;
1351 }
1352
1353
1354 /* tp_methods */
1355
1356 static PyMethodDef odict_methods[] = {
1357
1358 /* overridden dict methods */
1359 ORDEREDDICT_FROMKEYS_METHODDEF
1360 {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
1361 odict_sizeof__doc__},
1362 {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
1363 odict_reduce__doc__},
1364 ORDEREDDICT_SETDEFAULT_METHODDEF
1365 {"pop", (PyCFunction)(void(*)(void))odict_pop,
1366 METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
1367 ORDEREDDICT_POPITEM_METHODDEF
1368 {"keys", odictkeys_new, METH_NOARGS,
1369 odict_keys__doc__},
1370 {"values", odictvalues_new, METH_NOARGS,
1371 odict_values__doc__},
1372 {"items", odictitems_new, METH_NOARGS,
1373 odict_items__doc__},
1374 {"update", (PyCFunction)(void(*)(void))odict_update, METH_VARARGS | METH_KEYWORDS,
1375 odict_update__doc__},
1376 {"clear", (PyCFunction)odict_clear, METH_NOARGS,
1377 odict_clear__doc__},
1378 {"copy", (PyCFunction)odict_copy, METH_NOARGS,
1379 odict_copy__doc__},
1380
1381 /* new methods */
1382 {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
1383 odict_reversed__doc__},
1384 ORDEREDDICT_MOVE_TO_END_METHODDEF
1385
1386 {NULL, NULL} /* sentinel */
1387 };
1388
1389
1390 /* ----------------------------------------------
1391 * OrderedDict members
1392 */
1393
1394 /* tp_getset */
1395
1396 static PyGetSetDef odict_getset[] = {
1397 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1398 {NULL}
1399 };
1400
1401 /* ----------------------------------------------
1402 * OrderedDict type slot methods
1403 */
1404
1405 /* tp_dealloc */
1406
1407 static void
odict_dealloc(PyODictObject * self)1408 odict_dealloc(PyODictObject *self)
1409 {
1410 PyObject_GC_UnTrack(self);
1411 Py_TRASHCAN_BEGIN(self, odict_dealloc)
1412
1413 Py_XDECREF(self->od_inst_dict);
1414 if (self->od_weakreflist != NULL)
1415 PyObject_ClearWeakRefs((PyObject *)self);
1416
1417 _odict_clear_nodes(self);
1418 PyDict_Type.tp_dealloc((PyObject *)self);
1419
1420 Py_TRASHCAN_END
1421 }
1422
1423 /* tp_repr */
1424
1425 static PyObject *
odict_repr(PyODictObject * self)1426 odict_repr(PyODictObject *self)
1427 {
1428 int i;
1429 PyObject *pieces = NULL, *result = NULL;
1430
1431 if (PyODict_SIZE(self) == 0)
1432 return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
1433
1434 i = Py_ReprEnter((PyObject *)self);
1435 if (i != 0) {
1436 return i > 0 ? PyUnicode_FromString("...") : NULL;
1437 }
1438
1439 if (PyODict_CheckExact(self)) {
1440 Py_ssize_t count = 0;
1441 _ODictNode *node;
1442 pieces = PyList_New(PyODict_SIZE(self));
1443 if (pieces == NULL)
1444 goto Done;
1445
1446 _odict_FOREACH(self, node) {
1447 PyObject *pair;
1448 PyObject *key = _odictnode_KEY(node);
1449 PyObject *value = _odictnode_VALUE(node, self);
1450 if (value == NULL) {
1451 if (!PyErr_Occurred())
1452 PyErr_SetObject(PyExc_KeyError, key);
1453 goto Done;
1454 }
1455 pair = PyTuple_Pack(2, key, value);
1456 if (pair == NULL)
1457 goto Done;
1458
1459 if (count < PyList_GET_SIZE(pieces))
1460 PyList_SET_ITEM(pieces, count, pair); /* steals reference */
1461 else {
1462 if (PyList_Append(pieces, pair) < 0) {
1463 Py_DECREF(pair);
1464 goto Done;
1465 }
1466 Py_DECREF(pair);
1467 }
1468 count++;
1469 }
1470 if (count < PyList_GET_SIZE(pieces)) {
1471 Py_SET_SIZE(pieces, count);
1472 }
1473 }
1474 else {
1475 PyObject *items = _PyObject_CallMethodIdNoArgs((PyObject *)self,
1476 &PyId_items);
1477 if (items == NULL)
1478 goto Done;
1479 pieces = PySequence_List(items);
1480 Py_DECREF(items);
1481 if (pieces == NULL)
1482 goto Done;
1483 }
1484
1485 result = PyUnicode_FromFormat("%s(%R)",
1486 _PyType_Name(Py_TYPE(self)), pieces);
1487
1488 Done:
1489 Py_XDECREF(pieces);
1490 Py_ReprLeave((PyObject *)self);
1491 return result;
1492 }
1493
1494 /* tp_doc */
1495
1496 PyDoc_STRVAR(odict_doc,
1497 "Dictionary that remembers insertion order");
1498
1499 /* tp_traverse */
1500
1501 static int
odict_traverse(PyODictObject * od,visitproc visit,void * arg)1502 odict_traverse(PyODictObject *od, visitproc visit, void *arg)
1503 {
1504 _ODictNode *node;
1505
1506 Py_VISIT(od->od_inst_dict);
1507 _odict_FOREACH(od, node) {
1508 Py_VISIT(_odictnode_KEY(node));
1509 }
1510 return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1511 }
1512
1513 /* tp_clear */
1514
1515 static int
odict_tp_clear(PyODictObject * od)1516 odict_tp_clear(PyODictObject *od)
1517 {
1518 Py_CLEAR(od->od_inst_dict);
1519 PyDict_Clear((PyObject *)od);
1520 _odict_clear_nodes(od);
1521 return 0;
1522 }
1523
1524 /* tp_richcompare */
1525
1526 static PyObject *
odict_richcompare(PyObject * v,PyObject * w,int op)1527 odict_richcompare(PyObject *v, PyObject *w, int op)
1528 {
1529 if (!PyODict_Check(v) || !PyDict_Check(w)) {
1530 Py_RETURN_NOTIMPLEMENTED;
1531 }
1532
1533 if (op == Py_EQ || op == Py_NE) {
1534 PyObject *res, *cmp;
1535 int eq;
1536
1537 cmp = PyDict_Type.tp_richcompare(v, w, op);
1538 if (cmp == NULL)
1539 return NULL;
1540 if (!PyODict_Check(w))
1541 return cmp;
1542 if (op == Py_EQ && cmp == Py_False)
1543 return cmp;
1544 if (op == Py_NE && cmp == Py_True)
1545 return cmp;
1546 Py_DECREF(cmp);
1547
1548 /* Try comparing odict keys. */
1549 eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);
1550 if (eq < 0)
1551 return NULL;
1552
1553 res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1554 Py_INCREF(res);
1555 return res;
1556 } else {
1557 Py_RETURN_NOTIMPLEMENTED;
1558 }
1559 }
1560
1561 /* tp_iter */
1562
1563 static PyObject *
odict_iter(PyODictObject * od)1564 odict_iter(PyODictObject *od)
1565 {
1566 return odictiter_new(od, _odict_ITER_KEYS);
1567 }
1568
1569 /* tp_init */
1570
1571 static int
odict_init(PyObject * self,PyObject * args,PyObject * kwds)1572 odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1573 {
1574 PyObject *res;
1575 Py_ssize_t len = PyObject_Length(args);
1576
1577 if (len == -1)
1578 return -1;
1579 if (len > 1) {
1580 const char *msg = "expected at most 1 arguments, got %zd";
1581 PyErr_Format(PyExc_TypeError, msg, len);
1582 return -1;
1583 }
1584
1585 /* __init__() triggering update() is just the way things are! */
1586 res = odict_update(self, args, kwds);
1587 if (res == NULL) {
1588 return -1;
1589 } else {
1590 Py_DECREF(res);
1591 return 0;
1592 }
1593 }
1594
1595 /* PyODict_Type */
1596
1597 PyTypeObject PyODict_Type = {
1598 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1599 "collections.OrderedDict", /* tp_name */
1600 sizeof(PyODictObject), /* tp_basicsize */
1601 0, /* tp_itemsize */
1602 (destructor)odict_dealloc, /* tp_dealloc */
1603 0, /* tp_vectorcall_offset */
1604 0, /* tp_getattr */
1605 0, /* tp_setattr */
1606 0, /* tp_as_async */
1607 (reprfunc)odict_repr, /* tp_repr */
1608 &odict_as_number, /* tp_as_number */
1609 0, /* tp_as_sequence */
1610 &odict_as_mapping, /* tp_as_mapping */
1611 0, /* tp_hash */
1612 0, /* tp_call */
1613 0, /* tp_str */
1614 0, /* tp_getattro */
1615 0, /* tp_setattro */
1616 0, /* tp_as_buffer */
1617 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1618 odict_doc, /* tp_doc */
1619 (traverseproc)odict_traverse, /* tp_traverse */
1620 (inquiry)odict_tp_clear, /* tp_clear */
1621 (richcmpfunc)odict_richcompare, /* tp_richcompare */
1622 offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */
1623 (getiterfunc)odict_iter, /* tp_iter */
1624 0, /* tp_iternext */
1625 odict_methods, /* tp_methods */
1626 0, /* tp_members */
1627 odict_getset, /* tp_getset */
1628 &PyDict_Type, /* tp_base */
1629 0, /* tp_dict */
1630 0, /* tp_descr_get */
1631 0, /* tp_descr_set */
1632 offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
1633 (initproc)odict_init, /* tp_init */
1634 PyType_GenericAlloc, /* tp_alloc */
1635 0, /* tp_new */
1636 0, /* tp_free */
1637 };
1638
1639
1640 /* ----------------------------------------------
1641 * the public OrderedDict API
1642 */
1643
1644 PyObject *
PyODict_New(void)1645 PyODict_New(void)
1646 {
1647 return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
1648 }
1649
1650 static int
_PyODict_SetItem_KnownHash(PyObject * od,PyObject * key,PyObject * value,Py_hash_t hash)1651 _PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1652 Py_hash_t hash)
1653 {
1654 int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
1655 if (res == 0) {
1656 res = _odict_add_new_node((PyODictObject *)od, key, hash);
1657 if (res < 0) {
1658 /* Revert setting the value on the dict */
1659 PyObject *exc, *val, *tb;
1660 PyErr_Fetch(&exc, &val, &tb);
1661 (void) _PyDict_DelItem_KnownHash(od, key, hash);
1662 _PyErr_ChainExceptions(exc, val, tb);
1663 }
1664 }
1665 return res;
1666 }
1667
1668 int
PyODict_SetItem(PyObject * od,PyObject * key,PyObject * value)1669 PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1670 {
1671 Py_hash_t hash = PyObject_Hash(key);
1672 if (hash == -1)
1673 return -1;
1674 return _PyODict_SetItem_KnownHash(od, key, value, hash);
1675 }
1676
1677 int
PyODict_DelItem(PyObject * od,PyObject * key)1678 PyODict_DelItem(PyObject *od, PyObject *key)
1679 {
1680 int res;
1681 Py_hash_t hash = PyObject_Hash(key);
1682 if (hash == -1)
1683 return -1;
1684 res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);
1685 if (res < 0)
1686 return -1;
1687 return _PyDict_DelItem_KnownHash(od, key, hash);
1688 }
1689
1690
1691 /* -------------------------------------------
1692 * The OrderedDict views (keys/values/items)
1693 */
1694
1695 typedef struct {
1696 PyObject_HEAD
1697 int kind;
1698 PyODictObject *di_odict;
1699 Py_ssize_t di_size;
1700 size_t di_state;
1701 PyObject *di_current;
1702 PyObject *di_result; /* reusable result tuple for iteritems */
1703 } odictiterobject;
1704
1705 static void
odictiter_dealloc(odictiterobject * di)1706 odictiter_dealloc(odictiterobject *di)
1707 {
1708 _PyObject_GC_UNTRACK(di);
1709 Py_XDECREF(di->di_odict);
1710 Py_XDECREF(di->di_current);
1711 if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) {
1712 Py_DECREF(di->di_result);
1713 }
1714 PyObject_GC_Del(di);
1715 }
1716
1717 static int
odictiter_traverse(odictiterobject * di,visitproc visit,void * arg)1718 odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1719 {
1720 Py_VISIT(di->di_odict);
1721 Py_VISIT(di->di_current); /* A key could be any type, not just str. */
1722 Py_VISIT(di->di_result);
1723 return 0;
1724 }
1725
1726 /* In order to protect against modifications during iteration, we track
1727 * the current key instead of the current node. */
1728 static PyObject *
odictiter_nextkey(odictiterobject * di)1729 odictiter_nextkey(odictiterobject *di)
1730 {
1731 PyObject *key = NULL;
1732 _ODictNode *node;
1733 int reversed = di->kind & _odict_ITER_REVERSED;
1734
1735 if (di->di_odict == NULL)
1736 return NULL;
1737 if (di->di_current == NULL)
1738 goto done; /* We're already done. */
1739
1740 /* Check for unsupported changes. */
1741 if (di->di_odict->od_state != di->di_state) {
1742 PyErr_SetString(PyExc_RuntimeError,
1743 "OrderedDict mutated during iteration");
1744 goto done;
1745 }
1746 if (di->di_size != PyODict_SIZE(di->di_odict)) {
1747 PyErr_SetString(PyExc_RuntimeError,
1748 "OrderedDict changed size during iteration");
1749 di->di_size = -1; /* Make this state sticky */
1750 return NULL;
1751 }
1752
1753 /* Get the key. */
1754 node = _odict_find_node(di->di_odict, di->di_current);
1755 if (node == NULL) {
1756 if (!PyErr_Occurred())
1757 PyErr_SetObject(PyExc_KeyError, di->di_current);
1758 /* Must have been deleted. */
1759 Py_CLEAR(di->di_current);
1760 return NULL;
1761 }
1762 key = di->di_current;
1763
1764 /* Advance to the next key. */
1765 node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1766 if (node == NULL) {
1767 /* Reached the end. */
1768 di->di_current = NULL;
1769 }
1770 else {
1771 di->di_current = _odictnode_KEY(node);
1772 Py_INCREF(di->di_current);
1773 }
1774
1775 return key;
1776
1777 done:
1778 Py_CLEAR(di->di_odict);
1779 return key;
1780 }
1781
1782 static PyObject *
odictiter_iternext(odictiterobject * di)1783 odictiter_iternext(odictiterobject *di)
1784 {
1785 PyObject *result, *value;
1786 PyObject *key = odictiter_nextkey(di); /* new reference */
1787
1788 if (key == NULL)
1789 return NULL;
1790
1791 /* Handle the keys case. */
1792 if (! (di->kind & _odict_ITER_VALUES)) {
1793 return key;
1794 }
1795
1796 value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
1797 if (value == NULL) {
1798 if (!PyErr_Occurred())
1799 PyErr_SetObject(PyExc_KeyError, key);
1800 Py_DECREF(key);
1801 goto done;
1802 }
1803 Py_INCREF(value);
1804
1805 /* Handle the values case. */
1806 if (!(di->kind & _odict_ITER_KEYS)) {
1807 Py_DECREF(key);
1808 return value;
1809 }
1810
1811 /* Handle the items case. */
1812 result = di->di_result;
1813
1814 if (Py_REFCNT(result) == 1) {
1815 /* not in use so we can reuse it
1816 * (the common case during iteration) */
1817 Py_INCREF(result);
1818 Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */
1819 Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */
1820 }
1821 else {
1822 result = PyTuple_New(2);
1823 if (result == NULL) {
1824 Py_DECREF(key);
1825 Py_DECREF(value);
1826 goto done;
1827 }
1828 }
1829
1830 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
1831 PyTuple_SET_ITEM(result, 1, value); /* steals reference */
1832 return result;
1833
1834 done:
1835 Py_CLEAR(di->di_current);
1836 Py_CLEAR(di->di_odict);
1837 return NULL;
1838 }
1839
1840 /* No need for tp_clear because odictiterobject is not mutable. */
1841
1842 PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1843
1844 static PyObject *
odictiter_reduce(odictiterobject * di,PyObject * Py_UNUSED (ignored))1845 odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
1846 {
1847 _Py_IDENTIFIER(iter);
1848 /* copy the iterator state */
1849 odictiterobject tmp = *di;
1850 Py_XINCREF(tmp.di_odict);
1851 Py_XINCREF(tmp.di_current);
1852
1853 /* iterate the temporary into a list */
1854 PyObject *list = PySequence_List((PyObject*)&tmp);
1855 Py_XDECREF(tmp.di_odict);
1856 Py_XDECREF(tmp.di_current);
1857 if (list == NULL) {
1858 return NULL;
1859 }
1860 return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
1861 }
1862
1863 static PyMethodDef odictiter_methods[] = {
1864 {"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},
1865 {NULL, NULL} /* sentinel */
1866 };
1867
1868 PyTypeObject PyODictIter_Type = {
1869 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1870 "odict_iterator", /* tp_name */
1871 sizeof(odictiterobject), /* tp_basicsize */
1872 0, /* tp_itemsize */
1873 /* methods */
1874 (destructor)odictiter_dealloc, /* tp_dealloc */
1875 0, /* tp_vectorcall_offset */
1876 0, /* tp_getattr */
1877 0, /* tp_setattr */
1878 0, /* tp_as_async */
1879 0, /* tp_repr */
1880 0, /* tp_as_number */
1881 0, /* tp_as_sequence */
1882 0, /* tp_as_mapping */
1883 0, /* tp_hash */
1884 0, /* tp_call */
1885 0, /* tp_str */
1886 PyObject_GenericGetAttr, /* tp_getattro */
1887 0, /* tp_setattro */
1888 0, /* tp_as_buffer */
1889 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1890 0, /* tp_doc */
1891 (traverseproc)odictiter_traverse, /* tp_traverse */
1892 0, /* tp_clear */
1893 0, /* tp_richcompare */
1894 0, /* tp_weaklistoffset */
1895 PyObject_SelfIter, /* tp_iter */
1896 (iternextfunc)odictiter_iternext, /* tp_iternext */
1897 odictiter_methods, /* tp_methods */
1898 0,
1899 };
1900
1901 static PyObject *
odictiter_new(PyODictObject * od,int kind)1902 odictiter_new(PyODictObject *od, int kind)
1903 {
1904 odictiterobject *di;
1905 _ODictNode *node;
1906 int reversed = kind & _odict_ITER_REVERSED;
1907
1908 di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1909 if (di == NULL)
1910 return NULL;
1911
1912 if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){
1913 di->di_result = PyTuple_Pack(2, Py_None, Py_None);
1914 if (di->di_result == NULL) {
1915 Py_DECREF(di);
1916 return NULL;
1917 }
1918 }
1919 else
1920 di->di_result = NULL;
1921
1922 di->kind = kind;
1923 node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1924 di->di_current = node ? _odictnode_KEY(node) : NULL;
1925 Py_XINCREF(di->di_current);
1926 di->di_size = PyODict_SIZE(od);
1927 di->di_state = od->od_state;
1928 di->di_odict = od;
1929 Py_INCREF(od);
1930
1931 _PyObject_GC_TRACK(di);
1932 return (PyObject *)di;
1933 }
1934
1935 /* keys() */
1936
1937 static PyObject *
odictkeys_iter(_PyDictViewObject * dv)1938 odictkeys_iter(_PyDictViewObject *dv)
1939 {
1940 if (dv->dv_dict == NULL) {
1941 Py_RETURN_NONE;
1942 }
1943 return odictiter_new((PyODictObject *)dv->dv_dict,
1944 _odict_ITER_KEYS);
1945 }
1946
1947 static PyObject *
odictkeys_reversed(_PyDictViewObject * dv,PyObject * Py_UNUSED (ignored))1948 odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
1949 {
1950 if (dv->dv_dict == NULL) {
1951 Py_RETURN_NONE;
1952 }
1953 return odictiter_new((PyODictObject *)dv->dv_dict,
1954 _odict_ITER_KEYS|_odict_ITER_REVERSED);
1955 }
1956
1957 static PyMethodDef odictkeys_methods[] = {
1958 {"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},
1959 {NULL, NULL} /* sentinel */
1960 };
1961
1962 PyTypeObject PyODictKeys_Type = {
1963 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1964 "odict_keys", /* tp_name */
1965 0, /* tp_basicsize */
1966 0, /* tp_itemsize */
1967 0, /* tp_dealloc */
1968 0, /* tp_vectorcall_offset */
1969 0, /* tp_getattr */
1970 0, /* tp_setattr */
1971 0, /* tp_as_async */
1972 0, /* tp_repr */
1973 0, /* tp_as_number */
1974 0, /* tp_as_sequence */
1975 0, /* tp_as_mapping */
1976 0, /* tp_hash */
1977 0, /* tp_call */
1978 0, /* tp_str */
1979 0, /* tp_getattro */
1980 0, /* tp_setattro */
1981 0, /* tp_as_buffer */
1982 0, /* tp_flags */
1983 0, /* tp_doc */
1984 0, /* tp_traverse */
1985 0, /* tp_clear */
1986 0, /* tp_richcompare */
1987 0, /* tp_weaklistoffset */
1988 (getiterfunc)odictkeys_iter, /* tp_iter */
1989 0, /* tp_iternext */
1990 odictkeys_methods, /* tp_methods */
1991 0, /* tp_members */
1992 0, /* tp_getset */
1993 &PyDictKeys_Type, /* tp_base */
1994 };
1995
1996 static PyObject *
odictkeys_new(PyObject * od,PyObject * Py_UNUSED (ignored))1997 odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
1998 {
1999 return _PyDictView_New(od, &PyODictKeys_Type);
2000 }
2001
2002 /* items() */
2003
2004 static PyObject *
odictitems_iter(_PyDictViewObject * dv)2005 odictitems_iter(_PyDictViewObject *dv)
2006 {
2007 if (dv->dv_dict == NULL) {
2008 Py_RETURN_NONE;
2009 }
2010 return odictiter_new((PyODictObject *)dv->dv_dict,
2011 _odict_ITER_KEYS|_odict_ITER_VALUES);
2012 }
2013
2014 static PyObject *
odictitems_reversed(_PyDictViewObject * dv,PyObject * Py_UNUSED (ignored))2015 odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
2016 {
2017 if (dv->dv_dict == NULL) {
2018 Py_RETURN_NONE;
2019 }
2020 return odictiter_new((PyODictObject *)dv->dv_dict,
2021 _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2022 }
2023
2024 static PyMethodDef odictitems_methods[] = {
2025 {"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},
2026 {NULL, NULL} /* sentinel */
2027 };
2028
2029 PyTypeObject PyODictItems_Type = {
2030 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2031 "odict_items", /* tp_name */
2032 0, /* tp_basicsize */
2033 0, /* tp_itemsize */
2034 0, /* tp_dealloc */
2035 0, /* tp_vectorcall_offset */
2036 0, /* tp_getattr */
2037 0, /* tp_setattr */
2038 0, /* tp_as_async */
2039 0, /* tp_repr */
2040 0, /* tp_as_number */
2041 0, /* tp_as_sequence */
2042 0, /* tp_as_mapping */
2043 0, /* tp_hash */
2044 0, /* tp_call */
2045 0, /* tp_str */
2046 0, /* tp_getattro */
2047 0, /* tp_setattro */
2048 0, /* tp_as_buffer */
2049 0, /* tp_flags */
2050 0, /* tp_doc */
2051 0, /* tp_traverse */
2052 0, /* tp_clear */
2053 0, /* tp_richcompare */
2054 0, /* tp_weaklistoffset */
2055 (getiterfunc)odictitems_iter, /* tp_iter */
2056 0, /* tp_iternext */
2057 odictitems_methods, /* tp_methods */
2058 0, /* tp_members */
2059 0, /* tp_getset */
2060 &PyDictItems_Type, /* tp_base */
2061 };
2062
2063 static PyObject *
odictitems_new(PyObject * od,PyObject * Py_UNUSED (ignored))2064 odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2065 {
2066 return _PyDictView_New(od, &PyODictItems_Type);
2067 }
2068
2069 /* values() */
2070
2071 static PyObject *
odictvalues_iter(_PyDictViewObject * dv)2072 odictvalues_iter(_PyDictViewObject *dv)
2073 {
2074 if (dv->dv_dict == NULL) {
2075 Py_RETURN_NONE;
2076 }
2077 return odictiter_new((PyODictObject *)dv->dv_dict,
2078 _odict_ITER_VALUES);
2079 }
2080
2081 static PyObject *
odictvalues_reversed(_PyDictViewObject * dv,PyObject * Py_UNUSED (ignored))2082 odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
2083 {
2084 if (dv->dv_dict == NULL) {
2085 Py_RETURN_NONE;
2086 }
2087 return odictiter_new((PyODictObject *)dv->dv_dict,
2088 _odict_ITER_VALUES|_odict_ITER_REVERSED);
2089 }
2090
2091 static PyMethodDef odictvalues_methods[] = {
2092 {"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},
2093 {NULL, NULL} /* sentinel */
2094 };
2095
2096 PyTypeObject PyODictValues_Type = {
2097 PyVarObject_HEAD_INIT(&PyType_Type, 0)
2098 "odict_values", /* tp_name */
2099 0, /* tp_basicsize */
2100 0, /* tp_itemsize */
2101 0, /* tp_dealloc */
2102 0, /* tp_vectorcall_offset */
2103 0, /* tp_getattr */
2104 0, /* tp_setattr */
2105 0, /* tp_as_async */
2106 0, /* tp_repr */
2107 0, /* tp_as_number */
2108 0, /* tp_as_sequence */
2109 0, /* tp_as_mapping */
2110 0, /* tp_hash */
2111 0, /* tp_call */
2112 0, /* tp_str */
2113 0, /* tp_getattro */
2114 0, /* tp_setattro */
2115 0, /* tp_as_buffer */
2116 0, /* tp_flags */
2117 0, /* tp_doc */
2118 0, /* tp_traverse */
2119 0, /* tp_clear */
2120 0, /* tp_richcompare */
2121 0, /* tp_weaklistoffset */
2122 (getiterfunc)odictvalues_iter, /* tp_iter */
2123 0, /* tp_iternext */
2124 odictvalues_methods, /* tp_methods */
2125 0, /* tp_members */
2126 0, /* tp_getset */
2127 &PyDictValues_Type, /* tp_base */
2128 };
2129
2130 static PyObject *
odictvalues_new(PyObject * od,PyObject * Py_UNUSED (ignored))2131 odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2132 {
2133 return _PyDictView_New(od, &PyODictValues_Type);
2134 }
2135
2136
2137 /* ----------------------------------------------
2138 MutableMapping implementations
2139
2140 Mapping:
2141
2142 ============ ===========
2143 method uses
2144 ============ ===========
2145 __contains__ __getitem__
2146 __eq__ items
2147 __getitem__ +
2148 __iter__ +
2149 __len__ +
2150 __ne__ __eq__
2151 get __getitem__
2152 items ItemsView
2153 keys KeysView
2154 values ValuesView
2155 ============ ===========
2156
2157 ItemsView uses __len__, __iter__, and __getitem__.
2158 KeysView uses __len__, __iter__, and __contains__.
2159 ValuesView uses __len__, __iter__, and __getitem__.
2160
2161 MutableMapping:
2162
2163 ============ ===========
2164 method uses
2165 ============ ===========
2166 __delitem__ +
2167 __setitem__ +
2168 clear popitem
2169 pop __getitem__
2170 __delitem__
2171 popitem __iter__
2172 _getitem__
2173 __delitem__
2174 setdefault __getitem__
2175 __setitem__
2176 update __setitem__
2177 ============ ===========
2178 */
2179
2180 static int
mutablemapping_add_pairs(PyObject * self,PyObject * pairs)2181 mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2182 {
2183 PyObject *pair, *iterator, *unexpected;
2184 int res = 0;
2185
2186 iterator = PyObject_GetIter(pairs);
2187 if (iterator == NULL)
2188 return -1;
2189 PyErr_Clear();
2190
2191 while ((pair = PyIter_Next(iterator)) != NULL) {
2192 /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2193 PyObject *key = NULL, *value = NULL;
2194 PyObject *pair_iterator = PyObject_GetIter(pair);
2195 if (pair_iterator == NULL)
2196 goto Done;
2197
2198 key = PyIter_Next(pair_iterator);
2199 if (key == NULL) {
2200 if (!PyErr_Occurred())
2201 PyErr_SetString(PyExc_ValueError,
2202 "need more than 0 values to unpack");
2203 goto Done;
2204 }
2205
2206 value = PyIter_Next(pair_iterator);
2207 if (value == NULL) {
2208 if (!PyErr_Occurred())
2209 PyErr_SetString(PyExc_ValueError,
2210 "need more than 1 value to unpack");
2211 goto Done;
2212 }
2213
2214 unexpected = PyIter_Next(pair_iterator);
2215 if (unexpected != NULL) {
2216 Py_DECREF(unexpected);
2217 PyErr_SetString(PyExc_ValueError,
2218 "too many values to unpack (expected 2)");
2219 goto Done;
2220 }
2221 else if (PyErr_Occurred())
2222 goto Done;
2223
2224 res = PyObject_SetItem(self, key, value);
2225
2226 Done:
2227 Py_DECREF(pair);
2228 Py_XDECREF(pair_iterator);
2229 Py_XDECREF(key);
2230 Py_XDECREF(value);
2231 if (PyErr_Occurred())
2232 break;
2233 }
2234 Py_DECREF(iterator);
2235
2236 if (res < 0 || PyErr_Occurred() != NULL)
2237 return -1;
2238 else
2239 return 0;
2240 }
2241
2242 static int
mutablemapping_update_arg(PyObject * self,PyObject * arg)2243 mutablemapping_update_arg(PyObject *self, PyObject *arg)
2244 {
2245 int res = 0;
2246 if (PyDict_CheckExact(arg)) {
2247 PyObject *items = PyDict_Items(arg);
2248 if (items == NULL) {
2249 return -1;
2250 }
2251 res = mutablemapping_add_pairs(self, items);
2252 Py_DECREF(items);
2253 return res;
2254 }
2255 _Py_IDENTIFIER(keys);
2256 PyObject *func;
2257 if (_PyObject_LookupAttrId(arg, &PyId_keys, &func) < 0) {
2258 return -1;
2259 }
2260 if (func != NULL) {
2261 PyObject *keys = _PyObject_CallNoArg(func);
2262 Py_DECREF(func);
2263 if (keys == NULL) {
2264 return -1;
2265 }
2266 PyObject *iterator = PyObject_GetIter(keys);
2267 Py_DECREF(keys);
2268 if (iterator == NULL) {
2269 return -1;
2270 }
2271 PyObject *key;
2272 while (res == 0 && (key = PyIter_Next(iterator))) {
2273 PyObject *value = PyObject_GetItem(arg, key);
2274 if (value != NULL) {
2275 res = PyObject_SetItem(self, key, value);
2276 Py_DECREF(value);
2277 }
2278 else {
2279 res = -1;
2280 }
2281 Py_DECREF(key);
2282 }
2283 Py_DECREF(iterator);
2284 if (res != 0 || PyErr_Occurred()) {
2285 return -1;
2286 }
2287 return 0;
2288 }
2289 if (_PyObject_LookupAttrId(arg, &PyId_items, &func) < 0) {
2290 return -1;
2291 }
2292 if (func != NULL) {
2293 PyObject *items = _PyObject_CallNoArg(func);
2294 Py_DECREF(func);
2295 if (items == NULL) {
2296 return -1;
2297 }
2298 res = mutablemapping_add_pairs(self, items);
2299 Py_DECREF(items);
2300 return res;
2301 }
2302 res = mutablemapping_add_pairs(self, arg);
2303 return res;
2304 }
2305
2306 static PyObject *
mutablemapping_update(PyObject * self,PyObject * args,PyObject * kwargs)2307 mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2308 {
2309 int res;
2310 /* first handle args, if any */
2311 assert(args == NULL || PyTuple_Check(args));
2312 Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2313 if (len > 1) {
2314 const char *msg = "update() takes at most 1 positional argument (%zd given)";
2315 PyErr_Format(PyExc_TypeError, msg, len);
2316 return NULL;
2317 }
2318
2319 if (len) {
2320 PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
2321 assert(other != NULL);
2322 Py_INCREF(other);
2323 res = mutablemapping_update_arg(self, other);
2324 Py_DECREF(other);
2325 if (res < 0) {
2326 return NULL;
2327 }
2328 }
2329
2330 /* now handle kwargs */
2331 assert(kwargs == NULL || PyDict_Check(kwargs));
2332 if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2333 PyObject *items = PyDict_Items(kwargs);
2334 if (items == NULL)
2335 return NULL;
2336 res = mutablemapping_add_pairs(self, items);
2337 Py_DECREF(items);
2338 if (res == -1)
2339 return NULL;
2340 }
2341
2342 Py_RETURN_NONE;
2343 }
2344