/* Ordered Dictionary object implementation.12This implementation is necessarily explicitly equivalent to the pure Python3OrderedDict class in Lib/collections/__init__.py. The strategy there4involves using a doubly-linked-list to capture the order. We keep to that5strategy, using a lower-level linked-list.67About the Linked-List8=====================910For the linked list we use a basic doubly-linked-list. Using a circularly-11linked-list does have some benefits, but they don't apply so much here12since OrderedDict is focused on the ends of the list (for the most part).13Furthermore, there are some features of generic linked-lists that we simply14don't need for OrderedDict. Thus a simple custom implementation meets our15needs. Alternatives to our simple approach include the QCIRCLE_*16macros from BSD's queue.h, and the linux's list.h.1718Getting O(1) Node Lookup19------------------------2021One invariant of Python's OrderedDict is that it preserves time complexity22of dict's methods, particularly the O(1) operations. Simply adding a23linked-list on top of dict is not sufficient here; operations for nodes in24the middle of the linked-list implicitly require finding the node first.25With a simple linked-list like we're using, that is an O(n) operation.26Consequently, methods like __delitem__() would change from O(1) to O(n),27which is unacceptable.2829In order to preserve O(1) performance for node removal (finding nodes), we30must do better than just looping through the linked-list. Here are options31we've considered:32331. use a second dict to map keys to nodes (a la the pure Python version).342. keep a simple hash table mirroring the order of dict's, mapping each key35to the corresponding node in the linked-list.363. use a version of shared keys (split dict) that allows non-unicode keys.374. have the value stored for each key be a (value, node) pair, and adjust38__getitem__(), get(), etc. accordingly.3940The approach with the least performance impact (time and space) is #2,41mirroring the key order of dict's dk_entries with an array of node pointers.42While _Py_dict_lookup() does not give us the index into the array,43we make use of pointer arithmetic to get that index. An alternative would44be to refactor _Py_dict_lookup() to provide the index, explicitly exposing45the implementation detail. We could even just use a custom lookup function46for OrderedDict that facilitates our need. However, both approaches are47significantly more complicated than just using pointer arithmetic.4849The catch with mirroring the hash table ordering is that we have to keep50the ordering in sync through any dict resizes. However, that order only51matters during node lookup. We can simply defer any potential resizing52until we need to do a lookup.5354Linked-List Nodes55-----------------5657The current implementation stores a pointer to the associated key only.58One alternative would be to store a pointer to the PyDictKeyEntry instead.59This would save one pointer de-reference per item, which is nice during60calls to values() and items(). However, it adds unnecessary overhead61otherwise, so we stick with just the key.6263Linked-List API64---------------6566As noted, the linked-list implemented here does not have all the bells and67whistles. However, we recognize that the implementation may need to68change to accommodate performance improvements or extra functionality. To69that end, we use a simple API to interact with the linked-list. Here's a70summary of the methods/macros:7172Node info:7374* _odictnode_KEY(node)75* _odictnode_VALUE(od, node)76* _odictnode_PREV(node)77* _odictnode_NEXT(node)7879Linked-List info:8081* _odict_FIRST(od)82* _odict_LAST(od)83* _odict_EMPTY(od)84* _odict_FOREACH(od, node) - used in place of `for (node=...)`8586For adding nodes:8788* _odict_add_head(od, node)89* _odict_add_tail(od, node)90* _odict_add_new_node(od, key, hash)9192For removing nodes:9394* _odict_clear_node(od, node, key, hash)95* _odict_clear_nodes(od, clear_each)9697Others:9899* _odict_find_node_hash(od, key, hash)100* _odict_find_node(od, key)101* _odict_keys_equal(od1, od2)102103And here's a look at how the linked-list relates to the OrderedDict API:104105============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===106method key val prev next mem 1st last empty iter find add rmv clr keq107============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===108__del__ ~ X109__delitem__ free ~ node110__eq__ ~ X111__iter__ X X112__new__ X X113__reduce__ X ~ X114__repr__ X X X115__reversed__ X X116__setitem__ key117__sizeof__ size X118clear ~ ~ X119copy X X X120items X X X121keys X X122move_to_end X X X ~ h/t key123pop free key124popitem X X free X X node125setdefault ~ ? ~126values X X127============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===128129__delitem__ is the only method that directly relies on finding an arbitrary130node in the linked-list. Everything else is iteration or relates to the131ends of the linked-list.132133Situation that Endangers Consistency134------------------------------------135Using a raw linked-list for OrderedDict exposes a key situation that can136cause problems. If a node is stored in a variable, there is a chance that137the node may have been deallocated before the variable gets used, thus138potentially leading to a segmentation fault. A key place where this shows139up is during iteration through the linked list (via _odict_FOREACH or140otherwise).141142A number of solutions are available to resolve this situation:143144* defer looking up the node until as late as possible and certainly after145any code that could possibly result in a deletion;146* if the node is needed both before and after a point where the node might147be removed, do a check before using the node at the "after" location to148see if the node is still valid;149* like the last one, but simply pull the node again to ensure it's right;150* keep the key in the variable instead of the node and then look up the151node using the key at the point where the node is needed (this is what152we do for the iterators).153154Another related problem, preserving consistent ordering during iteration,155is described below. That one is not exclusive to using linked-lists.156157158Challenges from Subclassing dict159================================160161OrderedDict subclasses dict, which is an unusual relationship between two162builtin types (other than the base object type). Doing so results in163some complication and deserves further explanation. There are two things164to consider here. First, in what circumstances or with what adjustments165can OrderedDict be used as a drop-in replacement for dict (at the C level)?166Second, how can the OrderedDict implementation leverage the dict167implementation effectively without introducing unnecessary coupling or168inefficiencies?169170This second point is reflected here and in the implementation, so the171further focus is on the first point. It is worth noting that for172overridden methods, the dict implementation is deferred to as much as173possible. Furthermore, coupling is limited to as little as is reasonable.174175Concrete API Compatibility176--------------------------177178Use of the concrete C-API for dict (PyDict_*) with OrderedDict is179problematic. (See http://bugs.python.org/issue10977.) The concrete API180has a number of hard-coded assumptions tied to the dict implementation.181This is, in part, due to performance reasons, which is understandable182given the part dict plays in Python.183184Any attempt to replace dict with OrderedDict for any role in the185interpreter (e.g. **kwds) faces a challenge. Such any effort must186recognize that the instances in affected locations currently interact with187the concrete API.188189Here are some ways to address this challenge:1901911. Change the relevant usage of the concrete API in CPython and add192PyDict_CheckExact() calls to each of the concrete API functions.1932. Adjust the relevant concrete API functions to explicitly accommodate194OrderedDict.1953. As with #1, add the checks, but improve the abstract API with smart fast196paths for dict and OrderedDict, and refactor CPython to use the abstract197API. Improvements to the abstract API would be valuable regardless.198199Adding the checks to the concrete API would help make any interpreter200switch to OrderedDict less painful for extension modules. However, this201won't work. The equivalent C API call to `dict.__setitem__(obj, k, v)`202is 'PyDict_SetItem(obj, k, v)`. This illustrates how subclasses in C call203the base class's methods, since there is no equivalent of super() in the204C API. Calling into Python for parent class API would work, but some205extension modules already rely on this feature of the concrete API.206207For reference, here is a breakdown of some of the dict concrete API:208209========================== ============= =======================210concrete API uses abstract API211========================== ============= =======================212PyDict_Check PyMapping_Check213(PyDict_CheckExact) -214(PyDict_New) -215(PyDictProxy_New) -216PyDict_Clear -217PyDict_Contains PySequence_Contains218PyDict_Copy -219PyDict_SetItem PyObject_SetItem220PyDict_SetItemString PyMapping_SetItemString221PyDict_DelItem PyMapping_DelItem222PyDict_DelItemString PyMapping_DelItemString223PyDict_GetItem -224PyDict_GetItemWithError PyObject_GetItem225_PyDict_GetItemIdWithError -226PyDict_GetItemString PyMapping_GetItemString227PyDict_Items PyMapping_Items228PyDict_Keys PyMapping_Keys229PyDict_Values PyMapping_Values230PyDict_Size PyMapping_Size231PyMapping_Length232PyDict_Next PyIter_Next233_PyDict_Next -234PyDict_Merge -235PyDict_Update -236PyDict_MergeFromSeq2 -237PyDict_ClearFreeList -238- PyMapping_HasKeyString239- PyMapping_HasKey240========================== ============= =======================241242243The dict Interface Relative to OrderedDict244==========================================245246Since OrderedDict subclasses dict, understanding the various methods and247attributes of dict is important for implementing OrderedDict.248249Relevant Type Slots250-------------------251252================= ================ =================== ================253slot attribute object dict254================= ================ =================== ================255tp_dealloc - object_dealloc dict_dealloc256tp_repr __repr__ object_repr dict_repr257sq_contains __contains__ - dict_contains258mp_length __len__ - dict_length259mp_subscript __getitem__ - dict_subscript260mp_ass_subscript __setitem__ - dict_ass_sub261__delitem__262tp_hash __hash__ _Py_HashPointer ..._HashNotImpl263tp_str __str__ object_str -264tp_getattro __getattribute__ ..._GenericGetAttr (repeated)265__getattr__266tp_setattro __setattr__ ..._GenericSetAttr (disabled)267tp_doc __doc__ (literal) dictionary_doc268tp_traverse - - dict_traverse269tp_clear - - dict_tp_clear270tp_richcompare __eq__ object_richcompare dict_richcompare271__ne__272tp_weaklistoffset (__weakref__) - -273tp_iter __iter__ - dict_iter274tp_dictoffset (__dict__) - -275tp_init __init__ object_init dict_init276tp_alloc - PyType_GenericAlloc (repeated)277tp_new __new__ object_new dict_new278tp_free - PyObject_Del PyObject_GC_Del279================= ================ =================== ================280281Relevant Methods282----------------283284================ =================== ===============285method object dict286================ =================== ===============287__reduce__ object_reduce -288__sizeof__ object_sizeof dict_sizeof289clear - dict_clear290copy - dict_copy291fromkeys - dict_fromkeys292get - dict_get293items - dictitems_new294keys - dictkeys_new295pop - dict_pop296popitem - dict_popitem297setdefault - dict_setdefault298update - dict_update299values - dictvalues_new300================ =================== ===============301302303Pure Python OrderedDict304=======================305306As already noted, compatibility with the pure Python OrderedDict307implementation is a key goal of this C implementation. To further that308goal, here's a summary of how OrderedDict-specific methods are implemented309in collections/__init__.py. Also provided is an indication of which310methods directly mutate or iterate the object, as well as any relationship311with the underlying linked-list.312313============= ============== == ================ === === ====314method impl used ll uses inq mut iter315============= ============== == ================ === === ====316__contains__ dict - - X317__delitem__ OrderedDict Y dict.__delitem__ X318__eq__ OrderedDict N OrderedDict ~319dict.__eq__320__iter__321__getitem__ dict - - X322__iter__ OrderedDict Y - X323__init__ OrderedDict N update324__len__ dict - - X325__ne__ MutableMapping - __eq__ ~326__reduce__ OrderedDict N OrderedDict ~327__iter__328__getitem__329__repr__ OrderedDict N __class__ ~330items331__reversed__ OrderedDict Y - X332__setitem__ OrderedDict Y __contains__ X333dict.__setitem__334__sizeof__ OrderedDict Y __len__ ~335__dict__336clear OrderedDict Y dict.clear X337copy OrderedDict N __class__338__init__339fromkeys OrderedDict N __setitem__340get dict - - ~341items MutableMapping - ItemsView X342keys MutableMapping - KeysView X343move_to_end OrderedDict Y - X344pop OrderedDict N __contains__ X345__getitem__346__delitem__347popitem OrderedDict Y dict.pop X348setdefault OrderedDict N __contains__ ~349__getitem__350__setitem__351update MutableMapping - __setitem__ ~352values MutableMapping - ValuesView X353============= ============== == ================ === === ====354355__reversed__ and move_to_end are both exclusive to OrderedDict.356357358C OrderedDict Implementation359============================360361================= ================362slot impl363================= ================364tp_dealloc odict_dealloc365tp_repr odict_repr366mp_ass_subscript odict_ass_sub367tp_doc odict_doc368tp_traverse odict_traverse369tp_clear odict_tp_clear370tp_richcompare odict_richcompare371tp_weaklistoffset (offset)372tp_iter odict_iter373tp_dictoffset (offset)374tp_init odict_init375tp_alloc (repeated)376================= ================377378================= ================379method impl380================= ================381__reduce__ odict_reduce382__sizeof__ odict_sizeof383clear odict_clear384copy odict_copy385fromkeys odict_fromkeys386items odictitems_new387keys odictkeys_new388pop odict_pop389popitem odict_popitem390setdefault odict_setdefault391update odict_update392values odictvalues_new393================= ================394395Inherited unchanged from object/dict:396397================ ==========================398method type field399================ ==========================400- tp_free401__contains__ tp_as_sequence.sq_contains402__getattr__ tp_getattro403__getattribute__ tp_getattro404__getitem__ tp_as_mapping.mp_subscript405__hash__ tp_hash406__len__ tp_as_mapping.mp_length407__setattr__ tp_setattro408__str__ tp_str409get -410================ ==========================411412413Other Challenges414================415416Preserving Ordering During Iteration417------------------------------------418During iteration through an OrderedDict, it is possible that items could419get added, removed, or reordered. For a linked-list implementation, as420with some other implementations, that situation may lead to undefined421behavior. The documentation for dict mentions this in the `iter()` section422of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.423In this implementation we follow dict's lead (as does the pure Python424implementation) for __iter__(), keys(), values(), and items().425426For internal iteration (using _odict_FOREACH or not), there is still the427risk that not all nodes that we expect to be seen in the loop actually get428seen. Thus, we are careful in each of those places to ensure that they429are. This comes, of course, at a small price at each location. The430solutions are much the same as those detailed in the `Situation that431Endangers Consistency` section above.432433434Potential Optimizations435=======================436437* Allocate the nodes as a block via od_fast_nodes instead of individually.438- Set node->key to NULL to indicate the node is not-in-use.439- Add _odict_EXISTS()?440- How to maintain consistency across resizes? Existing node pointers441would be invalidated after a resize, which is particularly problematic442for the iterators.443* Use a more stream-lined implementation of update() and, likely indirectly,444__init__().445446*/447448/* TODO449450sooner:451- reentrancy (make sure everything is at a thread-safe state when calling452into Python). I've already checked this multiple times, but want to453make one more pass.454- add unit tests for reentrancy?455456later:457- make the dict views support the full set API (the pure Python impl does)458- implement a fuller MutableMapping API in C?459- move the MutableMapping implementation to abstract.c?460- optimize mutablemapping_update461- use PyObject_Malloc (small object allocator) for odict nodes?462- support subclasses better (e.g. in odict_richcompare)463464*/465466#include "Python.h"467#include "pycore_call.h" // _PyObject_CallNoArgs()468#include "pycore_object.h" // _PyObject_GC_UNTRACK()469#include "pycore_dict.h" // _Py_dict_lookup()470#include <stddef.h> // offsetof()471472#include "clinic/odictobject.c.h"473474/*[clinic input]475class OrderedDict "PyODictObject *" "&PyODict_Type"476[clinic start generated code]*/477/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/478479480typedef struct _odictnode _ODictNode;481482/* PyODictObject */483struct _odictobject {484PyDictObject od_dict; /* the underlying dict */485_ODictNode *od_first; /* first node in the linked list, if any */486_ODictNode *od_last; /* last node in the linked list, if any */487/* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed488* by _odict_resize().489* Note that we rely on implementation details of dict for both. */490_ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */491Py_ssize_t od_fast_nodes_size;492void *od_resize_sentinel; /* changes if odict should be resized */493494size_t od_state; /* incremented whenever the LL changes */495PyObject *od_inst_dict; /* OrderedDict().__dict__ */496PyObject *od_weakreflist; /* holds weakrefs to the odict */497};498499500/* ----------------------------------------------501* odict keys (a simple doubly-linked list)502*/503504struct _odictnode {505PyObject *key;506Py_hash_t hash;507_ODictNode *next;508_ODictNode *prev;509};510511#define _odictnode_KEY(node) \512(node->key)513#define _odictnode_HASH(node) \514(node->hash)515/* borrowed reference */516#define _odictnode_VALUE(node, od) \517PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))518#define _odictnode_PREV(node) (node->prev)519#define _odictnode_NEXT(node) (node->next)520521#define _odict_FIRST(od) (((PyODictObject *)od)->od_first)522#define _odict_LAST(od) (((PyODictObject *)od)->od_last)523#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)524#define _odict_FOREACH(od, node) \525for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))526527/* Return the index into the hash table, regardless of a valid node. */528static Py_ssize_t529_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)530{531PyObject *value = NULL;532PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;533Py_ssize_t ix;534535ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);536if (ix == DKIX_EMPTY) {537return keys->dk_nentries; /* index of new entry */538}539if (ix < 0)540return -1;541/* We use pointer arithmetic to get the entry's index into the table. */542return ix;543}544545#define ONE ((Py_ssize_t)1)546547/* Replace od->od_fast_nodes with a new table matching the size of dict's. */548static int549_odict_resize(PyODictObject *od)550{551Py_ssize_t size, i;552_ODictNode **fast_nodes, *node;553554/* Initialize a new "fast nodes" table. */555size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);556fast_nodes = PyMem_NEW(_ODictNode *, size);557if (fast_nodes == NULL) {558PyErr_NoMemory();559return -1;560}561for (i = 0; i < size; i++)562fast_nodes[i] = NULL;563564/* Copy the current nodes into the table. */565_odict_FOREACH(od, node) {566i = _odict_get_index_raw(od, _odictnode_KEY(node),567_odictnode_HASH(node));568if (i < 0) {569PyMem_Free(fast_nodes);570return -1;571}572fast_nodes[i] = node;573}574575/* Replace the old fast nodes table. */576PyMem_Free(od->od_fast_nodes);577od->od_fast_nodes = fast_nodes;578od->od_fast_nodes_size = size;579od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;580return 0;581}582583/* Return the index into the hash table, regardless of a valid node. */584static Py_ssize_t585_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)586{587PyDictKeysObject *keys;588589assert(key != NULL);590keys = ((PyDictObject *)od)->ma_keys;591592/* Ensure od_fast_nodes and dk_entries are in sync. */593if (od->od_resize_sentinel != keys ||594od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {595int resize_res = _odict_resize(od);596if (resize_res < 0)597return -1;598}599600return _odict_get_index_raw(od, key, hash);601}602603/* Returns NULL if there was some error or the key was not found. */604static _ODictNode *605_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)606{607Py_ssize_t index;608609if (_odict_EMPTY(od))610return NULL;611index = _odict_get_index(od, key, hash);612if (index < 0)613return NULL;614assert(od->od_fast_nodes != NULL);615return od->od_fast_nodes[index];616}617618static _ODictNode *619_odict_find_node(PyODictObject *od, PyObject *key)620{621Py_ssize_t index;622Py_hash_t hash;623624if (_odict_EMPTY(od))625return NULL;626hash = PyObject_Hash(key);627if (hash == -1)628return NULL;629index = _odict_get_index(od, key, hash);630if (index < 0)631return NULL;632assert(od->od_fast_nodes != NULL);633return od->od_fast_nodes[index];634}635636static void637_odict_add_head(PyODictObject *od, _ODictNode *node)638{639_odictnode_PREV(node) = NULL;640_odictnode_NEXT(node) = _odict_FIRST(od);641if (_odict_FIRST(od) == NULL)642_odict_LAST(od) = node;643else644_odictnode_PREV(_odict_FIRST(od)) = node;645_odict_FIRST(od) = node;646od->od_state++;647}648649static void650_odict_add_tail(PyODictObject *od, _ODictNode *node)651{652_odictnode_PREV(node) = _odict_LAST(od);653_odictnode_NEXT(node) = NULL;654if (_odict_LAST(od) == NULL)655_odict_FIRST(od) = node;656else657_odictnode_NEXT(_odict_LAST(od)) = node;658_odict_LAST(od) = node;659od->od_state++;660}661662/* adds the node to the end of the list */663static int664_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)665{666Py_ssize_t i;667_ODictNode *node;668669Py_INCREF(key);670i = _odict_get_index(od, key, hash);671if (i < 0) {672if (!PyErr_Occurred())673PyErr_SetObject(PyExc_KeyError, key);674Py_DECREF(key);675return -1;676}677assert(od->od_fast_nodes != NULL);678if (od->od_fast_nodes[i] != NULL) {679/* We already have a node for the key so there's no need to add one. */680Py_DECREF(key);681return 0;682}683684/* must not be added yet */685node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));686if (node == NULL) {687Py_DECREF(key);688PyErr_NoMemory();689return -1;690}691692_odictnode_KEY(node) = key;693_odictnode_HASH(node) = hash;694_odict_add_tail(od, node);695od->od_fast_nodes[i] = node;696return 0;697}698699/* Putting the decref after the free causes problems. */700#define _odictnode_DEALLOC(node) \701do { \702Py_DECREF(_odictnode_KEY(node)); \703PyMem_Free((void *)node); \704} while (0)705706/* Repeated calls on the same node are no-ops. */707static void708_odict_remove_node(PyODictObject *od, _ODictNode *node)709{710if (_odict_FIRST(od) == node)711_odict_FIRST(od) = _odictnode_NEXT(node);712else if (_odictnode_PREV(node) != NULL)713_odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);714715if (_odict_LAST(od) == node)716_odict_LAST(od) = _odictnode_PREV(node);717else if (_odictnode_NEXT(node) != NULL)718_odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);719720_odictnode_PREV(node) = NULL;721_odictnode_NEXT(node) = NULL;722od->od_state++;723}724725/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll726get all sorts of problems here. In PyODict_DelItem we make sure to727call _odict_clear_node first.728729This matters in the case of colliding keys. Suppose we add 3 keys:730[A, B, C], where the hash of C collides with A and the next possible731index in the hash table is occupied by B. If we remove B then for C732the dict's looknode func will give us the old index of B instead of733the index we got before deleting B. However, the node for C in734od_fast_nodes is still at the old dict index of C. Thus to be sure735things don't get out of sync, we clear the node in od_fast_nodes736*before* calling PyDict_DelItem.737738The same must be done for any other OrderedDict operations where739we modify od_fast_nodes.740*/741static int742_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,743Py_hash_t hash)744{745Py_ssize_t i;746747assert(key != NULL);748if (_odict_EMPTY(od)) {749/* Let later code decide if this is a KeyError. */750return 0;751}752753i = _odict_get_index(od, key, hash);754if (i < 0)755return PyErr_Occurred() ? -1 : 0;756757assert(od->od_fast_nodes != NULL);758if (node == NULL)759node = od->od_fast_nodes[i];760assert(node == od->od_fast_nodes[i]);761if (node == NULL) {762/* Let later code decide if this is a KeyError. */763return 0;764}765766// Now clear the node.767od->od_fast_nodes[i] = NULL;768_odict_remove_node(od, node);769_odictnode_DEALLOC(node);770return 0;771}772773static void774_odict_clear_nodes(PyODictObject *od)775{776_ODictNode *node, *next;777778PyMem_Free(od->od_fast_nodes);779od->od_fast_nodes = NULL;780od->od_fast_nodes_size = 0;781od->od_resize_sentinel = NULL;782783node = _odict_FIRST(od);784_odict_FIRST(od) = NULL;785_odict_LAST(od) = NULL;786while (node != NULL) {787next = _odictnode_NEXT(node);788_odictnode_DEALLOC(node);789node = next;790}791}792793/* There isn't any memory management of nodes past this point. */794#undef _odictnode_DEALLOC795796static int797_odict_keys_equal(PyODictObject *a, PyODictObject *b)798{799_ODictNode *node_a, *node_b;800801node_a = _odict_FIRST(a);802node_b = _odict_FIRST(b);803while (1) {804if (node_a == NULL && node_b == NULL)805/* success: hit the end of each at the same time */806return 1;807else if (node_a == NULL || node_b == NULL)808/* unequal length */809return 0;810else {811int res = PyObject_RichCompareBool(812(PyObject *)_odictnode_KEY(node_a),813(PyObject *)_odictnode_KEY(node_b),814Py_EQ);815if (res < 0)816return res;817else if (res == 0)818return 0;819820/* otherwise it must match, so move on to the next one */821node_a = _odictnode_NEXT(node_a);822node_b = _odictnode_NEXT(node_b);823}824}825}826827828/* ----------------------------------------------829* OrderedDict mapping methods830*/831832/* mp_ass_subscript: __setitem__() and __delitem__() */833834static int835odict_mp_ass_sub(PyODictObject *od, PyObject *v, PyObject *w)836{837if (w == NULL)838return PyODict_DelItem((PyObject *)od, v);839else840return PyODict_SetItem((PyObject *)od, v, w);841}842843/* tp_as_mapping */844845static PyMappingMethods odict_as_mapping = {8460, /*mp_length*/8470, /*mp_subscript*/848(objobjargproc)odict_mp_ass_sub, /*mp_ass_subscript*/849};850851852/* ----------------------------------------------853* OrderedDict number methods854*/855856static int mutablemapping_update_arg(PyObject*, PyObject*);857858static PyObject *859odict_or(PyObject *left, PyObject *right)860{861PyTypeObject *type;862PyObject *other;863if (PyODict_Check(left)) {864type = Py_TYPE(left);865other = right;866}867else {868type = Py_TYPE(right);869other = left;870}871if (!PyDict_Check(other)) {872Py_RETURN_NOTIMPLEMENTED;873}874PyObject *new = PyObject_CallOneArg((PyObject*)type, left);875if (!new) {876return NULL;877}878if (mutablemapping_update_arg(new, right) < 0) {879Py_DECREF(new);880return NULL;881}882return new;883}884885static PyObject *886odict_inplace_or(PyObject *self, PyObject *other)887{888if (mutablemapping_update_arg(self, other) < 0) {889return NULL;890}891return Py_NewRef(self);892}893894/* tp_as_number */895896static PyNumberMethods odict_as_number = {897.nb_or = odict_or,898.nb_inplace_or = odict_inplace_or,899};900901902/* ----------------------------------------------903* OrderedDict methods904*/905906/* fromkeys() */907908/*[clinic input]909@classmethod910OrderedDict.fromkeys911912iterable as seq: object913value: object = None914915Create a new ordered dictionary with keys from iterable and values set to value.916[clinic start generated code]*/917918static PyObject *919OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)920/*[clinic end generated code: output=c10390d452d78d6d input=1a0476c229c597b3]*/921{922return _PyDict_FromKeys((PyObject *)type, seq, value);923}924925/* __sizeof__() */926927/* OrderedDict.__sizeof__() does not have a docstring. */928PyDoc_STRVAR(odict_sizeof__doc__, "");929930static PyObject *931odict_sizeof(PyODictObject *od, PyObject *Py_UNUSED(ignored))932{933Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);934res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */935if (!_odict_EMPTY(od)) {936res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */937}938return PyLong_FromSsize_t(res);939}940941/* __reduce__() */942943PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");944945static PyObject *946odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))947{948PyObject *state, *result = NULL;949PyObject *items_iter, *items, *args = NULL;950951/* capture any instance state */952state = _PyObject_GetState((PyObject *)od);953if (state == NULL)954goto Done;955956/* build the result */957args = PyTuple_New(0);958if (args == NULL)959goto Done;960961items = PyObject_CallMethodNoArgs((PyObject *)od, &_Py_ID(items));962if (items == NULL)963goto Done;964965items_iter = PyObject_GetIter(items);966Py_DECREF(items);967if (items_iter == NULL)968goto Done;969970result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);971Py_DECREF(items_iter);972973Done:974Py_XDECREF(state);975Py_XDECREF(args);976977return result;978}979980/* setdefault(): Skips __missing__() calls. */981982983/*[clinic input]984OrderedDict.setdefault985986key: object987default: object = None988989Insert key with a value of default if key is not in the dictionary.990991Return the value for key if key is in the dictionary, else default.992[clinic start generated code]*/993994static PyObject *995OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,996PyObject *default_value)997/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/998{999PyObject *result = NULL;10001001if (PyODict_CheckExact(self)) {1002result = PyODict_GetItemWithError(self, key); /* borrowed */1003if (result == NULL) {1004if (PyErr_Occurred())1005return NULL;1006assert(_odict_find_node(self, key) == NULL);1007if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {1008result = Py_NewRef(default_value);1009}1010}1011else {1012Py_INCREF(result);1013}1014}1015else {1016int exists = PySequence_Contains((PyObject *)self, key);1017if (exists < 0) {1018return NULL;1019}1020else if (exists) {1021result = PyObject_GetItem((PyObject *)self, key);1022}1023else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {1024result = Py_NewRef(default_value);1025}1026}10271028return result;1029}10301031/* pop() */10321033static PyObject *1034_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,1035Py_hash_t hash)1036{1037PyObject *value = NULL;10381039_ODictNode *node = _odict_find_node_hash((PyODictObject *)od, key, hash);1040if (node != NULL) {1041/* Pop the node first to avoid a possible dict resize (due to1042eval loop reentrancy) and complications due to hash collision1043resolution. */1044int res = _odict_clear_node((PyODictObject *)od, node, key, hash);1045if (res < 0) {1046return NULL;1047}1048/* Now delete the value from the dict. */1049value = _PyDict_Pop_KnownHash(od, key, hash, failobj);1050}1051else if (value == NULL && !PyErr_Occurred()) {1052/* Apply the fallback value, if necessary. */1053if (failobj) {1054value = Py_NewRef(failobj);1055}1056else {1057PyErr_SetObject(PyExc_KeyError, key);1058}1059}10601061return value;1062}10631064/* Skips __missing__() calls. */1065/*[clinic input]1066OrderedDict.pop10671068key: object1069default: object = NULL10701071od.pop(key[,default]) -> v, remove specified key and return the corresponding value.10721073If the key is not found, return the default if given; otherwise,1074raise a KeyError.1075[clinic start generated code]*/10761077static PyObject *1078OrderedDict_pop_impl(PyODictObject *self, PyObject *key,1079PyObject *default_value)1080/*[clinic end generated code: output=7a6447d104e7494b input=7efe36601007dff7]*/1081{1082Py_hash_t hash = PyObject_Hash(key);1083if (hash == -1)1084return NULL;1085return _odict_popkey_hash((PyObject *)self, key, default_value, hash);1086}108710881089/* popitem() */10901091/*[clinic input]1092OrderedDict.popitem10931094last: bool = True10951096Remove and return a (key, value) pair from the dictionary.10971098Pairs are returned in LIFO order if last is true or FIFO order if false.1099[clinic start generated code]*/11001101static PyObject *1102OrderedDict_popitem_impl(PyODictObject *self, int last)1103/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/1104{1105PyObject *key, *value, *item = NULL;1106_ODictNode *node;11071108/* pull the item */11091110if (_odict_EMPTY(self)) {1111PyErr_SetString(PyExc_KeyError, "dictionary is empty");1112return NULL;1113}11141115node = last ? _odict_LAST(self) : _odict_FIRST(self);1116key = Py_NewRef(_odictnode_KEY(node));1117value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));1118if (value == NULL)1119return NULL;1120item = PyTuple_Pack(2, key, value);1121Py_DECREF(key);1122Py_DECREF(value);1123return item;1124}11251126/* keys() */11271128/* MutableMapping.keys() does not have a docstring. */1129PyDoc_STRVAR(odict_keys__doc__, "");11301131static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */11321133/* values() */11341135/* MutableMapping.values() does not have a docstring. */1136PyDoc_STRVAR(odict_values__doc__, "");11371138static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */11391140/* items() */11411142/* MutableMapping.items() does not have a docstring. */1143PyDoc_STRVAR(odict_items__doc__, "");11441145static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */11461147/* update() */11481149/* MutableMapping.update() does not have a docstring. */1150PyDoc_STRVAR(odict_update__doc__, "");11511152/* forward */1153static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);11541155#define odict_update mutablemapping_update11561157/* clear() */11581159PyDoc_STRVAR(odict_clear__doc__,1160"od.clear() -> None. Remove all items from od.");11611162static PyObject *1163odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))1164{1165PyDict_Clear((PyObject *)od);1166_odict_clear_nodes(od);1167Py_RETURN_NONE;1168}11691170/* copy() */11711172/* forward */1173static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,1174Py_hash_t);11751176PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");11771178static PyObject *1179odict_copy(register PyODictObject *od, PyObject *Py_UNUSED(ignored))1180{1181_ODictNode *node;1182PyObject *od_copy;11831184if (PyODict_CheckExact(od))1185od_copy = PyODict_New();1186else1187od_copy = _PyObject_CallNoArgs((PyObject *)Py_TYPE(od));1188if (od_copy == NULL)1189return NULL;11901191if (PyODict_CheckExact(od)) {1192_odict_FOREACH(od, node) {1193PyObject *key = _odictnode_KEY(node);1194PyObject *value = _odictnode_VALUE(node, od);1195if (value == NULL) {1196if (!PyErr_Occurred())1197PyErr_SetObject(PyExc_KeyError, key);1198goto fail;1199}1200if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,1201_odictnode_HASH(node)) != 0)1202goto fail;1203}1204}1205else {1206_odict_FOREACH(od, node) {1207int res;1208PyObject *value = PyObject_GetItem((PyObject *)od,1209_odictnode_KEY(node));1210if (value == NULL)1211goto fail;1212res = PyObject_SetItem((PyObject *)od_copy,1213_odictnode_KEY(node), value);1214Py_DECREF(value);1215if (res != 0)1216goto fail;1217}1218}1219return od_copy;12201221fail:1222Py_DECREF(od_copy);1223return NULL;1224}12251226/* __reversed__() */12271228PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");12291230#define _odict_ITER_REVERSED 11231#define _odict_ITER_KEYS 21232#define _odict_ITER_VALUES 41233#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES)12341235/* forward */1236static PyObject * odictiter_new(PyODictObject *, int);12371238static PyObject *1239odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))1240{1241return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);1242}124312441245/* move_to_end() */12461247/*[clinic input]1248OrderedDict.move_to_end12491250key: object1251last: bool = True12521253Move an existing element to the end (or beginning if last is false).12541255Raise KeyError if the element does not exist.1256[clinic start generated code]*/12571258static PyObject *1259OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)1260/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/1261{1262_ODictNode *node;12631264if (_odict_EMPTY(self)) {1265PyErr_SetObject(PyExc_KeyError, key);1266return NULL;1267}1268node = last ? _odict_LAST(self) : _odict_FIRST(self);1269if (key != _odictnode_KEY(node)) {1270node = _odict_find_node(self, key);1271if (node == NULL) {1272if (!PyErr_Occurred())1273PyErr_SetObject(PyExc_KeyError, key);1274return NULL;1275}1276if (last) {1277/* Only move if not already the last one. */1278if (node != _odict_LAST(self)) {1279_odict_remove_node(self, node);1280_odict_add_tail(self, node);1281}1282}1283else {1284/* Only move if not already the first one. */1285if (node != _odict_FIRST(self)) {1286_odict_remove_node(self, node);1287_odict_add_head(self, node);1288}1289}1290}1291Py_RETURN_NONE;1292}129312941295/* tp_methods */12961297static PyMethodDef odict_methods[] = {12981299/* overridden dict methods */1300ORDEREDDICT_FROMKEYS_METHODDEF1301{"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,1302odict_sizeof__doc__},1303{"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,1304odict_reduce__doc__},1305ORDEREDDICT_SETDEFAULT_METHODDEF1306ORDEREDDICT_POP_METHODDEF1307ORDEREDDICT_POPITEM_METHODDEF1308{"keys", odictkeys_new, METH_NOARGS,1309odict_keys__doc__},1310{"values", odictvalues_new, METH_NOARGS,1311odict_values__doc__},1312{"items", odictitems_new, METH_NOARGS,1313odict_items__doc__},1314{"update", _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,1315odict_update__doc__},1316{"clear", (PyCFunction)odict_clear, METH_NOARGS,1317odict_clear__doc__},1318{"copy", (PyCFunction)odict_copy, METH_NOARGS,1319odict_copy__doc__},13201321/* new methods */1322{"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,1323odict_reversed__doc__},1324ORDEREDDICT_MOVE_TO_END_METHODDEF13251326{NULL, NULL} /* sentinel */1327};132813291330/* ----------------------------------------------1331* OrderedDict members1332*/13331334/* tp_getset */13351336static PyGetSetDef odict_getset[] = {1337{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},1338{NULL}1339};13401341/* ----------------------------------------------1342* OrderedDict type slot methods1343*/13441345/* tp_dealloc */13461347static void1348odict_dealloc(PyODictObject *self)1349{1350PyObject_GC_UnTrack(self);1351Py_TRASHCAN_BEGIN(self, odict_dealloc)13521353Py_XDECREF(self->od_inst_dict);1354if (self->od_weakreflist != NULL)1355PyObject_ClearWeakRefs((PyObject *)self);13561357_odict_clear_nodes(self);1358PyDict_Type.tp_dealloc((PyObject *)self);13591360Py_TRASHCAN_END1361}13621363/* tp_repr */13641365static PyObject *1366odict_repr(PyODictObject *self)1367{1368int i;1369PyObject *result = NULL, *dcopy = NULL;13701371if (PyODict_SIZE(self) == 0)1372return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));13731374i = Py_ReprEnter((PyObject *)self);1375if (i != 0) {1376return i > 0 ? PyUnicode_FromString("...") : NULL;1377}13781379dcopy = PyDict_Copy((PyObject *)self);1380if (dcopy == NULL) {1381goto Done;1382}13831384result = PyUnicode_FromFormat("%s(%R)",1385_PyType_Name(Py_TYPE(self)),1386dcopy);1387Py_DECREF(dcopy);13881389Done:1390Py_ReprLeave((PyObject *)self);1391return result;1392}13931394/* tp_doc */13951396PyDoc_STRVAR(odict_doc,1397"Dictionary that remembers insertion order");13981399/* tp_traverse */14001401static int1402odict_traverse(PyODictObject *od, visitproc visit, void *arg)1403{1404_ODictNode *node;14051406Py_VISIT(od->od_inst_dict);1407_odict_FOREACH(od, node) {1408Py_VISIT(_odictnode_KEY(node));1409}1410return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);1411}14121413/* tp_clear */14141415static int1416odict_tp_clear(PyODictObject *od)1417{1418Py_CLEAR(od->od_inst_dict);1419PyDict_Clear((PyObject *)od);1420_odict_clear_nodes(od);1421return 0;1422}14231424/* tp_richcompare */14251426static PyObject *1427odict_richcompare(PyObject *v, PyObject *w, int op)1428{1429if (!PyODict_Check(v) || !PyDict_Check(w)) {1430Py_RETURN_NOTIMPLEMENTED;1431}14321433if (op == Py_EQ || op == Py_NE) {1434PyObject *res, *cmp;1435int eq;14361437cmp = PyDict_Type.tp_richcompare(v, w, op);1438if (cmp == NULL)1439return NULL;1440if (!PyODict_Check(w))1441return cmp;1442if (op == Py_EQ && cmp == Py_False)1443return cmp;1444if (op == Py_NE && cmp == Py_True)1445return cmp;1446Py_DECREF(cmp);14471448/* Try comparing odict keys. */1449eq = _odict_keys_equal((PyODictObject *)v, (PyODictObject *)w);1450if (eq < 0)1451return NULL;14521453res = (eq == (op == Py_EQ)) ? Py_True : Py_False;1454return Py_NewRef(res);1455} else {1456Py_RETURN_NOTIMPLEMENTED;1457}1458}14591460/* tp_iter */14611462static PyObject *1463odict_iter(PyODictObject *od)1464{1465return odictiter_new(od, _odict_ITER_KEYS);1466}14671468/* tp_init */14691470static int1471odict_init(PyObject *self, PyObject *args, PyObject *kwds)1472{1473PyObject *res;1474Py_ssize_t len = PyObject_Length(args);14751476if (len == -1)1477return -1;1478if (len > 1) {1479const char *msg = "expected at most 1 arguments, got %zd";1480PyErr_Format(PyExc_TypeError, msg, len);1481return -1;1482}14831484/* __init__() triggering update() is just the way things are! */1485res = odict_update(self, args, kwds);1486if (res == NULL) {1487return -1;1488} else {1489Py_DECREF(res);1490return 0;1491}1492}14931494/* PyODict_Type */14951496PyTypeObject PyODict_Type = {1497PyVarObject_HEAD_INIT(&PyType_Type, 0)1498"collections.OrderedDict", /* tp_name */1499sizeof(PyODictObject), /* tp_basicsize */15000, /* tp_itemsize */1501(destructor)odict_dealloc, /* tp_dealloc */15020, /* tp_vectorcall_offset */15030, /* tp_getattr */15040, /* tp_setattr */15050, /* tp_as_async */1506(reprfunc)odict_repr, /* tp_repr */1507&odict_as_number, /* tp_as_number */15080, /* tp_as_sequence */1509&odict_as_mapping, /* tp_as_mapping */15100, /* tp_hash */15110, /* tp_call */15120, /* tp_str */15130, /* tp_getattro */15140, /* tp_setattro */15150, /* tp_as_buffer */1516Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */1517odict_doc, /* tp_doc */1518(traverseproc)odict_traverse, /* tp_traverse */1519(inquiry)odict_tp_clear, /* tp_clear */1520(richcmpfunc)odict_richcompare, /* tp_richcompare */1521offsetof(PyODictObject, od_weakreflist), /* tp_weaklistoffset */1522(getiterfunc)odict_iter, /* tp_iter */15230, /* tp_iternext */1524odict_methods, /* tp_methods */15250, /* tp_members */1526odict_getset, /* tp_getset */1527&PyDict_Type, /* tp_base */15280, /* tp_dict */15290, /* tp_descr_get */15300, /* tp_descr_set */1531offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */1532(initproc)odict_init, /* tp_init */1533PyType_GenericAlloc, /* tp_alloc */15340, /* tp_new */15350, /* tp_free */1536};153715381539/* ----------------------------------------------1540* the public OrderedDict API1541*/15421543PyObject *1544PyODict_New(void)1545{1546return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);1547}15481549static int1550_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,1551Py_hash_t hash)1552{1553int res = _PyDict_SetItem_KnownHash(od, key, value, hash);1554if (res == 0) {1555res = _odict_add_new_node((PyODictObject *)od, key, hash);1556if (res < 0) {1557/* Revert setting the value on the dict */1558PyObject *exc = PyErr_GetRaisedException();1559(void) _PyDict_DelItem_KnownHash(od, key, hash);1560_PyErr_ChainExceptions1(exc);1561}1562}1563return res;1564}15651566int1567PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)1568{1569Py_hash_t hash = PyObject_Hash(key);1570if (hash == -1)1571return -1;1572return _PyODict_SetItem_KnownHash(od, key, value, hash);1573}15741575int1576PyODict_DelItem(PyObject *od, PyObject *key)1577{1578int res;1579Py_hash_t hash = PyObject_Hash(key);1580if (hash == -1)1581return -1;1582res = _odict_clear_node((PyODictObject *)od, NULL, key, hash);1583if (res < 0)1584return -1;1585return _PyDict_DelItem_KnownHash(od, key, hash);1586}158715881589/* -------------------------------------------1590* The OrderedDict views (keys/values/items)1591*/15921593typedef struct {1594PyObject_HEAD1595int kind;1596PyODictObject *di_odict;1597Py_ssize_t di_size;1598size_t di_state;1599PyObject *di_current;1600PyObject *di_result; /* reusable result tuple for iteritems */1601} odictiterobject;16021603static void1604odictiter_dealloc(odictiterobject *di)1605{1606_PyObject_GC_UNTRACK(di);1607Py_XDECREF(di->di_odict);1608Py_XDECREF(di->di_current);1609if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {1610Py_DECREF(di->di_result);1611}1612PyObject_GC_Del(di);1613}16141615static int1616odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)1617{1618Py_VISIT(di->di_odict);1619Py_VISIT(di->di_current); /* A key could be any type, not just str. */1620Py_VISIT(di->di_result);1621return 0;1622}16231624/* In order to protect against modifications during iteration, we track1625* the current key instead of the current node. */1626static PyObject *1627odictiter_nextkey(odictiterobject *di)1628{1629PyObject *key = NULL;1630_ODictNode *node;1631int reversed = di->kind & _odict_ITER_REVERSED;16321633if (di->di_odict == NULL)1634return NULL;1635if (di->di_current == NULL)1636goto done; /* We're already done. */16371638/* Check for unsupported changes. */1639if (di->di_odict->od_state != di->di_state) {1640PyErr_SetString(PyExc_RuntimeError,1641"OrderedDict mutated during iteration");1642goto done;1643}1644if (di->di_size != PyODict_SIZE(di->di_odict)) {1645PyErr_SetString(PyExc_RuntimeError,1646"OrderedDict changed size during iteration");1647di->di_size = -1; /* Make this state sticky */1648return NULL;1649}16501651/* Get the key. */1652node = _odict_find_node(di->di_odict, di->di_current);1653if (node == NULL) {1654if (!PyErr_Occurred())1655PyErr_SetObject(PyExc_KeyError, di->di_current);1656/* Must have been deleted. */1657Py_CLEAR(di->di_current);1658return NULL;1659}1660key = di->di_current;16611662/* Advance to the next key. */1663node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);1664if (node == NULL) {1665/* Reached the end. */1666di->di_current = NULL;1667}1668else {1669di->di_current = Py_NewRef(_odictnode_KEY(node));1670}16711672return key;16731674done:1675Py_CLEAR(di->di_odict);1676return key;1677}16781679static PyObject *1680odictiter_iternext(odictiterobject *di)1681{1682PyObject *result, *value;1683PyObject *key = odictiter_nextkey(di); /* new reference */16841685if (key == NULL)1686return NULL;16871688/* Handle the keys case. */1689if (! (di->kind & _odict_ITER_VALUES)) {1690return key;1691}16921693value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */1694if (value == NULL) {1695if (!PyErr_Occurred())1696PyErr_SetObject(PyExc_KeyError, key);1697Py_DECREF(key);1698goto done;1699}1700Py_INCREF(value);17011702/* Handle the values case. */1703if (!(di->kind & _odict_ITER_KEYS)) {1704Py_DECREF(key);1705return value;1706}17071708/* Handle the items case. */1709result = di->di_result;17101711if (Py_REFCNT(result) == 1) {1712/* not in use so we can reuse it1713* (the common case during iteration) */1714Py_INCREF(result);1715Py_DECREF(PyTuple_GET_ITEM(result, 0)); /* borrowed */1716Py_DECREF(PyTuple_GET_ITEM(result, 1)); /* borrowed */1717// bpo-42536: The GC may have untracked this result tuple. Since we're1718// recycling it, make sure it's tracked again:1719if (!_PyObject_GC_IS_TRACKED(result)) {1720_PyObject_GC_TRACK(result);1721}1722}1723else {1724result = PyTuple_New(2);1725if (result == NULL) {1726Py_DECREF(key);1727Py_DECREF(value);1728goto done;1729}1730}17311732PyTuple_SET_ITEM(result, 0, key); /* steals reference */1733PyTuple_SET_ITEM(result, 1, value); /* steals reference */1734return result;17351736done:1737Py_CLEAR(di->di_current);1738Py_CLEAR(di->di_odict);1739return NULL;1740}17411742/* No need for tp_clear because odictiterobject is not mutable. */17431744PyDoc_STRVAR(reduce_doc, "Return state information for pickling");17451746static PyObject *1747odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))1748{1749/* copy the iterator state */1750odictiterobject tmp = *di;1751Py_XINCREF(tmp.di_odict);1752Py_XINCREF(tmp.di_current);17531754/* iterate the temporary into a list */1755PyObject *list = PySequence_List((PyObject*)&tmp);1756Py_XDECREF(tmp.di_odict);1757Py_XDECREF(tmp.di_current);1758if (list == NULL) {1759return NULL;1760}1761return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);1762}17631764static PyMethodDef odictiter_methods[] = {1765{"__reduce__", (PyCFunction)odictiter_reduce, METH_NOARGS, reduce_doc},1766{NULL, NULL} /* sentinel */1767};17681769PyTypeObject PyODictIter_Type = {1770PyVarObject_HEAD_INIT(&PyType_Type, 0)1771"odict_iterator", /* tp_name */1772sizeof(odictiterobject), /* tp_basicsize */17730, /* tp_itemsize */1774/* methods */1775(destructor)odictiter_dealloc, /* tp_dealloc */17760, /* tp_vectorcall_offset */17770, /* tp_getattr */17780, /* tp_setattr */17790, /* tp_as_async */17800, /* tp_repr */17810, /* tp_as_number */17820, /* tp_as_sequence */17830, /* tp_as_mapping */17840, /* tp_hash */17850, /* tp_call */17860, /* tp_str */1787PyObject_GenericGetAttr, /* tp_getattro */17880, /* tp_setattro */17890, /* tp_as_buffer */1790Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */17910, /* tp_doc */1792(traverseproc)odictiter_traverse, /* tp_traverse */17930, /* tp_clear */17940, /* tp_richcompare */17950, /* tp_weaklistoffset */1796PyObject_SelfIter, /* tp_iter */1797(iternextfunc)odictiter_iternext, /* tp_iternext */1798odictiter_methods, /* tp_methods */17990,1800};18011802static PyObject *1803odictiter_new(PyODictObject *od, int kind)1804{1805odictiterobject *di;1806_ODictNode *node;1807int reversed = kind & _odict_ITER_REVERSED;18081809di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);1810if (di == NULL)1811return NULL;18121813if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {1814di->di_result = PyTuple_Pack(2, Py_None, Py_None);1815if (di->di_result == NULL) {1816Py_DECREF(di);1817return NULL;1818}1819}1820else {1821di->di_result = NULL;1822}18231824di->kind = kind;1825node = reversed ? _odict_LAST(od) : _odict_FIRST(od);1826di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;1827di->di_size = PyODict_SIZE(od);1828di->di_state = od->od_state;1829di->di_odict = (PyODictObject*)Py_NewRef(od);18301831_PyObject_GC_TRACK(di);1832return (PyObject *)di;1833}18341835/* keys() */18361837static PyObject *1838odictkeys_iter(_PyDictViewObject *dv)1839{1840if (dv->dv_dict == NULL) {1841Py_RETURN_NONE;1842}1843return odictiter_new((PyODictObject *)dv->dv_dict,1844_odict_ITER_KEYS);1845}18461847static PyObject *1848odictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))1849{1850if (dv->dv_dict == NULL) {1851Py_RETURN_NONE;1852}1853return odictiter_new((PyODictObject *)dv->dv_dict,1854_odict_ITER_KEYS|_odict_ITER_REVERSED);1855}18561857static PyMethodDef odictkeys_methods[] = {1858{"__reversed__", (PyCFunction)odictkeys_reversed, METH_NOARGS, NULL},1859{NULL, NULL} /* sentinel */1860};18611862PyTypeObject PyODictKeys_Type = {1863PyVarObject_HEAD_INIT(&PyType_Type, 0)1864"odict_keys", /* tp_name */18650, /* tp_basicsize */18660, /* tp_itemsize */18670, /* tp_dealloc */18680, /* tp_vectorcall_offset */18690, /* tp_getattr */18700, /* tp_setattr */18710, /* tp_as_async */18720, /* tp_repr */18730, /* tp_as_number */18740, /* tp_as_sequence */18750, /* tp_as_mapping */18760, /* tp_hash */18770, /* tp_call */18780, /* tp_str */18790, /* tp_getattro */18800, /* tp_setattro */18810, /* tp_as_buffer */18820, /* tp_flags */18830, /* tp_doc */18840, /* tp_traverse */18850, /* tp_clear */18860, /* tp_richcompare */18870, /* tp_weaklistoffset */1888(getiterfunc)odictkeys_iter, /* tp_iter */18890, /* tp_iternext */1890odictkeys_methods, /* tp_methods */18910, /* tp_members */18920, /* tp_getset */1893&PyDictKeys_Type, /* tp_base */1894};18951896static PyObject *1897odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))1898{1899return _PyDictView_New(od, &PyODictKeys_Type);1900}19011902/* items() */19031904static PyObject *1905odictitems_iter(_PyDictViewObject *dv)1906{1907if (dv->dv_dict == NULL) {1908Py_RETURN_NONE;1909}1910return odictiter_new((PyODictObject *)dv->dv_dict,1911_odict_ITER_KEYS|_odict_ITER_VALUES);1912}19131914static PyObject *1915odictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))1916{1917if (dv->dv_dict == NULL) {1918Py_RETURN_NONE;1919}1920return odictiter_new((PyODictObject *)dv->dv_dict,1921_odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);1922}19231924static PyMethodDef odictitems_methods[] = {1925{"__reversed__", (PyCFunction)odictitems_reversed, METH_NOARGS, NULL},1926{NULL, NULL} /* sentinel */1927};19281929PyTypeObject PyODictItems_Type = {1930PyVarObject_HEAD_INIT(&PyType_Type, 0)1931"odict_items", /* tp_name */19320, /* tp_basicsize */19330, /* tp_itemsize */19340, /* tp_dealloc */19350, /* tp_vectorcall_offset */19360, /* tp_getattr */19370, /* tp_setattr */19380, /* tp_as_async */19390, /* tp_repr */19400, /* tp_as_number */19410, /* tp_as_sequence */19420, /* tp_as_mapping */19430, /* tp_hash */19440, /* tp_call */19450, /* tp_str */19460, /* tp_getattro */19470, /* tp_setattro */19480, /* tp_as_buffer */19490, /* tp_flags */19500, /* tp_doc */19510, /* tp_traverse */19520, /* tp_clear */19530, /* tp_richcompare */19540, /* tp_weaklistoffset */1955(getiterfunc)odictitems_iter, /* tp_iter */19560, /* tp_iternext */1957odictitems_methods, /* tp_methods */19580, /* tp_members */19590, /* tp_getset */1960&PyDictItems_Type, /* tp_base */1961};19621963static PyObject *1964odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))1965{1966return _PyDictView_New(od, &PyODictItems_Type);1967}19681969/* values() */19701971static PyObject *1972odictvalues_iter(_PyDictViewObject *dv)1973{1974if (dv->dv_dict == NULL) {1975Py_RETURN_NONE;1976}1977return odictiter_new((PyODictObject *)dv->dv_dict,1978_odict_ITER_VALUES);1979}19801981static PyObject *1982odictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))1983{1984if (dv->dv_dict == NULL) {1985Py_RETURN_NONE;1986}1987return odictiter_new((PyODictObject *)dv->dv_dict,1988_odict_ITER_VALUES|_odict_ITER_REVERSED);1989}19901991static PyMethodDef odictvalues_methods[] = {1992{"__reversed__", (PyCFunction)odictvalues_reversed, METH_NOARGS, NULL},1993{NULL, NULL} /* sentinel */1994};19951996PyTypeObject PyODictValues_Type = {1997PyVarObject_HEAD_INIT(&PyType_Type, 0)1998"odict_values", /* tp_name */19990, /* tp_basicsize */20000, /* tp_itemsize */20010, /* tp_dealloc */20020, /* tp_vectorcall_offset */20030, /* tp_getattr */20040, /* tp_setattr */20050, /* tp_as_async */20060, /* tp_repr */20070, /* tp_as_number */20080, /* tp_as_sequence */20090, /* tp_as_mapping */20100, /* tp_hash */20110, /* tp_call */20120, /* tp_str */20130, /* tp_getattro */20140, /* tp_setattro */20150, /* tp_as_buffer */20160, /* tp_flags */20170, /* tp_doc */20180, /* tp_traverse */20190, /* tp_clear */20200, /* tp_richcompare */20210, /* tp_weaklistoffset */2022(getiterfunc)odictvalues_iter, /* tp_iter */20230, /* tp_iternext */2024odictvalues_methods, /* tp_methods */20250, /* tp_members */20260, /* tp_getset */2027&PyDictValues_Type, /* tp_base */2028};20292030static PyObject *2031odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))2032{2033return _PyDictView_New(od, &PyODictValues_Type);2034}203520362037/* ----------------------------------------------2038MutableMapping implementations20392040Mapping:20412042============ ===========2043method uses2044============ ===========2045__contains__ __getitem__2046__eq__ items2047__getitem__ +2048__iter__ +2049__len__ +2050__ne__ __eq__2051get __getitem__2052items ItemsView2053keys KeysView2054values ValuesView2055============ ===========20562057ItemsView uses __len__, __iter__, and __getitem__.2058KeysView uses __len__, __iter__, and __contains__.2059ValuesView uses __len__, __iter__, and __getitem__.20602061MutableMapping:20622063============ ===========2064method uses2065============ ===========2066__delitem__ +2067__setitem__ +2068clear popitem2069pop __getitem__2070__delitem__2071popitem __iter__2072_getitem__2073__delitem__2074setdefault __getitem__2075__setitem__2076update __setitem__2077============ ===========2078*/20792080static int2081mutablemapping_add_pairs(PyObject *self, PyObject *pairs)2082{2083PyObject *pair, *iterator, *unexpected;2084int res = 0;20852086iterator = PyObject_GetIter(pairs);2087if (iterator == NULL)2088return -1;2089PyErr_Clear();20902091while ((pair = PyIter_Next(iterator)) != NULL) {2092/* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */2093PyObject *key = NULL, *value = NULL;2094PyObject *pair_iterator = PyObject_GetIter(pair);2095if (pair_iterator == NULL)2096goto Done;20972098key = PyIter_Next(pair_iterator);2099if (key == NULL) {2100if (!PyErr_Occurred())2101PyErr_SetString(PyExc_ValueError,2102"need more than 0 values to unpack");2103goto Done;2104}21052106value = PyIter_Next(pair_iterator);2107if (value == NULL) {2108if (!PyErr_Occurred())2109PyErr_SetString(PyExc_ValueError,2110"need more than 1 value to unpack");2111goto Done;2112}21132114unexpected = PyIter_Next(pair_iterator);2115if (unexpected != NULL) {2116Py_DECREF(unexpected);2117PyErr_SetString(PyExc_ValueError,2118"too many values to unpack (expected 2)");2119goto Done;2120}2121else if (PyErr_Occurred())2122goto Done;21232124res = PyObject_SetItem(self, key, value);21252126Done:2127Py_DECREF(pair);2128Py_XDECREF(pair_iterator);2129Py_XDECREF(key);2130Py_XDECREF(value);2131if (PyErr_Occurred())2132break;2133}2134Py_DECREF(iterator);21352136if (res < 0 || PyErr_Occurred() != NULL)2137return -1;2138else2139return 0;2140}21412142static int2143mutablemapping_update_arg(PyObject *self, PyObject *arg)2144{2145int res = 0;2146if (PyDict_CheckExact(arg)) {2147PyObject *items = PyDict_Items(arg);2148if (items == NULL) {2149return -1;2150}2151res = mutablemapping_add_pairs(self, items);2152Py_DECREF(items);2153return res;2154}2155PyObject *func;2156if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) {2157return -1;2158}2159if (func != NULL) {2160PyObject *keys = _PyObject_CallNoArgs(func);2161Py_DECREF(func);2162if (keys == NULL) {2163return -1;2164}2165PyObject *iterator = PyObject_GetIter(keys);2166Py_DECREF(keys);2167if (iterator == NULL) {2168return -1;2169}2170PyObject *key;2171while (res == 0 && (key = PyIter_Next(iterator))) {2172PyObject *value = PyObject_GetItem(arg, key);2173if (value != NULL) {2174res = PyObject_SetItem(self, key, value);2175Py_DECREF(value);2176}2177else {2178res = -1;2179}2180Py_DECREF(key);2181}2182Py_DECREF(iterator);2183if (res != 0 || PyErr_Occurred()) {2184return -1;2185}2186return 0;2187}2188if (_PyObject_LookupAttr(arg, &_Py_ID(items), &func) < 0) {2189return -1;2190}2191if (func != NULL) {2192PyObject *items = _PyObject_CallNoArgs(func);2193Py_DECREF(func);2194if (items == NULL) {2195return -1;2196}2197res = mutablemapping_add_pairs(self, items);2198Py_DECREF(items);2199return res;2200}2201res = mutablemapping_add_pairs(self, arg);2202return res;2203}22042205static PyObject *2206mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)2207{2208int res;2209/* first handle args, if any */2210assert(args == NULL || PyTuple_Check(args));2211Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;2212if (len > 1) {2213const char *msg = "update() takes at most 1 positional argument (%zd given)";2214PyErr_Format(PyExc_TypeError, msg, len);2215return NULL;2216}22172218if (len) {2219PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */2220assert(other != NULL);2221Py_INCREF(other);2222res = mutablemapping_update_arg(self, other);2223Py_DECREF(other);2224if (res < 0) {2225return NULL;2226}2227}22282229/* now handle kwargs */2230assert(kwargs == NULL || PyDict_Check(kwargs));2231if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {2232PyObject *items = PyDict_Items(kwargs);2233if (items == NULL)2234return NULL;2235res = mutablemapping_add_pairs(self, items);2236Py_DECREF(items);2237if (res == -1)2238return NULL;2239}22402241Py_RETURN_NONE;2242}224322442245